From 6dccf9ef884a6b1613f14682d8ae181563a00559 Mon Sep 17 00:00:00 2001 From: Dan Legg Date: Thu, 28 Mar 2024 18:06:25 -0700 Subject: [PATCH 01/91] Pipeline changes to build, publish, and test (#1400) Co-authored-by: Dan Legg --- .pipelines/OneBranch.Official.yml | 4 ---- .pipelines/jobs/OneBranchNuGet.yml | 15 ++++++++------- .pipelines/jobs/OneBranchTest.yml | 3 +++ .pipelines/jobs/OneBranchVsix.yml | 4 ++-- test/test_cpp20/format.cpp | 9 +++++++++ 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index def1114a8..3c2ffdfcd 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -34,10 +34,6 @@ extends: globalSdl: tsa: enabled: false - - nugetPublishing: - feeds: - name: CppWinRT stages: - stage: build diff --git a/.pipelines/jobs/OneBranchNuGet.yml b/.pipelines/jobs/OneBranchNuGet.yml index 803e6f9f7..e2a871114 100644 --- a/.pipelines/jobs/OneBranchNuGet.yml +++ b/.pipelines/jobs/OneBranchNuGet.yml @@ -15,7 +15,6 @@ jobs: variables: ob_outputDirectory: '$(Build.SourcesDirectory)\out' - ob_nugetPublishing_enabled: ${{ parameters.OfficialBuild }} PackageVersion: ${{ parameters.BuildVersion }} steps: @@ -59,12 +58,8 @@ jobs: - task: NuGetCommand@2 displayName: 'Build NuGet package' inputs: - command: 'pack' - packagesToPack: 'nuget/Microsoft.Windows.CppWinRT.nuspec' - versioningScheme: byEnvVar - versionEnvVar: 'PackageVersion' - buildProperties: 'cppwinrt_exe=$(Build.SourcesDirectory)\x86\cppwinrt\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=$(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib' - packDestination: $(ob_outputDirectory)\packages + command: 'custom' + arguments: 'pack nuget/Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory $(ob_outputDirectory)\packages -Properties Configuration=release;cppwinrt_exe=$(Build.SourcesDirectory)\x86\cppwinrt\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=$(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib;target_version=$(PackageVersion) -Version $(PackageVersion) -Verbosity Detailed' - task: onebranch.pipeline.signing@1 displayName: '🔒 Onebranch Signing for NuGet package' @@ -74,3 +69,9 @@ jobs: signing_profile: external_distribution files_to_sign: 'Microsoft.Windows.CppWinRT.*.nupkg' search_root: $(ob_outputDirectory)\packages + + - task: NuGetCommand@2 + displayName: 'Publish NuGet package' + inputs: + command: 'custom' + arguments: 'push $(ob_outputDirectory)\packages\Microsoft.Windows.CppWinRT.$(PackageVersion).nupkg -NonInteractive -Source https://microsoft.pkgs.visualstudio.com/_packaging/CppWinRT/nuget/v3/index.json -ApiKey VSTS' \ No newline at end of file diff --git a/.pipelines/jobs/OneBranchTest.yml b/.pipelines/jobs/OneBranchTest.yml index d9634ff1e..bba8dac20 100644 --- a/.pipelines/jobs/OneBranchTest.yml +++ b/.pipelines/jobs/OneBranchTest.yml @@ -8,6 +8,9 @@ jobs: - job: pool: type: windows + isCustom: true + name: 'Azure Pipelines' + vmImage: 'windows-2022' # (or 2019) strategy: matrix: test.x86: diff --git a/.pipelines/jobs/OneBranchVsix.yml b/.pipelines/jobs/OneBranchVsix.yml index 2efa5b29c..3526712eb 100644 --- a/.pipelines/jobs/OneBranchVsix.yml +++ b/.pipelines/jobs/OneBranchVsix.yml @@ -108,8 +108,8 @@ jobs: inputs: command: sign signing_profile: external_distribution - files_to_sign: '**/Microsoft.Windows.CppWinRT.*.dll' - search_root: '$(Agent.TempDirectory)\$(VsixFilename)' + files_to_sign: '**\*.dll' + search_root: '$(Agent.TempDirectory)' - task: ArchiveFiles@2 displayName: 'Repack signed VSIX contents' diff --git a/test/test_cpp20/format.cpp b/test/test_cpp20/format.cpp index 0c40a4113..d16193328 100644 --- a/test/test_cpp20/format.cpp +++ b/test/test_cpp20/format.cpp @@ -17,17 +17,26 @@ TEST_CASE("format") winrt::hstring str = L"World"; REQUIRE(std::format(L"Hello {}", str) == L"Hello World"); } +} +TEST_CASE("format_make") +{ { winrt::Windows::Foundation::IStringable obj = winrt::make(); REQUIRE(std::format(L"This is {}", obj) == L"This is a stringable object"); } +} +TEST_CASE("format_json") +{ { winrt::Windows::Data::Json::JsonArray jsonArray; REQUIRE(std::format(L"The contents of the array are: {}", jsonArray) == L"The contents of the array are: []"); } +} +TEST_CASE("format_wstring") +{ #if __cpp_lib_format >= 202207L { std::wstring str = L"World"; From bdf6dc462bf6b827d7c8ce893e725faf5acba6b0 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Fri, 29 Mar 2024 10:42:29 -0700 Subject: [PATCH 02/91] Merlinbot baseline (#1401) * Merged PR 9973274: Auto-generated baselines by 1ES Pipeline Templates This pull request includes baselines **with an expiration date of 180 days from now** automatically generated for your 1ES PT-based pipelines. Complete this pull request as soon as possible to make sure that your pipeline becomes compliant. Longer delays in completing this PR can trigger additional emails or S360 alerts in the future. 1ES PT Auto-baselining feature helps capture existing violations in your repo and ensures to break your pipeline only for newly introduced SDL violations after baselining. Running SDL tools in break mode is required for your pipeline to be compliant. Go to https://aka.ms/1espt-autobaselining for more details. * Merged PR 9973274: Auto-generated baselines by 1ES Pipeline Templates This pull request includes baselines **with an expiration date of 180 days from now** automatically generated for your 1ES PT-based pipelines. Complete this pull request as soon as possible to make sure that your pipeline becomes compliant. Longer delays in completing this PR can trigger additional emails or S360 alerts in the future. 1ES PT Auto-baselining feature helps capture existing violations in your repo and ensures to break your pipeline only for newly introduced SDL violations after baselining. Running SDL tools in break mode is required for your pipeline to be compliant. Go to https://aka.ms/1espt-autobaselining for more details. --------- Co-authored-by: MerlinBot --- .config/1espt/PipelineAutobaseliningConfig.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .config/1espt/PipelineAutobaseliningConfig.yml diff --git a/.config/1espt/PipelineAutobaseliningConfig.yml b/.config/1espt/PipelineAutobaseliningConfig.yml new file mode 100644 index 000000000..a14f9aaaa --- /dev/null +++ b/.config/1espt/PipelineAutobaseliningConfig.yml @@ -0,0 +1,14 @@ +## DO NOT MODIFY THIS FILE MANUALLY. This is part of auto-baselining from 1ES Pipeline Templates. Go to [https://aka.ms/1espt-autobaselining] for more details. + +pipelines: + 98194: + retail: + source: + credscan: + lastModifiedDate: 2023-12-06 + eslint: + lastModifiedDate: 2023-12-06 + psscriptanalyzer: + lastModifiedDate: 2023-12-06 + armory: + lastModifiedDate: 2023-12-06 From adc6ef93185b2fa40e5f89d99fcd59b8b856dec7 Mon Sep 17 00:00:00 2001 From: TDBuild Date: Sun, 31 Mar 2024 05:01:31 +0000 Subject: [PATCH 03/91] TDBuild - updating localized resource files. --- .../1espt/PipelineAutobaseliningConfig.yml | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/.config/1espt/PipelineAutobaseliningConfig.yml b/.config/1espt/PipelineAutobaseliningConfig.yml index a14f9aaaa..4b9969c37 100644 --- a/.config/1espt/PipelineAutobaseliningConfig.yml +++ b/.config/1espt/PipelineAutobaseliningConfig.yml @@ -1,14 +1,14 @@ -## DO NOT MODIFY THIS FILE MANUALLY. This is part of auto-baselining from 1ES Pipeline Templates. Go to [https://aka.ms/1espt-autobaselining] for more details. - -pipelines: - 98194: - retail: - source: - credscan: - lastModifiedDate: 2023-12-06 - eslint: - lastModifiedDate: 2023-12-06 - psscriptanalyzer: - lastModifiedDate: 2023-12-06 - armory: - lastModifiedDate: 2023-12-06 +## DO NOT MODIFY THIS FILE MANUALLY. This is part of auto-baselining from 1ES Pipeline Templates. Go to [https://aka.ms/1espt-autobaselining] for more details. + +pipelines: + 98194: + retail: + source: + credscan: + lastModifiedDate: 2023-12-06 + eslint: + lastModifiedDate: 2023-12-06 + psscriptanalyzer: + lastModifiedDate: 2023-12-06 + armory: + lastModifiedDate: 2023-12-06 From f0ce6c67980f4617340282c352aabfef8dbdc41b Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 5 Apr 2024 07:52:22 -0500 Subject: [PATCH 04/91] Create dependabot.yml --- .github/dependabot.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..47f88349d --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "daily" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" From dfad7ed2cae3f4d6e5c5f07c2416804245c98409 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Apr 2024 07:55:51 -0500 Subject: [PATCH 05/91] Bump actions/checkout from 3 to 4 (#1406) --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d37aa360..f4d0458d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: config: Release runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - id: setup-llvm name: Set up LLVM (MSVC) @@ -107,7 +107,7 @@ jobs: config: Release runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - id: setup-llvm name: Set up LLVM (MSVC) @@ -260,7 +260,7 @@ jobs: CMAKE_COLOR_DIAGNOSTICS: 1 CLICOLOR_FORCE: 1 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install cross compiler run: | @@ -293,7 +293,7 @@ jobs: Deployment: [Component, Standalone] runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Download nuget run: | @@ -331,7 +331,7 @@ jobs: config: [Release] runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Fetch cppwinrt executables uses: actions/download-artifact@v3 @@ -381,7 +381,7 @@ jobs: name: Build nuget package with MSVC runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Package run: | From 523eda71a6fdd73534c7910b974554ac9850830f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Apr 2024 07:56:22 -0500 Subject: [PATCH 06/91] Bump actions/stale from 6 to 9 (#1405) --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 20bf8f2a4..c081bdf43 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -13,7 +13,7 @@ jobs: pull-requests: write steps: - - uses: actions/stale@v6 + - uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 10 From 6f7495288c4a90b29e95808ab08a0489f7d94f72 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Apr 2024 07:59:41 -0500 Subject: [PATCH 07/91] Bump actions/upload-artifact from 3 to 4 (#1407) --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f4d0458d9..3351eb550 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,7 +71,7 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt - name: Upload built executables - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -240,7 +240,7 @@ jobs: - name: Upload arm64 test executables if: matrix.arch == 'arm64' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: msvc-tests-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -279,7 +279,7 @@ jobs: cmake --build build/cross_x64/ --target install -j2 - name: Upload cppwinrt.exe - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: cross-build-${{ matrix.arch }}-bin path: install/bin/cppwinrt.exe @@ -396,7 +396,7 @@ jobs: } - name: Upload nuget package artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: package path: "*.nupkg" From ea187691c1c0d508399c1b069635383082fd9e5b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Apr 2024 08:11:19 -0500 Subject: [PATCH 08/91] Bump actions/download-artifact from 3 to 4 (#1408) --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3351eb550..898369f1c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -116,14 +116,14 @@ jobs: - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: msvc-build-x86-Release-bin path: _build/x86/Release/ @@ -334,7 +334,7 @@ jobs: - uses: actions/checkout@v4 - name: Fetch cppwinrt executables - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ From 2b8fe6e000ea9ce4402e97fa85c3919fe9a81281 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 5 Apr 2024 08:35:15 -0500 Subject: [PATCH 09/91] Revert "Bump actions/upload-artifact from 3 to 4 (#1407)" --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 898369f1c..ad5e708d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,7 +71,7 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt - name: Upload built executables - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v3 with: name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -240,7 +240,7 @@ jobs: - name: Upload arm64 test executables if: matrix.arch == 'arm64' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v3 with: name: msvc-tests-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -279,7 +279,7 @@ jobs: cmake --build build/cross_x64/ --target install -j2 - name: Upload cppwinrt.exe - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v3 with: name: cross-build-${{ matrix.arch }}-bin path: install/bin/cppwinrt.exe @@ -396,7 +396,7 @@ jobs: } - name: Upload nuget package artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v3 with: name: package path: "*.nupkg" From 17d095ac936f21007ef94f9594aec52d250240a6 Mon Sep 17 00:00:00 2001 From: Kenny Kerr Date: Fri, 5 Apr 2024 09:39:24 -0500 Subject: [PATCH 10/91] Fix build following dependabot updates (#1409) --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ad5e708d7..f4d0458d9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -116,14 +116,14 @@ jobs: - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v3 with: name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v3 with: name: msvc-build-x86-Release-bin path: _build/x86/Release/ @@ -334,7 +334,7 @@ jobs: - uses: actions/checkout@v4 - name: Fetch cppwinrt executables - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v3 with: name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ From e03bdc4e3987b8eb1425b9fe4f2ebbba548be423 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Fri, 5 Apr 2024 14:16:37 -0400 Subject: [PATCH 11/91] Use latest upload/download actions (#1410) --- .github/workflows/ci.yml | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f4d0458d9..af61bbe99 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,9 +71,9 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt - name: Upload built executables - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: | _build/${{ matrix.arch }}/${{ matrix.config }}/*.exe _build/${{ matrix.arch }}/${{ matrix.config }}/*.dll @@ -116,16 +116,16 @@ jobs: - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: - name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: - name: msvc-build-x86-Release-bin + name: msvc-build-${{ matrix.compiler}}-x86-Release-bin path: _build/x86/Release/ - name: Download nuget @@ -240,9 +240,9 @@ jobs: - name: Upload arm64 test executables if: matrix.arch == 'arm64' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: msvc-tests-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-tests-${{ matrix.test_exe }}-${{ matrix.compiler }}-${{ matrix.arch }}-${{ matrix.config }}-bin path: | _build/${{ matrix.arch }}/${{ matrix.config }}/*.exe _build/${{ matrix.arch }}/${{ matrix.config }}/*.dll @@ -279,7 +279,7 @@ jobs: cmake --build build/cross_x64/ --target install -j2 - name: Upload cppwinrt.exe - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: cross-build-${{ matrix.arch }}-bin path: install/bin/cppwinrt.exe @@ -323,10 +323,12 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" /p:Deployment=${{ matrix.Deployment }} natvis\cppwinrtvisualizer.sln build-msvc-nuget-test: - name: 'Build nuget test' + name: 'Build nuget test (${{ matrix.arch }})' needs: test-msvc-cppwinrt-build strategy: matrix: + compiler: + - MSVC arch: [x86, x64] config: [Release] runs-on: windows-latest @@ -334,9 +336,9 @@ jobs: - uses: actions/checkout@v4 - name: Fetch cppwinrt executables - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: - name: msvc-build-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Download nuget @@ -396,7 +398,7 @@ jobs: } - name: Upload nuget package artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: package path: "*.nupkg" From d2a66776bb16e1da9dac60770c977e847485e24b Mon Sep 17 00:00:00 2001 From: Scott Jones Date: Fri, 5 Apr 2024 13:15:18 -0700 Subject: [PATCH 12/91] Remove references to stale winmd files to fix incremental builds (#1404) The original attempt at a fix for this was too aggressive: https://github.com/microsoft/cppwinrt/pull/1381/files This fix is targeted specifically at removing references to stale winmd files that have yet to be copied from referenced projects (e.g., from a runtime component to an app). --- nuget/Microsoft.Windows.CppWinRT.targets | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index f5606caec..4d861e12a 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -861,7 +861,9 @@ $(XamlMetaDataProviderPch) Condition="'@(Page)@(ApplicationDefinition)' != '' and '$(XamlLanguage)' == 'CppWinRT'" DependsOnTargets="$(CppWinRTAddXamlReferencesDependsOn);CppWinRTGetResolvedWinMD;GetCppWinRTProjectWinMDReferences"> - + + + From bc19737a14e54d9fc8a98993df2e2c9033cadd42 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Fri, 5 Apr 2024 18:27:02 -0400 Subject: [PATCH 13/91] Use latest cache action (#1411) --- .github/actions/setup-llvm-mingw/action.yml | 4 ++-- .github/actions/setup-llvm-msvc/action.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/setup-llvm-mingw/action.yml b/.github/actions/setup-llvm-mingw/action.yml index 9926bbe93..50fe696b7 100644 --- a/.github/actions/setup-llvm-mingw/action.yml +++ b/.github/actions/setup-llvm-mingw/action.yml @@ -19,7 +19,7 @@ runs: - name: Cache llvm-mingw (Windows) id: cache-llvm if: runner.os == 'Windows' - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: .llvm-mingw key: llvm-mingw-${{ runner.os }}-${{ inputs.llvm-mingw-version }}-${{ inputs.host-arch }} @@ -50,7 +50,7 @@ runs: - name: Cache llvm-mingw (Linux) id: cache-llvm-linux if: runner.os == 'Linux' - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: /opt/llvm-mingw key: llvm-mingw-${{ runner.os }}-${{ inputs.llvm-mingw-version }}-${{ inputs.host-arch }} diff --git a/.github/actions/setup-llvm-msvc/action.yml b/.github/actions/setup-llvm-msvc/action.yml index d6a2a5faa..036d0fa28 100644 --- a/.github/actions/setup-llvm-msvc/action.yml +++ b/.github/actions/setup-llvm-msvc/action.yml @@ -14,7 +14,7 @@ runs: steps: - name: Cache LLVM and tools id: cache-llvm - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | .LLVM From 881b5614b850a03794997c6d01f5d1131594a864 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Sat, 6 Apr 2024 08:17:18 -0400 Subject: [PATCH 14/91] Spelling (#1412) --- cross-mingw-toolchain.cmake | 2 +- natvis/object_visualizer.h | 2 +- nuget/Microsoft.Windows.CppWinRT.targets | 2 +- nuget/readme.md | 6 +++--- test/catch.hpp | 4 ++-- test/old_tests/Component/Component.idl | 4 ++-- test/old_tests/UnitTests/abi_guard.cpp | 12 ++++++------ test/old_tests/UnitTests/async.cpp | 2 +- test/old_tests/UnitTests/delegate.cpp | 2 +- test/old_tests/UnitTests/make_self.cpp | 2 +- test/old_tests/UnitTests/marshal.cpp | 2 +- test/old_tests/UnitTests/produce.cpp | 2 +- test/old_tests/UnitTests/produce_async.cpp | 2 +- test/old_tests/UnitTests/produce_map.cpp | 2 +- test/old_tests/UnitTests/produce_vector.cpp | 2 +- test/old_tests/UnitTests/struct.cpp | 4 ++-- test/test/abi_guard.cpp | 12 ++++++------ test/test/cmd_reader.cpp | 2 +- test/test/thread_pool.cpp | 2 +- test/test_component_base/pch.h | 2 +- 20 files changed, 35 insertions(+), 35 deletions(-) diff --git a/cross-mingw-toolchain.cmake b/cross-mingw-toolchain.cmake index d58bb278d..23156e11b 100644 --- a/cross-mingw-toolchain.cmake +++ b/cross-mingw-toolchain.cmake @@ -1,5 +1,5 @@ # This is a cmake-toolchain(5) file that can be used to cross-build -# cppwinrt.exe fron Linux or other operating systems using a mingw-w64 cross +# cppwinrt.exe from Linux or other operating systems using a mingw-w64 cross # toolchain. This should work with both GCC-based and llvm-mingw toolchains. # # Example usage with external toolchain: diff --git a/natvis/object_visualizer.h b/natvis/object_visualizer.h index 08cc40f72..ad83d79d7 100644 --- a/natvis/object_visualizer.h +++ b/natvis/object_visualizer.h @@ -26,7 +26,7 @@ enum class ObjectType Projection, }; -// Metatdata for resolving a runtime class property value +// Metadata for resolving a runtime class property value struct PropertyData { std::wstring iid; diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index 4d861e12a..7fe83b14d 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -28,7 +28,7 @@ Copyright (C) Microsoft Corporation. All rights reserved. $(CppWinRTParameters) -fastabi "$(CppWinRTPackageDir)bin\" "$(CppWinRTPackageDir)" - + true C++ diff --git a/nuget/readme.md b/nuget/readme.md index 991fd2768..9379aa716 100644 --- a/nuget/readme.md +++ b/nuget/readme.md @@ -41,7 +41,7 @@ It sets the following project properties and item metadata: | Link.AdditionalDependencies | WindowsApp.lib | Umbrella library for Windows Runtime imports | | Midl.AdditionalOptions | /reference ... | Enables faster compilation with winmd references (versus idl imports) | | Midl.EnableWindowsRuntime | true | Enables Windows Runtime semantics | -| Midl.MetadataFileName | Unmerged\%(Filename).winmd | Generates unmerged metadata in a tempoary location | +| Midl.MetadataFileName | Unmerged\%(Filename).winmd | Generates unmerged metadata in a temporary location | | Midl.GenerateClientFiles, GenerateServerFiles, GenerateStublessProxies, GenerateTypeLibrary, HeaderFileName, DllDataFileName, InterfaceIdentifierFileName, ProxyFileName, TypeLibraryName | *nul, *None, *false | Disable unnecessary output | \*If not already set @@ -114,7 +114,7 @@ void MyComponent::InitializeComponent() ***[Windows|Microsoft]::UI::Xaml::Markup::ComponentConnectorT*** -A consequence of calling InitializeComponent outside construction is that Xaml runtime callbacks to IComponentConnector::Connect and IComponentConnector2::GetBindingConnector are now dispatched to the most derived implementations. Previously, these calls were dispatched directly to the class under construction, as the vtable had yet to be initialized. For objects with markup that derive from composable base classes with markup, this is a breaking change. Derived classes must now implement IComponentConnector::Connect and IComponentConnector2::GetBindingConnector by explicitly calling into the base class. The ComponentConnectorT template provides a correct implemenation for these interfaces: +A consequence of calling InitializeComponent outside construction is that Xaml runtime callbacks to IComponentConnector::Connect and IComponentConnector2::GetBindingConnector are now dispatched to the most derived implementations. Previously, these calls were dispatched directly to the class under construction, as the vtable had yet to be initialized. For objects with markup that derive from composable base classes with markup, this is a breaking change. Derived classes must now implement IComponentConnector::Connect and IComponentConnector2::GetBindingConnector by explicitly calling into the base class. The ComponentConnectorT template provides a correct implementation for these interfaces: ```cpp struct DerivedPage : winrt::Windows::UI::Xaml::Markup::ComponentConnectorT> @@ -147,7 +147,7 @@ For example, if the verbosity is set to minimal, then only messages with high im The default importance of C++/WinRT build messages is 'normal', but this can be overridden with the CppWinRTVerbosity property to enable throttling of C++/WinRT messages independent of the overall verbosity level. Example: -> msbuild project.vcxproj /vebosity:minimal /property:CppWinRTVerbosity=high ... +> msbuild project.vcxproj /verbosity:minimal /property:CppWinRTVerbosity=high ... For more complex analysis of build errors, the [MSBuild Binary and Structured Log Viewer](http://msbuildlog.com/) is highly recommended. diff --git a/test/catch.hpp b/test/catch.hpp index e949ee88c..d008973a6 100644 --- a/test/catch.hpp +++ b/test/catch.hpp @@ -7779,7 +7779,7 @@ namespace Catch { result = -erfc_inv(2.0 * p); // result *= normal distribution standard deviation (1.0) * sqrt(2) result *= /*sd * */ ROOT_TWO; - // result += normal disttribution mean (0) + // result += normal distribution mean (0) return result; } @@ -11310,7 +11310,7 @@ namespace Catch { std::string TagInfo::all() const { size_t size = 0; for (auto const& spelling : spellings) { - // Add 2 for the brackes + // Add 2 for the brackets size += spelling.size() + 2; } diff --git a/test/old_tests/Component/Component.idl b/test/old_tests/Component/Component.idl index 157297ee9..3c306ad69 100644 --- a/test/old_tests/Component/Component.idl +++ b/test/old_tests/Component/Component.idl @@ -247,7 +247,7 @@ namespace Component runtimeclass FastInputVector { // Don't confuse this for a high-performance vector. This is for testing fast-input binding support. - // The default interface is intentionally not one of the collection intefaces to force them to be convertible for testing. + // The default interface is intentionally not one of the collection interfaces to force them to be convertible for testing. [default] interface Windows.Foundation.IClosable; interface Windows.Foundation.Collections.IVector; interface Windows.Foundation.Collections.IVectorView; @@ -265,7 +265,7 @@ namespace Component runtimeclass FastInputMap { // Don't confuse this for a high-performance map. This is for testing fast-input binding support. - // The default interface is intentionally not one of the collection intefaces to force them to be convertible for testing. + // The default interface is intentionally not one of the collection interfaces to force them to be convertible for testing. [default] interface Windows.Foundation.IClosable; interface Windows.Foundation.Collections.IMap; interface Windows.Foundation.Collections.IMapView; diff --git a/test/old_tests/UnitTests/abi_guard.cpp b/test/old_tests/UnitTests/abi_guard.cpp index 3108baf62..70800323c 100644 --- a/test/old_tests/UnitTests/abi_guard.cpp +++ b/test/old_tests/UnitTests/abi_guard.cpp @@ -12,7 +12,7 @@ using namespace Windows::Foundation; namespace { // - // This implemenetation uses the simplest abi_enter and abi_exit methods. + // This implementation uses the simplest abi_enter and abi_exit methods. // struct A : implements { @@ -60,7 +60,7 @@ namespace } // - // This implemenetation uses the abi_enter but omits the abi_exit method. + // This implementation uses the abi_enter but omits the abi_exit method. // struct B : implements { @@ -102,7 +102,7 @@ namespace } // - // This implemenetation throws from the abi_enter method. + // This implementation throws from the abi_enter method. // struct C : implements { @@ -145,7 +145,7 @@ namespace } // - // This implemenetation provides a nested abi_guard + // This implementation provides a nested abi_guard // struct D : implements { @@ -223,7 +223,7 @@ namespace }; // - // This implemenetation use an abi_guard type alias + // This implementation use an abi_guard type alias // struct E : implements { @@ -275,7 +275,7 @@ namespace }; // - // This implemenetation use an abi_guard type alias that thows + // This implementation use an abi_guard type alias that throws // struct F : implements { diff --git a/test/old_tests/UnitTests/async.cpp b/test/old_tests/UnitTests/async.cpp index 979c2aac7..037e16ab7 100644 --- a/test/old_tests/UnitTests/async.cpp +++ b/test/old_tests/UnitTests/async.cpp @@ -1098,7 +1098,7 @@ TEST_CASE("async, Cancel_IAsyncOperationWithProgress, 2") } // -// These tests confirm the implicit cancelation behavior. The obeservable behavior should be the same as above +// These tests confirm the implicit cancelation behavior. The observable behavior should be the same as above // but the implementation relies on an exception so we confirm that the state changes occur as before. // diff --git a/test/old_tests/UnitTests/delegate.cpp b/test/old_tests/UnitTests/delegate.cpp index ab83a2a65..5951b7bf6 100644 --- a/test/old_tests/UnitTests/delegate.cpp +++ b/test/old_tests/UnitTests/delegate.cpp @@ -680,7 +680,7 @@ TEST_CASE("delegate,MapChangedEventHandler") TEST_CASE("delegate,collection") { // - // Mostly a compiliation test to ensure that we can create collections of delegates. This is a rare corner case that was + // Mostly a compilation test to ensure that we can create collections of delegates. This is a rare corner case that was // previously not working. // diff --git a/test/old_tests/UnitTests/make_self.cpp b/test/old_tests/UnitTests/make_self.cpp index f7c0b1e3e..6ac17a3c0 100644 --- a/test/old_tests/UnitTests/make_self.cpp +++ b/test/old_tests/UnitTests/make_self.cpp @@ -8,7 +8,7 @@ #endif // -// These tests ensure that the make_self function works as expected to provide direct acccess +// These tests ensure that the make_self function works as expected to provide direct access // to an implementation. // // The IMakeSelf IUnknown interface is also tested as this covers an edge case in the implements diff --git a/test/old_tests/UnitTests/marshal.cpp b/test/old_tests/UnitTests/marshal.cpp index e183aa674..b260e7528 100644 --- a/test/old_tests/UnitTests/marshal.cpp +++ b/test/old_tests/UnitTests/marshal.cpp @@ -2,7 +2,7 @@ #include "catch.hpp" // These tests do not attempt to test the FTM itself, but merely to confirm that the presence and -// absence of the non_agile marker does indeed produce the correct reponses from QueryInterface. +// absence of the non_agile marker does indeed produce the correct responses from QueryInterface. // CoMarshalInterfaceXxxx is also used to exercise the code paths. Also, these tests confirm that // the weak reference object inherits the same agility as the source. Although much of this is // tested elsewhere, it was helpful to have these tests as a set. diff --git a/test/old_tests/UnitTests/produce.cpp b/test/old_tests/UnitTests/produce.cpp index 403f0df2b..149466002 100644 --- a/test/old_tests/UnitTests/produce.cpp +++ b/test/old_tests/UnitTests/produce.cpp @@ -4,7 +4,7 @@ // // These tests cover the production of the three core interfaces namely IUnknown, IInspectable, and IActivationFactory. // Tests ensure that the ABI surface lines up on the consumer and producer sides and this is mainly done simply by calling -// the various inteface methods. +// the various interface methods. // using namespace winrt; diff --git a/test/old_tests/UnitTests/produce_async.cpp b/test/old_tests/UnitTests/produce_async.cpp index e37842e12..ed8ee50db 100644 --- a/test/old_tests/UnitTests/produce_async.cpp +++ b/test/old_tests/UnitTests/produce_async.cpp @@ -4,7 +4,7 @@ // // These tests cover the production of the various async interfaces. // Tests ensure that the ABI surface lines up on the consumer and producer sides and this is mainly done simply by calling -// the various inteface methods. +// the various interface methods. // using namespace winrt; diff --git a/test/old_tests/UnitTests/produce_map.cpp b/test/old_tests/UnitTests/produce_map.cpp index b456082a4..0c66a1820 100644 --- a/test/old_tests/UnitTests/produce_map.cpp +++ b/test/old_tests/UnitTests/produce_map.cpp @@ -5,7 +5,7 @@ // // These tests cover the production of the various map-related interfaces. // Tests ensure that the ABI surface lines up on the consumer and producer sides and this is mainly done simply by calling -// the various inteface methods. +// the various interface methods. // using namespace winrt; diff --git a/test/old_tests/UnitTests/produce_vector.cpp b/test/old_tests/UnitTests/produce_vector.cpp index fbf3d3b84..16111f96d 100644 --- a/test/old_tests/UnitTests/produce_vector.cpp +++ b/test/old_tests/UnitTests/produce_vector.cpp @@ -5,7 +5,7 @@ // // These tests cover the production of the various vector-related interfaces. // Tests ensure that the ABI surface lines up on the consumer and producer sides and this is mainly done simply by calling -// the various inteface methods. +// the various interface methods. // using namespace winrt; diff --git a/test/old_tests/UnitTests/struct.cpp b/test/old_tests/UnitTests/struct.cpp index bce62e25d..995f495a4 100644 --- a/test/old_tests/UnitTests/struct.cpp +++ b/test/old_tests/UnitTests/struct.cpp @@ -10,7 +10,7 @@ using namespace Windows::Web::Http; // // This first test ensures that structures with HSTRING fields are projected correctly. // In this case, a suitable interface is provided by the Windows SDK to simplify testing. -// IControlTemplate provides the necessary methods for excercising input and output +// IControlTemplate provides the necessary methods for exercising input and output // patterns for code generation. // @@ -47,7 +47,7 @@ TEST_CASE("struct, TypeName") // // This second test ensures that structures with IReference fields are projected correctly. // In this case, a suitable interface is not available in the Windows SDK so we hand-roll the -// the necessary intput and output patterms for code generation. We also rely on a custom +// the necessary input and output patterns for code generation. We also rely on a custom // implementation of IReference so that we can additionally check that the object is // destroyed correctly. // diff --git a/test/test/abi_guard.cpp b/test/test/abi_guard.cpp index c0244a475..b2931b278 100644 --- a/test/test/abi_guard.cpp +++ b/test/test/abi_guard.cpp @@ -6,7 +6,7 @@ using namespace Windows::Foundation; namespace { // - // This implemenetation uses the simplest abi_enter and abi_exit methods + // This implementation uses the simplest abi_enter and abi_exit methods // struct Simple : implements { @@ -34,7 +34,7 @@ namespace }; // - // This implemenetation uses the abi_enter but omits the abi_exit method + // This implementation uses the abi_enter but omits the abi_exit method // struct OnlyEnter : implements { @@ -56,7 +56,7 @@ namespace }; // - // This implemenetation throws from the abi_enter method + // This implementation throws from the abi_enter method // struct Throwing : implements { @@ -83,7 +83,7 @@ namespace }; // - // This implemenetation provides a nested abi_guard + // This implementation provides a nested abi_guard // struct NestedGuard : implements { @@ -138,7 +138,7 @@ namespace }; // - // This implemenetation use an abi_guard type alias + // This implementation use an abi_guard type alias // struct GuardAlias : implements { @@ -167,7 +167,7 @@ namespace }; // - // This implemenetation use an abi_guard type alias that thows + // This implementation use an abi_guard type alias that throws // struct ThrowAlias : implements { diff --git a/test/test/cmd_reader.cpp b/test/test/cmd_reader.cpp index 731922fd8..a7b9a7ad1 100644 --- a/test/test/cmd_reader.cpp +++ b/test/test/cmd_reader.cpp @@ -122,7 +122,7 @@ TEST_CASE("cmd_reader") REQUIRE_FALSE(args.exists("verbose")); } - // response file #4: really really long path + // response file #4: really, really, long path { const char* argv[] = { "progname", "@respfile.txt" }; const size_t argc = _countof(argv); diff --git a/test/test/thread_pool.cpp b/test/test/thread_pool.cpp index ac75dac18..c55cffe1d 100644 --- a/test/test/thread_pool.cpp +++ b/test/test/thread_pool.cpp @@ -53,7 +53,7 @@ TEST_CASE("thread_pool") uint32_t const stable_counter = test(test_iterations, 1, 1); uint32_t const unstable_counter = test(test_iterations, 10, 10); - // This is determinstic since the queue is single-threaded. + // This is deterministic since the queue is single-threaded. REQUIRE(stable_counter == test_iterations); // This is unlikely to fail since the pool is multi-threaded. diff --git a/test/test_component_base/pch.h b/test/test_component_base/pch.h index e5c39a869..a6f43eada 100644 --- a/test/test_component_base/pch.h +++ b/test/test_component_base/pch.h @@ -4,6 +4,6 @@ #include "winrt/base.h" // get_module_lock will always return true if WINRT_NO_MODULE_LOCK is defined. -// This ensures that if the DLL unecessarily exports DllCanUnloadNow that it +// This ensures that if the DLL unnecessarily exports DllCanUnloadNow that it // will in turn return S_FALSE. static_assert(winrt::get_module_lock()); From a22626ae6f63778aafee7013de655db57ba0839d Mon Sep 17 00:00:00 2001 From: Dependabot Date: Tue, 16 Apr 2024 19:50:15 +0000 Subject: [PATCH 15/91] Merge pull request 10563206 from dependabot/nuget/vsix/Newtonsoft.Json-13.0.1 into master --- vsix/Dev16/vsix.Dev16.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/vsix/Dev16/vsix.Dev16.csproj b/vsix/Dev16/vsix.Dev16.csproj index e9c5d140e..1e89b390b 100644 --- a/vsix/Dev16/vsix.Dev16.csproj +++ b/vsix/Dev16/vsix.Dev16.csproj @@ -92,6 +92,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all + From 4834e605f49b4b70a52398eded2c12b1ca13eb41 Mon Sep 17 00:00:00 2001 From: Felix Patschkowski <49550034+Patschkowski@users.noreply.github.com> Date: Thu, 11 Jul 2024 22:34:26 +0800 Subject: [PATCH 16/91] Changed visibility of `observable_map_base::call_changed` to `protected` --- strings/base_collections_base.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/strings/base_collections_base.h b/strings/base_collections_base.h index b2d58f602..db84b1044 100644 --- a/strings/base_collections_base.h +++ b/strings/base_collections_base.h @@ -619,15 +619,17 @@ WINRT_EXPORT namespace winrt call_changed(Windows::Foundation::Collections::CollectionChange::Reset, impl::empty_value()); } - private: - - event> m_changed; + protected: void call_changed(Windows::Foundation::Collections::CollectionChange const change, K const& key) { m_changed(static_cast(*this), make(change, key)); } + private: + + event> m_changed; + struct args : implements> { args(Windows::Foundation::Collections::CollectionChange const change, K const& key) noexcept : From 0deecf1ea4fcc6acd10602e2340e243fcdcf4f47 Mon Sep 17 00:00:00 2001 From: Michael Maltsev <4129781+m417z@users.noreply.github.com> Date: Wed, 31 Jul 2024 18:54:05 +0300 Subject: [PATCH 17/91] Add missing `` to `base_includes.h` (#1427) --- strings/base_includes.h | 1 + 1 file changed, 1 insertion(+) diff --git a/strings/base_includes.h b/strings/base_includes.h index ee22bc0aa..819e3c98f 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include From 2e4bdb05da1fe86080c523a2e00f81d62f209b17 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Thu, 5 Sep 2024 10:22:01 -0700 Subject: [PATCH 18/91] Add NuGet config with public feed (#1433) --- nuget.config | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 nuget.config diff --git a/nuget.config b/nuget.config new file mode 100644 index 000000000..a7584f8d9 --- /dev/null +++ b/nuget.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file From 64d2a52dd5e5c11df69db2b309e0d0fe8b5a8d09 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Tue, 10 Sep 2024 14:30:54 -0700 Subject: [PATCH 19/91] Update NuGetCommand to use nuget.config (#1434) --- .pipelines/build.yml | 8 ++++++++ .pipelines/jobs/OneBranchBuild.yml | 4 ++++ .pipelines/jobs/OneBranchTest.yml | 2 ++ .pipelines/jobs/OneBranchVsix.yml | 2 ++ 4 files changed, 16 insertions(+) diff --git a/.pipelines/build.yml b/.pipelines/build.yml index 8a7ee5568..b46e36eb9 100644 --- a/.pipelines/build.yml +++ b/.pipelines/build.yml @@ -49,6 +49,10 @@ jobs: - task: NuGetCommand@2 displayName: NuGet restore + inputs: + command: 'restore' + feedsToUse: config + nugetConfigPath: NuGet.config - task: CmdLine@2 displayName: Build Tools @@ -322,6 +326,10 @@ jobs: - task: NuGetCommand@2 displayName: NuGet restore + inputs: + command: 'restore' + feedsToUse: config + nugetConfigPath: NuGet.config - task: DownloadPipelineArtifact@1 displayName: Download x86 Artifacts diff --git a/.pipelines/jobs/OneBranchBuild.yml b/.pipelines/jobs/OneBranchBuild.yml index 984530eba..f8ca8cedc 100644 --- a/.pipelines/jobs/OneBranchBuild.yml +++ b/.pipelines/jobs/OneBranchBuild.yml @@ -51,6 +51,8 @@ jobs: inputs: command: 'restore' restoreSolution: '$(Build.SourcesDirectory)\cppwinrt.sln' + feedsToUse: config + nugetConfigPath: NuGet.config - task: VSBuild@1 displayName: Build fast_fwd @@ -72,6 +74,8 @@ jobs: inputs: command: 'restore' restoreSolution: '$(Build.SourcesDirectory)\natvis\cppwinrtvisualizer.sln' + feedsToUse: config + nugetConfigPath: NuGet.config - task: VSBuild@1 displayName: Build Component visualizer diff --git a/.pipelines/jobs/OneBranchTest.yml b/.pipelines/jobs/OneBranchTest.yml index bba8dac20..307f5e168 100644 --- a/.pipelines/jobs/OneBranchTest.yml +++ b/.pipelines/jobs/OneBranchTest.yml @@ -80,6 +80,8 @@ jobs: inputs: command: 'restore' restoreSolution: '$(Build.SourcesDirectory)\cppwinrt.sln' + feedsToUse: config + nugetConfigPath: NuGet.config - task: PowerShell@2 displayName: Remove cppwinrt dependency from test projects diff --git a/.pipelines/jobs/OneBranchVsix.yml b/.pipelines/jobs/OneBranchVsix.yml index 3526712eb..b4d23eb44 100644 --- a/.pipelines/jobs/OneBranchVsix.yml +++ b/.pipelines/jobs/OneBranchVsix.yml @@ -56,6 +56,8 @@ jobs: inputs: command: 'restore' restoreSolution: '$(Build.SourcesDirectory)\vsix\vsix.sln' + feedsToUse: config + nugetConfigPath: NuGet.config - task: DownloadPipelineArtifact@2 displayName: 'Download x86 binaries' From c5e0aaeb533735b641c4236b12a7fdf72cda53aa Mon Sep 17 00:00:00 2001 From: Nate Thorn Date: Mon, 16 Sep 2024 13:33:55 -0700 Subject: [PATCH 20/91] Clarify how InitializeComponent works in the template comment (#1435) --- vsix/ItemTemplates/BlankPage/BlankPage.h | 1 + vsix/ItemTemplates/BlankUserControl/BlankUserControl.h | 1 + vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.h | 1 + 3 files changed, 3 insertions(+) diff --git a/vsix/ItemTemplates/BlankPage/BlankPage.h b/vsix/ItemTemplates/BlankPage/BlankPage.h index 58c0f3648..4f7b2b0dd 100644 --- a/vsix/ItemTemplates/BlankPage/BlankPage.h +++ b/vsix/ItemTemplates/BlankPage/BlankPage.h @@ -9,6 +9,7 @@ namespace winrt::$rootnamespace$::implementation $safeitemname$() { // Xaml objects should not call InitializeComponent during construction. + // If a Xaml object needs to access a Xaml property during initialization, it should override InitializeComponent. // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent } diff --git a/vsix/ItemTemplates/BlankUserControl/BlankUserControl.h b/vsix/ItemTemplates/BlankUserControl/BlankUserControl.h index 0ab08377a..210b99659 100644 --- a/vsix/ItemTemplates/BlankUserControl/BlankUserControl.h +++ b/vsix/ItemTemplates/BlankUserControl/BlankUserControl.h @@ -13,6 +13,7 @@ namespace winrt::$rootnamespace$::implementation $safeitemname$() { // Xaml objects should not call InitializeComponent during construction. + // If a Xaml object needs to access a Xaml property during initialization, it should override InitializeComponent. // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent } diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.h b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.h index 92e0a689d..366ef6614 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.h +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/MainPage.h @@ -9,6 +9,7 @@ namespace winrt::$safeprojectname$::implementation MainPage() { // Xaml objects should not call InitializeComponent during construction. + // If a Xaml object needs to access a Xaml property during initialization, it should override InitializeComponent. // See https://github.com/microsoft/cppwinrt/tree/master/nuget#initializecomponent } From f9ec1986083a70d2f99d726b06b00a38cb2d1054 Mon Sep 17 00:00:00 2001 From: Duncan Horn <40036384+dunhor@users.noreply.github.com> Date: Wed, 2 Oct 2024 15:15:26 -0700 Subject: [PATCH 21/91] Silence clang-tidy warnings (#1438) --- strings/base_collections_base.h | 44 +++++++++++++++---------------- strings/base_collections_vector.h | 12 ++++----- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/strings/base_collections_base.h b/strings/base_collections_base.h index db84b1044..f3ede9ed4 100644 --- a/strings/base_collections_base.h +++ b/strings/base_collections_base.h @@ -108,7 +108,7 @@ WINRT_EXPORT namespace winrt auto First() { // NOTE: iterator's constructor requires shared access - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); return make(static_cast(this)); } @@ -161,7 +161,7 @@ WINRT_EXPORT namespace winrt T Current() const { - auto guard = m_owner->acquire_shared(); + [[maybe_unused]] auto guard = m_owner->acquire_shared(); this->check_version(*m_owner); if (m_current == m_end) @@ -174,14 +174,14 @@ WINRT_EXPORT namespace winrt bool HasCurrent() const { - auto guard = m_owner->acquire_shared(); + [[maybe_unused]] auto guard = m_owner->acquire_shared(); this->check_version(*m_owner); return m_current != m_end; } bool MoveNext() { - auto guard = m_owner->acquire_exclusive(); + [[maybe_unused]] auto guard = m_owner->acquire_exclusive(); this->check_version(*m_owner); if (m_current != m_end) { @@ -193,7 +193,7 @@ WINRT_EXPORT namespace winrt uint32_t GetMany(array_view values) { - auto guard = m_owner->acquire_exclusive(); + [[maybe_unused]] auto guard = m_owner->acquire_exclusive(); this->check_version(*m_owner); return GetMany(values, typename std::iterator_traits::iterator_category()); } @@ -248,7 +248,7 @@ WINRT_EXPORT namespace winrt { T GetAt(uint32_t const index) const { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); if (index >= container_size()) { throw hresult_out_of_bounds(); @@ -259,13 +259,13 @@ WINRT_EXPORT namespace winrt uint32_t Size() const noexcept { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); return container_size(); } bool IndexOf(T const& value, uint32_t& index) const noexcept { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); auto first = std::find_if(static_cast(*this).get_container().begin(), static_cast(*this).get_container().end(), [&](auto&& match) { return value == static_cast(*this).unwrap_value(match); @@ -277,7 +277,7 @@ WINRT_EXPORT namespace winrt uint32_t GetMany(uint32_t const startIndex, array_view values) const { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); if (startIndex >= container_size()) { return 0; @@ -308,7 +308,7 @@ WINRT_EXPORT namespace winrt { impl::removed_value::value_type> oldValue; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); if (index >= static_cast(*this).get_container().size()) { throw hresult_out_of_bounds(); @@ -322,7 +322,7 @@ WINRT_EXPORT namespace winrt void InsertAt(uint32_t const index, T const& value) { - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); if (index > static_cast(*this).get_container().size()) { throw hresult_out_of_bounds(); @@ -336,7 +336,7 @@ WINRT_EXPORT namespace winrt { impl::removed_value::value_type> removedValue; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); if (index >= static_cast(*this).get_container().size()) { throw hresult_out_of_bounds(); @@ -350,7 +350,7 @@ WINRT_EXPORT namespace winrt void Append(T const& value) { - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); this->increment_version(); static_cast(*this).get_container().push_back(static_cast(*this).wrap_value(value)); } @@ -359,7 +359,7 @@ WINRT_EXPORT namespace winrt { impl::removed_value::value_type> removedValue; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); if (static_cast(*this).get_container().empty()) { throw hresult_out_of_bounds(); @@ -374,7 +374,7 @@ WINRT_EXPORT namespace winrt { impl::removed_values oldContainer; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); this->increment_version(); oldContainer.assign(static_cast(*this).get_container()); } @@ -383,7 +383,7 @@ WINRT_EXPORT namespace winrt { impl::removed_values oldContainer; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); this->increment_version(); oldContainer.assign(static_cast(*this).get_container()); assign(value.begin(), value.end()); @@ -508,7 +508,7 @@ WINRT_EXPORT namespace winrt { V Lookup(K const& key) const { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); auto pair = static_cast(*this).get_container().find(static_cast(*this).wrap_value(key)); if (pair == static_cast(*this).get_container().end()) @@ -521,13 +521,13 @@ WINRT_EXPORT namespace winrt uint32_t Size() const noexcept { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); return static_cast(static_cast(*this).get_container().size()); } bool HasKey(K const& key) const noexcept { - auto guard = static_cast(*this).acquire_shared(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); return static_cast(*this).get_container().find(static_cast(*this).wrap_value(key)) != static_cast(*this).get_container().end(); } @@ -550,7 +550,7 @@ WINRT_EXPORT namespace winrt { impl::removed_value::mapped_type> oldValue; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); this->increment_version(); auto [itr, added] = static_cast(*this).get_container().emplace(static_cast(*this).wrap_value(key), static_cast(*this).wrap_value(value)); if (!added) @@ -566,7 +566,7 @@ WINRT_EXPORT namespace winrt { typename impl::container_type_t::node_type removedNode; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); auto& container = static_cast(*this).get_container(); auto found = container.find(static_cast(*this).wrap_value(key)); if (found == container.end()) @@ -581,7 +581,7 @@ WINRT_EXPORT namespace winrt { impl::removed_values oldContainer; - auto guard = static_cast(*this).acquire_exclusive(); + [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); this->increment_version(); oldContainer.assign(static_cast(*this).get_container()); } diff --git a/strings/base_collections_vector.h b/strings/base_collections_vector.h index ff0ad6bec..cef7ef2d3 100644 --- a/strings/base_collections_vector.h +++ b/strings/base_collections_vector.h @@ -82,7 +82,7 @@ namespace winrt::impl operator wfc::IIterator() { - auto guard = container->acquire_shared(); + [[maybe_unused]] auto guard = container->acquire_shared(); return make(container); } }; @@ -141,7 +141,7 @@ namespace winrt::impl uint32_t GetMany(uint32_t const startIndex, array_view values) const { - auto guard = this->acquire_shared(); + [[maybe_unused]] auto guard = this->acquire_shared(); if (startIndex >= m_values.size()) { return 0; @@ -239,7 +239,7 @@ namespace winrt::impl Windows::Foundation::IInspectable Current() const { - auto guard = m_owner->acquire_shared(); + [[maybe_unused]] auto guard = m_owner->acquire_shared(); check_version(*m_owner); if (m_current == m_end) { @@ -251,14 +251,14 @@ namespace winrt::impl bool HasCurrent() const { - auto guard = m_owner->acquire_shared(); + [[maybe_unused]] auto guard = m_owner->acquire_shared(); check_version(*m_owner); return m_current != m_end; } bool MoveNext() { - auto guard = m_owner->acquire_exclusive(); + [[maybe_unused]] auto guard = m_owner->acquire_exclusive(); check_version(*m_owner); if (m_current != m_end) { @@ -270,7 +270,7 @@ namespace winrt::impl uint32_t GetMany(array_view values) { - auto guard = m_owner->acquire_exclusive(); + [[maybe_unused]] auto guard = m_owner->acquire_exclusive(); check_version(*m_owner); uint32_t const actual = (std::min)(static_cast(std::distance(m_current, m_end)), values.size()); From 2744f5cc706a8060ebe2d50a37eed190d7802c47 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Tue, 29 Oct 2024 14:40:36 -0700 Subject: [PATCH 22/91] Value-init fields of WinRT structs (#1443) --- cppwinrt/code_writers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 3c77269cd..44b889b81 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -2716,7 +2716,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable static void write_struct_field(writer& w, std::pair const& field) { - w.write(" @ %;\n", + w.write(" @ % {};\n", field.second, field.first); } From b82340f3fce1ee9bbcc13151f6f74c374d03f24d Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Wed, 30 Oct 2024 09:54:35 -0700 Subject: [PATCH 23/91] Bug: Projected winrt::consume_ methods will nullptr crash if the underlying QueryInterface call fails (#1442) # Why is this change being made? The generated projection code for interfaces that the metadata declares as required for a runtimeclass assume that QueryInterface never fails. Assuming the metadata is correct in the first place, this is a valid assumption for inproc calls. However, for cross-process calls the QI can fail even if the metadata is correct and the class really does implement all of the required interfaces. It can fail with E_ACCESSDENIED and a variety of other RPC error codes. When this happens there is a nullptr crash in the generated consume method. This can be very painful to debug because the HRESULT is lost by the time it crashes. # Briefly summarize what changed This set of changes fixes the crash by detecting the QueryInterface error and throwing an exception when that occurs during one of these required casts. The try_as method was changed to capture COM error context when the QI fails. The code gen surrounding WINRT_IMPL_STUB was changed to save the result into a temporary variable and then pass it to a new check_cast_result method. check_cast_result is marked noinline so that the binary size impact of throwing exceptions is limited to a single function instead of inlining into high-volume generated code. If the cast succeeded then nothing happens. If the cast failed, returning null, then the stored COM exception is retrieved. Assuming it is available the HRESULT is pulled out of it and it is thrown. This then propagates like any other exception. Callers are free to try and catch it or let it go uncaught and crash. Now they have the choice. I also added a new file of test code that exercises this code path. The test_component IDL declares a runtimeclass that implements IStringable. And then the implementation fails to implement IStringable. When ToString is called on this object it hits the failure path. The cppwinrt code gen will not allow this to happen so I had to directly use winrt::implements. # How was this change tested? Besides the new test cases I also wrote a little console app that crashes this way. I built and ran it using the latest stable cppwinrt as well as my private new one. As expected the debugger blame is far more useful with these changes. --- cppwinrt.sln | 3 + cppwinrt/code_writers.h | 20 +- scratch/scratch.vcxproj | 255 ++-------------------- strings/base_error.h | 22 ++ strings/base_extern.h | 3 + strings/base_windows.h | 6 +- test/test/missing_required_interfaces.cpp | 25 +++ test/test/test.vcxproj | 1 + test/test_component/test_component.idl | 7 + 9 files changed, 106 insertions(+), 236 deletions(-) create mode 100644 test/test/missing_required_interfaces.cpp diff --git a/cppwinrt.sln b/cppwinrt.sln index 43e96ffab..e2ac95942 100644 --- a/cppwinrt.sln +++ b/cppwinrt.sln @@ -88,6 +88,9 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fast_fwd", "fast_fwd\fast_fwd.vcxproj", "{A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scratch", "scratch\scratch.vcxproj", "{E893622C-47DE-4F83-B422-0A26711590A4}" + ProjectSection(ProjectDependencies) = postProject + {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_module_lock_none", "test\test_module_lock_none\test_module_lock_none.vcxproj", "{D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}" ProjectSection(ProjectDependencies) = postProject diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 44b889b81..0e516b528 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1129,9 +1129,16 @@ namespace cppwinrt if (is_remove_overload(method)) { // we intentionally ignore errors when unregistering event handlers to be consistent with event_revoker + // + // The `noexcept` versions will crash if check_cast_result throws but that is no different than previous + // behavior where it would not check the cast result and nullptr crash. At least the exception will terminate + // immediately while preserving the error code and local variables. format = R"( template auto consume_%::%(%) const noexcept {% - WINRT_IMPL_SHIM(%)->%(%);% + auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const abiType = *(abi_t<%>**)&castedResult; + check_cast_result(abiType); + abiType->%(%);% } )"; } @@ -1139,7 +1146,10 @@ namespace cppwinrt { format = R"( template auto consume_%::%(%) const noexcept {% - WINRT_VERIFY_(0, WINRT_IMPL_SHIM(%)->%(%));% + auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const abiType = *(abi_t<%>**)&castedResult; + check_cast_result(abiType); + WINRT_VERIFY_(0, abiType->%(%));% } )"; } @@ -1148,7 +1158,10 @@ namespace cppwinrt { format = R"( template auto consume_%::%(%) const {% - check_hresult(WINRT_IMPL_SHIM(%)->%(%));% + auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const abiType = *(abi_t<%>**)&castedResult; + check_cast_result(abiType); + check_hresult(abiType->%(%));% } )"; } @@ -1161,6 +1174,7 @@ namespace cppwinrt bind(signature), bind(signature, false), type, + type, get_abi_name(method), bind(signature), bind(signature)); diff --git a/scratch/scratch.vcxproj b/scratch/scratch.vcxproj index 4a26617b4..45122c13d 100644 --- a/scratch/scratch.vcxproj +++ b/scratch/scratch.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -35,277 +36,67 @@ + true + true + true + true 16.0 {E893622C-47DE-4F83-B422-0A26711590A4} scratch scratch - - - - Application - true - - - Application - true - - Application - true + + ..\_build\$(Platform)\$(Configuration) + false - - Application - false - true - - - Application - false - true - - - Application - false - true - - - Application + + true - - Application + false true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\..\..\library - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreaded - - - Console - true - true - - - - - - - - - - - - - Disabled - $(OutputPath);Generated Files;..\..\..\library - _MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreadedDebug - - - Console - - - - - - - - - - - + - Disabled - $(OutputPath);Generated Files;..\..\..\library - _MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreadedDebug + $(OutputPath);Generated Files; Console - - - - - - - - - - - Disabled - $(OutputPath);Generated Files;..\..\..\library - _MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreadedDebug - - - Console - - - - - - - - - - - - - Disabled - $(OutputPath);Generated Files;..\..\..\library - _MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreadedDebug - - - Console - - - - - - - - - - - + MaxSpeed true true - $(OutputPath);Generated Files;..\..\..\library NOMINMAX;_MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) MultiThreaded - Console true true - - - - - - - - - + - MaxSpeed - true - true - $(OutputPath);Generated Files;..\..\..\library - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreaded - - - Console - true - true - - - - - - - - - - - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\..\..\library - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - %(AdditionalOptions) - MultiThreaded + Disabled + _MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug - - Console - true - true - - - - - - - - - - NotUsing - Use - Use - Use - Use - Use - Use - Use - Use + Use - Create - Create - Create - Create - Create - Create - Create - Create + Create + + + diff --git a/strings/base_error.h b/strings/base_error.h index 6e0aa103a..8a3a3a088 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -546,6 +546,28 @@ namespace winrt::impl } return result; } + + template + WINRT_IMPL_NOINLINE void check_cast_result(T* from WINRT_IMPL_SOURCE_LOCATION_ARGS) + { + if (!from) + { + com_ptr restrictedError; + if (WINRT_IMPL_GetRestrictedErrorInfo(restrictedError.put_void()) == 0) + { + WINRT_IMPL_SetRestrictedErrorInfo(restrictedError.get()); + + int32_t code; + impl::bstr_handle description; + impl::bstr_handle restrictedDescription; + impl::bstr_handle capabilitySid; + if (restrictedError->GetErrorDetails(description.put(), &code, restrictedDescription.put(), capabilitySid.put()) == 0) + { + throw hresult_error(code, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + } + } + } + } } #undef WINRT_IMPL_RETURNADDRESS diff --git a/strings/base_extern.h b/strings/base_extern.h index 92872d416..c0e83e75a 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -29,8 +29,11 @@ extern "C" int32_t __stdcall WINRT_IMPL_SetThreadpoolTimerEx(winrt::impl::ptp_timer, void*, uint32_t, uint32_t) noexcept WINRT_IMPL_LINK(SetThreadpoolTimerEx, 16); int32_t __stdcall WINRT_IMPL_SetThreadpoolWaitEx(winrt::impl::ptp_wait, void*, void*, void*) noexcept WINRT_IMPL_LINK(SetThreadpoolWaitEx, 16); int32_t __stdcall WINRT_IMPL_RoOriginateLanguageException(int32_t error, void* message, void* exception) noexcept WINRT_IMPL_LINK(RoOriginateLanguageException, 12); + int32_t __stdcall WINRT_IMPL_RoCaptureErrorContext(int32_t error) noexcept WINRT_IMPL_LINK(RoCaptureErrorContext, 4); void __stdcall WINRT_IMPL_RoFailFastWithErrorContext(int32_t) noexcept WINRT_IMPL_LINK(RoFailFastWithErrorContext, 4); int32_t __stdcall WINRT_IMPL_RoTransformError(int32_t, int32_t, void*) noexcept WINRT_IMPL_LINK(RoTransformError, 12); + int32_t __stdcall WINRT_IMPL_GetRestrictedErrorInfo(void**) noexcept WINRT_IMPL_LINK(GetRestrictedErrorInfo, 4); + int32_t __stdcall WINRT_IMPL_SetRestrictedErrorInfo(void*) noexcept WINRT_IMPL_LINK(SetRestrictedErrorInfo, 4); void* __stdcall WINRT_IMPL_LoadLibraryExW(wchar_t const* name, void* unused, uint32_t flags) noexcept WINRT_IMPL_LINK(LoadLibraryExW, 12); int32_t __stdcall WINRT_IMPL_FreeLibrary(void* library) noexcept WINRT_IMPL_LINK(FreeLibrary, 4); diff --git a/strings/base_windows.h b/strings/base_windows.h index 41030d368..f5230e1c8 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -128,7 +128,11 @@ namespace winrt::impl } void* result{}; - ptr->QueryInterface(guid_of(), &result); + hresult code = ptr->QueryInterface(guid_of(), &result); + if (code < 0) + { + WINRT_IMPL_RoCaptureErrorContext(code); + } return wrap_as_result(result); } } diff --git a/test/test/missing_required_interfaces.cpp b/test/test/missing_required_interfaces.cpp new file mode 100644 index 000000000..237e4ff41 --- /dev/null +++ b/test/test/missing_required_interfaces.cpp @@ -0,0 +1,25 @@ +#include "pch.h" + +// Unset lean and mean so we can implement a type from the test_component namespace +#undef WINRT_LEAN_AND_MEAN +#include + +namespace +{ + struct LiesAboutInheritance : public winrt::implements + { + LiesAboutInheritance() = default; + void StubMethod() {} + }; +} + +TEST_CASE("missing_required_interfaces") +{ + auto lies = winrt::make_self().as(); + REQUIRE(lies); + REQUIRE_NOTHROW(lies.StubMethod()); + + // The IStringable::ToString method does not exist on this type. In previous versions of cppwinrt + // this line would crash with a nullptr deference. It now throws an exception. + REQUIRE_THROWS_AS(lies.ToString(), winrt::hresult_error); +} diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index b75f2e219..a82465149 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -387,6 +387,7 @@ NotUsing + NotUsing NotUsing diff --git a/test/test_component/test_component.idl b/test/test_component/test_component.idl index fb7444889..a027c394c 100644 --- a/test/test_component/test_component.idl +++ b/test/test_component/test_component.idl @@ -163,6 +163,13 @@ namespace test_component static void StaticMethodWithAsyncReturn(); } + // This class declares that it implements another interface but under the covers it actually does + // not. This allows us to test the behavior when QI's that should not fail, do fail. + runtimeclass LiesAboutInheritance : Windows.Foundation.IStringable + { + void StubMethod(); + } + namespace Structs { struct All From e53db0f9f6ca8b399a521b284f1ebea65df01d94 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Mon, 4 Nov 2024 14:53:42 -0800 Subject: [PATCH 24/91] WINRT_SOURCE_LOCATION has ODR checks that prevent mixing cpp17 and cpp20 static libraries (#1444) Why is this change being made? Someone is trying to upgrade the cppwinrt version used by a large project that has many static libraries using cppwinrt. Some binaries in that project are mixing static libs with different cpp language versions. (This seems like not a great idea generally but it is the state of the world so to some degree we have to live with it). In those binaries the ODR checks for cppwinrt source_location usage are breaking the build. For good reason, it is not safe to mix this functionality across language versions. This set of changes is aimed at making that upgrade process easier without losing any useful functionality. Briefly summarize what changed We already have winrt::impl::slim_source_location which is a lot like std::source_location, minus always containing the very impactful FUNCTION data. This type is powered by the same intrinsics as the STL version so it works as well as the STL library. The existence of this class means that we can avoid the ODR violations by always using winrt::impl::slim_source_location. Some new macros are used to control what goes into the constructor. cpp20 code that does not suppress source_location will get valid source information passed in. Code that is cpp17, or suppresses this feature, will have zero's passed in. Furthermore, when compiling as _DEBUG this will also include the FUNCTION data, matching previous behavior. The net result is that there is no more ODR violation because the function signatures are always the same. How was this change tested? build_test_all.cmd for both release and debug. I also created a little project that mixes cpp17 and cpp20 libraries. With the latest public release of cppwinrt this project does not build because of the ODR violations. With these changes it builds and runs as expected. --- strings/base_error.h | 162 ++++++++++++++++++++---------------------- strings/base_macros.h | 125 ++++++++++++++++---------------- strings/base_meta.h | 2 +- 3 files changed, 141 insertions(+), 148 deletions(-) diff --git a/strings/base_error.h b/strings/base_error.h index 8a3a3a088..21010ccb2 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -104,17 +104,17 @@ WINRT_EXPORT namespace winrt return *this; } - explicit hresult_error(hresult const code WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : m_code(verify_error(code)) + explicit hresult_error(hresult const code, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : m_code(verify_error(code)) { - originate(code, nullptr WINRT_IMPL_SOURCE_LOCATION_FORWARD); + originate(code, nullptr, sourceInformation); } - hresult_error(hresult const code, param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : m_code(verify_error(code)) + hresult_error(hresult const code, param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : m_code(verify_error(code)) { - originate(code, get_abi(message) WINRT_IMPL_SOURCE_LOCATION_FORWARD); + originate(code, get_abi(message), sourceInformation); } - hresult_error(hresult const code, take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : m_code(verify_error(code)) + hresult_error(hresult const code, take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : m_code(verify_error(code)) { com_ptr info; WINRT_IMPL_GetErrorInfo(0, info.put_void()); @@ -144,7 +144,7 @@ WINRT_EXPORT namespace winrt message = impl::trim_hresult_message(legacy.get(), WINRT_IMPL_SysStringLen(legacy.get())); } - originate(code, get_abi(message) WINRT_IMPL_SOURCE_LOCATION_FORWARD); + originate(code, get_abi(message), sourceInformation); } } @@ -199,7 +199,7 @@ WINRT_EXPORT namespace winrt private: - void originate(hresult const code, void* message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept + void originate(hresult const code, void* message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept { WINRT_VERIFY(WINRT_IMPL_RoOriginateLanguageException(code, message, nullptr)); @@ -208,11 +208,7 @@ WINRT_EXPORT namespace winrt // information is available on the caller who generated the error. if (winrt_throw_hresult_handler) { -#ifdef WINRT_SOURCE_LOCATION_ACTIVE winrt_throw_hresult_handler(sourceInformation.line(), sourceInformation.file_name(), sourceInformation.function_name(), WINRT_IMPL_RETURNADDRESS(), code); -#else - winrt_throw_hresult_handler(0, nullptr, nullptr, WINRT_IMPL_RETURNADDRESS(), code); -#endif } com_ptr info; @@ -244,104 +240,100 @@ WINRT_EXPORT namespace winrt struct hresult_access_denied : hresult_error { - hresult_access_denied(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_access_denied WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_access_denied(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_access_denied, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_access_denied(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_access_denied, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_access_denied(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_access_denied, sourceInformation) {} + hresult_access_denied(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_access_denied, message, sourceInformation) {} + hresult_access_denied(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_access_denied, take_ownership_from_abi, sourceInformation) {} }; struct hresult_wrong_thread : hresult_error { - hresult_wrong_thread(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_wrong_thread WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_wrong_thread(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_wrong_thread, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_wrong_thread(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_wrong_thread, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_wrong_thread(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_wrong_thread, sourceInformation) {} + hresult_wrong_thread(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_wrong_thread, message, sourceInformation) {} + hresult_wrong_thread(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_wrong_thread, take_ownership_from_abi, sourceInformation) {} }; struct hresult_not_implemented : hresult_error { - hresult_not_implemented(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_not_implemented WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_not_implemented(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_not_implemented, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_not_implemented(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_not_implemented, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_not_implemented(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_not_implemented, sourceInformation) {} + hresult_not_implemented(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_not_implemented, message, sourceInformation) {} + hresult_not_implemented(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_not_implemented, take_ownership_from_abi, sourceInformation) {} }; struct hresult_invalid_argument : hresult_error { - hresult_invalid_argument(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_invalid_argument WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_invalid_argument(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_invalid_argument, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_invalid_argument(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_invalid_argument, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_invalid_argument(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_invalid_argument, sourceInformation) {} + hresult_invalid_argument(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_invalid_argument, message, sourceInformation) {} + hresult_invalid_argument(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_invalid_argument, take_ownership_from_abi, sourceInformation) {} }; struct hresult_out_of_bounds : hresult_error { - hresult_out_of_bounds(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_out_of_bounds WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_out_of_bounds(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_out_of_bounds, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_out_of_bounds(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_out_of_bounds, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_out_of_bounds(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_out_of_bounds, sourceInformation) {} + hresult_out_of_bounds(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_out_of_bounds, message, sourceInformation) {} + hresult_out_of_bounds(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_out_of_bounds, take_ownership_from_abi, sourceInformation) {} }; struct hresult_no_interface : hresult_error { - hresult_no_interface(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_no_interface WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_no_interface(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_no_interface, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_no_interface(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_no_interface, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_no_interface(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_no_interface, sourceInformation) {} + hresult_no_interface(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_no_interface, message, sourceInformation) {} + hresult_no_interface(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_no_interface, take_ownership_from_abi, sourceInformation) {} }; struct hresult_class_not_available : hresult_error { - hresult_class_not_available(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_class_not_available WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_class_not_available(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_class_not_available, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_class_not_available(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_class_not_available, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_class_not_available(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_class_not_available, sourceInformation) {} + hresult_class_not_available(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_class_not_available, message, sourceInformation) {} + hresult_class_not_available(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_class_not_available, take_ownership_from_abi, sourceInformation) {} }; struct hresult_class_not_registered : hresult_error { - hresult_class_not_registered(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_class_not_registered WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_class_not_registered(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_class_not_registered, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_class_not_registered(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_class_not_registered, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_class_not_registered(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_class_not_registered, sourceInformation) {} + hresult_class_not_registered(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_class_not_registered, message, sourceInformation) {} + hresult_class_not_registered(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_class_not_registered, take_ownership_from_abi, sourceInformation) {} }; struct hresult_changed_state : hresult_error { - hresult_changed_state(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_changed_state WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_changed_state(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_changed_state, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_changed_state(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_changed_state, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_changed_state(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_changed_state, sourceInformation) {} + hresult_changed_state(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_changed_state, message, sourceInformation) {} + hresult_changed_state(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_changed_state, take_ownership_from_abi, sourceInformation) {} }; struct hresult_illegal_method_call : hresult_error { - hresult_illegal_method_call(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_illegal_method_call WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_illegal_method_call(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_method_call, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_illegal_method_call(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_method_call, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_illegal_method_call(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_method_call, sourceInformation) {} + hresult_illegal_method_call(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_method_call, message, sourceInformation) {} + hresult_illegal_method_call(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_method_call, take_ownership_from_abi, sourceInformation) {} }; struct hresult_illegal_state_change : hresult_error { - hresult_illegal_state_change(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_illegal_state_change WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_illegal_state_change(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_state_change, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_illegal_state_change(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_state_change, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_illegal_state_change(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_state_change, sourceInformation) {} + hresult_illegal_state_change(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_state_change, message, sourceInformation) {} + hresult_illegal_state_change(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_state_change, take_ownership_from_abi, sourceInformation) {} }; struct hresult_illegal_delegate_assignment : hresult_error { - hresult_illegal_delegate_assignment(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_illegal_delegate_assignment WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_illegal_delegate_assignment(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_delegate_assignment, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_illegal_delegate_assignment(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_illegal_delegate_assignment, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_illegal_delegate_assignment(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_delegate_assignment, sourceInformation) {} + hresult_illegal_delegate_assignment(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_delegate_assignment, message, sourceInformation) {} + hresult_illegal_delegate_assignment(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_illegal_delegate_assignment, take_ownership_from_abi, sourceInformation) {} }; struct hresult_canceled : hresult_error { - hresult_canceled(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) noexcept : hresult_error(impl::error_canceled WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_canceled(param::hstring const& message WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_canceled, message WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} - hresult_canceled(take_ownership_from_abi_t WINRT_IMPL_SOURCE_LOCATION_ARGS) noexcept : hresult_error(impl::error_canceled, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD) {} + hresult_canceled(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_canceled, sourceInformation) {} + hresult_canceled(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_canceled, message, sourceInformation) {} + hresult_canceled(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_canceled, take_ownership_from_abi, sourceInformation) {} }; - [[noreturn]] inline WINRT_IMPL_NOINLINE void throw_hresult(hresult const result WINRT_IMPL_SOURCE_LOCATION_ARGS) + [[noreturn]] inline WINRT_IMPL_NOINLINE void throw_hresult(hresult const result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (winrt_throw_hresult_handler) { -#ifdef WINRT_SOURCE_LOCATION_ACTIVE winrt_throw_hresult_handler(sourceInformation.line(), sourceInformation.file_name(), sourceInformation.function_name(), WINRT_IMPL_RETURNADDRESS(), result); -#else - winrt_throw_hresult_handler(0, nullptr, nullptr, WINRT_IMPL_RETURNADDRESS(), result); -#endif } if (result == impl::error_bad_alloc) @@ -351,70 +343,70 @@ WINRT_EXPORT namespace winrt if (result == impl::error_access_denied) { - throw hresult_access_denied(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_access_denied(take_ownership_from_abi, sourceInformation); } if (result == impl::error_wrong_thread) { - throw hresult_wrong_thread(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_wrong_thread(take_ownership_from_abi, sourceInformation); } if (result == impl::error_not_implemented) { - throw hresult_not_implemented(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_not_implemented(take_ownership_from_abi, sourceInformation); } if (result == impl::error_invalid_argument) { - throw hresult_invalid_argument(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_invalid_argument(take_ownership_from_abi, sourceInformation); } if (result == impl::error_out_of_bounds) { - throw hresult_out_of_bounds(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_out_of_bounds(take_ownership_from_abi, sourceInformation); } if (result == impl::error_no_interface) { - throw hresult_no_interface(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_no_interface(take_ownership_from_abi, sourceInformation); } if (result == impl::error_class_not_available) { - throw hresult_class_not_available(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_class_not_available(take_ownership_from_abi, sourceInformation); } if (result == impl::error_class_not_registered) { - throw hresult_class_not_registered(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_class_not_registered(take_ownership_from_abi, sourceInformation); } if (result == impl::error_changed_state) { - throw hresult_changed_state(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_changed_state(take_ownership_from_abi, sourceInformation); } if (result == impl::error_illegal_method_call) { - throw hresult_illegal_method_call(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_illegal_method_call(take_ownership_from_abi, sourceInformation); } if (result == impl::error_illegal_state_change) { - throw hresult_illegal_state_change(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_illegal_state_change(take_ownership_from_abi, sourceInformation); } if (result == impl::error_illegal_delegate_assignment) { - throw hresult_illegal_delegate_assignment(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_illegal_delegate_assignment(take_ownership_from_abi, sourceInformation); } if (result == impl::error_canceled) { - throw hresult_canceled(take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_canceled(take_ownership_from_abi, sourceInformation); } - throw hresult_error(result, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_error(result, take_ownership_from_abi, sourceInformation); } inline WINRT_IMPL_NOINLINE hresult to_hresult() noexcept @@ -475,55 +467,55 @@ WINRT_EXPORT namespace winrt } } - [[noreturn]] inline void throw_last_error(WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM) + [[noreturn]] inline void throw_last_error(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { - throw_hresult(impl::hresult_from_win32(WINRT_IMPL_GetLastError()) WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw_hresult(impl::hresult_from_win32(WINRT_IMPL_GetLastError()), sourceInformation); } - inline hresult check_hresult(hresult const result WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT) + inline hresult check_hresult(hresult const result, winrt::impl::slim_source_location const& sourceInformation) { if (result < 0) { - throw_hresult(result WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw_hresult(result, sourceInformation); } return result; } template - void check_nt(T result WINRT_IMPL_SOURCE_LOCATION_ARGS) + void check_nt(T result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (result != 0) { - throw_hresult(impl::hresult_from_nt(result) WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw_hresult(impl::hresult_from_nt(result), sourceInformation); } } template - void check_win32(T result WINRT_IMPL_SOURCE_LOCATION_ARGS) + void check_win32(T result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (result != 0) { - throw_hresult(impl::hresult_from_win32(result) WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw_hresult(impl::hresult_from_win32(result), sourceInformation); } } template - T check_bool(T result WINRT_IMPL_SOURCE_LOCATION_ARGS) + T check_bool(T result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (!result) { - winrt::throw_last_error(WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM); + winrt::throw_last_error(sourceInformation); } return result; } template - T* check_pointer(T* pointer WINRT_IMPL_SOURCE_LOCATION_ARGS) + T* check_pointer(T* pointer, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (!pointer) { - throw_last_error(WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM); + throw_last_error(sourceInformation); } return pointer; @@ -538,17 +530,17 @@ WINRT_EXPORT namespace winrt namespace winrt::impl { - inline hresult check_hresult_allow_bounds(hresult const result WINRT_IMPL_SOURCE_LOCATION_ARGS) + inline hresult check_hresult_allow_bounds(hresult const result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (result != impl::error_out_of_bounds && result != impl::error_fail && result != impl::error_file_not_found) { - check_hresult(result WINRT_IMPL_SOURCE_LOCATION_FORWARD); + check_hresult(result, sourceInformation); } return result; } template - WINRT_IMPL_NOINLINE void check_cast_result(T* from WINRT_IMPL_SOURCE_LOCATION_ARGS) + WINRT_IMPL_NOINLINE void check_cast_result(T* from, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (!from) { @@ -563,7 +555,7 @@ namespace winrt::impl impl::bstr_handle capabilitySid; if (restrictedError->GetErrorDetails(description.put(), &code, restrictedDescription.put(), capabilitySid.put()) == 0) { - throw hresult_error(code, take_ownership_from_abi WINRT_IMPL_SOURCE_LOCATION_FORWARD); + throw hresult_error(code, take_ownership_from_abi, sourceInformation); } } } diff --git a/strings/base_macros.h b/strings/base_macros.h index e0167d152..d9e19547e 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -77,14 +77,56 @@ struct IUnknown; typedef struct _GUID GUID; #endif -// std::source_location is a C++20 feature, which is above the C++17 feature floor for cppwinrt. The source location needs -// to be the calling code, not cppwinrt itself, so that it is useful to developers building on top of this library. As a -// result any public-facing method that can result in an error needs a default-constructed source_location argument. Because -// this type does not exist in C++17 we need to use a macro to optionally add parameters and forwarding wherever appropriate. +#if defined(__cpp_consteval) +#define WINRT_IMPL_CONSTEVAL consteval +#else +#define WINRT_IMPL_CONSTEVAL constexpr +#endif + +// The intrinsics (such as __builtin_FILE()) that power std::source_location are also used to power winrt:impl::slim_source_location. +// The source location needs to be for the calling code, not cppwinrt itself, so that it is useful to developers building on top of +// this library. As a result any public-facing method that can result in an error needs a default-constructed slim_source_location +// argument so that it will collect source information from the application code that is calling into cppwinrt. +// +// We do not directly use std::source_location for two reasons: +// 1) std::source_location::function_name() is unavoidable. These strings end up in the final binary, bloating their size. This +// is particularly impactful for code bases that use templates heavily. Cases of 50% binary size growth have been observed. +// 2) std::source_location is a cpp20 feature, which is above the cpp17 feature floor for cppwinrt. By defining our own version +// we can avoid ODR violations in mixed cpp17/cpp20 builds. cpp17 callers will have an ABI that matches cpp20 callers (they +// will just not have useful file/line/function information). // -// Some projects may decide to disable std::source_location support to prevent source code information from ending up in their -// release binaries, or to reduce binary size. Defining WINRT_NO_SOURCE_LOCATION will prevent this feature from activating. -#if defined(__cpp_lib_source_location) && !defined(WINRT_NO_SOURCE_LOCATION) +// Some projects may decide that the source information binary size impact is not worth the benefit. Defining WINRT_NO_SOURCE_LOCATION +// will prevent this feature from activating. The slim_source_location type will be forwarded around but it will not include any +// nonzero data. That eliminates the biggest source of binary size overhead. +// +// To help with debugging the __builtin_FUNCTION() intrinsic will be used in _DEBUG builds. This will provide a bit more diagnostic +// value at the cost of binary size. The assumption is that binary size is considered less important in debug builds so this tradeoff +// is acceptable. +// +// The different behavior of the default parameters to winrt::impl::slim_source_location::current() is technically an ODR violation, +// albeit a minor one. There should be no serious consequence to this violation. In practice it means that mixing cpp17/cpp20, +// or mixing WINRT_NO_SOURCE_LOCATION with undefining it, will lead to inconsistent source location information. It may be missing +// when it is expected to be included, or it may be present when it is not expected. The behavior will depend on the linker's choice +// when there are multiple translation units with different options. This violation is tracked by https://github.com/microsoft/cppwinrt/issues/1445. + +#if !defined(__cpp_lib_source_location) || defined(WINRT_NO_SOURCE_LOCATION) +// Case1: cpp17 mode. The source_location intrinsics are not available. +// Case2: The caller has disabled source_location support. Ensure that there is no binary size overhead for line/file/function. +#define WINRT_IMPL_BUILTIN_LINE 0 +#define WINRT_IMPL_BUILTIN_FILE nullptr +#define WINRT_IMPL_BUILTIN_FUNCTION nullptr +#elif _DEBUG +// cpp20 _DEBUG builds include function information, which has a heavy binary size impact, in addition to file/line. +#define WINRT_IMPL_BUILTIN_LINE __builtin_LINE() +#define WINRT_IMPL_BUILTIN_FILE __builtin_FILE() +#define WINRT_IMPL_BUILTIN_FUNCTION __builtin_FUNCTION() +#else +// Release builds in cpp20 mode get file and line information but NOT function information. Function strings +// quickly add up to a substantial binary size impact, especially when templates are heavily used. +#define WINRT_IMPL_BUILTIN_LINE __builtin_LINE() +#define WINRT_IMPL_BUILTIN_FILE __builtin_FILE() +#define WINRT_IMPL_BUILTIN_FUNCTION nullptr +#endif namespace winrt::impl { @@ -93,19 +135,23 @@ namespace winrt::impl // have heavy binary size overhead when templates cause many permutations to exist. struct slim_source_location { - [[nodiscard]] static consteval slim_source_location current( - const std::uint_least32_t line = __builtin_LINE(), - const char* const file = __builtin_FILE()) noexcept + [[nodiscard]] static WINRT_IMPL_CONSTEVAL slim_source_location current( + const std::uint_least32_t line = WINRT_IMPL_BUILTIN_LINE, + const char* const file = WINRT_IMPL_BUILTIN_FILE, + const char* const function = WINRT_IMPL_BUILTIN_FUNCTION) noexcept { - return slim_source_location{ line, file }; + return slim_source_location{ line, file, function }; } [[nodiscard]] constexpr slim_source_location() noexcept = default; - [[nodiscard]] constexpr slim_source_location(const std::uint_least32_t line, - const char* const file) noexcept : + [[nodiscard]] constexpr slim_source_location( + const std::uint_least32_t line, + const char* const file, + const char* const function) noexcept : m_line(line), - m_file(file) + m_file(file), + m_function(function) {} [[nodiscard]] constexpr std::uint_least32_t line() const noexcept @@ -118,63 +164,18 @@ namespace winrt::impl return m_file; } - constexpr const char* function_name() const noexcept + [[nodiscard]] constexpr const char* function_name() const noexcept { - // This is intentionally not included. See comment above. - return nullptr; + return m_function; } private: const std::uint_least32_t m_line{}; const char* const m_file{}; + const char* const m_function{}; }; } -// std::source_location includes function_name which can be helpful but creates a lot of binary size impact. Many consumers -// have defined WINRT_NO_SOURCE_LOCATION to prevent this impact, losing the value of source_location. We have defined a -// slim_source_location struct that is equivalent but excludes function_name. This should have the vast majority of the -// usefulness of source_location while having a much smaller binary impact. -// -// When building _DEBUG binary size is not usually much of a concern, so we can use the full source_location type. -#ifdef _DEBUG -#define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT , std::source_location const& sourceInformation -#define WINRT_IMPL_SOURCE_LOCATION_ARGS , std::source_location const& sourceInformation = std::source_location::current() -#define WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM std::source_location const& sourceInformation = std::source_location::current() - -#define WINRT_IMPL_SOURCE_LOCATION_FORWARD , sourceInformation -#define WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM sourceInformation - -#define WINRT_SOURCE_LOCATION_ACTIVE - -#ifdef _MSC_VER -#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "true") -#endif // _MSC_VER - -#else // !_DEBUG -#define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT , winrt::impl::slim_source_location const& sourceInformation -#define WINRT_IMPL_SOURCE_LOCATION_ARGS , winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current() -#define WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current() - -#define WINRT_IMPL_SOURCE_LOCATION_FORWARD , sourceInformation -#define WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM sourceInformation - -#define WINRT_SOURCE_LOCATION_ACTIVE - #ifdef _MSC_VER #pragma detect_mismatch("WINRT_SOURCE_LOCATION", "slim") #endif // _MSC_VER - -#endif // _DEBUG - -#else -#define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT -#define WINRT_IMPL_SOURCE_LOCATION_ARGS -#define WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM - -#define WINRT_IMPL_SOURCE_LOCATION_FORWARD -#define WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM - -#ifdef _MSC_VER -#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "false") -#endif // _MSC_VER -#endif // defined(__cpp_lib_source_location) && !defined(WINRT_NO_SOURCE_LOCATION) diff --git a/strings/base_meta.h b/strings/base_meta.h index 2c1796e9c..25deb42ec 100644 --- a/strings/base_meta.h +++ b/strings/base_meta.h @@ -1,7 +1,7 @@ WINRT_EXPORT namespace winrt { - hresult check_hresult(hresult const result WINRT_IMPL_SOURCE_LOCATION_ARGS); + hresult check_hresult(hresult const result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()); hresult to_hresult() noexcept; template From 849498c6176b92264afdda38ed6f2492893ad5bf Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Thu, 7 Nov 2024 16:40:49 -0800 Subject: [PATCH 25/91] Latest vpack has an extra cppwinrt folder (#1447) --- .pipelines/OneBranch.Official.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 3c2ffdfcd..5ecc638b6 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -85,10 +85,10 @@ extends: - task: CopyFiles@2 displayName: 'Stage compiler vpack contents' inputs: - SourceFolder: $(Build.SourcesDirectory)/x86 + SourceFolder: $(Build.SourcesDirectory)/x86/cppwinrt Contents: | - cppwinrt/cppwinrt.exe - cppwinrt/cppwinrt.pdb + cppwinrt.exe + cppwinrt.pdb TargetFolder: $(ob_outputDirectory) - job: MSBuild_vpack From d296af6a43a1aabde45f7c9905a304414edcdcd5 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Mon, 11 Nov 2024 16:09:14 -0800 Subject: [PATCH 26/91] Reduce the code size of generated consume methods by skipping casts when the type is already a match (#1448) Why is this change being made? I have been doing some local builds of an internal component against the latest cppwinrt.exe, which includes the fixes in #1442. I have noticed some modest (1%) binary size grown when comparing the April 2024 release and the latest. Using SizeBench to analyze binary size differences I determined that the inlined code gen seems to explain the difference. This change eliminates that increase, at least for the binary I'm testing against, and even shrinks it a bit further. Briefly summarize what changed The various winrt::impl::consume_THING methods get heavily inlined in release builds. The current code gen has some casts for when the types don't match (and is an AddRef/Release when they do match). The small amount of new cast result checking ends up at many call sites and slowly adds up a bit. I think we can do better in the cases where the types already match. This seems to have proven true in practice. Using if constexpr to determine if the type is a match allows us to skip any casts when this is true. In fact that is a net improvement over the original baseline because we don't need to AddRef/Release either. We can directly call the appropriate method. When a cast is necessary the code gen is identical to the previous baseline. The QueryInterface call is unavoidable and so is checking the result. The code writer format string is definitely starting to creak under the weight of many arguments. I don't want to refactor that as part of this PR but it would be good to simplify in the future. Also included is late feedback from the previous PR from @oldnewthing. The check_cast_result method can take void* instead of a template argument because it only null checks it. In my local measurements the optimizer already folded them so it makes no binary size difference but it is still a nice change to take. How was this change tested? Ran the full suite of cppwinrt tests locally. I also debugged into Windows.Foundation.IStringable.ToString for cases where it both is and is not the correct type. They run the expected code paths. I also checked the binary size of a large example to confirm the expected reduction. The disassembly for a Release build similarly matches expectations. --- cppwinrt/code_writers.h | 52 +++++++++++++++++++++++++++++++---------- strings/base_error.h | 3 +-- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 0e516b528..f93279a74 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1135,10 +1135,18 @@ namespace cppwinrt // immediately while preserving the error code and local variables. format = R"( template auto consume_%::%(%) const noexcept {% - auto const& castedResult = static_cast<% const&>(static_cast(*this)); - auto const abiType = *(abi_t<%>**)&castedResult; - check_cast_result(abiType); - abiType->%(%);% + if constexpr (!std::is_same_v) + { + auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const abiType = *(abi_t<%>**)&castedResult; + check_cast_result(abiType); + abiType->%(%); + } + else + { + auto const abiType = *(abi_t<%>**)this; + abiType->%(%); + }% } )"; } @@ -1146,10 +1154,18 @@ namespace cppwinrt { format = R"( template auto consume_%::%(%) const noexcept {% - auto const& castedResult = static_cast<% const&>(static_cast(*this)); - auto const abiType = *(abi_t<%>**)&castedResult; - check_cast_result(abiType); - WINRT_VERIFY_(0, abiType->%(%));% + if constexpr (!std::is_same_v) + { + auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const abiType = *(abi_t<%>**)&castedResult; + check_cast_result(abiType); + WINRT_VERIFY_(0, abiType->%(%)); + } + else + { + auto const abiType = *(abi_t<%>**)this; + WINRT_VERIFY_(0, abiType->%(%)); + }% } )"; } @@ -1158,10 +1174,18 @@ namespace cppwinrt { format = R"( template auto consume_%::%(%) const {% - auto const& castedResult = static_cast<% const&>(static_cast(*this)); - auto const abiType = *(abi_t<%>**)&castedResult; - check_cast_result(abiType); - check_hresult(abiType->%(%));% + if constexpr (!std::is_same_v) + { + auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const abiType = *(abi_t<%>**)&castedResult; + check_cast_result(abiType); + check_hresult(abiType->%(%)); + } + else + { + auto const abiType = *(abi_t<%>**)this; + check_hresult(abiType->%(%)); + }% } )"; } @@ -1175,6 +1199,10 @@ namespace cppwinrt bind(signature, false), type, type, + type, + get_abi_name(method), + bind(signature), + type, get_abi_name(method), bind(signature), bind(signature)); diff --git a/strings/base_error.h b/strings/base_error.h index 21010ccb2..9b9624277 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -539,8 +539,7 @@ namespace winrt::impl return result; } - template - WINRT_IMPL_NOINLINE void check_cast_result(T* from, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) + inline WINRT_IMPL_NOINLINE void check_cast_result(void* from, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { if (!from) { From 8da835950cee482af43e2d457f345a00a413d0b5 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Fri, 15 Nov 2024 11:27:27 -0800 Subject: [PATCH 27/91] try_as casts should not store COM error context; consume method cast checking should use return codes directly (#1450) Why is this change being made? I have been trying to ingest the HEAD of cppwinrt for some large internal projects and one of them had some test failures with the new version. The failures are because there is a try_as cast in their code that fails and is handled fine, but it leaves a COM error context floating around on that thread. Subsequent code fails to originate an error because it sees a context already active on the thread and NOOP'ed. What this boils down to is that try_as should not have a behavioral change to store context when the cast fails. Briefly summarize what changed To address this problem I am taking a PR suggestion from @oldnewthing to have a new try_as_with_reason method that returns both the cast result as well as the HRESULT. The error context logic was only there to smuggle the HRESULT out of a call without an HRESULT return value, so if it is a direct return we don't need that anymore. The new method directly returns the HRESULT so there is no ambiguity. The previous approach relied on a cast operator to call try_as (or just addref when the type is already a match). Thanks to the recent if constexpr code gen change those cases are now separated out. We have a code block where we know a cast is needed so try_as_with_reason can be called unconditionally. The code path where no cast is needed already circumvents this and is nicely unaffected. This also made check_cast_result equiavelnt to check_hresult so it was deleted in favor of just calling check_hresult. How was this change tested? I did local builds of cppwinrt (both Debug and Release) and ran the tests. I am also compiling some large internal projects with it to ensure that there are no obvious breaks or regressions. I am expecting minimal to no binary size impact from this change. --- cppwinrt/code_writers.h | 14 +++++++------- strings/base_error.h | 21 --------------------- strings/base_extern.h | 2 -- strings/base_implements.h | 11 +++++++++++ strings/base_windows.h | 33 +++++++++++++++++++++++++++++---- 5 files changed, 47 insertions(+), 34 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index f93279a74..01f7dea10 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1130,16 +1130,16 @@ namespace cppwinrt { // we intentionally ignore errors when unregistering event handlers to be consistent with event_revoker // - // The `noexcept` versions will crash if check_cast_result throws but that is no different than previous + // The `noexcept` versions will crash if check_hresult throws but that is no different than previous // behavior where it would not check the cast result and nullptr crash. At least the exception will terminate // immediately while preserving the error code and local variables. format = R"( template auto consume_%::%(%) const noexcept {% if constexpr (!std::is_same_v) { - auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const [castedResult, code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); + check_hresult(code); auto const abiType = *(abi_t<%>**)&castedResult; - check_cast_result(abiType); abiType->%(%); } else @@ -1156,9 +1156,9 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const [castedResult, code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); + check_hresult(code); auto const abiType = *(abi_t<%>**)&castedResult; - check_cast_result(abiType); WINRT_VERIFY_(0, abiType->%(%)); } else @@ -1176,9 +1176,9 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const& castedResult = static_cast<% const&>(static_cast(*this)); + auto const [castedResult, code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); + check_hresult(code); auto const abiType = *(abi_t<%>**)&castedResult; - check_cast_result(abiType); check_hresult(abiType->%(%)); } else diff --git a/strings/base_error.h b/strings/base_error.h index 9b9624277..85de70f63 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -538,27 +538,6 @@ namespace winrt::impl } return result; } - - inline WINRT_IMPL_NOINLINE void check_cast_result(void* from, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) - { - if (!from) - { - com_ptr restrictedError; - if (WINRT_IMPL_GetRestrictedErrorInfo(restrictedError.put_void()) == 0) - { - WINRT_IMPL_SetRestrictedErrorInfo(restrictedError.get()); - - int32_t code; - impl::bstr_handle description; - impl::bstr_handle restrictedDescription; - impl::bstr_handle capabilitySid; - if (restrictedError->GetErrorDetails(description.put(), &code, restrictedDescription.put(), capabilitySid.put()) == 0) - { - throw hresult_error(code, take_ownership_from_abi, sourceInformation); - } - } - } - } } #undef WINRT_IMPL_RETURNADDRESS diff --git a/strings/base_extern.h b/strings/base_extern.h index c0e83e75a..2412f9f2c 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -32,8 +32,6 @@ extern "C" int32_t __stdcall WINRT_IMPL_RoCaptureErrorContext(int32_t error) noexcept WINRT_IMPL_LINK(RoCaptureErrorContext, 4); void __stdcall WINRT_IMPL_RoFailFastWithErrorContext(int32_t) noexcept WINRT_IMPL_LINK(RoFailFastWithErrorContext, 4); int32_t __stdcall WINRT_IMPL_RoTransformError(int32_t, int32_t, void*) noexcept WINRT_IMPL_LINK(RoTransformError, 12); - int32_t __stdcall WINRT_IMPL_GetRestrictedErrorInfo(void**) noexcept WINRT_IMPL_LINK(GetRestrictedErrorInfo, 4); - int32_t __stdcall WINRT_IMPL_SetRestrictedErrorInfo(void*) noexcept WINRT_IMPL_LINK(SetRestrictedErrorInfo, 4); void* __stdcall WINRT_IMPL_LoadLibraryExW(wchar_t const* name, void* unused, uint32_t flags) noexcept WINRT_IMPL_LINK(LoadLibraryExW, 12); int32_t __stdcall WINRT_IMPL_FreeLibrary(void* library) noexcept WINRT_IMPL_LINK(FreeLibrary, 4); diff --git a/strings/base_implements.h b/strings/base_implements.h index d0bb09012..0847f5019 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -792,9 +792,20 @@ namespace winrt::impl { return m_inner.operator bool(); } + + template + friend auto winrt::impl::try_as_with_reason(From ptr) noexcept; + protected: static constexpr bool is_composing = true; Windows::Foundation::IInspectable m_inner; + + private: + template + auto try_as_with_reason() const noexcept + { + return m_inner.try_as_with_reason(); + } }; template diff --git a/strings/base_windows.h b/strings/base_windows.h index f5230e1c8..a67ef0b20 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -128,12 +128,31 @@ namespace winrt::impl } void* result{}; - hresult code = ptr->QueryInterface(guid_of(), &result); - if (code < 0) + ptr->QueryInterface(guid_of(), &result); + return wrap_as_result(result); + } + + template , int> = 0> + std::pair, hresult> try_as_with_reason(From* ptr) noexcept + { +#ifdef WINRT_DIAGNOSTICS + get_diagnostics_info().add_query(); +#endif + + if (!ptr) { - WINRT_IMPL_RoCaptureErrorContext(code); + return { nullptr, 0 }; } - return wrap_as_result(result); + + void* result{}; + hresult code = ptr->QueryInterface(guid_of(), &result); + return { wrap_as_result(result), code }; + } + + template + auto try_as_with_reason(From ptr) noexcept + { + return ptr->template try_as_with_reason(); } } @@ -209,6 +228,12 @@ WINRT_EXPORT namespace winrt::Windows::Foundation return impl::try_as(m_ptr); } + template + auto try_as_with_reason() const noexcept + { + return impl::try_as_with_reason(m_ptr); + } + template void as(To& to) const { From febda5dfa1d5840096e5d94c5f317b770f4cbf86 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:12:21 -0800 Subject: [PATCH 28/91] Try to fix the disabled/failing nuget test build step (#1451) These failures were pointed out yesterday when the CLA policy was stuck. They are not blocking but have seemingly been failing for a long time and the failure is suppressed. The issue seems to be that some of these test projects reference an old NuGet package while also referencing the props/targets that are about to go into the new NuGet package. Double-including essentially the same files twice is what caused the build breaks in these projects. Some projects also had build breaks that seem to be related to a very old Windows SDK minimum version. I increased the floor to 10.0.18362.0 (early 2019; almost 6 years ago) and that fixed the remaining breaks. The random packages.config that downloaded random builds of cppwinrt from 2019 or 2020 have been deleted too. This set of changes aims to fix the build breaks and un-suppress this failure. It now builds locally on my device but I'll need an official PR build to ensure that the GitHub Actions flow is also passing. --- .github/workflows/ci.yml | 5 ----- .../ConsoleApplication1/ConsoleApplication1.vcxproj | 9 --------- test/nuget/ConsoleApplication1/packages.config | 4 ---- .../TestRuntimeComponentCSharp.csproj | 4 ++-- .../packages.config | 4 ---- .../TestStaticLibrary7/TestStaticLibrary7.vcxproj | 11 ++--------- test/nuget/TestStaticLibrary7/packages.config | 4 ---- .../ConsoleApplication/ConsoleApplication.vcxproj | 2 +- .../VC/Windows Universal/BlankApp/BlankApp.vcxproj | 2 +- .../VC/Windows Universal/CoreApp/CoreApp.vcxproj | 2 +- .../StaticLibrary/StaticLibrary.vcxproj | 2 +- .../WindowsRuntimeComponent.vcxproj | 2 +- 12 files changed, 9 insertions(+), 42 deletions(-) delete mode 100644 test/nuget/ConsoleApplication1/packages.config delete mode 100644 test/nuget/TestRuntimeComponentNamespaceUnderscore/packages.config delete mode 100644 test/nuget/TestStaticLibrary7/packages.config diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af61bbe99..7f99be8fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -373,11 +373,6 @@ jobs: - name: Run nuget test run: | cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" test\nuget\NugetTest.sln - if ($LastExitCode -ne 0) { - echo "::warning::nuget test failed" - } - # FIXME: This build was failing from the start - exit 0 build-nuget: name: Build nuget package with MSVC diff --git a/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj b/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj index 94248f8a2..15d9a8842 100644 --- a/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj +++ b/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj @@ -1,6 +1,5 @@ - true @@ -54,7 +53,6 @@ - @@ -121,11 +119,4 @@ - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - \ No newline at end of file diff --git a/test/nuget/ConsoleApplication1/packages.config b/test/nuget/ConsoleApplication1/packages.config deleted file mode 100644 index be196b1fc..000000000 --- a/test/nuget/ConsoleApplication1/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj b/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj index 869819889..b2a1dfbe8 100644 --- a/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj +++ b/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj @@ -11,8 +11,8 @@ TestRuntimeComponentCSharp en-US UAP - 10.0.18362.0 - 10.0.15063.0 + 10.0.22621.0 + 10.0.18362.0 14 512 {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} diff --git a/test/nuget/TestRuntimeComponentNamespaceUnderscore/packages.config b/test/nuget/TestRuntimeComponentNamespaceUnderscore/packages.config deleted file mode 100644 index 17dbbb252..000000000 --- a/test/nuget/TestRuntimeComponentNamespaceUnderscore/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj b/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj index a8f21c356..3189c7294 100644 --- a/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj +++ b/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj @@ -1,6 +1,6 @@ - + true true @@ -127,13 +127,6 @@ - + - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - diff --git a/test/nuget/TestStaticLibrary7/packages.config b/test/nuget/TestStaticLibrary7/packages.config deleted file mode 100644 index c4867c30b..000000000 --- a/test/nuget/TestStaticLibrary7/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj b/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj index ad52af212..f82376473 100644 --- a/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj @@ -10,7 +10,7 @@ Win32Proj $safeprojectname$ $targetplatformversion$ - 10.0.17134.0 + 10.0.18362.0 diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj index af2b41932..c270aa038 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj @@ -14,7 +14,7 @@ Windows Store 10.0 $targetplatformversion$ - 10.0.17134.0 + 10.0.18362.0 diff --git a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj index d2f2b002a..bd839b0b2 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj @@ -13,7 +13,7 @@ Windows Store 10.0 $targetplatformversion$ - 10.0.17134.0 + 10.0.18362.0 diff --git a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj index 77cc1e005..accf6d492 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj @@ -15,7 +15,7 @@ Windows Store 10.0 $targetplatformversion$ - 10.0.17134.0 + 10.0.18362.0 diff --git a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj index 55a39d0dd..7846860c0 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj @@ -14,7 +14,7 @@ Windows Store 10.0 $targetplatformversion$ - 10.0.17134.0 + 10.0.18362.0 From 2aed347fb7b54f1f01e9db53339ad9d2b4305ab9 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Mon, 18 Nov 2024 16:52:31 -0800 Subject: [PATCH 29/91] GitHub Actions workflow cannot build arm32 after updating Windows SDK (#1454) arm32 is not supported anymore by Windows. There has not been a native arm32 OS since before Win11. The wow32 backcompat on arm64 devices to run arm32 programs was removed with Win11 24H2. Most notably, the ability to build arm32 with newer SDKs and toolsets has seemingly been removed. This is now breaking the CI build. The easiest fix is to simply remove arm32 support. --- .pipelines/OneBranch.Official.yml | 7 - .pipelines/build.yml | 18 +- .pipelines/jobs/OneBranchBuild.yml | 2 - .pipelines/jobs/OneBranchNuGet.yml | 8 +- .pipelines/jobs/OneBranchVsix.yml | 6 - Directory.Build.Props | 2 +- README.md | 2 +- build_nuget.cmd | 3 +- build_prior_projection.cmd | 1 - build_projection.cmd | 1 - build_test_all.cmd | 2 - build_vsix.cmd | 3 +- cppwinrt.sln | 86 --------- cppwinrt/cppwinrt.vcxproj | 63 ------- fast_fwd/arm/thunks.asm | 58 ------- fast_fwd/fast_fwd.vcxproj | 16 +- nuget/Microsoft.Windows.CppWinRT.nuspec | 1 - prebuild/prebuild.vcxproj | 47 ----- prepare_versionless_diffs.cmd | 1 - scratch/scratch.vcxproj | 8 - strings/base_activation.h | 8 +- .../ConsoleApplication1.vcxproj | 8 + test/nuget/Directory.Build.props | 2 +- test/nuget/NuGetTest.sln | 156 +++++++---------- test/nuget/TestApp/TestApp.vcxproj | 8 +- .../TestRuntimeComponent1.vcxproj | 8 +- .../TestRuntimeComponent2.vcxproj | 8 +- .../TestRuntimeComponent3.vcxproj | 8 +- .../TestRuntimeComponentCSharp.csproj | 18 -- .../TestRuntimeComponentCX.vcxproj | 54 ------ ...entCXReferencingWinRTStaticLibrary.vcxproj | 61 ------- .../TestRuntimeComponentEmpty.vcxproj | 8 +- ...untimeComponentNamespaceUnderscore.vcxproj | 8 +- .../TestStaticLibrary1.vcxproj | 20 +-- .../TestStaticLibrary2.vcxproj | 20 +-- .../TestStaticLibrary3.vcxproj | 20 +-- .../TestStaticLibrary4.vcxproj | 24 +-- .../TestStaticLibrary5.vcxproj | 24 +-- .../TestStaticLibrary6.vcxproj | 24 +-- .../TestStaticLibrary7.vcxproj | 8 +- test/old_tests/Component/Component.vcxproj | 120 ------------- test/old_tests/Composable/Composable.vcxproj | 118 ------------- test/old_tests/UnitTests/Tests.vcxproj | 63 ------- test/test/test.vcxproj | 77 --------- test/test_component/test_component.vcxproj | 135 --------------- .../test_component_base.vcxproj | 161 ----------------- .../test_component_derived.vcxproj | 163 ------------------ .../test_component_fast.vcxproj | 163 ------------------ .../test_component_folders.vcxproj | 161 ----------------- .../test_component_no_pch.vcxproj | 163 ------------------ test/test_cpp20/test_cpp20.vcxproj | 65 ------- .../test_cpp20_no_sourcelocation.vcxproj | 65 ------- test/test_fast/test_fast.vcxproj | 65 ------- test/test_fast_fwd/test_fast_fwd.vcxproj | 66 ------- .../test_module_lock_custom.vcxproj | 65 ------- .../test_module_lock_none.vcxproj | 65 ------- test/test_slow/test_slow.vcxproj | 63 ------- .../BlankApp/BlankApp.vcxproj | 8 - .../Windows Universal/CoreApp/CoreApp.vcxproj | 8 - .../StaticLibrary/StaticLibrary.vcxproj | 8 - .../WindowsRuntimeComponent.vcxproj | 8 - 61 files changed, 172 insertions(+), 2468 deletions(-) delete mode 100644 fast_fwd/arm/thunks.asm diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 5ecc638b6..91e686622 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -130,12 +130,6 @@ extends: artifactName: 'drop_build_x64' targetPath: '$(Build.SourcesDirectory)/x64' - - task: DownloadPipelineArtifact@2 - displayName: 'Download arm artifacts' - inputs: - artifactName: 'drop_build_arm' - targetPath: '$(Build.SourcesDirectory)/arm' - - task: DownloadPipelineArtifact@2 displayName: 'Download arm64 artifacts' inputs: @@ -159,7 +153,6 @@ extends: echo d | xcopy $(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib build\native\lib\Win32 echo d | xcopy $(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib build\native\lib\amd64 echo d | xcopy $(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib build\native\lib\x64 - echo d | xcopy $(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib build\native\lib\arm echo d | xcopy $(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib build\native\lib\arm64 - stage: NuGet diff --git a/.pipelines/build.yml b/.pipelines/build.yml index b46e36eb9..ebe8ad041 100644 --- a/.pipelines/build.yml +++ b/.pipelines/build.yml @@ -31,8 +31,6 @@ jobs: buildPlatform: 'x86' x64: buildPlatform: 'x64' - arm: - buildPlatform: 'arm' arm64: buildPlatform: 'arm64' @@ -169,12 +167,6 @@ jobs: artifactName: $(BuildConfiguration)_x64 downloadPath: $(Build.SourcesDirectory)\x64 - - task: DownloadPipelineArtifact@1 - displayName: Download arm Artifacts - inputs: - artifactName: $(BuildConfiguration)_arm - downloadPath: $(Build.SourcesDirectory)\arm - - task: DownloadPipelineArtifact@1 displayName: Download arm64 Artifacts inputs: @@ -262,7 +254,7 @@ jobs: - task: CmdLine@2 displayName: Stage MSBuild vpack inputs: - script: "set TargetDir=$(Build.SourcesDirectory)\\msbuild\nrd /s /q %TargetDir% >nul 2>&1\nmd %TargetDir%\ncd %TargetDir%\n\ncopy $(Build.SourcesDirectory)\\vsix\\Microsoft.Cpp.CppWinRT.props\ncopy $(Build.SourcesDirectory)\\nuget\\Microsoft.Windows.CppWinRT.props Microsoft.Cpp.CppWinRTEnabled.props \ncopy $(Build.SourcesDirectory)\\nuget\\Microsoft.Windows.CppWinRT.targets Microsoft.Cpp.CppWinRTEnabled.targets\ncopy $(Build.SourcesDirectory)\\nuget\\CppWinrtRules.Project.xml CppWinrtRules.Project.xml\necho d | xcopy $(Build.SourcesDirectory)\\x86\\cppwinrt_fast_forwarder.lib build\\native\\lib\\i386\necho d | xcopy $(Build.SourcesDirectory)\\x86\\cppwinrt_fast_forwarder.lib build\\native\\lib\\Win32\necho d | xcopy $(Build.SourcesDirectory)\\x64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\amd64\necho d | xcopy $(Build.SourcesDirectory)\\x64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\x64\necho d | xcopy $(Build.SourcesDirectory)\\arm\\cppwinrt_fast_forwarder.lib build\\native\\lib\\arm\necho d | xcopy $(Build.SourcesDirectory)\\arm64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\arm64\n" + script: "set TargetDir=$(Build.SourcesDirectory)\\msbuild\nrd /s /q %TargetDir% >nul 2>&1\nmd %TargetDir%\ncd %TargetDir%\n\ncopy $(Build.SourcesDirectory)\\vsix\\Microsoft.Cpp.CppWinRT.props\ncopy $(Build.SourcesDirectory)\\nuget\\Microsoft.Windows.CppWinRT.props Microsoft.Cpp.CppWinRTEnabled.props \ncopy $(Build.SourcesDirectory)\\nuget\\Microsoft.Windows.CppWinRT.targets Microsoft.Cpp.CppWinRTEnabled.targets\ncopy $(Build.SourcesDirectory)\\nuget\\CppWinrtRules.Project.xml CppWinrtRules.Project.xml\necho d | xcopy $(Build.SourcesDirectory)\\x86\\cppwinrt_fast_forwarder.lib build\\native\\lib\\i386\necho d | xcopy $(Build.SourcesDirectory)\\x86\\cppwinrt_fast_forwarder.lib build\\native\\lib\\Win32\necho d | xcopy $(Build.SourcesDirectory)\\x64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\amd64\necho d | xcopy $(Build.SourcesDirectory)\\x64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\x64\necho d | xcopy $(Build.SourcesDirectory)\\arm64\\cppwinrt_fast_forwarder.lib build\\native\\lib\\arm64\n" failOnStderr: true - task: PkgESVPack@12 @@ -343,12 +335,6 @@ jobs: artifactName: $(BuildConfiguration)_x64 downloadPath: $(Build.SourcesDirectory)\x64 - - task: DownloadPipelineArtifact@1 - displayName: Download arm Artifacts - inputs: - artifactName: $(BuildConfiguration)_arm - downloadPath: $(Build.SourcesDirectory)\arm - - task: DownloadPipelineArtifact@1 displayName: Download arm64 Artifacts inputs: @@ -430,7 +416,7 @@ jobs: command: pack searchPatternPack: nuget/Microsoft.Windows.CppWinRT.nuspec versioningScheme: byBuildNumber - buildProperties: 'target_version=$(Build.BuildNumber);cppwinrt_exe=$(Build.ArtifactStagingDirectory)\x86\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=$(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib ' + buildProperties: 'target_version=$(Build.BuildNumber);cppwinrt_exe=$(Build.ArtifactStagingDirectory)\x86\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib ' - task: ComponentGovernanceComponentDetection@0 displayName: Component Detection diff --git a/.pipelines/jobs/OneBranchBuild.yml b/.pipelines/jobs/OneBranchBuild.yml index f8ca8cedc..9053fc21c 100644 --- a/.pipelines/jobs/OneBranchBuild.yml +++ b/.pipelines/jobs/OneBranchBuild.yml @@ -20,8 +20,6 @@ jobs: BuildPlatform: 'x86' x64: BuildPlatform: 'x64' - arm: - BuildPlatform: 'arm' arm64: BuildPlatform: 'arm64' diff --git a/.pipelines/jobs/OneBranchNuGet.yml b/.pipelines/jobs/OneBranchNuGet.yml index e2a871114..4d4a7b2ea 100644 --- a/.pipelines/jobs/OneBranchNuGet.yml +++ b/.pipelines/jobs/OneBranchNuGet.yml @@ -43,12 +43,6 @@ jobs: artifactName: 'drop_build_x64' targetPath: '$(Build.SourcesDirectory)/x64' - - task: DownloadPipelineArtifact@1 - displayName: 'Download arm artifacts' - inputs: - artifactName: 'drop_build_arm' - targetPath: '$(Build.SourcesDirectory)/arm' - - task: DownloadPipelineArtifact@1 displayName: 'Download arm64 artifacts' inputs: @@ -59,7 +53,7 @@ jobs: displayName: 'Build NuGet package' inputs: command: 'custom' - arguments: 'pack nuget/Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory $(ob_outputDirectory)\packages -Properties Configuration=release;cppwinrt_exe=$(Build.SourcesDirectory)\x86\cppwinrt\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=$(Build.SourcesDirectory)\arm\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib;target_version=$(PackageVersion) -Version $(PackageVersion) -Verbosity Detailed' + arguments: 'pack nuget/Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory $(ob_outputDirectory)\packages -Properties Configuration=release;cppwinrt_exe=$(Build.SourcesDirectory)\x86\cppwinrt\cppwinrt.exe;cppwinrt_fast_fwd_x86=$(Build.SourcesDirectory)\x86\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=$(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=$(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib;target_version=$(PackageVersion) -Version $(PackageVersion) -Verbosity Detailed' - task: onebranch.pipeline.signing@1 displayName: '🔒 Onebranch Signing for NuGet package' diff --git a/.pipelines/jobs/OneBranchVsix.yml b/.pipelines/jobs/OneBranchVsix.yml index b4d23eb44..b1a6c8eeb 100644 --- a/.pipelines/jobs/OneBranchVsix.yml +++ b/.pipelines/jobs/OneBranchVsix.yml @@ -71,12 +71,6 @@ jobs: artifactName: 'drop_build_x64' targetPath: '$(Build.SourcesDirectory)\x64' - - task: DownloadPipelineArtifact@2 - displayName: 'Download arm binaries' - inputs: - artifactName: 'drop_build_arm' - targetPath: '$(Build.SourcesDirectory)\arm' - - task: DownloadPipelineArtifact@2 displayName: 'Download arm64 binaries' inputs: diff --git a/Directory.Build.Props b/Directory.Build.Props index 95286d288..cff3f7bda 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -42,7 +42,7 @@ x86 $(SolutionDir)_build\$(CppWinRTPlatform)\$(Configuration)\ $(OutDir) - $(SolutionDir)_build\x86\$(Configuration)\ + $(SolutionDir)_build\x86\$(Configuration)\ diff --git a/README.md b/README.md index 691809d31..1749fea0c 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ If you really want to build it yourself, the simplest way to do so is to run the * Open the `cppwinrt.sln` solution. * Choose a configuration (x64, x86, Release, Debug) and build projects as needed. -If you are working on an ARM64 or ARM specific issue from an x64 or x86 host, you will need to instead: +If you are working on an ARM64 specific issue from an x64 or x86 host, you will need to instead: * Open the `cppwinrt.sln` solution * Build the x86 version of the "cppwinrt" project first diff --git a/build_nuget.cmd b/build_nuget.cmd index cb950a625..3926e4d0b 100644 --- a/build_nuget.cmd +++ b/build_nuget.cmd @@ -5,9 +5,8 @@ if "%target_version%"=="" set target_version=3.0.0.0 call msbuild /m /p:Configuration=Release,Platform=x86,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd call msbuild /m /p:Configuration=Release,Platform=x64,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd -call msbuild /m /p:Configuration=Release,Platform=arm,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd call msbuild /m /p:Configuration=Release,Platform=arm64,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd call msbuild /m /p:Configuration=Release,Platform=x86,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:cppwinrt -nuget pack nuget\Microsoft.Windows.CppWinRT.nuspec -Properties target_version=%target_version%;cppwinrt_exe=%cd%\_build\x86\Release\cppwinrt.exe;cppwinrt_fast_fwd_x86=%cd%\_build\x86\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%cd%\_build\x64\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=%cd%\_build\arm\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%cd%\_build\arm64\Release\cppwinrt_fast_forwarder.lib +nuget pack nuget\Microsoft.Windows.CppWinRT.nuspec -Properties target_version=%target_version%;cppwinrt_exe=%cd%\_build\x86\Release\cppwinrt.exe;cppwinrt_fast_fwd_x86=%cd%\_build\x86\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%cd%\_build\x64\Release\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%cd%\_build\arm64\Release\cppwinrt_fast_forwarder.lib diff --git a/build_prior_projection.cmd b/build_prior_projection.cmd index c7bdf2f64..9d10f3eaa 100644 --- a/build_prior_projection.cmd +++ b/build_prior_projection.cmd @@ -12,7 +12,6 @@ if /I "%target_platform%" equ "all" ( ) call %0 x86 !target_configuration! call %0 x64 !target_configuration! - call %0 arm !target_configuration! call %0 arm64 !target_configuration! goto :eof ) diff --git a/build_projection.cmd b/build_projection.cmd index 778fa7aca..140e6c7f8 100644 --- a/build_projection.cmd +++ b/build_projection.cmd @@ -12,7 +12,6 @@ if /I "%target_platform%" equ "all" ( ) call %0 x86 !target_configuration! call %0 x64 !target_configuration! - call %0 arm !target_configuration! call %0 arm64 !target_configuration! goto :eof ) diff --git a/build_test_all.cmd b/build_test_all.cmd index 89967a04b..4372acfd5 100644 --- a/build_test_all.cmd +++ b/build_test_all.cmd @@ -18,8 +18,6 @@ call .nuget\nuget.exe restore test\nuget\NugetTest.sln call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd -if "%target_platform%"=="arm" goto :eof - call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,Deployment=Component;CppWinRTBuildVersion=%target_version% natvis\cppwinrtvisualizer.sln call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,Deployment=Standalone;CppWinRTBuildVersion=%target_version% natvis\cppwinrtvisualizer.sln diff --git a/build_vsix.cmd b/build_vsix.cmd index 111527a48..9908462ef 100644 --- a/build_vsix.cmd +++ b/build_vsix.cmd @@ -19,7 +19,6 @@ call .nuget\nuget.exe restore test\nuget\NugetTest.sln rem Build fast forwarder libs or all arches call msbuild /m /p:Configuration=%target_configuration%,Platform=x86,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd call msbuild /m /p:Configuration=%target_configuration%,Platform=x64,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd -call msbuild /m /p:Configuration=%target_configuration%,Platform=arm,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd call msbuild /m /p:Configuration=%target_configuration%,Platform=arm64,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd rem Build cppwinrt.exe for x86 only @@ -31,7 +30,7 @@ call msbuild /p:Configuration=%target_configuration%,Platform=x86,Deployment=%ta call msbuild /p:Configuration=%target_configuration%,Platform=arm64,Deployment=%target_deployment%,CppWinRTBuildVersion=%target_version% natvis\cppwinrtvisualizer.sln rem Build nuget -.nuget\nuget.exe pack nuget\Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory %this_dir%_build -Properties Configuration=%target_configuration%;cppwinrt_exe=%this_dir%_build\x86\%target_configuration%\cppwinrt.exe;cppwinrt_fast_fwd_x86=%this_dir%_build\x86\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%this_dir%_build\x64\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm=%this_dir%_build\arm\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%this_dir%_build\arm64\%target_configuration%\cppwinrt_fast_forwarder.lib -version %target_version% -Verbosity Detailed +.nuget\nuget.exe pack nuget\Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory %this_dir%_build -Properties Configuration=%target_configuration%;cppwinrt_exe=%this_dir%_build\x86\%target_configuration%\cppwinrt.exe;cppwinrt_fast_fwd_x86=%this_dir%_build\x86\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%this_dir%_build\x64\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%this_dir%_build\arm64\%target_configuration%\cppwinrt_fast_forwarder.lib -version %target_version% -Verbosity Detailed rem Build vsix call msbuild /restore /p:Configuration=%target_configuration%,Platform="Any CPU",Deployment=%target_deployment%,CppWinRTVersion=%target_version%,NatvisDirx86=%this_dir%natvis\x86\%target_configuration%\%target_deployment%,NatvisDirx64=%this_dir%natvis\x64\%target_configuration%\%target_deployment%,NatvisDirarm64=%this_dir%natvis\arm64\%target_configuration%\%target_deployment%,NupkgDir=%this_dir%_build vsix\vsix.sln diff --git a/cppwinrt.sln b/cppwinrt.sln index e2ac95942..5964f976b 100644 --- a/cppwinrt.sln +++ b/cppwinrt.sln @@ -134,346 +134,260 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 - Release|ARM = Release|ARM Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|ARM.ActiveCfg = Debug|ARM - {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|ARM.Build.0 = Debug|ARM {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|ARM64.ActiveCfg = Debug|ARM64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|ARM64.Build.0 = Debug|ARM64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|x64.ActiveCfg = Debug|x64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|x64.Build.0 = Debug|x64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|x86.ActiveCfg = Debug|Win32 {D613FB39-5035-4043-91E2-BAB323908AF4}.Debug|x86.Build.0 = Debug|Win32 - {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|ARM.ActiveCfg = Release|ARM - {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|ARM.Build.0 = Release|ARM {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|ARM64.ActiveCfg = Release|ARM64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|ARM64.Build.0 = Release|ARM64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|x64.ActiveCfg = Release|x64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|x64.Build.0 = Release|x64 {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|x86.ActiveCfg = Release|Win32 {D613FB39-5035-4043-91E2-BAB323908AF4}.Release|x86.Build.0 = Release|Win32 - {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|ARM.ActiveCfg = Debug|ARM - {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|ARM.Build.0 = Debug|ARM {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|ARM64.ActiveCfg = Debug|ARM64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|ARM64.Build.0 = Debug|ARM64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|x64.ActiveCfg = Debug|x64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|x64.Build.0 = Debug|x64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|x86.ActiveCfg = Debug|Win32 {FB239623-7D19-4025-BCEA-B43298D4A315}.Debug|x86.Build.0 = Debug|Win32 - {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|ARM.ActiveCfg = Release|ARM - {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|ARM.Build.0 = Release|ARM {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|ARM64.ActiveCfg = Release|ARM64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|ARM64.Build.0 = Release|ARM64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|x64.ActiveCfg = Release|x64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|x64.Build.0 = Release|x64 {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|x86.ActiveCfg = Release|Win32 {FB239623-7D19-4025-BCEA-B43298D4A315}.Release|x86.Build.0 = Release|Win32 - {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|ARM.ActiveCfg = Debug|ARM - {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|ARM.Build.0 = Debug|ARM {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|ARM64.ActiveCfg = Debug|ARM64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|ARM64.Build.0 = Debug|ARM64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|x64.ActiveCfg = Debug|x64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|x64.Build.0 = Debug|x64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|x86.ActiveCfg = Debug|Win32 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Debug|x86.Build.0 = Debug|Win32 - {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|ARM.ActiveCfg = Release|ARM - {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|ARM.Build.0 = Release|ARM {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|ARM64.ActiveCfg = Release|ARM64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|ARM64.Build.0 = Release|ARM64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|x64.ActiveCfg = Release|x64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|x64.Build.0 = Release|x64 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|x86.ActiveCfg = Release|Win32 {C8B95FCB-9B0B-4E9F-B7D5-643883C192C9}.Release|x86.Build.0 = Release|Win32 - {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|ARM.ActiveCfg = Debug|ARM - {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|ARM.Build.0 = Debug|ARM {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|ARM64.ActiveCfg = Debug|ARM64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|ARM64.Build.0 = Debug|ARM64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|x64.ActiveCfg = Debug|x64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|x64.Build.0 = Debug|x64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|x86.ActiveCfg = Debug|Win32 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Debug|x86.Build.0 = Debug|Win32 - {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|ARM.ActiveCfg = Release|ARM - {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|ARM.Build.0 = Release|ARM {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|ARM64.ActiveCfg = Release|ARM64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|ARM64.Build.0 = Release|ARM64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|x64.ActiveCfg = Release|x64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|x64.Build.0 = Release|x64 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|x86.ActiveCfg = Release|Win32 {559A7CF4-DC5F-4D62-BA6B-0C2B025593F8}.Release|x86.Build.0 = Release|Win32 - {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|ARM.ActiveCfg = Debug|ARM - {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|ARM.Build.0 = Debug|ARM {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|ARM64.ActiveCfg = Debug|ARM64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|ARM64.Build.0 = Debug|ARM64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|x64.ActiveCfg = Debug|x64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|x64.Build.0 = Debug|x64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|x86.ActiveCfg = Debug|Win32 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Debug|x86.Build.0 = Debug|Win32 - {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|ARM.ActiveCfg = Release|ARM - {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|ARM.Build.0 = Release|ARM {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|ARM64.ActiveCfg = Release|ARM64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|ARM64.Build.0 = Release|ARM64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|x64.ActiveCfg = Release|x64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|x64.Build.0 = Release|x64 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|x86.ActiveCfg = Release|Win32 {152E4C6E-9A9D-4D5A-B38D-4905D173649A}.Release|x86.Build.0 = Release|Win32 - {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|ARM.ActiveCfg = Debug|ARM - {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|ARM.Build.0 = Debug|ARM {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|ARM64.ActiveCfg = Debug|ARM64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|ARM64.Build.0 = Debug|ARM64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|x64.ActiveCfg = Debug|x64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|x64.Build.0 = Debug|x64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|x86.ActiveCfg = Debug|Win32 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Debug|x86.Build.0 = Debug|Win32 - {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|ARM.ActiveCfg = Release|ARM - {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|ARM.Build.0 = Release|ARM {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|ARM64.ActiveCfg = Release|ARM64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|ARM64.Build.0 = Release|ARM64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|x64.ActiveCfg = Release|x64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|x64.Build.0 = Release|x64 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|x86.ActiveCfg = Release|Win32 {A91B8BF3-28E4-4D9E-8DBA-64B70E4F0270}.Release|x86.Build.0 = Release|Win32 - {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|ARM.ActiveCfg = Debug|ARM - {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|ARM.Build.0 = Debug|ARM {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|ARM64.ActiveCfg = Debug|ARM64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|ARM64.Build.0 = Debug|ARM64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|x64.ActiveCfg = Debug|x64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|x64.Build.0 = Debug|x64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|x86.ActiveCfg = Debug|Win32 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Debug|x86.Build.0 = Debug|Win32 - {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|ARM.ActiveCfg = Release|ARM - {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|ARM.Build.0 = Release|ARM {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|ARM64.ActiveCfg = Release|ARM64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|ARM64.Build.0 = Release|ARM64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|x64.ActiveCfg = Release|x64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|x64.Build.0 = Release|x64 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|x86.ActiveCfg = Release|Win32 {D2961EA1-A8CA-4A62-B760-948403DC8494}.Release|x86.Build.0 = Release|Win32 - {85695954-3800-4558-9857-966E69E9F9EC}.Debug|ARM.ActiveCfg = Debug|ARM - {85695954-3800-4558-9857-966E69E9F9EC}.Debug|ARM.Build.0 = Debug|ARM {85695954-3800-4558-9857-966E69E9F9EC}.Debug|ARM64.ActiveCfg = Debug|ARM64 {85695954-3800-4558-9857-966E69E9F9EC}.Debug|ARM64.Build.0 = Debug|ARM64 {85695954-3800-4558-9857-966E69E9F9EC}.Debug|x64.ActiveCfg = Debug|x64 {85695954-3800-4558-9857-966E69E9F9EC}.Debug|x64.Build.0 = Debug|x64 {85695954-3800-4558-9857-966E69E9F9EC}.Debug|x86.ActiveCfg = Debug|Win32 {85695954-3800-4558-9857-966E69E9F9EC}.Debug|x86.Build.0 = Debug|Win32 - {85695954-3800-4558-9857-966E69E9F9EC}.Release|ARM.ActiveCfg = Release|ARM - {85695954-3800-4558-9857-966E69E9F9EC}.Release|ARM.Build.0 = Release|ARM {85695954-3800-4558-9857-966E69E9F9EC}.Release|ARM64.ActiveCfg = Release|ARM64 {85695954-3800-4558-9857-966E69E9F9EC}.Release|ARM64.Build.0 = Release|ARM64 {85695954-3800-4558-9857-966E69E9F9EC}.Release|x64.ActiveCfg = Release|x64 {85695954-3800-4558-9857-966E69E9F9EC}.Release|x64.Build.0 = Release|x64 {85695954-3800-4558-9857-966E69E9F9EC}.Release|x86.ActiveCfg = Release|Win32 {85695954-3800-4558-9857-966E69E9F9EC}.Release|x86.Build.0 = Release|Win32 - {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|ARM.ActiveCfg = Debug|ARM - {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|ARM.Build.0 = Debug|ARM {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|ARM64.ActiveCfg = Debug|ARM64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|ARM64.Build.0 = Debug|ARM64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|x64.ActiveCfg = Debug|x64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|x64.Build.0 = Debug|x64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|x86.ActiveCfg = Debug|Win32 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Debug|x86.Build.0 = Debug|Win32 - {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|ARM.ActiveCfg = Release|ARM - {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|ARM.Build.0 = Release|ARM {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|ARM64.ActiveCfg = Release|ARM64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|ARM64.Build.0 = Release|ARM64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|x64.ActiveCfg = Release|x64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|x64.Build.0 = Release|x64 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|x86.ActiveCfg = Release|Win32 {F1C915B3-2C64-4992-AFB7-7F035B1A7607}.Release|x86.Build.0 = Release|Win32 - {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|ARM.ActiveCfg = Debug|ARM - {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|ARM.Build.0 = Debug|ARM {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|ARM64.ActiveCfg = Debug|ARM64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|ARM64.Build.0 = Debug|ARM64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|x64.ActiveCfg = Debug|x64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|x64.Build.0 = Debug|x64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|x86.ActiveCfg = Debug|Win32 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Debug|x86.Build.0 = Debug|Win32 - {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|ARM.ActiveCfg = Release|ARM - {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|ARM.Build.0 = Release|ARM {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|ARM64.ActiveCfg = Release|ARM64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|ARM64.Build.0 = Release|ARM64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|x64.ActiveCfg = Release|x64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|x64.Build.0 = Release|x64 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|x86.ActiveCfg = Release|Win32 {13333A6F-6A4A-48CD-865C-0F65135EB018}.Release|x86.Build.0 = Release|Win32 - {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|ARM.ActiveCfg = Debug|ARM - {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|ARM.Build.0 = Debug|ARM {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|ARM64.ActiveCfg = Debug|ARM64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|ARM64.Build.0 = Debug|ARM64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|x64.ActiveCfg = Debug|x64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|x64.Build.0 = Debug|x64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|x86.ActiveCfg = Debug|Win32 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Debug|x86.Build.0 = Debug|Win32 - {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|ARM.ActiveCfg = Release|ARM - {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|ARM.Build.0 = Release|ARM {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|ARM64.ActiveCfg = Release|ARM64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|ARM64.Build.0 = Release|ARM64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|x64.ActiveCfg = Release|x64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|x64.Build.0 = Release|x64 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|x86.ActiveCfg = Release|Win32 {0080F6D1-AEC3-4F89-ADE1-3D22A7EBF99E}.Release|x86.Build.0 = Release|Win32 - {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|ARM.ActiveCfg = Debug|ARM - {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|ARM.Build.0 = Debug|ARM {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|ARM64.ActiveCfg = Debug|ARM64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|ARM64.Build.0 = Debug|ARM64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|x64.ActiveCfg = Debug|x64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|x64.Build.0 = Debug|x64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|x86.ActiveCfg = Debug|Win32 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Debug|x86.Build.0 = Debug|Win32 - {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|ARM.ActiveCfg = Release|ARM - {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|ARM.Build.0 = Release|ARM {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|ARM64.ActiveCfg = Release|ARM64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|ARM64.Build.0 = Release|ARM64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|x64.ActiveCfg = Release|x64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|x64.Build.0 = Release|x64 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|x86.ActiveCfg = Release|Win32 {0E0ACA62-A92F-44CF-BD41-AEB541946DF8}.Release|x86.Build.0 = Release|Win32 - {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|ARM.ActiveCfg = Debug|ARM - {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|ARM.Build.0 = Debug|ARM {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|ARM64.ActiveCfg = Debug|ARM64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|ARM64.Build.0 = Debug|ARM64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|x64.ActiveCfg = Debug|x64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|x64.Build.0 = Debug|x64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|x86.ActiveCfg = Debug|Win32 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Debug|x86.Build.0 = Debug|Win32 - {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|ARM.ActiveCfg = Release|ARM - {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|ARM.Build.0 = Release|ARM {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|ARM64.ActiveCfg = Release|ARM64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|ARM64.Build.0 = Release|ARM64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|x64.ActiveCfg = Release|x64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|x64.Build.0 = Release|x64 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|x86.ActiveCfg = Release|Win32 {F8A1FE5A-DC8A-49DF-B882-DEF76E38E484}.Release|x86.Build.0 = Release|Win32 - {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|ARM.ActiveCfg = Debug|ARM - {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|ARM.Build.0 = Debug|ARM {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|ARM64.ActiveCfg = Debug|ARM64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|ARM64.Build.0 = Debug|ARM64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|x64.ActiveCfg = Debug|x64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|x64.Build.0 = Debug|x64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|x86.ActiveCfg = Debug|Win32 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Debug|x86.Build.0 = Debug|Win32 - {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|ARM.ActiveCfg = Release|ARM - {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|ARM.Build.0 = Release|ARM {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|ARM64.ActiveCfg = Release|ARM64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|ARM64.Build.0 = Release|ARM64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|x64.ActiveCfg = Release|x64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|x64.Build.0 = Release|x64 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|x86.ActiveCfg = Release|Win32 {B68C61C6-4699-41E6-A158-EA1BE029E7A0}.Release|x86.Build.0 = Release|Win32 - {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|ARM.ActiveCfg = Debug|ARM - {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|ARM.Build.0 = Debug|ARM {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|ARM64.ActiveCfg = Debug|ARM64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|ARM64.Build.0 = Debug|ARM64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|x64.ActiveCfg = Debug|x64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|x64.Build.0 = Debug|x64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|x86.ActiveCfg = Debug|Win32 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Debug|x86.Build.0 = Debug|Win32 - {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|ARM.ActiveCfg = Release|ARM - {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|ARM.Build.0 = Release|ARM {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|ARM64.ActiveCfg = Release|ARM64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|ARM64.Build.0 = Release|ARM64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|x64.ActiveCfg = Release|x64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|x64.Build.0 = Release|x64 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|x86.ActiveCfg = Release|Win32 {303CC0FE-7D66-4F9F-B7A1-0AF7F9359074}.Release|x86.Build.0 = Release|Win32 - {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|ARM.ActiveCfg = Debug|ARM - {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|ARM.Build.0 = Debug|ARM {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|ARM64.ActiveCfg = Debug|ARM64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|ARM64.Build.0 = Debug|ARM64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|x64.ActiveCfg = Debug|x64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|x64.Build.0 = Debug|x64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|x86.ActiveCfg = Debug|Win32 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Debug|x86.Build.0 = Debug|Win32 - {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|ARM.ActiveCfg = Release|ARM - {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|ARM.Build.0 = Release|ARM {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|ARM64.ActiveCfg = Release|ARM64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|ARM64.Build.0 = Release|ARM64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|x64.ActiveCfg = Release|x64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|x64.Build.0 = Release|x64 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|x86.ActiveCfg = Release|Win32 {A63B3AD1-AB7B-461E-9FFF-2447F5BCD459}.Release|x86.Build.0 = Release|Win32 - {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|ARM.ActiveCfg = Debug|ARM - {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|ARM.Build.0 = Debug|ARM {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|ARM64.ActiveCfg = Debug|ARM64 {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|ARM64.Build.0 = Debug|ARM64 {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|x64.ActiveCfg = Debug|x64 {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|x64.Build.0 = Debug|x64 {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|x86.ActiveCfg = Debug|Win32 {E893622C-47DE-4F83-B422-0A26711590A4}.Debug|x86.Build.0 = Debug|Win32 - {E893622C-47DE-4F83-B422-0A26711590A4}.Release|ARM.ActiveCfg = Release|ARM - {E893622C-47DE-4F83-B422-0A26711590A4}.Release|ARM.Build.0 = Release|ARM {E893622C-47DE-4F83-B422-0A26711590A4}.Release|ARM64.ActiveCfg = Release|ARM64 {E893622C-47DE-4F83-B422-0A26711590A4}.Release|ARM64.Build.0 = Release|ARM64 {E893622C-47DE-4F83-B422-0A26711590A4}.Release|x64.ActiveCfg = Release|x64 {E893622C-47DE-4F83-B422-0A26711590A4}.Release|x64.Build.0 = Release|x64 {E893622C-47DE-4F83-B422-0A26711590A4}.Release|x86.ActiveCfg = Release|Win32 {E893622C-47DE-4F83-B422-0A26711590A4}.Release|x86.Build.0 = Release|Win32 - {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|ARM.ActiveCfg = Debug|ARM - {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|ARM.Build.0 = Debug|ARM {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|ARM64.ActiveCfg = Debug|ARM64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|ARM64.Build.0 = Debug|ARM64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|x64.ActiveCfg = Debug|x64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|x64.Build.0 = Debug|x64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|x86.ActiveCfg = Debug|Win32 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Debug|x86.Build.0 = Debug|Win32 - {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|ARM.ActiveCfg = Release|ARM - {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|ARM.Build.0 = Release|ARM {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|ARM64.ActiveCfg = Release|ARM64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|ARM64.Build.0 = Release|ARM64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|x64.ActiveCfg = Release|x64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|x64.Build.0 = Release|x64 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|x86.ActiveCfg = Release|Win32 {D48A96C2-8512-4CC3-B6E4-7CFF07ED8ED3}.Release|x86.Build.0 = Release|Win32 - {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|ARM.ActiveCfg = Debug|ARM - {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|ARM.Build.0 = Debug|ARM {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|ARM64.ActiveCfg = Debug|ARM64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|ARM64.Build.0 = Debug|ARM64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|x64.ActiveCfg = Debug|x64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|x64.Build.0 = Debug|x64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|x86.ActiveCfg = Debug|Win32 {08C40663-B6A3-481E-8755-AE32BAD99501}.Debug|x86.Build.0 = Debug|Win32 - {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|ARM.ActiveCfg = Release|ARM - {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|ARM.Build.0 = Release|ARM {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|ARM64.ActiveCfg = Release|ARM64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|ARM64.Build.0 = Release|ARM64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x64.ActiveCfg = Release|x64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x64.Build.0 = Release|x64 {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x86.ActiveCfg = Release|Win32 {08C40663-B6A3-481E-8755-AE32BAD99501}.Release|x86.Build.0 = Release|Win32 - {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM.ActiveCfg = Debug|ARM - {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM.Build.0 = Debug|ARM {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM64.ActiveCfg = Debug|ARM64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|ARM64.Build.0 = Debug|ARM64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x64.ActiveCfg = Debug|x64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x64.Build.0 = Debug|x64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x86.ActiveCfg = Debug|Win32 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Debug|x86.Build.0 = Debug|Win32 - {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM.ActiveCfg = Release|ARM - {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM.Build.0 = Release|ARM {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM64.ActiveCfg = Release|ARM64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|ARM64.Build.0 = Release|ARM64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x64.ActiveCfg = Release|x64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x64.Build.0 = Release|x64 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x86.ActiveCfg = Release|Win32 {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA}.Release|x86.Build.0 = Release|Win32 - {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|ARM.ActiveCfg = Debug|ARM - {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|ARM.Build.0 = Debug|ARM {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|ARM64.ActiveCfg = Debug|ARM64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|ARM64.Build.0 = Debug|ARM64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|x64.ActiveCfg = Debug|x64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|x64.Build.0 = Debug|x64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|x86.ActiveCfg = Debug|Win32 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Debug|x86.Build.0 = Debug|Win32 - {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|ARM.ActiveCfg = Release|ARM - {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|ARM.Build.0 = Release|ARM {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|ARM64.ActiveCfg = Release|ARM64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|ARM64.Build.0 = Release|ARM64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x64.ActiveCfg = Release|x64 diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index 46b5836e7..069f8103a 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -2,10 +2,6 @@ - - Debug - ARM - Debug ARM64 @@ -14,10 +10,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -132,10 +124,6 @@ Application true - - Application - true - Application true @@ -145,11 +133,6 @@ false true - - Application - false - true - Application false @@ -172,18 +155,12 @@ - - - - - - @@ -211,23 +188,6 @@ - - - Disabled - ..\inc;$(OutputPath);$(WinMDPackageDir); - MultiThreadedDebug - - - Console - - - $(OutputPath)prebuild.exe ..\strings $(OutputPath) - - - - - - Disabled @@ -285,29 +245,6 @@ - - - MaxSpeed - true - true - ..\inc;$(OutputPath);$(WinMDPackageDir); - MultiThreaded - Guard - - - Console - true - true - /DEBUGTYPE:CV,FIXUP %(AdditionalOptions) - - - $(OutputPath)prebuild.exe ..\strings $(OutputPath) - - - - - - MaxSpeed diff --git a/fast_fwd/arm/thunks.asm b/fast_fwd/arm/thunks.asm deleted file mode 100644 index 9010908b6..000000000 --- a/fast_fwd/arm/thunks.asm +++ /dev/null @@ -1,58 +0,0 @@ -; ARM fast forwarder thunk implementations -; Calling convention: https://docs.microsoft.com/en-us/cpp/build/overview-of-arm-abi-conventions - -#include "ksarm.h" - - IMPORT __guard_check_icall_fptr - - TEXTAREA - - CFG_ALIGN - NESTED_ENTRY InvokeForwarder - - ; Save enregistered args and return address - PROLOG_PUSH {r0-r4, lr} - - ; Replace forwarder abi with owner abi - ldr r1, [r0, #4] - str r1, [sp] - - ; Add offset and index (on stack) - ldr r2, [sp, #24] - ldr r3, [r0, #8] - add r2, r2, r3 - - ; Get method address from owner abi vtable - ldr r0, [r1] - ldr r4, [r0, r2, lsl #2] - mov r0, r4 - - ; Verify indirect call target - mov32 r12, __guard_check_icall_fptr - ldr r12, [r12] - blx r12 - - ; Restore method address, return address, and args - mov r12, r4 - EPILOG_POP {r0-r4, lr} - EPILOG_NOP add sp, #4 - - ; Jump to method - EPILOG_NOP bx r12 - - NESTED_END InvokeForwarder - - ; Define thunks - MACRO - WINRT_FF_THUNK $i - LEAF_ENTRY winrt_ff_thunk$i - ; Note: no scratch registers available (r12/IP is used by CFG), must use stack - mov r12, $i - push r12 - ldr pc, =InvokeForwarder - LEAF_END winrt_ff_thunk$i - MEND - -#include "thunks.inc" - - END \ No newline at end of file diff --git a/fast_fwd/fast_fwd.vcxproj b/fast_fwd/fast_fwd.vcxproj index 6d7a42d77..b9452d149 100644 --- a/fast_fwd/fast_fwd.vcxproj +++ b/fast_fwd/fast_fwd.vcxproj @@ -17,14 +17,6 @@ Release x64 - - Debug - ARM - - - Release - ARM - Debug ARM64 @@ -79,16 +71,10 @@ - true + true false !$(Platform_Arm) - - cppwinrt_fast_forwarder - - - cppwinrt_fast_forwarder - cppwinrt_fast_forwarder diff --git a/nuget/Microsoft.Windows.CppWinRT.nuspec b/nuget/Microsoft.Windows.CppWinRT.nuspec index 882931734..a63e08bf9 100644 --- a/nuget/Microsoft.Windows.CppWinRT.nuspec +++ b/nuget/Microsoft.Windows.CppWinRT.nuspec @@ -20,7 +20,6 @@ - diff --git a/prebuild/prebuild.vcxproj b/prebuild/prebuild.vcxproj index 8308ae560..e5fa52565 100644 --- a/prebuild/prebuild.vcxproj +++ b/prebuild/prebuild.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -44,10 +36,6 @@ Application true - - Application - true - Application true @@ -57,11 +45,6 @@ false true - - Application - false - true - Application false @@ -84,18 +67,12 @@ - - - - - - @@ -116,16 +93,6 @@ Console - - - Disabled - ..\cppwinrt - MultiThreadedDebug - - - Console - - Disabled @@ -160,20 +127,6 @@ true - - - MaxSpeed - true - true - ..\cppwinrt - MultiThreaded - - - Console - true - true - - MaxSpeed diff --git a/prepare_versionless_diffs.cmd b/prepare_versionless_diffs.cmd index 468645657..05cb6dd0b 100644 --- a/prepare_versionless_diffs.cmd +++ b/prepare_versionless_diffs.cmd @@ -12,7 +12,6 @@ if /I "%target_platform%" equ "all" ( ) call %0 x86 !target_configuration! call %0 x64 !target_configuration! - call %0 arm !target_configuration! call %0 arm64 !target_configuration! goto :eof ) diff --git a/scratch/scratch.vcxproj b/scratch/scratch.vcxproj index 45122c13d..98ed21948 100644 --- a/scratch/scratch.vcxproj +++ b/scratch/scratch.vcxproj @@ -2,10 +2,6 @@ - - Debug - ARM - Debug ARM64 @@ -14,10 +10,6 @@ Debug Win32 - - Release - ARM - Release ARM64 diff --git a/strings/base_activation.h b/strings/base_activation.h index bb6be5ca1..be24c6ad9 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -119,10 +119,8 @@ WINRT_EXPORT namespace winrt #pragma clang diagnostic ignored "-Wdeprecated-declarations" #endif -#if defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__)) +#if defined(__GNUC__) && defined(__aarch64__) #define WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER __asm__ __volatile__ ("dmb ish"); -#elif defined _M_ARM -#define WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER (__dmb(_ARM_BARRIER_ISH)); #elif defined _M_ARM64 #define WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER (__dmb(_ARM64_BARRIER_ISH)); #endif @@ -135,7 +133,7 @@ namespace winrt::impl int32_t const result = *target; _ReadWriteBarrier(); return result; -#elif defined _M_ARM || defined _M_ARM64 +#elif defined _M_ARM64 #if defined(__GNUC__) int32_t const result = *target; #else @@ -308,7 +306,7 @@ namespace winrt::impl static_assert(std::is_standard_layout_v); -#if !defined _M_IX86 && !defined _M_X64 && !defined _M_ARM && !defined _M_ARM64 +#if !defined _M_IX86 && !defined _M_X64 && !defined _M_ARM64 #error Unsupported architecture: verify that zero-initialization of SLIST_HEADER is still safe #endif diff --git a/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj b/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj index 15d9a8842..819c788d8 100644 --- a/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj +++ b/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj @@ -13,10 +13,18 @@ + + Debug + ARM64 + Debug Win32 + + Release + ARM64 + Release Win32 diff --git a/test/nuget/Directory.Build.props b/test/nuget/Directory.Build.props index 9f410480b..a54887b1e 100644 --- a/test/nuget/Directory.Build.props +++ b/test/nuget/Directory.Build.props @@ -23,7 +23,7 @@ $(IntDir)Generated Files\ high $(Platform) - x86 + x86 $(SolutionDir)..\..\_build\$(CppWinRTPlatform)\$(Configuration)\ diff --git a/test/nuget/NuGetTest.sln b/test/nuget/NuGetTest.sln index db32e2b61..310b0f252 100644 --- a/test/nuget/NuGetTest.sln +++ b/test/nuget/NuGetTest.sln @@ -49,270 +49,230 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestProxyStub", "TestProxyS EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 - Release|ARM = Release|ARM Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM.ActiveCfg = Debug|ARM - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM.Build.0 = Debug|ARM - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM.Deploy.0 = Debug|ARM - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM64.ActiveCfg = Debug|Win32 + {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM64.Build.0 = Debug|ARM64 + {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|ARM64.Deploy.0 = Debug|ARM64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|x64.ActiveCfg = Debug|x64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|x64.Build.0 = Debug|x64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|x64.Deploy.0 = Debug|x64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|x86.ActiveCfg = Debug|Win32 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|x86.Build.0 = Debug|Win32 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Debug|x86.Deploy.0 = Debug|Win32 - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM.ActiveCfg = Release|ARM - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM.Build.0 = Release|ARM - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM.Deploy.0 = Release|ARM - {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM64.ActiveCfg = Release|Win32 + {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM64.ActiveCfg = Release|ARM64 + {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM64.Build.0 = Release|ARM64 + {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|ARM64.Deploy.0 = Release|ARM64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|x64.ActiveCfg = Release|x64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|x64.Build.0 = Release|x64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|x64.Deploy.0 = Release|x64 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|x86.ActiveCfg = Release|Win32 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|x86.Build.0 = Release|Win32 {A8BDBDE9-1A3D-4F5E-8668-9F6E84790D44}.Release|x86.Deploy.0 = Release|Win32 - {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|ARM.ActiveCfg = Debug|ARM - {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|ARM.Build.0 = Debug|ARM - {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|ARM64.ActiveCfg = Debug|Win32 + {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|ARM64.Build.0 = Debug|ARM64 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|x64.ActiveCfg = Debug|x64 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|x64.Build.0 = Debug|x64 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|x86.ActiveCfg = Debug|Win32 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Debug|x86.Build.0 = Debug|Win32 - {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|ARM.ActiveCfg = Release|ARM - {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|ARM.Build.0 = Release|ARM - {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|ARM64.ActiveCfg = Release|Win32 + {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|ARM64.ActiveCfg = Release|ARM64 + {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|ARM64.Build.0 = Release|ARM64 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|x64.ActiveCfg = Release|x64 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|x64.Build.0 = Release|x64 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|x86.ActiveCfg = Release|Win32 {E0EBBE54-C046-4611-B048-3CE893B1DF8A}.Release|x86.Build.0 = Release|Win32 - {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|ARM.ActiveCfg = Debug|ARM - {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|ARM.Build.0 = Debug|ARM - {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|ARM64.ActiveCfg = Debug|Win32 + {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|ARM64.Build.0 = Debug|ARM64 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|x64.ActiveCfg = Debug|x64 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|x64.Build.0 = Debug|x64 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|x86.ActiveCfg = Debug|Win32 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Debug|x86.Build.0 = Debug|Win32 - {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|ARM.ActiveCfg = Release|ARM - {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|ARM.Build.0 = Release|ARM - {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|ARM64.ActiveCfg = Release|Win32 + {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|ARM64.ActiveCfg = Release|ARM64 + {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|ARM64.Build.0 = Release|ARM64 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|x64.ActiveCfg = Release|x64 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|x64.Build.0 = Release|x64 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|x86.ActiveCfg = Release|Win32 {4BBB2DE7-4596-4DA6-A923-E65E838363B5}.Release|x86.Build.0 = Release|Win32 - {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|ARM.ActiveCfg = Debug|Win32 - {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|ARM64.ActiveCfg = Debug|Win32 + {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|ARM64.Build.0 = Debug|ARM64 {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|x64.ActiveCfg = Debug|x64 {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|x64.Build.0 = Debug|x64 {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|x86.ActiveCfg = Debug|Win32 {2158F418-CA97-4599-8103-EFC133850BAA}.Debug|x86.Build.0 = Debug|Win32 - {2158F418-CA97-4599-8103-EFC133850BAA}.Release|ARM.ActiveCfg = Release|Win32 - {2158F418-CA97-4599-8103-EFC133850BAA}.Release|ARM64.ActiveCfg = Release|Win32 + {2158F418-CA97-4599-8103-EFC133850BAA}.Release|ARM64.ActiveCfg = Release|ARM64 + {2158F418-CA97-4599-8103-EFC133850BAA}.Release|ARM64.Build.0 = Release|ARM64 {2158F418-CA97-4599-8103-EFC133850BAA}.Release|x64.ActiveCfg = Release|x64 {2158F418-CA97-4599-8103-EFC133850BAA}.Release|x64.Build.0 = Release|x64 {2158F418-CA97-4599-8103-EFC133850BAA}.Release|x86.ActiveCfg = Release|Win32 {2158F418-CA97-4599-8103-EFC133850BAA}.Release|x86.Build.0 = Release|Win32 - {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|ARM.ActiveCfg = Debug|Win32 - {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|ARM64.ActiveCfg = Debug|Win32 + {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|ARM64.Build.0 = Debug|ARM64 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|x64.ActiveCfg = Debug|x64 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|x64.Build.0 = Debug|x64 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|x86.ActiveCfg = Debug|Win32 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Debug|x86.Build.0 = Debug|Win32 - {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|ARM.ActiveCfg = Release|Win32 - {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|ARM64.ActiveCfg = Release|Win32 + {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|ARM64.ActiveCfg = Release|ARM64 + {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|ARM64.Build.0 = Release|ARM64 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|x64.ActiveCfg = Release|x64 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|x64.Build.0 = Release|x64 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|x86.ActiveCfg = Release|Win32 {0011F69F-2363-4DFD-B02A-1E7E909BCE89}.Release|x86.Build.0 = Release|Win32 - {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|ARM.ActiveCfg = Debug|ARM - {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|ARM.Build.0 = Debug|ARM - {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|ARM64.ActiveCfg = Debug|Win32 + {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|ARM64.Build.0 = Debug|ARM64 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|x64.ActiveCfg = Debug|x64 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|x64.Build.0 = Debug|x64 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|x86.ActiveCfg = Debug|Win32 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Debug|x86.Build.0 = Debug|Win32 - {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|ARM.ActiveCfg = Release|ARM - {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|ARM.Build.0 = Release|ARM - {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|ARM64.ActiveCfg = Release|Win32 + {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|ARM64.ActiveCfg = Release|ARM64 + {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|ARM64.Build.0 = Release|ARM64 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|x64.ActiveCfg = Release|x64 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|x64.Build.0 = Release|x64 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|x86.ActiveCfg = Release|Win32 {C2820B98-A31F-46D0-A96D-B8F24392B049}.Release|x86.Build.0 = Release|Win32 - {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|ARM.ActiveCfg = Debug|ARM - {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|ARM.Build.0 = Debug|ARM - {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|ARM64.ActiveCfg = Debug|Win32 + {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|ARM64.Build.0 = Debug|ARM64 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|x64.ActiveCfg = Debug|x64 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|x64.Build.0 = Debug|x64 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|x86.ActiveCfg = Debug|Win32 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Debug|x86.Build.0 = Debug|Win32 - {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|ARM.ActiveCfg = Release|ARM - {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|ARM.Build.0 = Release|ARM - {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|ARM64.ActiveCfg = Release|Win32 + {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|ARM64.ActiveCfg = Release|ARM64 + {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|ARM64.Build.0 = Release|ARM64 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|x64.ActiveCfg = Release|x64 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|x64.Build.0 = Release|x64 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|x86.ActiveCfg = Release|Win32 {1350E626-038B-4BDF-8E1D-C751EF33D90F}.Release|x86.Build.0 = Release|Win32 - {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|ARM.ActiveCfg = Debug|ARM - {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|ARM.Build.0 = Debug|ARM {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|ARM64.ActiveCfg = Debug|ARM64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|ARM64.Build.0 = Debug|ARM64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|x64.ActiveCfg = Debug|x64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|x64.Build.0 = Debug|x64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|x86.ActiveCfg = Debug|Win32 {ADC53200-B456-4386-9851-5BF69DFB8928}.Debug|x86.Build.0 = Debug|Win32 - {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|ARM.ActiveCfg = Release|ARM - {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|ARM.Build.0 = Release|ARM {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|ARM64.ActiveCfg = Release|ARM64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|ARM64.Build.0 = Release|ARM64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|x64.ActiveCfg = Release|x64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|x64.Build.0 = Release|x64 {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|x86.ActiveCfg = Release|Win32 {ADC53200-B456-4386-9851-5BF69DFB8928}.Release|x86.Build.0 = Release|Win32 - {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|ARM.ActiveCfg = Debug|ARM - {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|ARM.Build.0 = Debug|ARM - {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|ARM64.ActiveCfg = Debug|Win32 + {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|ARM64.Build.0 = Debug|ARM64 {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|x64.ActiveCfg = Debug|x64 {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|x64.Build.0 = Debug|x64 {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|x86.ActiveCfg = Debug|Win32 {432068A4-B206-4468-9254-446CCEB15A2C}.Debug|x86.Build.0 = Debug|Win32 - {432068A4-B206-4468-9254-446CCEB15A2C}.Release|ARM.ActiveCfg = Release|ARM - {432068A4-B206-4468-9254-446CCEB15A2C}.Release|ARM.Build.0 = Release|ARM - {432068A4-B206-4468-9254-446CCEB15A2C}.Release|ARM64.ActiveCfg = Release|Win32 + {432068A4-B206-4468-9254-446CCEB15A2C}.Release|ARM64.ActiveCfg = Release|ARM64 + {432068A4-B206-4468-9254-446CCEB15A2C}.Release|ARM64.Build.0 = Release|ARM64 {432068A4-B206-4468-9254-446CCEB15A2C}.Release|x64.ActiveCfg = Release|x64 {432068A4-B206-4468-9254-446CCEB15A2C}.Release|x64.Build.0 = Release|x64 {432068A4-B206-4468-9254-446CCEB15A2C}.Release|x86.ActiveCfg = Release|Win32 {432068A4-B206-4468-9254-446CCEB15A2C}.Release|x86.Build.0 = Release|Win32 - {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|ARM.ActiveCfg = Debug|ARM - {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|ARM.Build.0 = Debug|ARM - {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|ARM64.ActiveCfg = Debug|Win32 + {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|ARM64.Build.0 = Debug|ARM64 {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|x64.ActiveCfg = Debug|x64 {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|x64.Build.0 = Debug|x64 {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|x86.ActiveCfg = Debug|Win32 {8456C55F-BF01-4798-B79B-7388681C398F}.Debug|x86.Build.0 = Debug|Win32 - {8456C55F-BF01-4798-B79B-7388681C398F}.Release|ARM.ActiveCfg = Release|ARM - {8456C55F-BF01-4798-B79B-7388681C398F}.Release|ARM.Build.0 = Release|ARM - {8456C55F-BF01-4798-B79B-7388681C398F}.Release|ARM64.ActiveCfg = Release|Win32 + {8456C55F-BF01-4798-B79B-7388681C398F}.Release|ARM64.ActiveCfg = Release|ARM64 + {8456C55F-BF01-4798-B79B-7388681C398F}.Release|ARM64.Build.0 = Release|ARM64 {8456C55F-BF01-4798-B79B-7388681C398F}.Release|x64.ActiveCfg = Release|x64 {8456C55F-BF01-4798-B79B-7388681C398F}.Release|x64.Build.0 = Release|x64 {8456C55F-BF01-4798-B79B-7388681C398F}.Release|x86.ActiveCfg = Release|Win32 {8456C55F-BF01-4798-B79B-7388681C398F}.Release|x86.Build.0 = Release|Win32 - {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|ARM.ActiveCfg = Debug|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|ARM.Build.0 = Debug|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|ARM64.ActiveCfg = Debug|Win32 + {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|ARM64.Build.0 = Debug|ARM64 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|x64.ActiveCfg = Debug|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|x64.Build.0 = Debug|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|x86.ActiveCfg = Debug|Win32 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Debug|x86.Build.0 = Debug|Win32 - {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|ARM.ActiveCfg = Release|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|ARM.Build.0 = Release|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|ARM64.ActiveCfg = Release|Win32 + {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|ARM64.ActiveCfg = Release|ARM64 + {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|ARM64.Build.0 = Release|ARM64 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|x64.ActiveCfg = Release|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|x64.Build.0 = Release|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|x86.ActiveCfg = Release|Win32 {DC435C3F-C38E-43D1-B702-DC03F530A3CB}.Release|x86.Build.0 = Release|Win32 - {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|ARM.ActiveCfg = Debug|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|ARM.Build.0 = Debug|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|ARM64.ActiveCfg = Debug|Win32 + {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|ARM64.Build.0 = Debug|ARM64 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|x64.ActiveCfg = Debug|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|x64.Build.0 = Debug|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|x86.ActiveCfg = Debug|Win32 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Debug|x86.Build.0 = Debug|Win32 - {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|ARM.ActiveCfg = Release|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|ARM.Build.0 = Release|ARM - {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|ARM64.ActiveCfg = Release|Win32 + {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|ARM64.ActiveCfg = Release|ARM64 + {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|ARM64.Build.0 = Release|ARM64 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|x64.ActiveCfg = Release|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|x64.Build.0 = Release|x64 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|x86.ActiveCfg = Release|Win32 {DC435C3F-C38E-43D1-B702-DC03F530A3DD}.Release|x86.Build.0 = Release|Win32 - {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|ARM.ActiveCfg = Debug|ARM - {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|ARM.Build.0 = Debug|ARM {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|ARM64.ActiveCfg = Debug|ARM64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|ARM64.Build.0 = Debug|ARM64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|x64.ActiveCfg = Debug|x64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|x64.Build.0 = Debug|x64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|x86.ActiveCfg = Debug|x86 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Debug|x86.Build.0 = Debug|x86 - {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|ARM.ActiveCfg = Release|ARM - {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|ARM.Build.0 = Release|ARM {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|ARM64.ActiveCfg = Release|ARM64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|ARM64.Build.0 = Release|ARM64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|x64.ActiveCfg = Release|x64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|x64.Build.0 = Release|x64 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|x86.ActiveCfg = Release|x86 {C47F8562-A2B9-4BA3-87AC-B42D015E241D}.Release|x86.Build.0 = Release|x86 - {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|ARM.ActiveCfg = Debug|ARM - {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|ARM.Build.0 = Debug|ARM - {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|ARM64.ActiveCfg = Debug|Win32 + {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|ARM64.Build.0 = Debug|ARM64 {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|x64.ActiveCfg = Debug|x64 {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|x64.Build.0 = Debug|x64 {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|x86.ActiveCfg = Debug|Win32 {8717FA32-34A8-457D-B77B-AE005703EB55}.Debug|x86.Build.0 = Debug|Win32 - {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|ARM.ActiveCfg = Release|ARM - {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|ARM.Build.0 = Release|ARM - {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|ARM64.ActiveCfg = Release|Win32 + {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|ARM64.ActiveCfg = Release|ARM64 + {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|ARM64.Build.0 = Release|ARM64 {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|x64.ActiveCfg = Release|x64 {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|x64.Build.0 = Release|x64 {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|x86.ActiveCfg = Release|Win32 {8717FA32-34A8-457D-B77B-AE005703EB55}.Release|x86.Build.0 = Release|Win32 - {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|ARM.ActiveCfg = Debug|ARM - {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|ARM.Build.0 = Debug|ARM {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|ARM64.ActiveCfg = Debug|ARM64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|ARM64.Build.0 = Debug|ARM64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|x64.ActiveCfg = Debug|x64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|x64.Build.0 = Debug|x64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|x86.ActiveCfg = Debug|Win32 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Debug|x86.Build.0 = Debug|Win32 - {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|ARM.ActiveCfg = Release|ARM - {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|ARM.Build.0 = Release|ARM {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|ARM64.ActiveCfg = Release|ARM64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|ARM64.Build.0 = Release|ARM64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|x64.ActiveCfg = Release|x64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|x64.Build.0 = Release|x64 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|x86.ActiveCfg = Release|Win32 {FF846D79-F4B8-495A-9FB4-79BAAEB98E4F}.Release|x86.Build.0 = Release|Win32 - {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|ARM.ActiveCfg = Debug|ARM - {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|ARM.Build.0 = Debug|ARM - {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|ARM64.ActiveCfg = Debug|Win32 + {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|ARM64.Build.0 = Debug|ARM64 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|x64.ActiveCfg = Debug|x64 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|x64.Build.0 = Debug|x64 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|x86.ActiveCfg = Debug|Win32 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Debug|x86.Build.0 = Debug|Win32 - {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|ARM.ActiveCfg = Release|ARM - {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|ARM.Build.0 = Release|ARM - {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|ARM64.ActiveCfg = Release|Win32 + {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|ARM64.ActiveCfg = Release|ARM64 + {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|ARM64.Build.0 = Release|ARM64 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|x64.ActiveCfg = Release|x64 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|x64.Build.0 = Release|x64 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|x86.ActiveCfg = Release|Win32 {F89C2185-7834-443D-A449-53BD52FFEA3B}.Release|x86.Build.0 = Release|Win32 - {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|ARM.ActiveCfg = Debug|Win32 - {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|ARM64.ActiveCfg = Debug|Win32 + {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|ARM64.Build.0 = Debug|ARM64 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|x64.ActiveCfg = Debug|x64 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|x64.Build.0 = Debug|x64 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|x86.ActiveCfg = Debug|Win32 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Debug|x86.Build.0 = Debug|Win32 - {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|ARM.ActiveCfg = Release|Win32 - {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|ARM64.ActiveCfg = Release|Win32 + {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|ARM64.ActiveCfg = Release|ARM64 + {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|ARM64.Build.0 = Release|ARM64 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|x64.ActiveCfg = Release|x64 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|x64.Build.0 = Release|x64 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|x86.ActiveCfg = Release|Win32 {4DD64EAE-4B27-415A-863E-55CB8D5863DD}.Release|x86.Build.0 = Release|Win32 - {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|ARM.ActiveCfg = Debug|x64 - {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|ARM.Build.0 = Debug|x64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|ARM64.ActiveCfg = Debug|ARM64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|ARM64.Build.0 = Debug|ARM64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|x64.ActiveCfg = Debug|x64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|x64.Build.0 = Debug|x64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|x86.ActiveCfg = Debug|Win32 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Debug|x86.Build.0 = Debug|Win32 - {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|ARM.ActiveCfg = Release|x64 - {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|ARM.Build.0 = Release|x64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|ARM64.ActiveCfg = Release|ARM64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|ARM64.Build.0 = Release|ARM64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|x64.ActiveCfg = Release|x64 diff --git a/test/nuget/TestApp/TestApp.vcxproj b/test/nuget/TestApp/TestApp.vcxproj index 582b95103..84029a4c9 100644 --- a/test/nuget/TestApp/TestApp.vcxproj +++ b/test/nuget/TestApp/TestApp.vcxproj @@ -16,9 +16,9 @@ - + Debug - ARM + ARM64 Debug @@ -28,9 +28,9 @@ Debug x64 - + Release - ARM + ARM64 Release diff --git a/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj b/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj index 7827c2b21..1b7621ea0 100644 --- a/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj +++ b/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj @@ -16,9 +16,9 @@ - + Debug - ARM + ARM64 Debug @@ -28,9 +28,9 @@ Debug x64 - + Release - ARM + ARM64 Release diff --git a/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj b/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj index eb12311c1..48f9acfb0 100644 --- a/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj +++ b/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj @@ -17,9 +17,9 @@ - + Debug - ARM + ARM64 Debug @@ -29,9 +29,9 @@ Debug x64 - + Release - ARM + ARM64 Release diff --git a/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj b/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj index 24d061de0..8a876e601 100644 --- a/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj +++ b/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj @@ -17,9 +17,9 @@ - + Debug - ARM + ARM64 Debug @@ -29,9 +29,9 @@ Debug x64 - + Release - ARM + ARM64 Release diff --git a/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj b/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj index b2a1dfbe8..57f14194d 100644 --- a/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj +++ b/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj @@ -36,24 +36,6 @@ false prompt - - ARM - true - DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP - ;2008 - full - false - prompt - - - ARM - TRACE;NETFX_CORE;WINDOWS_UWP - true - ;2008 - pdbonly - false - prompt - ARM64 true diff --git a/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj b/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj index 97b5c5613..237b9fcf3 100644 --- a/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj +++ b/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj @@ -2,10 +2,6 @@ - - Debug - ARM - Debug ARM64 @@ -18,10 +14,6 @@ Debug x64 - - Release - ARM - Release ARM64 @@ -69,12 +61,6 @@ - - - - - - @@ -95,12 +81,6 @@ false - - false - - - false - false @@ -145,38 +125,6 @@ false - - - Use - _WINRT_DLL;%(PreprocessorDefinitions) - pch.h - $(IntDir)pch.pch - $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) - /bigobj /Zc:twoPhase- %(AdditionalOptions) - 28204 - true - - - Console - false - - - - - Use - _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) - pch.h - $(IntDir)pch.pch - $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) - /bigobj /Zc:twoPhase- %(AdditionalOptions) - 28204 - true - - - Console - false - - Use @@ -251,8 +199,6 @@ Create Create Create - Create - Create Create Create diff --git a/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj b/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj index 6131345a9..68b71c94e 100644 --- a/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj +++ b/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj @@ -2,10 +2,6 @@ - - Debug - ARM - Debug ARM64 @@ -18,10 +14,6 @@ Debug x64 - - Release - ARM - Release ARM64 @@ -51,10 +43,6 @@ DynamicLibrary true - - DynamicLibrary - true - DynamicLibrary true @@ -68,11 +56,6 @@ false true - - DynamicLibrary - false - true - DynamicLibrary false @@ -94,12 +77,6 @@ - - - - - - @@ -120,12 +97,6 @@ false - - false - - - false - false @@ -168,36 +139,6 @@ false - - - Use - _WINRT_DLL;%(PreprocessorDefinitions) - pch.h - $(IntDir)pch.pch - $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) - /bigobj /Zc:twoPhase- %(AdditionalOptions) - 28204 - - - Console - false - - - - - Use - _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions) - pch.h - $(IntDir)pch.pch - $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) - /bigobj /Zc:twoPhase- %(AdditionalOptions) - 28204 - - - Console - false - - Use @@ -268,8 +209,6 @@ Create Create Create - Create - Create Create Create diff --git a/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj b/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj index 66a6713df..7572238eb 100644 --- a/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj +++ b/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj @@ -17,9 +17,9 @@ - + Debug - ARM + ARM64 Debug @@ -29,9 +29,9 @@ Debug x64 - + Release - ARM + ARM64 Release diff --git a/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj b/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj index b07497f7f..693a97596 100644 --- a/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj +++ b/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj @@ -17,9 +17,9 @@ - + Debug - ARM + ARM64 Debug @@ -29,9 +29,9 @@ Debug x64 - + Release - ARM + ARM64 Release diff --git a/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj b/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj index 679f4b60c..a34e7429c 100644 --- a/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj +++ b/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj @@ -18,9 +18,9 @@ - + Debug - ARM + ARM64 Debug @@ -30,9 +30,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -70,10 +70,10 @@ - + - + @@ -111,7 +111,7 @@ true - + Use Level4 @@ -170,7 +170,7 @@ true - + Use Level4 @@ -202,10 +202,10 @@ Create Create - Create + Create Create Create - Create + Create TestStaticLibrary1Class.idl diff --git a/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj b/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj index cb8352c96..5f3ee5220 100644 --- a/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj +++ b/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj @@ -18,9 +18,9 @@ - + Debug - ARM + ARM64 Debug @@ -30,9 +30,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -70,10 +70,10 @@ - + - + @@ -111,7 +111,7 @@ true - + Use Level4 @@ -170,7 +170,7 @@ true - + Use Level4 @@ -202,10 +202,10 @@ Create Create - Create + Create Create Create - Create + Create TestStaticLibrary2Class.idl diff --git a/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj b/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj index 8b2d75f40..c79a847a3 100644 --- a/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj +++ b/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj @@ -18,9 +18,9 @@ - + Debug - ARM + ARM64 Debug @@ -30,9 +30,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -70,10 +70,10 @@ - + - + @@ -111,7 +111,7 @@ true - + Use Level4 @@ -170,7 +170,7 @@ true - + Use Level4 @@ -202,10 +202,10 @@ Create Create - Create + Create Create Create - Create + Create TestStaticLibrary3Class.idl diff --git a/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj b/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj index 36fcfb1be..b3efe02c4 100644 --- a/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj +++ b/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj @@ -2,9 +2,9 @@ - + Debug - ARM + ARM64 Debug @@ -14,9 +14,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -65,10 +65,10 @@ - + - + @@ -85,10 +85,10 @@ false - + false - + false @@ -121,7 +121,7 @@ false - + Use false @@ -133,7 +133,7 @@ false - + Use false @@ -181,10 +181,10 @@ Create Create - Create - Create Create Create + Create + Create Create Create diff --git a/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj b/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj index e088b38f8..bfc6db45c 100644 --- a/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj +++ b/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj @@ -2,9 +2,9 @@ - + Debug - ARM + ARM64 Debug @@ -14,9 +14,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -65,10 +65,10 @@ - + - + @@ -85,10 +85,10 @@ false - + false - + false @@ -121,7 +121,7 @@ false - + Use false @@ -133,7 +133,7 @@ false - + Use false @@ -181,10 +181,10 @@ Create Create - Create - Create Create Create + Create + Create Create Create diff --git a/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj b/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj index 8cf328f99..89a0e55c9 100644 --- a/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj +++ b/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj @@ -2,9 +2,9 @@ - + Debug - ARM + ARM64 Debug @@ -14,9 +14,9 @@ Debug x64 - + Release - ARM + ARM64 Release @@ -65,10 +65,10 @@ - + - + @@ -85,10 +85,10 @@ false - + false - + false @@ -121,7 +121,7 @@ false - + Use false @@ -133,7 +133,7 @@ false - + Use false @@ -185,10 +185,10 @@ Create Create - Create - Create Create Create + Create + Create Create Create diff --git a/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj b/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj index 3189c7294..0fdf11744 100644 --- a/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj +++ b/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj @@ -18,9 +18,9 @@ - + Debug - ARM + ARM64 Debug @@ -30,9 +30,9 @@ Debug x64 - + Release - ARM + ARM64 Release diff --git a/test/old_tests/Component/Component.vcxproj b/test/old_tests/Component/Component.vcxproj index 9af296c51..dbc55f2d3 100644 --- a/test/old_tests/Component/Component.vcxproj +++ b/test/old_tests/Component/Component.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -17,10 +13,6 @@ Debug x64 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -67,12 +54,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -122,12 +97,6 @@ ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - - false - false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl - false false @@ -140,12 +109,6 @@ ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - - false - false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl - false false @@ -210,42 +173,6 @@ - - - false - $(ProjectDir);$(OutputPath);Generated Files;..\Composable\Generated Files - false - MultiThreadedDebug - NOMINMAX;_WINDLL;%(PreprocessorDefinitions) - 4100;4297;4458 - - - Console - false - module.def - true - - - - - - - - - ..\Composable - - - - - - - - - - - - - false @@ -315,41 +242,6 @@ - - - false - $(ProjectDir);$(OutputPath);Generated Files;..\Composable\Generated Files - MultiThreaded - NOMINMAX;_WINDLL;%(PreprocessorDefinitions) - 4100;4297;4458 - - - Console - false - module.def - true - - - - - - - - - ..\Composable - - - - - - - - - - - - - false @@ -478,50 +370,38 @@ $(SystemRoot)\System32\WinMetadata - $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata - $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(OutputPath)$(ProjectName).winmd - $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd - $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd true - true true true - true true true true $(OutputPath)$(ProjectName)_h.h - $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h - $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h ..\Composable - ..\Composable ..\Composable ..\Composable - ..\Composable ..\Composable ..\Composable ..\Composable true - true true true - true true true true diff --git a/test/old_tests/Composable/Composable.vcxproj b/test/old_tests/Composable/Composable.vcxproj index d13d779b9..3b78edce4 100644 --- a/test/old_tests/Composable/Composable.vcxproj +++ b/test/old_tests/Composable/Composable.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -17,10 +13,6 @@ Debug x64 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -67,12 +54,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -122,12 +97,6 @@ ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - - false - false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl - false false @@ -140,12 +109,6 @@ ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - - false - false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl - false false @@ -210,42 +173,6 @@ - - - false - $(ProjectDir);$(OutDir);Generated Files - false - MultiThreadedDebug - NOMINMAX;_WINDLL;%(PreprocessorDefinitions) - 4100;4297;4458 - precomp.hpp - - - Console - false - module.def - true - - - - - - - - - - - - - - - - - - - - - false @@ -315,41 +242,6 @@ - - - false - $(ProjectDir);$(OutDir);Generated Files - MultiThreaded - NOMINMAX;_WINDLL;%(PreprocessorDefinitions) - 4100;4297;4458 - precomp.hpp - - - Console - false - module.def - true - - - - - - - - - - - - - - - - - - - - - false @@ -470,42 +362,32 @@ $(SystemRoot)\System32\WinMetadata - $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata - $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(SystemRoot)\System32\WinMetadata $(OutputPath)$(ProjectName).winmd - $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd - $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd $(OutputPath)$(ProjectName).winmd true - true true true - true true true true $(OutputPath)$(ProjectName)_h.h - $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h - $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h $(OutputPath)$(ProjectName)_h.h true - true true true - true true true true diff --git a/test/old_tests/UnitTests/Tests.vcxproj b/test/old_tests/UnitTests/Tests.vcxproj index c0c178442..a0711f41d 100644 --- a/test/old_tests/UnitTests/Tests.vcxproj +++ b/test/old_tests/UnitTests/Tests.vcxproj @@ -1,10 +1,6 @@  - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -146,11 +138,6 @@ true x64 - - Application - true - x64 - Application true @@ -162,12 +149,6 @@ x64 true - - Application - false - x64 - true - Application false @@ -193,18 +174,12 @@ - - - - - - @@ -240,25 +215,6 @@ $(OutDir)test_old.exe - - - Disabled - _HAS_AUTO_PTR_ETC;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(OutputPath);..\Composable\Generated Files;..\Component\Generated Files;..\Composable;..\Reflection\Generated Files;..\..\; - ProgramDatabase - Default - false - false - MultiThreadedDebug - 4100;4297;4458 - - - Console - true - false - $(OutDir)test_old.exe - - Disabled @@ -316,25 +272,6 @@ $(OutDir)test_old.exe - - - MaxSpeed - true - true - _HAS_AUTO_PTR_ETC;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(OutputPath);..\Composable\Generated Files;..\Component\Generated Files;..\Composable;..\Reflection\Generated Files;..\..\; - MultiThreaded - 4100;4297;4458 - - - Console - true - true - true - false - $(OutDir)test_old.exe - - MaxSpeed diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index a82465149..f1035ab6c 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -45,10 +37,6 @@ Application true - - Application - true - Application true @@ -58,11 +46,6 @@ false true - - Application - false - true - Application false @@ -85,18 +68,12 @@ - - - - - - @@ -147,24 +124,6 @@ - - - Disabled - $(OutputPath);Generated Files;..;..\..\cppwinrt - _MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - Disabled @@ -223,28 +182,6 @@ - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..;..\..\cppwinrt - _MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component.winmd $(OutputPath)test_component_no_pch.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - MaxSpeed @@ -290,8 +227,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing @@ -300,8 +235,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing @@ -310,8 +243,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing @@ -349,8 +280,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing @@ -361,8 +290,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing @@ -374,8 +301,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing @@ -393,8 +318,6 @@ NotUsing NotUsing NotUsing - NotUsing - NotUsing NotUsing NotUsing diff --git a/test/test_component/test_component.vcxproj b/test/test_component/test_component.vcxproj index 15aa24447..b6b3aa5d4 100644 --- a/test/test_component/test_component.vcxproj +++ b/test/test_component/test_component.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -62,12 +49,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -119,10 +94,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -131,10 +102,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -183,55 +150,6 @@ true - - - Disabled - .;$(OutputPath);Generated Files - /Zc:threadSafeInit- /we4640 %(AdditionalOptions) - MultiThreadedDebug - - - exports.def - - - true - - - $(OutputPath)test_component.winmd - - - - - - - - - - - $(OutputPath)test_component.h - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - Disabled @@ -357,59 +275,6 @@ true - - - MaxSpeed - true - true - .;$(OutputPath);Generated Files - /Zc:threadSafeInit- /we4640 %(AdditionalOptions) - MultiThreaded - - - true - true - exports.def - - - true - - - $(OutputPath)test_component.winmd - - - - - - - - - - - $(OutputPath)test_component.h - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - MaxSpeed diff --git a/test/test_component_base/test_component_base.vcxproj b/test/test_component_base/test_component_base.vcxproj index d8768de47..2a2069da0 100644 --- a/test/test_component_base/test_component_base.vcxproj +++ b/test/test_component_base/test_component_base.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -62,12 +49,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -119,10 +94,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -131,10 +102,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -195,68 +162,6 @@ $(OutputPath)test_component_base.winmd - - - Disabled - $(ProjectDir);$(OutputPath);Generated Files - 4100 - MultiThreadedDebug - - - exports.def - - - true - - - $(OutputPath)test_component_base.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_base.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -name test_component_base - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_base.winmd - - Disabled @@ -419,72 +324,6 @@ $(OutputPath)test_component_base.winmd - - - MaxSpeed - true - true - $(ProjectDir);$(OutputPath);Generated Files - 4100 - MultiThreaded - - - true - true - exports.def - - - true - - - $(OutputPath)test_component_base.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_base.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -name test_component_base - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_base.winmd - - MaxSpeed diff --git a/test/test_component_derived/test_component_derived.vcxproj b/test/test_component_derived/test_component_derived.vcxproj index e80ab4af1..e31d675a8 100644 --- a/test/test_component_derived/test_component_derived.vcxproj +++ b/test/test_component_derived/test_component_derived.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -62,12 +49,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -119,10 +94,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -131,10 +102,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -196,69 +163,6 @@ $(OutputPath)test_component_derived.winmd - - - Disabled - $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files - 4100 - MultiThreadedDebug - - - exports.def - - - true - - - $(OutputPath)test_component_derived.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - ..\test_component_base - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_derived.winmd -ref $(OutputPath)test_component_base.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -name test_component_derived - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_derived.winmd - - Disabled @@ -424,73 +328,6 @@ $(OutputPath)test_component_derived.winmd - - - MaxSpeed - true - true - $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files - 4100 - MultiThreaded - - - true - true - exports.def - - - true - - - $(OutputPath)test_component_derived.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - ..\test_component_base - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_derived.winmd -ref $(OutputPath)test_component_base.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -name test_component_derived - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_derived.winmd - - MaxSpeed diff --git a/test/test_component_fast/test_component_fast.vcxproj b/test/test_component_fast/test_component_fast.vcxproj index b9d54604b..216afea69 100644 --- a/test/test_component_fast/test_component_fast.vcxproj +++ b/test/test_component_fast/test_component_fast.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -47,11 +39,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -63,12 +50,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -94,18 +75,12 @@ - - - - - - @@ -120,10 +95,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -132,10 +103,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -197,69 +164,6 @@ $(OutputPath)test_component_fast.winmd - - - Disabled - $(ProjectDir);$(OutputPath);Generated Files - /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) - 4100 - MultiThreadedDebug - - - exports.def - - - true - - - $(OutputPath)test_component_fast.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_fast.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi -prefix -opt -name test_component_fast - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_fast.winmd - - Disabled @@ -425,73 +329,6 @@ $(OutputPath)test_component_fast.winmd - - - MaxSpeed - true - true - $(ProjectDir);$(OutputPath);Generated Files - /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) - 4100 - MultiThreaded - - - true - true - exports.def - - - true - - - $(OutputPath)test_component_fast.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_fast.winmd -comp $(ProjectDir) -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi -prefix -opt -name test_component_fast - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_fast.winmd - - MaxSpeed diff --git a/test/test_component_folders/test_component_folders.vcxproj b/test/test_component_folders/test_component_folders.vcxproj index 0270ca257..0ddb18c6e 100644 --- a/test/test_component_folders/test_component_folders.vcxproj +++ b/test/test_component_folders/test_component_folders.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -62,12 +49,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -119,10 +94,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -131,10 +102,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -195,68 +162,6 @@ $(OutputPath)test_component_folders.winmd - - - Disabled - $(ProjectDir);$(OutputPath);Generated Files - 4100 - MultiThreadedDebug - - - exports.def - - - true - - - $(OutputPath)test_component_folders.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_folders.winmd -comp -out "$(ProjectDir)Generated Files" -ref sdk -verbose -overwrite -name test_component_folders - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_folders.winmd - - Disabled @@ -419,72 +324,6 @@ $(OutputPath)test_component_folders.winmd - - - MaxSpeed - true - true - $(ProjectDir);$(OutputPath);Generated Files - 4100 - MultiThreaded - - - true - true - exports.def - - - true - - - $(OutputPath)test_component_folders.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_folders.winmd -comp -out "$(ProjectDir)Generated Files" -ref sdk -verbose -overwrite -name test_component_folders - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_folders.winmd - - MaxSpeed diff --git a/test/test_component_no_pch/test_component_no_pch.vcxproj b/test/test_component_no_pch/test_component_no_pch.vcxproj index 594e85592..040ab13f6 100644 --- a/test/test_component_no_pch/test_component_no_pch.vcxproj +++ b/test/test_component_no_pch/test_component_no_pch.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,11 +38,6 @@ true x64 - - DynamicLibrary - true - x64 - DynamicLibrary true @@ -62,12 +49,6 @@ true x64 - - DynamicLibrary - false - true - x64 - DynamicLibrary false @@ -93,18 +74,12 @@ - - - - - - @@ -119,10 +94,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -131,10 +102,6 @@ Midl $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - - Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); - Midl $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); @@ -196,69 +163,6 @@ $(OutputPath)test_component_no_pch.winmd - - - Disabled - $(ProjectDir);$(OutputPath);Generated Files - 4100 - NotUsing - MultiThreadedDebug - - - exports.def - - - true - - - $(OutputPath)test_component_no_pch.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_no_pch.winmd -comp -out "$(ProjectDir)Generated Files" -ref sdk -verbose -overwrite -pch . -name test_component_no_pch - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_no_pch.winmd - - Disabled @@ -424,73 +328,6 @@ $(OutputPath)test_component_no_pch.winmd - - - MaxSpeed - true - true - $(ProjectDir);$(OutputPath);Generated Files - 4100 - NotUsing - MultiThreaded - - - true - true - exports.def - - - true - - - $(OutputPath)test_component_no_pch.winmd - - - - - - - - - - - nul - - - - - - - - - - - - - - - - - - - /nomidl %(AdditionalOptions) - C:\Windows\System32\WinMetadata - true - - - $(CppWinRTDir)cppwinrt -input $(OutputPath)test_component_no_pch.winmd -comp -out "$(ProjectDir)Generated Files" -ref sdk -verbose -overwrite -pch . -name test_component_no_pch - - - - - - - Generated Files\module.g.cpp - - - $(OutputPath)test_component_no_pch.winmd - - MaxSpeed diff --git a/test/test_cpp20/test_cpp20.vcxproj b/test/test_cpp20/test_cpp20.vcxproj index 72d203a37..832297f7f 100644 --- a/test/test_cpp20/test_cpp20.vcxproj +++ b/test/test_cpp20/test_cpp20.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,10 +38,6 @@ Application true - - Application - true - Application true @@ -59,11 +47,6 @@ false true - - Application - false - true - Application false @@ -86,18 +69,12 @@ - - - - - - @@ -150,25 +127,6 @@ - - - Disabled - $(OutputPath);Generated Files;..\ - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - - - - - - - - - - Disabled @@ -230,29 +188,6 @@ - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\ - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - - - - - - - - - - MaxSpeed diff --git a/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj b/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj index c71cfdc96..86a56a3b9 100644 --- a/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj +++ b/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -46,10 +38,6 @@ Application true - - Application - true - Application true @@ -59,11 +47,6 @@ false true - - Application - false - true - Application false @@ -86,18 +69,12 @@ - - - - - - @@ -156,25 +133,6 @@ - - - Disabled - $(OutputPath);Generated Files;..\ - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - - - - - - - - - - Disabled @@ -236,29 +194,6 @@ - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\ - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - - - - - - - - - - MaxSpeed diff --git a/test/test_fast/test_fast.vcxproj b/test/test_fast/test_fast.vcxproj index c256cad6b..27a7ea350 100644 --- a/test/test_fast/test_fast.vcxproj +++ b/test/test_fast/test_fast.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -45,10 +37,6 @@ Application true - - Application - true - Application true @@ -58,11 +46,6 @@ false true - - Application - false - true - Application false @@ -85,18 +68,12 @@ - - - - - - @@ -149,25 +126,6 @@ - - - Disabled - $(OutputPath);Generated Files;..\; - WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - false - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component_fast.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - Disabled @@ -229,29 +187,6 @@ - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\; - WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - false - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component_fast.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - MaxSpeed diff --git a/test/test_fast_fwd/test_fast_fwd.vcxproj b/test/test_fast_fwd/test_fast_fwd.vcxproj index c01406e38..d4b63c3fb 100644 --- a/test/test_fast_fwd/test_fast_fwd.vcxproj +++ b/test/test_fast_fwd/test_fast_fwd.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -126,30 +118,6 @@ - - - Disabled - true - true - $(CppWinRTDir);$(OutputPath);Generated Files;..\ - stdcpp17 - Use - pch.h - true - WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - - - Console - windowsapp.lib - - - $(CppWinRTDir)cppwinrt -in $(CppWinRTDir)test_component_fast.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - Disabled @@ -212,34 +180,6 @@ - - - MaxSpeed - true - true - true - true - $(CppWinRTDir);$(OutputPath);Generated Files;..\ - stdcpp17 - Use - pch.h - true - WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - - - Console - true - true - windowsapp.lib - - - $(CppWinRTDir)cppwinrt -in $(CppWinRTDir)test_component_fast.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose -fastabi - - - - - - @@ -325,18 +265,12 @@ false MultiThreaded - - MultiThreaded - MultiThreaded MultiThreaded - - MultiThreadedDebug - MultiThreadedDebug diff --git a/test/test_module_lock_custom/test_module_lock_custom.vcxproj b/test/test_module_lock_custom/test_module_lock_custom.vcxproj index 6bb40e761..6671a1156 100644 --- a/test/test_module_lock_custom/test_module_lock_custom.vcxproj +++ b/test/test_module_lock_custom/test_module_lock_custom.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -45,10 +37,6 @@ Application true - - Application - true - Application true @@ -58,11 +46,6 @@ false true - - Application - false - true - Application false @@ -85,18 +68,12 @@ - - - - - - @@ -149,25 +126,6 @@ - - - Disabled - $(OutputPath);Generated Files;..\; - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - - - - - - - - - - Disabled @@ -229,29 +187,6 @@ - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\; - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - - - - - - - - - - MaxSpeed diff --git a/test/test_module_lock_none/test_module_lock_none.vcxproj b/test/test_module_lock_none/test_module_lock_none.vcxproj index 7f460c6b2..381edbdfe 100644 --- a/test/test_module_lock_none/test_module_lock_none.vcxproj +++ b/test/test_module_lock_none/test_module_lock_none.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -45,10 +37,6 @@ Application true - - Application - true - Application true @@ -58,11 +46,6 @@ false true - - Application - false - true - Application false @@ -85,18 +68,12 @@ - - - - - - @@ -149,25 +126,6 @@ - - - Disabled - $(OutputPath);Generated Files;..\ - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - - - - - - - - - - Disabled @@ -229,29 +187,6 @@ - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\ - NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - - - - - - - - - - MaxSpeed diff --git a/test/test_slow/test_slow.vcxproj b/test/test_slow/test_slow.vcxproj index 75891b64b..eb6c7fc60 100644 --- a/test/test_slow/test_slow.vcxproj +++ b/test/test_slow/test_slow.vcxproj @@ -1,10 +1,6 @@ - - Debug - ARM - Debug ARM64 @@ -13,10 +9,6 @@ Debug Win32 - - Release - ARM - Release ARM64 @@ -45,10 +37,6 @@ Application true - - Application - true - Application true @@ -58,11 +46,6 @@ false true - - Application - false - true - Application false @@ -85,18 +68,12 @@ - - - - - - @@ -147,24 +124,6 @@ - - - Disabled - $(OutputPath);Generated Files;..\ - WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreadedDebug - - - Console - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component_fast.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose - - - - - - Disabled @@ -223,28 +182,6 @@ - - - MaxSpeed - true - true - $(OutputPath);Generated Files;..\ - WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) - MultiThreaded - - - Console - true - true - - - $(CppWinRTDir)cppwinrt -in $(OutputPath)test_component_fast.winmd -out "$(ProjectDir)Generated Files" -ref sdk -verbose - - - - - - MaxSpeed diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj index c270aa038..30630610e 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj @@ -18,10 +18,6 @@ - - Debug - ARM - Debug ARM64 @@ -34,10 +30,6 @@ Debug x64 - - Release - ARM - Release ARM64 diff --git a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj index bd839b0b2..841ff85c9 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj @@ -17,10 +17,6 @@ - - Debug - ARM - Debug ARM64 @@ -33,10 +29,6 @@ Debug x64 - - Release - ARM - Release ARM64 diff --git a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj index accf6d492..ec8126558 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj @@ -19,10 +19,6 @@ - - Debug - ARM - Debug ARM64 @@ -35,10 +31,6 @@ Debug x64 - - Release - ARM - Release ARM64 diff --git a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj index 7846860c0..78c477177 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj @@ -18,10 +18,6 @@ - - Debug - ARM - Debug ARM64 @@ -34,10 +30,6 @@ Debug x64 - - Release - ARM - Release ARM64 From fa079fb34b19b52dd92e215f8e58957f206c35e1 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Tue, 19 Nov 2024 16:25:25 -0800 Subject: [PATCH 30/91] Address variable name collisions in generated consume methods (#1455) Why is this change being made? Someone discovered a subtle compatibility issue with the cast result checking changes and certain projected methods. The variables in the consume_ method, such as the generically-named code variable, can shadow the parameters to the function. This led to a build break where a function took an int16_t named code and that was shadowed by the int32_t named code with the HRESULT in it. Fortunately the compiler had our back and flagged the size truncation as a build break so it was noticed. Briefly summarize what changed The variable names in these generated functions are now much uglier (and therefore less likely to collide by coincidence). They have an underscore prefix and then lowercase which should put them into an unofficial namespace that shouldn't collide with anything else. The code variable is now named _winrt_cast_result_code for example. While I was renaming everything I realized that my previous names mismatched the cppwinrt naming convention of snake_case so I fixed them up. --- cppwinrt/code_writers.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 01f7dea10..9d75d3476 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1137,15 +1137,15 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const [castedResult, code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); - check_hresult(code); - auto const abiType = *(abi_t<%>**)&castedResult; - abiType->%(%); + auto const [_winrt_casted_result, _winrt_cast_result_code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); + check_hresult(_winrt_cast_result_code); + auto const _winrt_abi_type = *(abi_t<%>**)&_winrt_casted_result; + _winrt_abi_type->%(%); } else { - auto const abiType = *(abi_t<%>**)this; - abiType->%(%); + auto const _winrt_abi_type = *(abi_t<%>**)this; + _winrt_abi_type->%(%); }% } )"; @@ -1156,15 +1156,15 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const [castedResult, code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); - check_hresult(code); - auto const abiType = *(abi_t<%>**)&castedResult; - WINRT_VERIFY_(0, abiType->%(%)); + auto const [_winrt_casted_result, _winrt_cast_result_code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); + check_hresult(_winrt_cast_result_code); + auto const _winrt_abi_type = *(abi_t<%>**)&_winrt_casted_result; + WINRT_VERIFY_(0, _winrt_abi_type->%(%)); } else { - auto const abiType = *(abi_t<%>**)this; - WINRT_VERIFY_(0, abiType->%(%)); + auto const _winrt_abi_type = *(abi_t<%>**)this; + WINRT_VERIFY_(0, _winrt_abi_type->%(%)); }% } )"; @@ -1176,15 +1176,15 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const [castedResult, code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); - check_hresult(code); - auto const abiType = *(abi_t<%>**)&castedResult; - check_hresult(abiType->%(%)); + auto const [_winrt_casted_result, _winrt_cast_result_code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); + check_hresult(_winrt_cast_result_code); + auto const _winrt_abi_type = *(abi_t<%>**)&_winrt_casted_result; + check_hresult(_winrt_abi_type->%(%)); } else { - auto const abiType = *(abi_t<%>**)this; - check_hresult(abiType->%(%)); + auto const _winrt_abi_type = *(abi_t<%>**)this; + check_hresult(_winrt_abi_type->%(%)); }% } )"; From cf96df51cb808872c98301092b25e75de576c7d6 Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Tue, 3 Dec 2024 19:58:26 -0500 Subject: [PATCH 31/91] Fix overloads coming from overridable interfaces (#1458) * Fix overloads coming from overridable interfaces Fixes #1457 * PR feedback --- cppwinrt/code_writers.h | 18 ++++++--- test/test_component/OverloadClass.cpp | 23 +++++++++++ test/test_component/OverloadClass.h | 21 ++++++++++ test/test_component/test_component.idl | 47 ++++++++++++++++++++++ test/test_component/test_component.vcxproj | 3 ++ test/test_component/test_overload.cpp | 19 +++++++++ 6 files changed, 125 insertions(+), 6 deletions(-) create mode 100644 test/test_component/OverloadClass.cpp create mode 100644 test/test_component/OverloadClass.h create mode 100644 test/test_component/test_overload.cpp diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 9d75d3476..0ff1887d1 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -2150,6 +2150,10 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable w.write("\n friend impl::consume_t;", name); w.write("\n friend impl::require_one;", name); } + else if (info.overridable) + { + w.write("\n friend impl::produce;", name); + } } } @@ -2275,13 +2279,13 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable static void write_class_override_usings(writer& w, get_interfaces_t const& required_interfaces) { - std::map> method_usage; + std::map> method_usage; - for (auto&& [interface_name, info] : required_interfaces) + for (auto&& interface_desc : required_interfaces) { - for (auto&& method : info.type.MethodList()) + for (auto&& method : interface_desc.second.type.MethodList()) { - method_usage[get_name(method)].insert(interface_name); + method_usage[get_name(method)].insert(interface_desc); } } @@ -2292,9 +2296,11 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable continue; } - for (auto&& interface_name : interfaces) + for (auto&& [interface_name, info] : interfaces) { - w.write(" using impl::consume_t::%;\n", + w.write(info.overridable + ? " using %T::%;\n" + : " using impl::consume_t::%;\n", interface_name, method_name); } diff --git a/test/test_component/OverloadClass.cpp b/test/test_component/OverloadClass.cpp new file mode 100644 index 000000000..d89f19ea5 --- /dev/null +++ b/test/test_component/OverloadClass.cpp @@ -0,0 +1,23 @@ +#include "pch.h" +#include "OverloadClass.h" +#include "OverloadClass.g.cpp" + +namespace winrt::test_component::implementation +{ + void OverloadClass::Overload() + { + throw hresult_not_implemented(); + } + void OverloadClass::Overload(int a) + { + throw hresult_not_implemented(); + } + void OverloadClass::Overload(int a, int b) + { + throw hresult_not_implemented(); + } + void OverloadClass::Overload(int a, int b, int c) + { + throw hresult_not_implemented(); + } +} diff --git a/test/test_component/OverloadClass.h b/test/test_component/OverloadClass.h new file mode 100644 index 000000000..1b155e801 --- /dev/null +++ b/test/test_component/OverloadClass.h @@ -0,0 +1,21 @@ +#pragma once +#include "OverloadClass.g.h" + +namespace winrt::test_component::implementation +{ + struct OverloadClass : OverloadClassT + { + OverloadClass() = default; + + void Overload(); + void Overload(int a); + void Overload(int a, int b); + void Overload(int a, int b, int c); + }; +} +namespace winrt::test_component::factory_implementation +{ + struct OverloadClass : OverloadClassT + { + }; +} diff --git a/test/test_component/test_component.idl b/test/test_component/test_component.idl index a027c394c..536a703f5 100644 --- a/test/test_component/test_component.idl +++ b/test/test_component/test_component.idl @@ -334,4 +334,51 @@ namespace test_component delegate void Delegate(); } + + [exclusiveto(test_component.OverloadClass)] + [version(1), uuid(EF902013-00F3-4549-9032-49E86D536C07)] + interface IOverloadClass : IInspectable + { + HRESULT Overload(); + } + + [exclusiveto(test_component.OverloadClass)] + [version(1), uuid(DFDFFB61-EA72-4977-B1A7-3F0D2C32BB58)] + interface IOverloadClassFactory : IInspectable + { + HRESULT CreateInstance([in] IInspectable* baseInterface, [out] IInspectable** innerInterface, [out][retval] test_component.OverloadClass** value); + } + + [exclusiveto(test_component.OverloadClass)] + [version(1), uuid(32510F72-9229-4C69-95BD-DE7B8189C85C)] + interface IOverloadClassOverrides : IInspectable + { + [overload("Overload")] HRESULT OverloadWithOne(int a); + } + + [exclusiveto(test_component.OverloadClass)] + [version(1), uuid(50205BCE-FAD3-4C66-801F-17AAD007B26C)] + interface IOverloadClassOverrides2 : IInspectable + { + [overload("Overload")] HRESULT OverloadWithTwo(int a, int b); + } + + [exclusiveto(test_component.OverloadClass)] + [version(1), uuid(6EDD1A3F-2616-45B7-9731-F84DA9CCECA1)] + interface IOverloadClassProtected : IInspectable + { + [overload("Overload")] HRESULT OverloadWithThree(int a, int b, int c); + } + + [composable(test_component.IOverloadClassFactory, public, 1)] + [marshaling_behavior(agile)] + [threading(both)] + [version(1)] + runtimeclass OverloadClass + { + [default] interface test_component.IOverloadClass; + [protected] interface test_component.IOverloadClassProtected; + [overridable] interface test_component.IOverloadClassOverrides; + [overridable] interface test_component.IOverloadClassOverrides2; + } } diff --git a/test/test_component/test_component.vcxproj b/test/test_component/test_component.vcxproj index b6b3aa5d4..001587bed 100644 --- a/test/test_component/test_component.vcxproj +++ b/test/test_component/test_component.vcxproj @@ -384,6 +384,8 @@ + + Create @@ -397,6 +399,7 @@ + diff --git a/test/test_component/test_overload.cpp b/test/test_component/test_overload.cpp new file mode 100644 index 000000000..9c21a06cf --- /dev/null +++ b/test/test_component/test_overload.cpp @@ -0,0 +1,19 @@ +#include "pch.h" +#include "winrt/test_component.h" + +// Simple compile-only test to validate overloads coming from overridable interfaces compile. + +using namespace winrt; +using namespace test_component; + +struct DerivedClass : OverloadClassT +{ + void Foo() + { + // make sure we can actually call the overloads (no ambiguous call errors) + Overload(); + Overload(1); + Overload(1, 2); + Overload(1, 2, 3); + } +}; \ No newline at end of file From d7c89b5f954aa90d9a74f93d21cc19a1fa687c3f Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 11 Dec 2024 17:51:18 -0800 Subject: [PATCH 32/91] Temporary std::pair sometimes causes spurious temporary dtor calls (#1462) --- cppwinrt/code_writers.h | 9 ++++++--- strings/base_implements.h | 6 +++--- strings/base_windows.h | 17 +++++++++-------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 0ff1887d1..d84abeecf 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1137,7 +1137,8 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const [_winrt_casted_result, _winrt_cast_result_code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); + winrt::hresult _winrt_cast_result_code; + auto const _winrt_casted_result = impl::try_as_with_reason<%, D const*>(static_cast(this), _winrt_cast_result_code); check_hresult(_winrt_cast_result_code); auto const _winrt_abi_type = *(abi_t<%>**)&_winrt_casted_result; _winrt_abi_type->%(%); @@ -1156,7 +1157,8 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const [_winrt_casted_result, _winrt_cast_result_code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); + winrt::hresult _winrt_cast_result_code; + auto const _winrt_casted_result = impl::try_as_with_reason<%, D const*>(static_cast(this), _winrt_cast_result_code); check_hresult(_winrt_cast_result_code); auto const _winrt_abi_type = *(abi_t<%>**)&_winrt_casted_result; WINRT_VERIFY_(0, _winrt_abi_type->%(%)); @@ -1176,7 +1178,8 @@ namespace cppwinrt {% if constexpr (!std::is_same_v) { - auto const [_winrt_casted_result, _winrt_cast_result_code] = impl::try_as_with_reason<%, D const*>(static_cast(this)); + winrt::hresult _winrt_cast_result_code; + auto const _winrt_casted_result = impl::try_as_with_reason<%, D const*>(static_cast(this), _winrt_cast_result_code); check_hresult(_winrt_cast_result_code); auto const _winrt_abi_type = *(abi_t<%>**)&_winrt_casted_result; check_hresult(_winrt_abi_type->%(%)); diff --git a/strings/base_implements.h b/strings/base_implements.h index 0847f5019..b620c6a6a 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -794,7 +794,7 @@ namespace winrt::impl } template - friend auto winrt::impl::try_as_with_reason(From ptr) noexcept; + friend auto winrt::impl::try_as_with_reason(From ptr, hresult& code) noexcept; protected: static constexpr bool is_composing = true; @@ -802,9 +802,9 @@ namespace winrt::impl private: template - auto try_as_with_reason() const noexcept + auto try_as_with_reason(hresult& code) const noexcept { - return m_inner.try_as_with_reason(); + return m_inner.try_as_with_reason(code); } }; diff --git a/strings/base_windows.h b/strings/base_windows.h index a67ef0b20..bf28440ef 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -133,7 +133,7 @@ namespace winrt::impl } template , int> = 0> - std::pair, hresult> try_as_with_reason(From* ptr) noexcept + com_ref try_as_with_reason(From* ptr, hresult& code) noexcept { #ifdef WINRT_DIAGNOSTICS get_diagnostics_info().add_query(); @@ -141,18 +141,19 @@ namespace winrt::impl if (!ptr) { - return { nullptr, 0 }; + code = 0; + return nullptr; } void* result{}; - hresult code = ptr->QueryInterface(guid_of(), &result); - return { wrap_as_result(result), code }; + code = ptr->QueryInterface(guid_of(), &result); + return wrap_as_result(result); } template - auto try_as_with_reason(From ptr) noexcept + auto try_as_with_reason(From ptr, hresult& code) noexcept { - return ptr->template try_as_with_reason(); + return ptr->template try_as_with_reason(code); } } @@ -229,9 +230,9 @@ WINRT_EXPORT namespace winrt::Windows::Foundation } template - auto try_as_with_reason() const noexcept + auto try_as_with_reason(hresult& code) const noexcept { - return impl::try_as_with_reason(m_ptr); + return impl::try_as_with_reason(m_ptr, code); } template From fd0e95950414f5b530ecf55185b6eccc5ae35eb6 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Thu, 12 Dec 2024 11:06:42 -0800 Subject: [PATCH 33/91] Fix warnings in natvis project (#1463) --- natvis/cppwinrt_visualizer.cpp | 14 +++++++------- natvis/object_visualizer.cpp | 2 +- natvis/pch.h | 3 +++ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/natvis/cppwinrt_visualizer.cpp b/natvis/cppwinrt_visualizer.cpp index f6affd566..7aa845e53 100644 --- a/natvis/cppwinrt_visualizer.cpp +++ b/natvis/cppwinrt_visualizer.cpp @@ -12,7 +12,7 @@ using namespace winrt; using namespace winmd::reader; std::vector db_files; -std::unique_ptr db; +std::unique_ptr db_cache; void MetadataDiagnostic(DkmProcess* process, std::wstring const& status, std::filesystem::path const& path) { @@ -105,7 +105,7 @@ void LoadMetadata(DkmProcess* process, WCHAR const* processPath, std::string_vie if (std::find(db_files.begin(), db_files.end(), path_string) == db_files.end()) { - db->add_database(path_string, [](TypeDef const& type) { return type.Flags().WindowsRuntime(); }); + db_cache->add_database(path_string, [](TypeDef const& type) { return type.Flags().WindowsRuntime(); }); db_files.push_back(path_string); } } @@ -120,12 +120,12 @@ void LoadMetadata(DkmProcess* process, WCHAR const* processPath, std::string_vie TypeDef FindType(DkmProcess* process, std::string_view const& typeName) { - auto type = db->find(typeName); + auto type = db_cache->find(typeName); if (!type) { auto processPath = process->Path()->Value(); LoadMetadata(process, processPath, typeName); - type = db->find(typeName); + type = db_cache->find(typeName); if (!type) { NatvisDiagnostic(process, @@ -137,7 +137,7 @@ TypeDef FindType(DkmProcess* process, std::string_view const& typeName) TypeDef FindType(DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName) { - auto type = db->find(typeNamespace, typeName); + auto type = db_cache->find(typeNamespace, typeName); if (!type) { std::string fullName(typeNamespace); @@ -165,7 +165,7 @@ cppwinrt_visualizer::cppwinrt_visualizer() db_files.push_back(file.path().string()); } } - db.reset(new cache(db_files, [](TypeDef const& type) { return type.Flags().WindowsRuntime(); })); + db_cache.reset(new cache(db_files, [](TypeDef const& type) { return type.Flags().WindowsRuntime(); })); } catch (...) { @@ -188,7 +188,7 @@ cppwinrt_visualizer::~cppwinrt_visualizer() { ClearTypeResolver(); db_files.clear(); - db.reset(); + db_cache.reset(); } HRESULT cppwinrt_visualizer::EvaluateVisualizedExpression( diff --git a/natvis/object_visualizer.cpp b/natvis/object_visualizer.cpp index 5308c33fc..a0803871a 100644 --- a/natvis/object_visualizer.cpp +++ b/natvis/object_visualizer.cpp @@ -671,7 +671,7 @@ HRESULT object_visualizer::GetItems( auto pParent = pVisualizedExpression; auto childCount = std::min(m_propertyData.size() - StartIndex, (size_t)Count); - for(auto i = 0; i < childCount; ++i) + for(size_t i = 0; i < childCount; ++i) { auto& prop = m_propertyData[i + (size_t)StartIndex]; com_ptr pPropertyVisualized; diff --git a/natvis/pch.h b/natvis/pch.h index c687b1f09..824d3aac1 100644 --- a/natvis/pch.h +++ b/natvis/pch.h @@ -4,7 +4,10 @@ #define NOMINMAX #include +#pragma warning(push) +#pragma warning(disable : 4471) #include +#pragma warning(pop) #include #include #include "base_includes.h" From 7bc7df630747922202417f24bef615a250c21d2e Mon Sep 17 00:00:00 2001 From: David Lechner Date: Tue, 28 Jan 2025 17:22:44 -0600 Subject: [PATCH 34/91] Fix reading past end of array. (#1468) Fix a bug in the `NonDelegatingGetIids()` implementation that could cause reading past the end of the returned array. `std::copy()` returns a pointer to the next element in the array after the last element copied. The output argument `*array` was being assinged to this pointer after the first copy, causing it to no longer point to the beginning of the array. If the caller tries to access the full array after this, it will read past the end of the array and will miss the first elements of the array. To fix, introduce a new temporary `_array` variable to pass the result of the first copy as the starting point of the second copy. Also add a test that failed before the fix and passes after the fix. --- strings/base_implements.h | 4 ++-- test/old_tests/UnitTests/Composable.cpp | 18 +++++++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/strings/base_implements.h b/strings/base_implements.h index b620c6a6a..89b6c5790 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -1033,8 +1033,8 @@ namespace winrt::impl { return error_bad_alloc; } - *array = std::copy(local_iids.second, local_iids.second + local_count, *array); - std::copy(inner_iids.cbegin(), inner_iids.cend(), *array); + auto next = std::copy(local_iids.second, local_iids.second + local_count, *array); + std::copy(inner_iids.cbegin(), inner_iids.cend(), next); } else { diff --git a/test/old_tests/UnitTests/Composable.cpp b/test/old_tests/UnitTests/Composable.cpp index 3cbc283d6..080e3769c 100644 --- a/test/old_tests/UnitTests/Composable.cpp +++ b/test/old_tests/UnitTests/Composable.cpp @@ -167,4 +167,20 @@ TEST_CASE("Composable conversions") { TestCalls(*make_self()); TestCalls(*make_self()); -} \ No newline at end of file +} + +TEST_CASE("Composable get_interfaces") +{ + struct Foo : Composable::BaseT { + hstring ToString() const { return L"Foo"; } + }; + + auto obj = make(); + auto iids = winrt::get_interfaces(obj); + // BaseOverrides IID gets repeated twice. There are only 4 unique interfaces. + REQUIRE(iids.size() == 5); + REQUIRE(std::find(iids.begin(), iids.end(), guid_of()) != iids.end()); + REQUIRE(std::find(iids.begin(), iids.end(), guid_of()) != iids.end()); + REQUIRE(std::find(iids.begin(), iids.end(), guid_of()) != iids.end()); + REQUIRE(std::find(iids.begin(), iids.end(), guid_of()) != iids.end()); +} From f2a7ffb321c6c06b1e4cdfea076dfbf1c6365fe4 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Tue, 28 Jan 2025 17:04:26 -0800 Subject: [PATCH 35/91] Fix setting of IntDir MSBuild property (#1471) --- Directory.Build.Props | 1 + Directory.Build.Targets | 7 ------- 2 files changed, 1 insertion(+), 7 deletions(-) delete mode 100644 Directory.Build.Targets diff --git a/Directory.Build.Props b/Directory.Build.Props index cff3f7bda..0a8e5b37b 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -41,6 +41,7 @@ $(Platform) x86 $(SolutionDir)_build\$(CppWinRTPlatform)\$(Configuration)\ + $(SolutionDir)_build\$(CppWinRTPlatform)\$(Configuration)\temp\$(MSBuildProjectName)\ $(OutDir) $(SolutionDir)_build\x86\$(Configuration)\ diff --git a/Directory.Build.Targets b/Directory.Build.Targets deleted file mode 100644 index 98abcdd3f..000000000 --- a/Directory.Build.Targets +++ /dev/null @@ -1,7 +0,0 @@ - - - - $(OutDir)temp\$(ProjectName)\ - - - From e4c0b264c2dc2d31f5b2a16dcd868ab2710edcba Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 5 Feb 2025 12:47:58 -0800 Subject: [PATCH 36/91] Allow visualization of properties on generic types (#1472) --- natvis/cppwinrt_visualizer.cpp | 131 ++++++++- natvis/cppwinrt_visualizer.h | 2 +- natvis/cppwinrtvisualizer.vcxproj | 4 +- natvis/object_visualizer.cpp | 445 +++++++++++++++++++++++------- natvis/object_visualizer.h | 5 + natvis/packages.config | 2 +- natvis/pch.h | 10 +- natvis/type_resolver.cpp | 69 +++-- 8 files changed, 526 insertions(+), 142 deletions(-) diff --git a/natvis/cppwinrt_visualizer.cpp b/natvis/cppwinrt_visualizer.cpp index 7aa845e53..4b0a0c370 100644 --- a/natvis/cppwinrt_visualizer.cpp +++ b/natvis/cppwinrt_visualizer.cpp @@ -11,8 +11,39 @@ using namespace std::filesystem; using namespace winrt; using namespace winmd::reader; -std::vector db_files; -std::unique_ptr db_cache; +namespace +{ + std::vector db_files; + std::unique_ptr db_cache; + coded_index guid_TypeRef{}; +} + +coded_index FindGuidType() +{ + if (!guid_TypeRef) + { + // There is no definitive TypeDef for System.Guid. But there are a variety of TypeRefs scattered about + // This one should be relatively quick to find + auto pv = db_cache->find("Windows.Foundation", "IPropertyValue"); + for (auto&& method : pv.MethodList()) + { + if (method.Name() == "GetGuid") + { + auto const& sig = method.Signature(); + auto const& type = sig.ReturnType().Type().Type(); + XLANG_ASSERT(std::holds_alternative>(type)); + if (std::holds_alternative>(type)) + { + guid_TypeRef = std::get>(type); + XLANG_ASSERT(guid_TypeRef.type() == TypeDefOrRef::TypeRef); + XLANG_ASSERT(guid_TypeRef.TypeRef().TypeNamespace() == "System"); + XLANG_ASSERT(guid_TypeRef.TypeRef().TypeName() == "Guid"); + } + } + } + } + return guid_TypeRef; +} void MetadataDiagnostic(DkmProcess* process, std::wstring const& status, std::filesystem::path const& path) { @@ -118,8 +149,9 @@ void LoadMetadata(DkmProcess* process, WCHAR const* processPath, std::string_vie } } -TypeDef FindType(DkmProcess* process, std::string_view const& typeName) +TypeDef FindSimpleType(DkmProcess* process, std::string_view const& typeName) { + XLANG_ASSERT(typeName.find('<') == std::string_view::npos); auto type = db_cache->find(typeName); if (!type) { @@ -135,19 +167,104 @@ TypeDef FindType(DkmProcess* process, std::string_view const& typeName) return type; } -TypeDef FindType(DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName) +TypeDef FindSimpleType(DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName) { + XLANG_ASSERT(typeName.find('<') == std::string_view::npos); auto type = db_cache->find(typeNamespace, typeName); if (!type) { std::string fullName(typeNamespace); fullName.append("."); fullName.append(typeName); - FindType(process, fullName); + FindSimpleType(process, fullName); } return type; } +std::vector ParseTypeName(std::string_view name) +{ + DWORD count; + HSTRING* parts; + auto wide_name = winrt::to_hstring(name); + winrt::check_hresult(::RoParseTypeName(static_cast(get_abi(wide_name)), &count, &parts)); + + winrt::com_array wide_parts{ parts, count, winrt::take_ownership_from_abi }; + std::vector result; + for (auto&& part : wide_parts) + { + result.push_back(winrt::to_string(part)); + } + return result; +} + +template sent> +TypeSig ResolveGenericTypePart(DkmProcess* process, iter& it, sent const& end) +{ + constexpr std::pair elementNames[] = { + {"Boolean", ElementType::Boolean}, + {"Int8", ElementType::I1}, + {"Int16", ElementType::I2}, + {"Int32", ElementType::I4}, + {"Int64", ElementType::I8}, + {"UInt8", ElementType::U1}, + {"UInt16", ElementType::U2}, + {"UInt32", ElementType::U4}, + {"UInt64", ElementType::U8}, + {"Single", ElementType::R4}, + {"Double", ElementType::R8}, + {"String", ElementType::String}, + {"Char16", ElementType::Char}, + {"Object", ElementType::Object} + }; + std::string_view partName = *it; + auto basic_type_pos = std::find_if(std::begin(elementNames), std::end(elementNames), [&partName](auto&& elem) { return elem.first == partName; }); + if (basic_type_pos != std::end(elementNames)) + { + return TypeSig{ basic_type_pos->second }; + } + + if (partName == "Guid") + { + return TypeSig{ FindGuidType() }; + } + + TypeDef type = FindSimpleType(process, partName); + auto tickPos = partName.rfind('`'); + if (tickPos == partName.npos) + { + return TypeSig{ type.coded_index() }; + } + + int paramCount = 0; + std::from_chars(partName.data() + tickPos + 1, partName.data() + partName.size(), paramCount); + std::vector genericArgs; + for (int i = 0; i < paramCount; ++i) + { + genericArgs.push_back(ResolveGenericTypePart(process, ++it, end)); + } + return TypeSig{ GenericTypeInstSig{ type.coded_index(), std::move(genericArgs) } }; +} + +TypeSig ResolveGenericType(DkmProcess* process, std::string_view genericName) +{ + auto parts = ParseTypeName(genericName); + auto begin = parts.begin(); + return ResolveGenericTypePart(process, begin, parts.end()); +} + +TypeSig FindType(DkmProcess* process, std::string_view const& typeName) +{ + auto paramIndex = typeName.find('<'); + if (paramIndex == std::string_view::npos) + { + return TypeSig{ FindSimpleType(process, typeName).coded_index() }; + } + else + { + return ResolveGenericType(process, typeName); + } +} + cppwinrt_visualizer::cppwinrt_visualizer() { try @@ -187,13 +304,14 @@ cppwinrt_visualizer::cppwinrt_visualizer() cppwinrt_visualizer::~cppwinrt_visualizer() { ClearTypeResolver(); + guid_TypeRef = {}; db_files.clear(); db_cache.reset(); } HRESULT cppwinrt_visualizer::EvaluateVisualizedExpression( _In_ DkmVisualizedExpression* pVisualizedExpression, - _Deref_out_ DkmEvaluationResult** ppResultObject + _COM_Outptr_result_maybenull_ DkmEvaluationResult** ppResultObject ) { try @@ -233,6 +351,7 @@ HRESULT cppwinrt_visualizer::EvaluateVisualizedExpression( // unrecognized type NatvisDiagnostic(pVisualizedExpression, std::wstring(L"Unrecognized type: ") + (LPWSTR)bstrTypeName, NatvisDiagnosticLevel::Error); + *ppResultObject = nullptr; return S_OK; } diff --git a/natvis/cppwinrt_visualizer.h b/natvis/cppwinrt_visualizer.h index 5f12ec39a..924dc3cbc 100644 --- a/natvis/cppwinrt_visualizer.h +++ b/natvis/cppwinrt_visualizer.h @@ -8,7 +8,7 @@ struct cppwinrt_visualizer : winrt::implements - + Debug @@ -321,6 +321,6 @@ - + \ No newline at end of file diff --git a/natvis/object_visualizer.cpp b/natvis/object_visualizer.cpp index a0803871a..2e0eb3971 100644 --- a/natvis/object_visualizer.cpp +++ b/natvis/object_visualizer.cpp @@ -110,7 +110,7 @@ static HRESULT EvaluatePropertyExpression( wchar_t wszEvalText[500]; std::wstring propCast; PCWSTR propField; - if (prop.category < PropertyCategory::Value) + if (IsBuiltIn(prop.category)) { propField = g_categoryData[(int)prop.category].propField; } @@ -278,7 +278,7 @@ static HRESULT CreateChildVisualizedExpression( IF_FAIL_RET(DkmString::Create(prop.displayName.c_str(), pDisplayName.put())); PCWSTR displayType; - if (prop.category < PropertyCategory::Value) + if (IsBuiltIn(prop.category)) { displayType = g_categoryData[(int)prop.category].displayType; } @@ -340,19 +340,291 @@ static HRESULT CreateChildVisualizedExpression( return S_OK; } -struct property_type +std::optional GetPropertyCategory( + Microsoft::VisualStudio::Debugger::DkmProcess* process, + TypeSig const& owningType, + TypeSig const& propertyType +) +{ + std::optional propCategory; + if (auto pElementType = std::get_if(&propertyType.Type())) + { + if ((ElementType::Boolean <= *pElementType) && (*pElementType <= ElementType::String)) + { + propCategory = (PropertyCategory)(static_cast::type>(*pElementType) - + static_cast::type>(ElementType::Boolean)); + } + else if (*pElementType == ElementType::Object) + { + // result = PropertyCategory::Class; + } + } + else if (auto pIndex = std::get_if>(&propertyType.Type())) + { + auto type = ResolveType(process, *pIndex); + if (type) + { + if (get_category(type) == category::class_type || get_category(type) == category::interface_type) + { + propCategory = PropertyCategory::Class; + } + else + { + propCategory = PropertyCategory::Value; + } + } + else if (pIndex->type() == TypeDefOrRef::TypeRef) + { + auto typeRef = pIndex->TypeRef(); + if (typeRef.TypeNamespace() == "System" && typeRef.TypeName() == "Guid") + { + propCategory = PropertyCategory::Guid; + } + } + } + else if (auto pGenericInst = std::get_if(&propertyType.Type())) + { + XLANG_ASSERT(get_category(ResolveType(process, pGenericInst->GenericType())) == category::interface_type); + propCategory = PropertyCategory::Class; + } + else if (auto pGenericIndex = std::get_if(&propertyType.Type())) + { + if (auto pOwner = std::get_if(&owningType.Type())) + { + auto const& index = pGenericIndex->index; + auto const& genericArgs = pOwner->GenericArgs(); + propCategory = GetPropertyCategory(process, owningType, genericArgs.first[index]); + } + else + { + NatvisDiagnostic(process, L"Can't resolve GenericTypeIndex property on non-generic Type", NatvisDiagnosticLevel::Warning); + } + } + else + { + NatvisDiagnostic(process, L"Unsupported TypeSig encountered", NatvisDiagnosticLevel::Warning); + } + return propCategory; +} + +struct writer { - MethodDef get; - MethodDef set; + std::vector generic_params; + + std::string result; + + void write(char c) + { + result.push_back(c); + } + + void write(std::string_view const& str) + { + for (auto c : str) + { + if (c == '.') + { + write(':'); + write(':'); + } + else if (c != '`') + { + write(c); + } + else + { + return; + } + } + } + + void write(ElementType type) + { + switch (type) + { + case ElementType::Boolean: + write("bool"); + break; + case ElementType::Char: + write("wchar_t"); + break; + case ElementType::I1: + write("int8_t"); + break; + case ElementType::U1: + write("uint8_t"); + break; + case ElementType::I2: + write("int16_t"); + break; + case ElementType::U2: + write("uint16_t"); + break; + case ElementType::I4: + write("int32_t"); + break; + case ElementType::U4: + write("uint32_t"); + break; + case ElementType::I8: + write("int64_t"); + break; + case ElementType::U8: + write("uint64_t"); + break; + case ElementType::R4: + write("float"); + break; + case ElementType::R8: + write("double"); + break; + case ElementType::String: + write("winrt::hstring"); + break; + case ElementType::Object: + write("winrt::Windows::Foundation::IInspectable"); + break; + default: + XLANG_ASSERT(false); + break; + }; + } + + void write_namespace_and_type(std::string_view ns, std::string_view name) + { + if (ns == "System") + { + if (name == "Guid") + { + ns = ""; + name = "guid"; + } + } + else if (ns == "Windows.Foundation") + { + if (name == "EventRegistrationToken") + { + ns = ""; + name = "event_token"; + } + else if (name == "HResult") + { + ns = ""; + name = "hresult"; + } + } + else if (ns == "Windows.Foundation.Numerics") + { + if (name == "Matrix3x2") { name = "float3x2"; } + else if (name == "Matrix4x4") { name = "float4x4"; } + else if (name == "Plane") { name = "plane"; } + else if (name == "Quaternion") { name = "quarternion"; } + else if (name == "Vector2") { name = "float2"; } + else if (name == "Vector3") { name = "float3"; } + else if (name == "Vector4") { name = "float4"; } + } + + write("winrt::"); + if (!ns.empty()) + { + write(ns); + write("::"); + } + write(name); + } + + void write(TypeRef const& type) + { + write_namespace_and_type(type.TypeNamespace(), type.TypeName()); + } + + void write(TypeDef const& type) + { + write_namespace_and_type(type.TypeNamespace(), type.TypeName()); + } + + void write(TypeSpec const& type) + { + write(type.Signature().GenericTypeInst()); + } + + void write(coded_index type) + { + switch (type.type()) + { + case TypeDefOrRef::TypeDef: + write(type.TypeDef()); + break; + case TypeDefOrRef::TypeRef: + write(type.TypeRef()); + break; + case TypeDefOrRef::TypeSpec: + write(type.TypeSpec()); + break; + } + } + + void write(GenericTypeInstSig const& type) + { + write(type.GenericType()); + bool first = true; + write("<"); + for (auto&& elem : type.GenericArgs()) + { + if (first) + { + first = false; + } + else + { + write(", "); + } + write(elem); + } + write(">"); + } + + void write(GenericTypeIndex const& var) + { + write(generic_params[var.index]); + } + + void write(GenericMethodTypeIndex const&) + { + // Nothing + } + + void write(TypeSig const& type) + { + std::visit([this](auto&& arg) + { + write(arg); + }, type.Type()); + } }; +std::wstring string_to_wstring(std::string_view const& str) +{ + int const size = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.size()), nullptr, 0); + if (size == 0) + { + return {}; + } + + std::wstring result(size, L'?'); + auto size_result = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.size()), result.data(), size); + XLANG_ASSERT(size == size_result); + return result; +} + void GetInterfaceData( Microsoft::VisualStudio::Debugger::DkmProcess* process, - coded_index index, + TypeSig const& typeSig, _Inout_ std::vector& propertyData, _Out_ bool& isStringable ){ - auto [type, propIid] = ResolveTypeInterface(process, index); + auto [type, propIid] = ResolveTypeInterface(process, typeSig); + if (!type) { return; @@ -375,106 +647,34 @@ void GetInterfaceData( continue; } - std::optional propCategory; - std::wstring propAbiType; - std::wstring propDisplayType; - - auto retType = method.Signature().ReturnType(); - std::visit(overloaded{ - [&](ElementType type) - { - if ((ElementType::Boolean <= type) && (type <= ElementType::String)) - { - propCategory = (PropertyCategory)(static_cast::type>(type) - - static_cast::type>(ElementType::Boolean)); - } - else if (type == ElementType::Object) - { - //propDisplayType = L"winrt::Windows::Foundation::IInspectable"; - //propCategory = PropertyCategory::Class; - //propAbiType = L"winrt::impl::inspectable_abi*"; - } - }, - [&](coded_index const& index) + std::optional propCategory = GetPropertyCategory(process, typeSig, method.Signature().ReturnType().Type()); + if (propCategory) + { + std::wstring propAbiType; + std::wstring propDisplayType; + if (!IsBuiltIn(*propCategory)) { - auto type = ResolveType(process, index); - if (!type) + writer writer; + if (auto pGenericTypeInst = std::get_if(&typeSig.Type())) { - return; + auto const& genericArgs = pGenericTypeInst->GenericArgs(); + writer.generic_params.assign(genericArgs.first, genericArgs.second); } - - auto typeName = type.TypeName(); - if (typeName == "GUID"sv) + writer.write(method.Signature().ReturnType().Type()); + propDisplayType = string_to_wstring(writer.result); + + if (*propCategory == PropertyCategory::Class) { - propCategory = PropertyCategory::Guid; + propAbiType = L"winrt::impl::inspectable_abi*"; } else { - auto ns = std::string(type.TypeNamespace()); - auto name = std::string(type.TypeName()); - - // Map numeric type names - if (ns == "Windows.Foundation.Numerics") - { - if (name == "Matrix3x2") { name = "float3x2"; } - else if (name == "Matrix4x4") { name = "float4x4"; } - else if (name == "Plane") { name = "plane"; } - else if (name == "Quaternion") { name = "quaternion"; } - else if (name == "Vector2") { name = "float2"; } - else if (name == "Vector3") { name = "float3"; } - else if (name == "Vector4") { name = "float4"; } - } - - // Types come back from winmd files with '.', need to be '::' - // Ex. Windows.Foundation.Uri needs to be Windows::Foundation::Uri - auto fullTypeName = ns + "::" + name; - wchar_t cppTypename[500]; - size_t i, j; - for (i = 0, j = 0; i < (fullTypeName.length() + 1); i++, j++) - { - if (fullTypeName[i] == L'.') - { - cppTypename[j++] = L':'; - cppTypename[j] = L':'; - } - else - { - cppTypename[j] = fullTypeName[i]; - } - } - - propDisplayType = std::wstring(L"winrt::") + cppTypename; - if(get_category(type) == category::class_type) - { - propCategory = PropertyCategory::Class; - propAbiType = L"winrt::impl::inspectable_abi*"; - } - else - { - propCategory = PropertyCategory::Value; - propAbiType = propDisplayType; - } + propAbiType = propDisplayType; } - }, - [&](GenericTypeIndex /*var*/) - { - NatvisDiagnostic(process, L"Generics not yet supported", NatvisDiagnosticLevel::Warning); - }, - [&](GenericMethodTypeIndex /*var*/) - { - NatvisDiagnostic(process, L"Generics not yet supported", NatvisDiagnosticLevel::Warning); - }, - [&](GenericTypeInstSig const& /*type*/) - { - NatvisDiagnostic(process, L"Generics not yet supported", NatvisDiagnosticLevel::Warning); } - }, retType.Type().Type()); - if (propCategory) - { auto propName = method.Name().substr(4); - std::wstring propDisplayName(propName.cbegin(), propName.cend()); - propertyData.push_back({ propIid, propIndex, *propCategory, propAbiType, propDisplayType, propDisplayName }); + propertyData.emplace_back(propIid, propIndex, *propCategory, std::move(propAbiType), std::move(propDisplayType), string_to_wstring(propName)); } } } @@ -493,10 +693,55 @@ void object_visualizer::GetPropertyData() GetTypeProperties(process, std::string_view{ rc.data() + 2, rc.length() - 3 }); } +GenericTypeInstSig ReplaceGenericIndices(GenericTypeInstSig const& sig, std::vector const& genericArgs) +{ + std::vector replacementArgs; + for (auto&& arg : sig.GenericArgs()) + { + if (auto pGenericSig = std::get_if(&arg.Type())) + { + replacementArgs.emplace_back(ReplaceGenericIndices(*pGenericSig, genericArgs)); + } + else if (auto pGenericIndex = std::get_if(&arg.Type())) + { + replacementArgs.push_back(genericArgs[pGenericIndex->index]); + } + else + { + replacementArgs.push_back(arg); + } + } + return GenericTypeInstSig{ sig.GenericType(), std::move(replacementArgs) }; +} + +TypeSig ExpandInterfaceImplForType(coded_index impl, TypeSig const& type) +{ + if (auto pGenericInst = std::get_if(&type.Type())) + { + if (impl.type() == TypeDefOrRef::TypeSpec) + { + auto const& genericArgs = pGenericInst->GenericArgs(); + auto newSig = ReplaceGenericIndices(impl.TypeSpec().Signature().GenericTypeInst(), std::vector{ genericArgs.first, genericArgs.second }); + return TypeSig{ newSig }; + } + } + return TypeSig{ impl }; +} + void object_visualizer::GetTypeProperties(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& type_name) { // TODO: add support for direct generic interface implementations (e.g., key_value_pair) - auto type = FindType(process, type_name); + auto typeSig = FindType(process, type_name); + TypeDef type{}; + if (auto const* index = std::get_if>(&typeSig.Type())) + { + type = ResolveType(process, *index); + } + else if (auto const* genericInst = std::get_if(&typeSig.Type())) + { + type = ResolveType(process, genericInst->GenericType()); + } + if (!type) { return; @@ -516,7 +761,7 @@ void object_visualizer::GetTypeProperties(Microsoft::VisualStudio::Debugger::Dkm auto impls = type.InterfaceImpl(); for (auto&& impl : impls) { - GetInterfaceData(process, impl.Interface(), m_propertyData, m_isStringable); + GetInterfaceData(process, ExpandInterfaceImplForType(impl.Interface(), typeSig), m_propertyData, m_isStringable); } } else if (get_category(type) == category::interface_type) @@ -524,9 +769,9 @@ void object_visualizer::GetTypeProperties(Microsoft::VisualStudio::Debugger::Dkm auto impls = type.InterfaceImpl(); for (auto&& impl : impls) { - GetInterfaceData(process, impl.Interface(), m_propertyData, m_isStringable); + GetInterfaceData(process, ExpandInterfaceImplForType(impl.Interface(), typeSig), m_propertyData, m_isStringable); } - GetInterfaceData(process, type.coded_index(), m_propertyData, m_isStringable); + GetInterfaceData(process, typeSig, m_propertyData, m_isStringable); } } diff --git a/natvis/object_visualizer.h b/natvis/object_visualizer.h index ad83d79d7..6d1a0f00c 100644 --- a/natvis/object_visualizer.h +++ b/natvis/object_visualizer.h @@ -20,6 +20,11 @@ enum class PropertyCategory Class, }; +inline constexpr bool IsBuiltIn(PropertyCategory value) noexcept +{ + return PropertyCategory::Bool <= value && value < PropertyCategory::Value; +} + enum class ObjectType { Abi, diff --git a/natvis/packages.config b/natvis/packages.config index 356e82f7f..7907cba44 100644 --- a/natvis/packages.config +++ b/natvis/packages.config @@ -2,5 +2,5 @@ - + \ No newline at end of file diff --git a/natvis/pch.h b/natvis/pch.h index 824d3aac1..95e561971 100644 --- a/natvis/pch.h +++ b/natvis/pch.h @@ -43,6 +43,7 @@ #include #include #include +#include #ifndef IF_FAIL_RET #define IF_FAIL_RET(expr) { HRESULT _hr = (expr); if(FAILED(_hr)) { return(_hr); } } @@ -91,8 +92,9 @@ inline bool starts_with(std::string_view const& value, std::string_view const& m return 0 == value.compare(0, match.size(), match); } -winmd::reader::TypeDef FindType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeName); -winmd::reader::TypeDef FindType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName); +winmd::reader::TypeDef FindSimpleType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeName); +winmd::reader::TypeDef FindSimpleType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeNamespace, std::string_view const& typeName); +winmd::reader::TypeSig FindType(Microsoft::VisualStudio::Debugger::DkmProcess* process, std::string_view const& typeName); inline winmd::reader::TypeDef ResolveType(Microsoft::VisualStudio::Debugger::DkmProcess* process, winmd::reader::coded_index index) noexcept { @@ -101,13 +103,13 @@ inline winmd::reader::TypeDef ResolveType(Microsoft::VisualStudio::Debugger::Dkm case winmd::reader::TypeDefOrRef::TypeDef: return index.TypeDef(); case winmd::reader::TypeDefOrRef::TypeRef: - return FindType(process, index.TypeRef().TypeNamespace(), index.TypeRef().TypeName()); + return FindSimpleType(process, index.TypeRef().TypeNamespace(), index.TypeRef().TypeName()); default: //case TypeDefOrRef::TypeSpec: return winmd::reader::find_required(index.TypeSpec().Signature(). GenericTypeInst().GenericType().TypeRef()); } } -std::pair ResolveTypeInterface(Microsoft::VisualStudio::Debugger::DkmProcess* process, winmd::reader::coded_index index); +std::pair ResolveTypeInterface(Microsoft::VisualStudio::Debugger::DkmProcess* process, winmd::reader::TypeSig const& typeSig); void ClearTypeResolver(); diff --git a/natvis/type_resolver.cpp b/natvis/type_resolver.cpp index 17999997f..de8af71f4 100644 --- a/natvis/type_resolver.cpp +++ b/natvis/type_resolver.cpp @@ -98,6 +98,18 @@ struct signature_generator } } + static std::string get_signature(GenericTypeInstSig const& type) + { + std::string sig = "pinterface(" + get_guid_signature(type.GenericType()); + for (auto&& arg : type.GenericArgs()) + { + sig += ";"; + sig += get_signature(arg); + } + sig += ")"; + return sig; + } + private: static std::string get_class_signature(TypeDef const& type) { @@ -152,20 +164,8 @@ struct signature_generator case TypeDefOrRef::TypeRef: return get_guid_signature(find_required(type.TypeRef())); default: //case TypeDefOrRef::TypeSpec: - return get_guid_signature(type.TypeSpec().Signature().GenericTypeInst().GenericType()); - } - } - - static std::string get_signature(GenericTypeInstSig const& type) - { - std::string sig = "pinterface(" + get_guid_signature(type.GenericType()); - for (auto&& arg : type.GenericArgs()) - { - sig += ";"; - sig += get_signature(arg); + return get_signature(type.TypeSpec().Signature().GenericTypeInst()); } - sig += ")"; - return sig; } static std::string get_signature(TypeSig::value_type const& type) @@ -266,7 +266,7 @@ static auto calculate_sha1(std::vector const& input) return get_result(intermediate_hash); } -static guid generate_guid(coded_index const& type) +static guid generate_guid(GenericTypeInstSig const& type) { constexpr guid namespace_guid = { 0xd57af411, 0x737b, 0xc042,{ 0xab, 0xae, 0x87, 0x8b, 0x1e, 0x16, 0xad, 0xee } }; constexpr auto namespace_bytes = winrt::impl::to_array(namespace_guid); @@ -278,25 +278,38 @@ static guid generate_guid(coded_index const& type) return set_named_guid_fields(endian_swap(to_guid(calculate_sha1(buffer)))); } -std::pair ResolveTypeInterface(DkmProcess* process, coded_index index) +std::pair ResolveTypeInterface(DkmProcess* process, winmd::reader::TypeSig const& typeSig) { - if (auto found = _cache.find(index); found != _cache.end()) + coded_index index; + if (auto ptrIndex = std::get_if>(&typeSig.Type())) { - return found->second; - } + index = *ptrIndex; + // TODO: Cache on the whole TypeSig, not just the generic index + if (auto found = _cache.find(index); found != _cache.end()) + { + return found->second; + } - TypeDef type = ResolveType(process, index); - if (!type) - { - return {}; - } + TypeDef type = ResolveType(process, index); + if (!type) + { + return {}; + } - auto guid = index.type() == TypeDefOrRef::TypeSpec ? - format_guid(generate_guid(index)) : format_guid(get_guid(type)); + auto guid = index.type() == TypeDefOrRef::TypeSpec ? + format_guid(generate_guid(index.TypeSpec().Signature().GenericTypeInst())) : format_guid(get_guid(type)); - auto type_guid = std::pair{ type, guid }; - _cache[index] = type_guid; - return type_guid; + auto type_guid = std::pair{ type, guid }; + _cache[index] = type_guid; + return type_guid; + } + else if (auto* ptrGeneric = std::get_if(&typeSig.Type())) + { + index = ptrGeneric->GenericType(); + auto guid = format_guid(generate_guid(*ptrGeneric)); + return { ResolveType(process, index), guid }; + } + return {}; }; void ClearTypeResolver() From 153e838a32c8bf5dfe87fbb908942387e9ad0233 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 5 Feb 2025 21:04:36 -0800 Subject: [PATCH 37/91] Fix various build warnings (#1473) --- cppwinrt/component_writers.h | 3 +++ prebuild/prebuild.vcxproj | 3 +++ strings/base_composable.h | 7 +++++++ strings/base_implements.h | 7 +++++++ test/old_tests/Component/Component.idl | 4 ++++ test/test/fast_iterator.cpp | 2 +- test/test_component/OverloadClass.cpp | 6 +++--- test/test_component_base/HierarchyB.cpp | 2 ++ 8 files changed, 30 insertions(+), 4 deletions(-) diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index 4a2cce556..c52f49a13 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -175,6 +175,9 @@ void* __stdcall %_get_activation_factory([[maybe_unused]] std::wstring_view cons int32_t __stdcall WINRT_CanUnloadNow() noexcept { #ifdef _WRL_MODULE_H_ +#ifdef _MSC_VER +#pragma warning(suppress: 4324) // structure was padded due to alignment specifier +#endif if (!::Microsoft::WRL::Module<::Microsoft::WRL::InProc>::GetModule().Terminate()) { return 1; diff --git a/prebuild/prebuild.vcxproj b/prebuild/prebuild.vcxproj index e5fa52565..6e0bc4b71 100644 --- a/prebuild/prebuild.vcxproj +++ b/prebuild/prebuild.vcxproj @@ -120,6 +120,7 @@ true ..\cppwinrt MultiThreaded + Guard Console @@ -134,6 +135,7 @@ true ..\cppwinrt MultiThreaded + Guard Console @@ -148,6 +150,7 @@ true ..\cppwinrt MultiThreaded + Guard Console diff --git a/strings/base_composable.h b/strings/base_composable.h index 7f675c970..e606d1292 100644 --- a/strings/base_composable.h +++ b/strings/base_composable.h @@ -4,6 +4,10 @@ namespace winrt::impl template struct composable_factory { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4702) // Compiler bug causing spurious "unreachable code" warnings +#endif template static I CreateInstance(const Windows::Foundation::IInspectable& outer, Windows::Foundation::IInspectable& inner, Args&&... args) { @@ -11,6 +15,9 @@ namespace winrt::impl inner = CreateInstanceImpl(outer, std::forward(args)...); return inner.as(); } +#ifdef _MSC_VER +#pragma warning(pop) +#endif private: template diff --git a/strings/base_implements.h b/strings/base_implements.h index 89b6c5790..b943c1d96 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -1390,6 +1390,10 @@ namespace winrt::impl WINRT_EXPORT namespace winrt { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4702) // Compiler bug causing spurious "unreachable code" warnings +#endif template auto make(Args&&... args) { @@ -1443,6 +1447,9 @@ WINRT_EXPORT namespace winrt return { impl::create_and_initialize(std::forward(args)...), take_ownership_from_abi }; } } +#ifdef _MSC_VER +#pragma warning(pop) +#endif template inline void clear_factory_static_lifetime() diff --git a/test/old_tests/Component/Component.idl b/test/old_tests/Component/Component.idl index 3c306ad69..ad51b5303 100644 --- a/test/old_tests/Component/Component.idl +++ b/test/old_tests/Component/Component.idl @@ -243,6 +243,8 @@ namespace Component HRESULT Create([in] Windows.Foundation.Collections.IVectorView* _in, [out, retval] FastInputVector** _out); }; + midl_pragma warning(disable: 4066) // A member name has been qualified with an interface name because name collisions occurred across interface members on a runtime class. + [version(1.0), activatable(IFastInputVectorFactory, 1.0)] runtimeclass FastInputVector { @@ -271,6 +273,8 @@ namespace Component interface Windows.Foundation.Collections.IMapView; }; + midl_pragma warning(default: 4066) + // // Boxing support for enums and their underlying types. // diff --git a/test/test/fast_iterator.cpp b/test/test/fast_iterator.cpp index 71ed6a918..f9e02dcec 100644 --- a/test/test/fast_iterator.cpp +++ b/test/test/fast_iterator.cpp @@ -48,7 +48,7 @@ TEST_CASE("fast_iterator") REQUIRE(2 - (vbegin + 4) > vbegin); REQUIRE(vbegin < vbegin + 2); REQUIRE(vbegin + 2 - 2 == vbegin); - REQUIRE(end(v) - begin(v) == v.Size()); + REQUIRE(static_cast(end(v) - begin(v)) == v.Size()); REQUIRE((begin(v) + 3)[-1] == 4); } { diff --git a/test/test_component/OverloadClass.cpp b/test/test_component/OverloadClass.cpp index d89f19ea5..0f78c5a1c 100644 --- a/test/test_component/OverloadClass.cpp +++ b/test/test_component/OverloadClass.cpp @@ -8,15 +8,15 @@ namespace winrt::test_component::implementation { throw hresult_not_implemented(); } - void OverloadClass::Overload(int a) + void OverloadClass::Overload(int /*a*/) { throw hresult_not_implemented(); } - void OverloadClass::Overload(int a, int b) + void OverloadClass::Overload(int /*a*/, int /*b*/) { throw hresult_not_implemented(); } - void OverloadClass::Overload(int a, int b, int c) + void OverloadClass::Overload(int /*a*/, int /*b*/, int /*c*/) { throw hresult_not_implemented(); } diff --git a/test/test_component_base/HierarchyB.cpp b/test/test_component_base/HierarchyB.cpp index 34c73104f..30b9f09ff 100644 --- a/test/test_component_base/HierarchyB.cpp +++ b/test/test_component_base/HierarchyB.cpp @@ -1,6 +1,8 @@ #include "pch.h" #include "HierarchyB.h" +#pragma warning(disable: 4702) + namespace winrt::test_component_base::implementation { HierarchyB::HierarchyB(hstring const& name) From 4bc0f82975e794cfc73306c0a023a77132324351 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Fri, 14 Feb 2025 16:16:40 -0800 Subject: [PATCH 38/91] Configure guardian, SDL, TSA, and CodeQL in Official Builds (#1474) --- .config/tsaoptions.json | 8 ++++++++ .gdn/.gdnsettings | 7 +++++++ .gdn/.gitignore | 11 +++++++++++ .pipelines/OneBranch.Official.yml | 8 +++++++- 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 .config/tsaoptions.json create mode 100644 .gdn/.gdnsettings create mode 100644 .gdn/.gitignore diff --git a/.config/tsaoptions.json b/.config/tsaoptions.json new file mode 100644 index 000000000..38fe35171 --- /dev/null +++ b/.config/tsaoptions.json @@ -0,0 +1,8 @@ +{ + "instanceUrl": "https://microsoft.visualstudio.com", + "projectName": "os", + "areaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\AmUse- App Metadata and User Setup Experience\\Projections\\Cppwinrt", + "notificationAliases": [ "cpp4uwpt@microsoft.com" ], + "ignoreBranchName": true, + "codebaseName": "cppwinrt" +} diff --git a/.gdn/.gdnsettings b/.gdn/.gdnsettings new file mode 100644 index 000000000..156408362 --- /dev/null +++ b/.gdn/.gdnsettings @@ -0,0 +1,7 @@ +{ + "files": { }, + "folders": { }, + "overwriteLogs": true, + "telemetryFlushTimeout": 10, + "variables": { } +} \ No newline at end of file diff --git a/.gdn/.gitignore b/.gdn/.gitignore new file mode 100644 index 000000000..decb1055f --- /dev/null +++ b/.gdn/.gitignore @@ -0,0 +1,11 @@ +## Ignore Guardian internal files +.r/ +rc/ +rs/ +i/ +p/ +c/ +o/ + +## Ignore Guardian Local settings +LocalSettings.gdn.json \ No newline at end of file diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 91e686622..fb6d68148 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -32,8 +32,14 @@ extends: enabled: false globalSdl: + asyncSdl: + enabled: true tsa: - enabled: false + enabled: true + codeql: + compiled: + enabled: true + tsaEnabled: true stages: - stage: build From 76eb09c9a1a75e89ef8f922f92d0794fffa48ccb Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Thu, 20 Feb 2025 10:49:19 -0800 Subject: [PATCH 39/91] Clean up more warnings and Component Governance (#1475) * Fix a couple more build warnings * Upgrade System.Text.Json to 6.0.10 * Better fix for unused size_result * Disable warning 4324 for all of wrl.h --- cppwinrt/component_writers.h | 1 + natvis/object_visualizer.cpp | 2 +- test/old_tests/Component/pch.h | 3 +++ vsix/Dev16/vsix.Dev16.csproj | 1 + vsix/Dev17/vsix.Dev17.csproj | 3 +++ 5 files changed, 9 insertions(+), 1 deletion(-) diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index c52f49a13..6865d49ef 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -198,6 +198,7 @@ int32_t __stdcall WINRT_GetActivationFactory(void* classId, void** factory) noex } #ifdef _WRL_MODULE_H_ +#pragma warning(suppress: 4324) // structure was padded due to alignment specifier return ::Microsoft::WRL::Module<::Microsoft::WRL::InProc>::GetModule().GetActivationFactory(static_cast(classId), reinterpret_cast<::IActivationFactory**>(factory)); #else return winrt::hresult_class_not_available(name).to_abi(); diff --git a/natvis/object_visualizer.cpp b/natvis/object_visualizer.cpp index 2e0eb3971..d953a1c03 100644 --- a/natvis/object_visualizer.cpp +++ b/natvis/object_visualizer.cpp @@ -612,7 +612,7 @@ std::wstring string_to_wstring(std::string_view const& str) } std::wstring result(size, L'?'); - auto size_result = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.size()), result.data(), size); + [[maybe_unused]] auto size_result = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.size()), result.data(), size); XLANG_ASSERT(size == size_result); return result; } diff --git a/test/old_tests/Component/pch.h b/test/old_tests/Component/pch.h index 5d84eecb6..b73230946 100644 --- a/test/old_tests/Component/pch.h +++ b/test/old_tests/Component/pch.h @@ -8,4 +8,7 @@ #include "winrt/Composable.h" // This is used to validate WRL interop support. +#pragma warning(push) +#pragma warning(disable: 4324) // structure was padded due to alignment specifier #include +#pragma warning(pop) \ No newline at end of file diff --git a/vsix/Dev16/vsix.Dev16.csproj b/vsix/Dev16/vsix.Dev16.csproj index 1e89b390b..dfb870ee1 100644 --- a/vsix/Dev16/vsix.Dev16.csproj +++ b/vsix/Dev16/vsix.Dev16.csproj @@ -93,6 +93,7 @@ all + diff --git a/vsix/Dev17/vsix.Dev17.csproj b/vsix/Dev17/vsix.Dev17.csproj index 3ef30ce63..be0cf3d17 100644 --- a/vsix/Dev17/vsix.Dev17.csproj +++ b/vsix/Dev17/vsix.Dev17.csproj @@ -168,6 +168,9 @@ + + + From f89f47fa9754f31436f401c6617d9c670b063ca7 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Fri, 28 Feb 2025 16:19:34 -0800 Subject: [PATCH 40/91] Stop manually downloading hardcoded version of llvm/clang. (#1478) * Stop manually downloading different version of llvm. Just use the one included in Visual Studio * Replace "custom llvm" msbuild props with PlatformToolset=ClangCl * Also disable the custom llvm install for test runs * Overriding ExecutablePath was causing clang-cl problems --- .github/workflows/ci.yml | 14 ++------------ test/old_tests/Component/Component.vcxproj | 6 ------ test/old_tests/Composable/Composable.vcxproj | 6 ------ test/test_component/test_component.vcxproj | 6 ------ .../test_component_base.vcxproj | 6 ------ .../test_component_derived.vcxproj | 6 ------ .../test_component_fast.vcxproj | 6 ------ .../test_component_folders.vcxproj | 6 ------ .../test_component_no_pch.vcxproj | 6 ------ 9 files changed, 2 insertions(+), 60 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7f99be8fb..8544bcf77 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,11 +25,6 @@ jobs: steps: - uses: actions/checkout@v4 - - id: setup-llvm - name: Set up LLVM (MSVC) - uses: ./.github/actions/setup-llvm-msvc - if: matrix.compiler == 'clang-cl' - - name: Download nuget run: | mkdir ".\.nuget" @@ -49,7 +44,7 @@ jobs: $target_version = "1.2.3.4" $props = "Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" if ("${{ matrix.compiler }}" -eq "clang-cl") { - $props += ",Clang=1,PlatformToolset=LLVM_v143,LLVMInstallDir=${{ steps.setup-llvm.outputs.llvm-path }}" + $props += ",Clang=1,PlatformToolset=ClangCl" } Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:$props" @@ -109,11 +104,6 @@ jobs: steps: - uses: actions/checkout@v4 - - id: setup-llvm - name: Set up LLVM (MSVC) - uses: ./.github/actions/setup-llvm-msvc - if: matrix.compiler == 'clang-cl' - - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' uses: actions/download-artifact@v4 @@ -147,7 +137,7 @@ jobs: $target_version = "1.2.3.4" $props = "Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" if ("${{ matrix.compiler }}" -eq "clang-cl") { - $props += ",Clang=1,PlatformToolset=LLVM_v143,LLVMInstallDir=${{ steps.setup-llvm.outputs.llvm-path }}" + $props += ",Clang=1,PlatformToolset=ClangCl" } Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:$props" diff --git a/test/old_tests/Component/Component.vcxproj b/test/old_tests/Component/Component.vcxproj index dbc55f2d3..6c7df9527 100644 --- a/test/old_tests/Component/Component.vcxproj +++ b/test/old_tests/Component/Component.vcxproj @@ -94,37 +94,31 @@ false false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl diff --git a/test/old_tests/Composable/Composable.vcxproj b/test/old_tests/Composable/Composable.vcxproj index 3b78edce4..4e49a255e 100644 --- a/test/old_tests/Composable/Composable.vcxproj +++ b/test/old_tests/Composable/Composable.vcxproj @@ -94,37 +94,31 @@ false false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl false false - ..\..;$(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl diff --git a/test/test_component/test_component.vcxproj b/test/test_component/test_component.vcxproj index 001587bed..9751fb5a2 100644 --- a/test/test_component/test_component.vcxproj +++ b/test/test_component/test_component.vcxproj @@ -92,27 +92,21 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); diff --git a/test/test_component_base/test_component_base.vcxproj b/test/test_component_base/test_component_base.vcxproj index 2a2069da0..947c53e8f 100644 --- a/test/test_component_base/test_component_base.vcxproj +++ b/test/test_component_base/test_component_base.vcxproj @@ -92,27 +92,21 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); diff --git a/test/test_component_derived/test_component_derived.vcxproj b/test/test_component_derived/test_component_derived.vcxproj index e31d675a8..a1c856c90 100644 --- a/test/test_component_derived/test_component_derived.vcxproj +++ b/test/test_component_derived/test_component_derived.vcxproj @@ -92,27 +92,21 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); diff --git a/test/test_component_fast/test_component_fast.vcxproj b/test/test_component_fast/test_component_fast.vcxproj index 216afea69..5d646cf78 100644 --- a/test/test_component_fast/test_component_fast.vcxproj +++ b/test/test_component_fast/test_component_fast.vcxproj @@ -93,27 +93,21 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); diff --git a/test/test_component_folders/test_component_folders.vcxproj b/test/test_component_folders/test_component_folders.vcxproj index 0ddb18c6e..6d642096f 100644 --- a/test/test_component_folders/test_component_folders.vcxproj +++ b/test/test_component_folders/test_component_folders.vcxproj @@ -92,27 +92,21 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); diff --git a/test/test_component_no_pch/test_component_no_pch.vcxproj b/test/test_component_no_pch/test_component_no_pch.vcxproj index 040ab13f6..0b1a98271 100644 --- a/test/test_component_no_pch/test_component_no_pch.vcxproj +++ b/test/test_component_no_pch/test_component_no_pch.vcxproj @@ -92,27 +92,21 @@ Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x86_ARM64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(SystemRoot)\SysWow64;$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); Midl - $(VC_ExecutablePath_x64);$(WindowsSDK_ExecutablePath);$(VS_ExecutablePath);$(MSBuild_ExecutablePath);$(FxCopDir);$(PATH); From 8d06be20d76a6063fd572fc336f5d81da2e96f02 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Fri, 28 Feb 2025 16:45:31 -0800 Subject: [PATCH 41/91] Enable prefast and warnings checker in SDL (#1477) * Enable prefast and warning checkers * globalSdl.isNativeCode is a simple bool, not an object with 'enabled' field * Re-enable SDL in cppwinrtvisualizer --- .pipelines/OneBranch.Official.yml | 3 +++ .pipelines/OneBranch.PullRequest.yml | 3 +++ .pipelines/jobs/OneBranchBuild.yml | 4 ++++ .pipelines/jobs/OneBranchNuGet.yml | 4 ++++ .pipelines/jobs/OneBranchTest.yml | 4 ++++ .pipelines/jobs/OneBranchVsix.yml | 4 ++++ natvis/cppwinrtvisualizer.vcxproj | 6 ------ 7 files changed, 22 insertions(+), 6 deletions(-) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index fb6d68148..1bcc24550 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -32,6 +32,7 @@ extends: enabled: false globalSdl: + isNativeCode: true asyncSdl: enabled: true tsa: @@ -40,6 +41,8 @@ extends: compiled: enabled: true tsaEnabled: true + prefast: + enabled: true stages: - stage: build diff --git a/.pipelines/OneBranch.PullRequest.yml b/.pipelines/OneBranch.PullRequest.yml index 2ee26d1ad..b5b358702 100644 --- a/.pipelines/OneBranch.PullRequest.yml +++ b/.pipelines/OneBranch.PullRequest.yml @@ -32,10 +32,13 @@ extends: product: 'build_tools' globalSdl: + isNativeCode: true tsa: enabled: false sbom: enabled: true + prefast: + enabled: true stages: - stage: build diff --git a/.pipelines/jobs/OneBranchBuild.yml b/.pipelines/jobs/OneBranchBuild.yml index 9053fc21c..b5c060cb9 100644 --- a/.pipelines/jobs/OneBranchBuild.yml +++ b/.pipelines/jobs/OneBranchBuild.yml @@ -31,6 +31,10 @@ jobs: ${{ if eq(parameters.OfficialBuild, 'false') }}: ob_sdl_codeSignValidation_excludes: '-|**\*.exe;-|**\*.dll' + ob_sdl_prefast_enabled: true + ob_sdl_prefast_runDuring: 'Build' + ob_sdl_checkCompliantCompilerWarnings: true + ob_symbolsPublishing_enabled: ${{ parameters.OfficialBuild }} ob_symbolsPublishing_symbolsFolder: '$(ob_outputDirectory)' ob_symbolsPublishing_searchPattern: '**\*.pdb' diff --git a/.pipelines/jobs/OneBranchNuGet.yml b/.pipelines/jobs/OneBranchNuGet.yml index 4d4a7b2ea..02133ee03 100644 --- a/.pipelines/jobs/OneBranchNuGet.yml +++ b/.pipelines/jobs/OneBranchNuGet.yml @@ -17,6 +17,10 @@ jobs: ob_outputDirectory: '$(Build.SourcesDirectory)\out' PackageVersion: ${{ parameters.BuildVersion }} + ob_sdl_prefast_enabled: true + ob_sdl_prefast_runDuring: 'Build' + ob_sdl_checkCompliantCompilerWarnings: true + steps: - task: UseDotNet@2 continueOnError: true diff --git a/.pipelines/jobs/OneBranchTest.yml b/.pipelines/jobs/OneBranchTest.yml index 307f5e168..0aa5c934b 100644 --- a/.pipelines/jobs/OneBranchTest.yml +++ b/.pipelines/jobs/OneBranchTest.yml @@ -51,6 +51,10 @@ jobs: ob_artifactSuffix: $(TestExe).$(BuildPlatform) ob_sdl_codeSignValidation_excludes: '-|**\*.exe;-|**\*.dll' + ob_sdl_prefast_enabled: true + ob_sdl_prefast_runDuring: 'Build' + ob_sdl_checkCompliantCompilerWarnings: true + BuildPath: '$(Build.SourcesDirectory)/_build/$(BuildPlatform)/${{ parameters.BuildConfiguration }}' steps: diff --git a/.pipelines/jobs/OneBranchVsix.yml b/.pipelines/jobs/OneBranchVsix.yml index b1a6c8eeb..18b74403b 100644 --- a/.pipelines/jobs/OneBranchVsix.yml +++ b/.pipelines/jobs/OneBranchVsix.yml @@ -36,6 +36,10 @@ jobs: ob_symbolsPublishing_symbolsFolder: '$(ob_outputDirectory)' ob_symbolsPublishing_searchPattern: '**\*.pdb' ob_symbolsPublishing_indexSources: true + + ob_sdl_prefast_enabled: true + ob_sdl_prefast_runDuring: 'Build' + ob_sdl_checkCompliantCompilerWarnings: true steps: - task: UseDotNet@2 diff --git a/natvis/cppwinrtvisualizer.vcxproj b/natvis/cppwinrtvisualizer.vcxproj index b77013ac4..cc17bf500 100644 --- a/natvis/cppwinrtvisualizer.vcxproj +++ b/natvis/cppwinrtvisualizer.vcxproj @@ -104,7 +104,6 @@ Use Level4 Disabled - false VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;WIN32;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 @@ -129,7 +128,6 @@ Use Level4 Disabled - false VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 @@ -153,7 +151,6 @@ Use Level4 Disabled - false VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 @@ -179,7 +176,6 @@ MaxSpeed true true - false VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;WIN32;NDEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 @@ -209,7 +205,6 @@ MaxSpeed true true - false VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;NDEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 @@ -239,7 +234,6 @@ MaxSpeed true true - false VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;NDEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) stdcpp20 From 48e2f6186b735db4de47be9c304d1d61757a811c Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Fri, 28 Feb 2025 16:57:04 -0800 Subject: [PATCH 42/91] Merge compiler and msbuild vpacks (#1479) --- .pipelines/OneBranch.Official.yml | 53 ++++++------------------------- 1 file changed, 10 insertions(+), 43 deletions(-) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 1bcc24550..531076f3f 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -77,48 +77,6 @@ extends: ob_createvpack_metadata: $(Build.SourceBranchName).x86.$(Build.BuildNumber).$(Build.SourceVersion) ob_createvpack_target: $(OSBuildToolsRoot)\cppwinrt - steps: - - task: UseDotNet@2 - continueOnError: true - inputs: - packageType: 'runtime' - version: '6.x' - performMultiLevelLookup: true - - - task: DownloadPipelineArtifact@2 - displayName: 'Download x86 artifacts' - inputs: - artifactName: 'drop_build_x86' - targetPath: '$(Build.SourcesDirectory)/x86' - - - task: CopyFiles@2 - displayName: 'Stage compiler vpack contents' - inputs: - SourceFolder: $(Build.SourcesDirectory)/x86/cppwinrt - Contents: | - cppwinrt.exe - cppwinrt.pdb - TargetFolder: $(ob_outputDirectory) - - - job: MSBuild_vpack - pool: - type: windows - variables: - ob_outputDirectory: '$(Build.SourcesDirectory)\out' - - ob_createvpack_enabled: true - ob_createvpack_packagename: CppWinRT.MSBuild - ob_createvpack_owneralias: cpp4uwpt - ob_createvpack_description: C++/WinRT MSBuild - ob_createvpack_provData: true - ob_createvpack_versionAs: parts - ob_createvpack_majorVer: $(MajorVersion) - ob_createvpack_minorVer: $(MinorVersion) - ob_createvpack_patchVer: $(PatchVersion) - ob_createvpack_metadata: $(Build.SourceBranchName).$(Build.BuildNumber).$(Build.SourceVersion) - ob_createvpack_verbose: true - ob_createvpack_target: $(OSBuildToolsRoot)\cppwinrt - steps: - task: UseDotNet@2 continueOnError: true @@ -144,6 +102,15 @@ extends: inputs: artifactName: 'drop_build_arm64' targetPath: '$(Build.SourcesDirectory)/arm64' + + - task: CopyFiles@2 + displayName: 'Stage compiler vpack contents' + inputs: + SourceFolder: $(Build.SourcesDirectory)/x86/cppwinrt + Contents: | + cppwinrt.exe + cppwinrt.pdb + TargetFolder: $(ob_outputDirectory) - task: CmdLine@2 displayName: 'Stage MSBuild vpack contents' @@ -163,7 +130,7 @@ extends: echo d | xcopy $(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib build\native\lib\amd64 echo d | xcopy $(Build.SourcesDirectory)\x64\cppwinrt_fast_forwarder.lib build\native\lib\x64 echo d | xcopy $(Build.SourcesDirectory)\arm64\cppwinrt_fast_forwarder.lib build\native\lib\arm64 - + - stage: NuGet dependsOn: build jobs: From 69c78cfc7920367c4ce9cc024cf8c5b8d217fb1b Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Mon, 3 Mar 2025 15:22:06 -0800 Subject: [PATCH 43/91] Fix vpack clobbering and update to newer Windows container image (#1480) * Update to newer Windows container image * Pass newer host version to templates * Stop clobbering compiler vpack contents --- .pipelines/OneBranch.Official.yml | 6 ++++-- .pipelines/OneBranch.PullRequest.yml | 4 ++++ .pipelines/variables/OneBranchVariables.yml | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 531076f3f..552ec761b 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -27,6 +27,10 @@ extends: platform: name: 'windows_undocked' product: 'build_tools' + + featureFlags: + WindowsHostVersion: + Version: 2022 cloudvault: enabled: false @@ -117,8 +121,6 @@ extends: inputs: script: | set TargetDir=$(ob_outputDirectory) - rd /s /q %TargetDir% >nul 2>&1 - md %TargetDir% cd %TargetDir% copy $(Build.SourcesDirectory)\vsix\Microsoft.Cpp.CppWinRT.props diff --git a/.pipelines/OneBranch.PullRequest.yml b/.pipelines/OneBranch.PullRequest.yml index b5b358702..bc08bbddf 100644 --- a/.pipelines/OneBranch.PullRequest.yml +++ b/.pipelines/OneBranch.PullRequest.yml @@ -31,6 +31,10 @@ extends: name: 'windows_undocked' product: 'build_tools' + featureFlags: + WindowsHostVersion: + Version: 2022 + globalSdl: isNativeCode: true tsa: diff --git a/.pipelines/variables/OneBranchVariables.yml b/.pipelines/variables/OneBranchVariables.yml index 8e6ad8af0..ff7a98adb 100644 --- a/.pipelines/variables/OneBranchVariables.yml +++ b/.pipelines/variables/OneBranchVariables.yml @@ -10,7 +10,7 @@ variables: NUGET_XMLDOC_MODE: none # Docker image which is used to build the project https://aka.ms/obpipelines/containers - WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2019/vse2022:latest' + WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2022/vse2022:latest' Codeql.Enabled: true # CodeQL once every 3 days on the default branch for all languages its applicable to in that pipeline. GDN_USE_DOTNET: true \ No newline at end of file From 80fa82f523587ceca271a60d5b183b7411021566 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 2 Apr 2025 18:52:52 -0700 Subject: [PATCH 44/91] Enable NuGet Central Package Management (#1483) * Enable NuGet Central Package Management * Enable NuGet Central Package Management --------- Co-authored-by: MerlinBot Co-authored-by: 1ES Gardener --- Directory.Packages.props | 12 ++++++++++++ .../TestRuntimeComponentCSharp.csproj | 4 +--- vsix/Dev16/vsix.Dev16.csproj | 7 +++---- vsix/Dev17/vsix.Dev17.csproj | 6 +++--- 4 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 Directory.Packages.props diff --git a/Directory.Packages.props b/Directory.Packages.props new file mode 100644 index 000000000..1d77adffd --- /dev/null +++ b/Directory.Packages.props @@ -0,0 +1,12 @@ + + + true + + + + + + + + + \ No newline at end of file diff --git a/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj b/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj index 57f14194d..d756e19b7 100644 --- a/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj +++ b/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj @@ -80,9 +80,7 @@ - - 5.4.7 - + 14.0 diff --git a/vsix/Dev16/vsix.Dev16.csproj b/vsix/Dev16/vsix.Dev16.csproj index dfb870ee1..72b9b4098 100644 --- a/vsix/Dev16/vsix.Dev16.csproj +++ b/vsix/Dev16/vsix.Dev16.csproj @@ -84,16 +84,15 @@ - 16.10.31321.278 + 16.10.31321.278 compile; build; native; contentfiles; analyzers; buildtransitive - 17.3.2093 runtime; build; native; contentfiles; analyzers; buildtransitive all - - + + diff --git a/vsix/Dev17/vsix.Dev17.csproj b/vsix/Dev17/vsix.Dev17.csproj index be0cf3d17..3326ce6fa 100644 --- a/vsix/Dev17/vsix.Dev17.csproj +++ b/vsix/Dev17/vsix.Dev17.csproj @@ -87,10 +87,10 @@ - + compile; build; native; contentfiles; analyzers; buildtransitive - + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -169,7 +169,7 @@ - + From 723f64b35d672200d444e6fe3615c8ef0705d5e8 Mon Sep 17 00:00:00 2001 From: Brady Hahn Date: Fri, 4 Apr 2025 14:07:09 -0700 Subject: [PATCH 45/91] Public LTO visibility for ABI type declarations (#1482) --- cppwinrt/code_writers.h | 6 +++--- strings/base_abi.h | 36 ++++++++++++++++++------------------ strings/base_delegate.h | 2 +- strings/base_fast_forward.h | 9 ++++++++- strings/base_macros.h | 8 ++++++++ 5 files changed, 38 insertions(+), 23 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index d84abeecf..ae2920d56 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -763,7 +763,7 @@ namespace cppwinrt { auto format = R"( template <> struct abi<%> { - struct WINRT_IMPL_NOVTABLE type : inspectable_abi + struct WINRT_IMPL_ABI_DECL type : inspectable_abi { )"; @@ -773,7 +773,7 @@ namespace cppwinrt { auto format = R"( template <%> struct abi<%> { - struct WINRT_IMPL_NOVTABLE type : inspectable_abi + struct WINRT_IMPL_ABI_DECL type : inspectable_abi { )"; @@ -814,7 +814,7 @@ namespace cppwinrt { auto format = R"( template <%> struct abi<%> { - struct WINRT_IMPL_NOVTABLE type : unknown_abi + struct WINRT_IMPL_ABI_DECL type : unknown_abi { virtual int32_t __stdcall Invoke(%) noexcept = 0; }; diff --git a/strings/base_abi.h b/strings/base_abi.h index d1eab2950..ec42fefe6 100644 --- a/strings/base_abi.h +++ b/strings/base_abi.h @@ -3,7 +3,7 @@ namespace winrt::impl { template <> struct abi { - struct WINRT_IMPL_NOVTABLE type + struct WINRT_IMPL_ABI_DECL type { virtual int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept = 0; virtual uint32_t __stdcall AddRef() noexcept = 0; @@ -15,7 +15,7 @@ namespace winrt::impl template <> struct abi { - struct WINRT_IMPL_NOVTABLE type : unknown_abi + struct WINRT_IMPL_ABI_DECL type : unknown_abi { virtual int32_t __stdcall GetIids(uint32_t* count, guid** ids) noexcept = 0; virtual int32_t __stdcall GetRuntimeClassName(void** name) noexcept = 0; @@ -27,20 +27,20 @@ namespace winrt::impl template <> struct abi { - struct WINRT_IMPL_NOVTABLE type : inspectable_abi + struct WINRT_IMPL_ABI_DECL type : inspectable_abi { virtual int32_t __stdcall ActivateInstance(void** instance) noexcept = 0; }; }; - struct WINRT_IMPL_NOVTABLE IAgileObject : unknown_abi {}; + struct WINRT_IMPL_ABI_DECL IAgileObject : unknown_abi {}; - struct WINRT_IMPL_NOVTABLE IAgileReference : unknown_abi + struct WINRT_IMPL_ABI_DECL IAgileReference : unknown_abi { virtual int32_t __stdcall Resolve(guid const& id, void** object) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IMarshal : unknown_abi + struct WINRT_IMPL_ABI_DECL IMarshal : unknown_abi { virtual int32_t __stdcall GetUnmarshalClass(guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, guid* pCid) noexcept = 0; virtual int32_t __stdcall GetMarshalSizeMax(guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, uint32_t* pSize) noexcept = 0; @@ -50,20 +50,20 @@ namespace winrt::impl virtual int32_t __stdcall DisconnectObject(uint32_t dwReserved) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IGlobalInterfaceTable : unknown_abi + struct WINRT_IMPL_ABI_DECL IGlobalInterfaceTable : unknown_abi { virtual int32_t __stdcall RegisterInterfaceInGlobal(void* object, guid const& iid, uint32_t* cookie) noexcept = 0; virtual int32_t __stdcall RevokeInterfaceFromGlobal(uint32_t cookie) noexcept = 0; virtual int32_t __stdcall GetInterfaceFromGlobal(uint32_t cookie, guid const& iid, void** object) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IStaticLifetime : inspectable_abi + struct WINRT_IMPL_ABI_DECL IStaticLifetime : inspectable_abi { virtual int32_t __stdcall unused() noexcept = 0; virtual int32_t __stdcall GetCollection(void** value) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IStaticLifetimeCollection : inspectable_abi + struct WINRT_IMPL_ABI_DECL IStaticLifetimeCollection : inspectable_abi { virtual int32_t __stdcall Lookup(void*, void**) noexcept = 0; virtual int32_t __stdcall unused() noexcept = 0; @@ -74,23 +74,23 @@ namespace winrt::impl virtual int32_t __stdcall unused4() noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IWeakReference : unknown_abi + struct WINRT_IMPL_ABI_DECL IWeakReference : unknown_abi { virtual int32_t __stdcall Resolve(guid const& iid, void** objectReference) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IWeakReferenceSource : unknown_abi + struct WINRT_IMPL_ABI_DECL IWeakReferenceSource : unknown_abi { virtual int32_t __stdcall GetWeakReference(IWeakReference** weakReference) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IRestrictedErrorInfo : unknown_abi + struct WINRT_IMPL_ABI_DECL IRestrictedErrorInfo : unknown_abi { virtual int32_t __stdcall GetErrorDetails(bstr* description, int32_t* error, bstr* restrictedDescription, bstr* capabilitySid) noexcept = 0; virtual int32_t __stdcall GetReference(bstr* reference) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IErrorInfo : unknown_abi + struct WINRT_IMPL_ABI_DECL IErrorInfo : unknown_abi { virtual int32_t __stdcall GetGUID(guid* value) noexcept = 0; virtual int32_t __stdcall GetSource(bstr* value) noexcept = 0; @@ -99,7 +99,7 @@ namespace winrt::impl virtual int32_t __stdcall GetHelpContext(uint32_t* value) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE ILanguageExceptionErrorInfo2 : unknown_abi + struct WINRT_IMPL_ABI_DECL ILanguageExceptionErrorInfo2 : unknown_abi { virtual int32_t __stdcall GetLanguageException(void** exception) noexcept = 0; virtual int32_t __stdcall GetPreviousLanguageExceptionErrorInfo(ILanguageExceptionErrorInfo2** previous) noexcept = 0; @@ -109,12 +109,12 @@ namespace winrt::impl struct ICallbackWithNoReentrancyToApplicationSTA; - struct WINRT_IMPL_NOVTABLE IContextCallback : unknown_abi + struct WINRT_IMPL_ABI_DECL IContextCallback : unknown_abi { virtual int32_t __stdcall ContextCallback(int32_t(__stdcall* callback)(com_callback_args*), com_callback_args* args, guid const& iid, int method, void* reserved) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IServerSecurity : unknown_abi + struct WINRT_IMPL_ABI_DECL IServerSecurity : unknown_abi { virtual int32_t __stdcall QueryBlanket(uint32_t*, uint32_t*, wchar_t**, uint32_t*, uint32_t*, void**, uint32_t*) noexcept = 0; virtual int32_t __stdcall ImpersonateClient() noexcept = 0; @@ -122,12 +122,12 @@ namespace winrt::impl virtual int32_t __stdcall IsImpersonating() noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IBufferByteAccess : unknown_abi + struct WINRT_IMPL_ABI_DECL IBufferByteAccess : unknown_abi { virtual int32_t __stdcall Buffer(uint8_t** value) noexcept = 0; }; - struct WINRT_IMPL_NOVTABLE IMemoryBufferByteAccess : unknown_abi + struct WINRT_IMPL_ABI_DECL IMemoryBufferByteAccess : unknown_abi { virtual int32_t __stdcall GetBuffer(uint8_t** value, uint32_t* capacity) noexcept = 0; }; diff --git a/strings/base_delegate.h b/strings/base_delegate.h index 8902b3cc6..3d1457c2e 100644 --- a/strings/base_delegate.h +++ b/strings/base_delegate.h @@ -109,7 +109,7 @@ namespace winrt::impl } template - struct WINRT_IMPL_NOVTABLE variadic_delegate_abi : unknown_abi + struct WINRT_IMPL_ABI_DECL variadic_delegate_abi : unknown_abi { virtual R invoke(Args const& ...) = 0; }; diff --git a/strings/base_fast_forward.h b/strings/base_fast_forward.h index 88d99469a..7291ab2af 100644 --- a/strings/base_fast_forward.h +++ b/strings/base_fast_forward.h @@ -10,6 +10,12 @@ #define WINRT_IMPL_FF_NOVTABLE #endif +#if defined(__clang__) && __has_attribute(__lto_visibility_public__) +#define WINRT_IMPL_FF_PUBLIC __attribute__((lto_visibility_public)) +#else +#define WINRT_IMPL_FF_PUBLIC +#endif + #if !defined(WINRT_FAST_ABI_SIZE) #define WINRT_FAST_ABI_SIZE % #endif @@ -36,7 +42,7 @@ namespace winrt::impl } }; - struct WINRT_IMPL_FF_NOVTABLE inspectable + struct WINRT_IMPL_FF_NOVTABLE WINRT_IMPL_FF_PUBLIC inspectable { virtual int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept = 0; virtual uint32_t __stdcall AddRef() noexcept = 0; @@ -137,3 +143,4 @@ namespace winrt #undef WINRT_IMPL_STRING #undef WINRT_IMPL_STRING_1 #undef WINRT_IMPL_FF_NOVTABLE +#undef WINRT_IMPL_FF_PUBLIC diff --git a/strings/base_macros.h b/strings/base_macros.h index d9e19547e..42e958649 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -61,6 +61,14 @@ #define WINRT_IMPL_NOVTABLE #endif +#if defined(__clang__) && __has_attribute(__lto_visibility_public__) +#define WINRT_IMPL_PUBLIC __attribute__((lto_visibility_public)) +#else +#define WINRT_IMPL_PUBLIC +#endif + +#define WINRT_IMPL_ABI_DECL WINRT_IMPL_NOVTABLE WINRT_IMPL_PUBLIC + #if defined(__clang__) #define WINRT_IMPL_HAS_DECLSPEC_UUID __has_declspec_attribute(uuid) #elif defined(_MSC_VER) From 46fd3ed1ce7b2264fcdef8199794828094dfcd88 Mon Sep 17 00:00:00 2001 From: David Machaj <46852402+dmachaj@users.noreply.github.com> Date: Fri, 25 Apr 2025 11:39:39 -0700 Subject: [PATCH 46/91] All cppwinrt vcxproj should build with /W4 and /WX (warnings turned up, treated as error). Fix existing violations. (#1487) Why is this change being made? The most recent PR introduced a warning for non-Clang consumers. Many projects build with warnings-as-errors so this is a build break for those projects. Because cppwinrt is widely used by many such projects it should itself build with warnings as errors enabled so that this doesn't happen again in the future. Plus it is general goodness to build with warnings cranked up and blocking. Briefly summarize what changed I added /WX to every single vcxproj in this repo (which required a whole lot of redundant edits). Many of them didn't have /W4 so I added it wherever it was missing. The project files definitely need some refactoring to reduce duplication. But for this change I decided to modify them as-is without also including a refactoring. I also fixed the newly-blocking warnings. MSVC only had the one new warning to fix. Clang had a whole bunch of previously-unknown warnings that needed to be fixed or suppressed to get the build passing again. I also removed a typo'd (warning is singular, not plural) that was trying to disable warnings in one specific project. It has no warnings so we might as well baseline them as blocking. I also added a new clang-only test file to try and exercise the LTO public visibility annotation. How was this change tested? It builds locally (x64 Debug+Release, MSVC + Clang). --- Directory.Build.Props | 1 + cppwinrt/component_writers.h | 2 +- cppwinrt/cppwinrt.vcxproj | 12 ++++++++++ natvis/cppwinrtvisualizer.vcxproj | 6 +++++ prebuild/prebuild.vcxproj | 12 ++++++++++ scratch/scratch.vcxproj | 2 ++ strings/base_activation.h | 3 +-- strings/base_fast_forward.h | 16 +++++++++++-- strings/base_macros.h | 6 ++++- strings/base_string.h | 4 ++-- .../ConsoleApplication1.vcxproj | 1 + test/nuget/TestApp/TestApp.vcxproj | 1 + .../nuget/TestProxyStub/TestProxyStub.vcxproj | 3 ++- .../TestRuntimeComponent1.vcxproj | 1 + .../TestRuntimeComponent2.vcxproj | 1 + .../TestRuntimeComponent3.vcxproj | 1 + .../TestRuntimeComponentCX.vcxproj | 12 ++++++++++ ...entCXReferencingWinRTStaticLibrary.vcxproj | 12 ++++++++++ .../TestRuntimeComponentEmpty.vcxproj | 1 + ...untimeComponentNamespaceUnderscore.vcxproj | 1 + .../TestStaticLibrary1.vcxproj | 6 +++++ .../TestStaticLibrary2.vcxproj | 6 +++++ .../TestStaticLibrary3.vcxproj | 6 +++++ .../TestStaticLibrary4.vcxproj | 12 ++++++++++ .../TestStaticLibrary5.vcxproj | 12 ++++++++++ .../TestStaticLibrary6.vcxproj | 12 ++++++++++ .../TestStaticLibrary7.vcxproj | 1 + test/old_tests/Component/Component.vcxproj | 12 ++++++++++ test/old_tests/Composable/Base.cpp | 2 +- test/old_tests/Composable/Composable.vcxproj | 12 ++++++++++ test/old_tests/UnitTests/Boxing2.cpp | 10 ++++---- test/old_tests/UnitTests/Composable.cpp | 2 +- .../IInspectable_GetRuntimeClassName.cpp | 7 ++++++ test/old_tests/UnitTests/Tests.vcxproj | 12 ++++++++++ test/old_tests/UnitTests/array.cpp | 2 +- test/old_tests/UnitTests/produce.cpp | 7 ++++++ test/old_tests/UnitTests/smart_pointers.cpp | 6 +++++ test/test/disconnected.cpp | 2 +- test/test/event_deferral.cpp | 14 +++++++---- test/test/inspectable_interop.cpp | 7 ++++++ test/test/multi_threaded_map.cpp | 2 +- test/test/out_params.cpp | 4 ++-- test/test/return_params_abi.cpp | 7 ++++++ test/test/struct_delegate.cpp | 2 +- test/test/test.vcxproj | 12 ++++++++++ test/test_component/Class.cpp | 7 ++++++ test/test_component/test_component.vcxproj | 12 ++++++++++ test/test_component_base/HierarchyA.cpp | 4 ++-- test/test_component_base/HierarchyB.cpp | 2 +- .../test_component_base.vcxproj | 12 ++++++++++ .../Nested.HierarchyD.cpp | 2 +- .../test_component_derived.vcxproj | 12 ++++++++++ .../test_component_fast.vcxproj | 12 ++++++++++ .../test_component_folders.vcxproj | 12 ++++++++++ .../test_component_no_pch.vcxproj | 12 ++++++++++ test/test_cpp20/array_span.cpp | 2 +- test/test_cpp20/clang_only.cpp | 23 +++++++++++++++++++ test/test_cpp20/test_cpp20.vcxproj | 19 +++++++++++++++ .../custom_error.cpp | 2 +- .../test_cpp20_no_sourcelocation.vcxproj | 2 ++ test/test_fast/Nomadic.cpp | 8 +++++++ test/test_fast/test_fast.vcxproj | 12 ++++++++++ test/test_fast_fwd/test_fast_fwd.vcxproj | 12 ++++++++++ .../test_module_lock_custom.vcxproj | 12 ++++++++++ test/test_module_lock_none/main.cpp | 7 ++++++ .../test_module_lock_none.vcxproj | 12 ++++++++++ test/test_slow/test_slow.vcxproj | 12 ++++++++++ .../ConsoleApplication.vcxproj | 1 + .../WindowsApplication.vcxproj | 1 + .../BlankApp/BlankApp.vcxproj | 1 + .../Windows Universal/CoreApp/CoreApp.vcxproj | 1 + .../StaticLibrary/StaticLibrary.vcxproj | 1 + .../WindowsRuntimeComponent.vcxproj | 1 + 73 files changed, 458 insertions(+), 33 deletions(-) create mode 100644 test/test_cpp20/clang_only.cpp diff --git a/Directory.Build.Props b/Directory.Build.Props index 0a8e5b37b..9088021c1 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -49,6 +49,7 @@ Level4 + true true true stdcpp17 diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index 6865d49ef..cb748917d 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -754,7 +754,7 @@ catch (...) { return winrt::to_hresult(); } using implements_type = typename %_base::implements_type; using implements_type::implements_type; %% - hstring GetRuntimeClassName() const + hstring GetRuntimeClassName() const override { return L"%.%"; } diff --git a/cppwinrt/cppwinrt.vcxproj b/cppwinrt/cppwinrt.vcxproj index 069f8103a..b8beed890 100644 --- a/cppwinrt/cppwinrt.vcxproj +++ b/cppwinrt/cppwinrt.vcxproj @@ -176,6 +176,8 @@ Disabled ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreadedDebug + Level4 + true Console @@ -193,6 +195,8 @@ Disabled ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreadedDebug + Level4 + true Console @@ -210,6 +214,8 @@ Disabled ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreadedDebug + Level4 + true Console @@ -230,6 +236,8 @@ ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreaded Guard + Level4 + true Console @@ -253,6 +261,8 @@ ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreaded Guard + Level4 + true Console @@ -276,6 +286,8 @@ ..\inc;$(OutputPath);$(WinMDPackageDir); MultiThreaded Guard + Level4 + true Console diff --git a/natvis/cppwinrtvisualizer.vcxproj b/natvis/cppwinrtvisualizer.vcxproj index cc17bf500..af3fbcf1f 100644 --- a/natvis/cppwinrtvisualizer.vcxproj +++ b/natvis/cppwinrtvisualizer.vcxproj @@ -103,6 +103,7 @@ Use Level4 + true Disabled VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;WIN32;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) @@ -127,6 +128,7 @@ Use Level4 + true Disabled VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) @@ -150,6 +152,7 @@ Use Level4 + true Disabled VSDEBUGENG_USE_CPP11_SCOPED_ENUMS;_DEBUG;VISUALIZER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) $(IntDir);..\cppwinrt;..\strings;$(DIASDKInc);%(AdditionalIncludeDirectories) @@ -173,6 +176,7 @@ Use Level4 + true MaxSpeed true true @@ -202,6 +206,7 @@ Use Level4 + true MaxSpeed true true @@ -231,6 +236,7 @@ Use Level4 + true MaxSpeed true true diff --git a/prebuild/prebuild.vcxproj b/prebuild/prebuild.vcxproj index 6e0bc4b71..9fad91fd8 100644 --- a/prebuild/prebuild.vcxproj +++ b/prebuild/prebuild.vcxproj @@ -88,6 +88,8 @@ Disabled ..\cppwinrt MultiThreadedDebug + Level4 + true Console @@ -98,6 +100,8 @@ Disabled ..\cppwinrt MultiThreadedDebug + Level4 + true Console @@ -108,6 +112,8 @@ Disabled ..\cppwinrt MultiThreadedDebug + Level4 + true Console @@ -121,6 +127,8 @@ ..\cppwinrt MultiThreaded Guard + Level4 + true Console @@ -136,6 +144,8 @@ ..\cppwinrt MultiThreaded Guard + Level4 + true Console @@ -151,6 +161,8 @@ ..\cppwinrt MultiThreaded Guard + Level4 + true Console diff --git a/scratch/scratch.vcxproj b/scratch/scratch.vcxproj index 98ed21948..84f6ce3d8 100644 --- a/scratch/scratch.vcxproj +++ b/scratch/scratch.vcxproj @@ -53,6 +53,8 @@ $(OutputPath);Generated Files; + Level4 + true Console diff --git a/strings/base_activation.h b/strings/base_activation.h index be24c6ad9..586df32e9 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -257,8 +257,7 @@ namespace winrt::impl } private: - - size_t& m_count; + [[maybe_unused]] size_t& m_count; // Field is unused when WINRT_NO_MODULE_LOCK is defined. }; struct factory_cache_entry_base diff --git a/strings/base_fast_forward.h b/strings/base_fast_forward.h index 7291ab2af..3ca34dba7 100644 --- a/strings/base_fast_forward.h +++ b/strings/base_fast_forward.h @@ -10,10 +10,14 @@ #define WINRT_IMPL_FF_NOVTABLE #endif -#if defined(__clang__) && __has_attribute(__lto_visibility_public__) +#if defined(__clang__) && defined(__has_attribute) +#if __has_attribute(__lto_visibility_public__) #define WINRT_IMPL_FF_PUBLIC __attribute__((lto_visibility_public)) #else #define WINRT_IMPL_FF_PUBLIC +#endif // __has_attribute(__lto_visibility_public__) +#else +#define WINRT_IMPL_FF_PUBLIC #endif #if !defined(WINRT_FAST_ABI_SIZE) @@ -59,7 +63,7 @@ namespace winrt::impl std::atomic m_references{ 1 }; fast_abi_forwarder(void* owner, guid const& iid, std::size_t offset) noexcept : - m_vfptr(s_vtable), m_owner(static_cast(owner)), m_iid(iid), m_offset(offset) + m_vfptr(s_vtable), m_owner(static_cast(owner)), m_offset(offset), m_iid(iid) { m_owner->AddRef(); } @@ -112,6 +116,11 @@ namespace winrt::impl return self->m_owner->GetTrustLevel(level); } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmicrosoft-cast" +#endif static inline void* const s_vtable[] = { QueryInterface, @@ -121,6 +130,9 @@ namespace winrt::impl GetRuntimeClassName, GetTrustLevel, % }; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif }; // Enforce assumptions made by thunk asm code diff --git a/strings/base_macros.h b/strings/base_macros.h index 42e958649..0c4357b1e 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -61,10 +61,14 @@ #define WINRT_IMPL_NOVTABLE #endif -#if defined(__clang__) && __has_attribute(__lto_visibility_public__) +#if defined(__clang__) && defined(__has_attribute) +#if __has_attribute(__lto_visibility_public__) #define WINRT_IMPL_PUBLIC __attribute__((lto_visibility_public)) #else #define WINRT_IMPL_PUBLIC +#endif // __has_attribute(__lto_visibility_public__) +#else +#define WINRT_IMPL_PUBLIC #endif #define WINRT_IMPL_ABI_DECL WINRT_IMPL_NOVTABLE WINRT_IMPL_PUBLIC diff --git a/strings/base_string.h b/strings/base_string.h index e70eed925..81229e3d5 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -574,8 +574,8 @@ namespace winrt::impl // when non-const (e.g. ranges::filter_view) so taking a const reference // as parameter wouldn't work for all scenarios. auto const size = std::formatted_size(args...); - WINRT_ASSERT(size < UINT_MAX); - auto const size32 = static_cast(size); + WINRT_ASSERT(size < INT_MAX); + auto const size32 = static_cast(size); hstring_builder builder(size32); WINRT_VERIFY_(size32, std::format_to_n(builder.data(), size32, args...).size); diff --git a/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj b/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj index 819c788d8..38f3ee4cc 100644 --- a/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj +++ b/test/nuget/ConsoleApplication1/ConsoleApplication1.vcxproj @@ -70,6 +70,7 @@ $(IntDir)pch.pch _CONSOLE;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) Level4 + true %(AdditionalOptions) /permissive- /bigobj diff --git a/test/nuget/TestApp/TestApp.vcxproj b/test/nuget/TestApp/TestApp.vcxproj index 84029a4c9..f14bd9f0b 100644 --- a/test/nuget/TestApp/TestApp.vcxproj +++ b/test/nuget/TestApp/TestApp.vcxproj @@ -70,6 +70,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj diff --git a/test/nuget/TestProxyStub/TestProxyStub.vcxproj b/test/nuget/TestProxyStub/TestProxyStub.vcxproj index 899a5c11c..69e41cfba 100644 --- a/test/nuget/TestProxyStub/TestProxyStub.vcxproj +++ b/test/nuget/TestProxyStub/TestProxyStub.vcxproj @@ -35,7 +35,6 @@ 10.0.22621.0 10.0.18362.0 - false false @@ -55,6 +54,8 @@ Use pch.h %(AdditionalIncludeDirectories);$(MSBuildThisFileDirectory) + Level4 + true Windows diff --git a/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj b/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj index 1b7621ea0..b1ee4f43f 100644 --- a/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj +++ b/test/nuget/TestRuntimeComponent1/TestRuntimeComponent1.vcxproj @@ -74,6 +74,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj 28204 _WINRT_DLL;%(PreprocessorDefinitions) diff --git a/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj b/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj index 48f9acfb0..c27db2602 100644 --- a/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj +++ b/test/nuget/TestRuntimeComponent2/TestRuntimeComponent2.vcxproj @@ -75,6 +75,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj 28204 _WINRT_DLL;%(PreprocessorDefinitions) diff --git a/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj b/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj index 8a876e601..01c84d830 100644 --- a/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj +++ b/test/nuget/TestRuntimeComponent3/TestRuntimeComponent3.vcxproj @@ -75,6 +75,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj 28204 _WINRT_DLL;%(PreprocessorDefinitions) diff --git a/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj b/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj index 237b9fcf3..819cff52b 100644 --- a/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj +++ b/test/nuget/TestRuntimeComponentCX/TestRuntimeComponentCX.vcxproj @@ -103,6 +103,8 @@ /bigobj /Zc:twoPhase- %(AdditionalOptions) 28204 true + Level4 + true Console @@ -119,6 +121,8 @@ /bigobj /Zc:twoPhase- %(AdditionalOptions) 28204 true + Level4 + true Console @@ -135,6 +139,8 @@ /bigobj /Zc:twoPhase- %(AdditionalOptions) 28204 true + Level4 + true Console @@ -151,6 +157,8 @@ /bigobj /Zc:twoPhase- %(AdditionalOptions) 28204 true + Level4 + true Console @@ -167,6 +175,8 @@ /bigobj /Zc:twoPhase- %(AdditionalOptions) 28204 true + Level4 + true Console @@ -183,6 +193,8 @@ /bigobj /Zc:twoPhase- %(AdditionalOptions) 28204 true + Level4 + true Console diff --git a/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj b/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj index 68b71c94e..6ce188345 100644 --- a/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj +++ b/test/nuget/TestRuntimeComponentCXReferencingWinRTStaticLibrary/TestRuntimeComponentCXReferencingWinRTStaticLibrary.vcxproj @@ -117,6 +117,8 @@ $(IntDir)pch.pch $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) /bigobj /Zc:twoPhase- %(AdditionalOptions) + Level4 + true 28204 @@ -132,6 +134,8 @@ $(IntDir)pch.pch $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) /bigobj /Zc:twoPhase- %(AdditionalOptions) + Level4 + true 28204 @@ -147,6 +151,8 @@ $(IntDir)pch.pch $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) /bigobj /Zc:twoPhase- %(AdditionalOptions) + Level4 + true 28204 @@ -162,6 +168,8 @@ $(IntDir)pch.pch $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) /bigobj /Zc:twoPhase- %(AdditionalOptions) + Level4 + true 28204 @@ -177,6 +185,8 @@ $(IntDir)pch.pch $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) /bigobj /Zc:twoPhase- %(AdditionalOptions) + Level4 + true 28204 @@ -192,6 +202,8 @@ $(IntDir)pch.pch $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) /bigobj /Zc:twoPhase- %(AdditionalOptions) + Level4 + true 28204 diff --git a/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj b/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj index 7572238eb..60786eddb 100644 --- a/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj +++ b/test/nuget/TestRuntimeComponentEmpty/TestRuntimeComponentEmpty.vcxproj @@ -75,6 +75,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj 28204 _WINRT_DLL;%(PreprocessorDefinitions) diff --git a/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj b/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj index 693a97596..fb8146340 100644 --- a/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj +++ b/test/nuget/TestRuntimeComponentNamespaceUnderscore/TestRuntimeComponentNamespaceUnderscore.vcxproj @@ -75,6 +75,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) diff --git a/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj b/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj index a34e7429c..13ac4e201 100644 --- a/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj +++ b/test/nuget/TestStaticLibrary1/TestStaticLibrary1.vcxproj @@ -81,6 +81,7 @@ Use Level4 + true Disabled true WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) @@ -98,6 +99,7 @@ Use Level4 + true Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) @@ -115,6 +117,7 @@ Use Level4 + true Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) @@ -132,6 +135,7 @@ Use Level4 + true MaxSpeed true true @@ -153,6 +157,7 @@ Use Level4 + true MaxSpeed true true @@ -174,6 +179,7 @@ Use Level4 + true MaxSpeed true true diff --git a/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj b/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj index 5f3ee5220..b419d183e 100644 --- a/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj +++ b/test/nuget/TestStaticLibrary2/TestStaticLibrary2.vcxproj @@ -81,6 +81,7 @@ Use Level4 + true Disabled true WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) @@ -98,6 +99,7 @@ Use Level4 + true Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) @@ -115,6 +117,7 @@ Use Level4 + true Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) @@ -132,6 +135,7 @@ Use Level4 + true MaxSpeed true true @@ -153,6 +157,7 @@ Use Level4 + true MaxSpeed true true @@ -174,6 +179,7 @@ Use Level4 + true MaxSpeed true true diff --git a/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj b/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj index c79a847a3..210802841 100644 --- a/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj +++ b/test/nuget/TestStaticLibrary3/TestStaticLibrary3.vcxproj @@ -81,6 +81,7 @@ Use Level4 + true Disabled true WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) @@ -98,6 +99,7 @@ Use Level4 + true Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) @@ -115,6 +117,7 @@ Use Level4 + true Disabled true _DEBUG;_LIB;%(PreprocessorDefinitions) @@ -132,6 +135,7 @@ Use Level4 + true MaxSpeed true true @@ -153,6 +157,7 @@ Use Level4 + true MaxSpeed true true @@ -174,6 +179,7 @@ Use Level4 + true MaxSpeed true true diff --git a/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj b/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj index b3efe02c4..357d0ca70 100644 --- a/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj +++ b/test/nuget/TestStaticLibrary4/TestStaticLibrary4.vcxproj @@ -102,6 +102,8 @@ Use false true + Level4 + true Console @@ -114,6 +116,8 @@ Use false true + Level4 + true Console @@ -126,6 +130,8 @@ Use false true + Level4 + true Console @@ -138,6 +144,8 @@ Use false true + Level4 + true Console @@ -150,6 +158,8 @@ Use false true + Level4 + true Console @@ -162,6 +172,8 @@ Use false true + Level4 + true Console diff --git a/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj b/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj index bfc6db45c..d93446a05 100644 --- a/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj +++ b/test/nuget/TestStaticLibrary5/TestStaticLibrary5.vcxproj @@ -102,6 +102,8 @@ Use false true + Level4 + true Console @@ -114,6 +116,8 @@ Use false true + Level4 + true Console @@ -126,6 +130,8 @@ Use false true + Level4 + true Console @@ -138,6 +144,8 @@ Use false true + Level4 + true Console @@ -150,6 +158,8 @@ Use false true + Level4 + true Console @@ -162,6 +172,8 @@ Use false true + Level4 + true Console diff --git a/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj b/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj index 89a0e55c9..626e60dab 100644 --- a/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj +++ b/test/nuget/TestStaticLibrary6/TestStaticLibrary6.vcxproj @@ -102,6 +102,8 @@ Use false true + Level4 + true Console @@ -114,6 +116,8 @@ Use false true + Level4 + true Console @@ -126,6 +130,8 @@ Use false true + Level4 + true Console @@ -138,6 +144,8 @@ Use false true + Level4 + true Console @@ -150,6 +158,8 @@ Use false true + Level4 + true Console @@ -162,6 +172,8 @@ Use false true + Level4 + true Console diff --git a/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj b/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj index 0fdf11744..85d6bec7f 100644 --- a/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj +++ b/test/nuget/TestStaticLibrary7/TestStaticLibrary7.vcxproj @@ -76,6 +76,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) diff --git a/test/old_tests/Component/Component.vcxproj b/test/old_tests/Component/Component.vcxproj index 6c7df9527..162c8fec7 100644 --- a/test/old_tests/Component/Component.vcxproj +++ b/test/old_tests/Component/Component.vcxproj @@ -140,6 +140,8 @@ false MultiThreadedDebug NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 @@ -174,6 +176,8 @@ false MultiThreadedDebug NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 @@ -209,6 +213,8 @@ $(ProjectDir);$(OutputPath);Generated Files;..\Composable\Generated Files MultiThreaded NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 @@ -242,6 +248,8 @@ $(ProjectDir);$(OutputPath);Generated Files;..\Composable\Generated Files MultiThreaded NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 @@ -278,6 +286,8 @@ false MultiThreadedDebug NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 @@ -311,6 +321,8 @@ $(ProjectDir);$(OutputPath);Generated Files;..\Composable\Generated Files MultiThreaded NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 diff --git a/test/old_tests/Composable/Base.cpp b/test/old_tests/Composable/Base.cpp index a1a1678ff..af2423569 100644 --- a/test/old_tests/Composable/Base.cpp +++ b/test/old_tests/Composable/Base.cpp @@ -43,7 +43,7 @@ namespace winrt::Composable::implementation int32_t Base::ProtectedMethod() { - return 0xDEADBEEF; + return static_cast(0xDEADBEEF); } hstring Base::Name() const diff --git a/test/old_tests/Composable/Composable.vcxproj b/test/old_tests/Composable/Composable.vcxproj index 4e49a255e..fcfd095fc 100644 --- a/test/old_tests/Composable/Composable.vcxproj +++ b/test/old_tests/Composable/Composable.vcxproj @@ -140,6 +140,8 @@ false MultiThreadedDebug NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 precomp.hpp @@ -174,6 +176,8 @@ false MultiThreadedDebug NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 precomp.hpp @@ -209,6 +213,8 @@ $(ProjectDir);$(OutDir);Generated Files MultiThreaded NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 precomp.hpp @@ -242,6 +248,8 @@ $(ProjectDir);$(OutDir);Generated Files MultiThreaded NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 precomp.hpp @@ -278,6 +286,8 @@ false MultiThreadedDebug NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 precomp.hpp @@ -311,6 +321,8 @@ $(ProjectDir);$(OutDir);Generated Files MultiThreaded NOMINMAX;_WINDLL;%(PreprocessorDefinitions) + Level4 + true 4100;4297;4458 precomp.hpp diff --git a/test/old_tests/UnitTests/Boxing2.cpp b/test/old_tests/UnitTests/Boxing2.cpp index cd912ce58..43ca7efd9 100644 --- a/test/old_tests/UnitTests/Boxing2.cpp +++ b/test/old_tests/UnitTests/Boxing2.cpp @@ -41,19 +41,19 @@ namespace REQUIRE(unbox_value_or(wrong_type, v2) == v2); } - REQUIRE(object.as() == v1); - REQUIRE(object.try_as() == v1); - REQUIRE(nothing.try_as() == std::nullopt); + REQUIRE(object.template as() == v1); + REQUIRE(object.template try_as() == v1); + REQUIRE(nothing.template try_as() == std::nullopt); REQUIRE(wrong_type.try_as() == std::nullopt); T result{ v2 }; - object.as(result); + object.template as(result); REQUIRE(result == v1); result = v1; REQUIRE(v1 != empty()); // Test must pass a v1 that is not equal to the empty value. - REQUIRE(!nothing.try_as(result)); + REQUIRE(!nothing.template try_as(result)); REQUIRE(result == empty()); // try_as explicitly empties the result on failure result = v1; diff --git a/test/old_tests/UnitTests/Composable.cpp b/test/old_tests/UnitTests/Composable.cpp index 080e3769c..a9d354c08 100644 --- a/test/old_tests/UnitTests/Composable.cpp +++ b/test/old_tests/UnitTests/Composable.cpp @@ -14,7 +14,7 @@ namespace constexpr auto Base_OverridableMethod{ L"Base::OverridableMethod"sv }; constexpr auto Base_OverridableVirtualMethod{ L"Base::OverridableVirtualMethod"sv }; constexpr auto Base_OverridableNoexceptMethod{ 42 }; - constexpr auto Base_ProtectedMethod{ 0xDEADBEEF }; + constexpr auto Base_ProtectedMethod{ static_cast(0xDEADBEEF) }; constexpr auto Derived_VirtualMethod{ L"Derived::VirtualMethod"sv }; constexpr auto Derived_OverridableVirtualMethod{ L"Derived::OverridableVirtualMethod"sv }; diff --git a/test/old_tests/UnitTests/IInspectable_GetRuntimeClassName.cpp b/test/old_tests/UnitTests/IInspectable_GetRuntimeClassName.cpp index 7db7ed869..53b5260fb 100644 --- a/test/old_tests/UnitTests/IInspectable_GetRuntimeClassName.cpp +++ b/test/old_tests/UnitTests/IInspectable_GetRuntimeClassName.cpp @@ -18,10 +18,17 @@ struct Test_GetRuntimeClassName_NoOverride : implements { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Woverloaded-virtual" +#endif hstring GetRuntimeClassName() { return L"GetRuntimeClassName"; } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif }; TEST_CASE("Test_GetRuntimeClassName_NoOverride") diff --git a/test/old_tests/UnitTests/Tests.vcxproj b/test/old_tests/UnitTests/Tests.vcxproj index a0711f41d..c5169ad4d 100644 --- a/test/old_tests/UnitTests/Tests.vcxproj +++ b/test/old_tests/UnitTests/Tests.vcxproj @@ -206,6 +206,8 @@ false false MultiThreadedDebug + Level4 + true 4100;4297;4458 @@ -225,6 +227,8 @@ false false MultiThreadedDebug + Level4 + true 4100;4297;4458 @@ -244,6 +248,8 @@ false false MultiThreadedDebug + Level4 + true 4100;4297;4458 @@ -261,6 +267,8 @@ _HAS_AUTO_PTR_ETC;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) $(OutputPath);..\Composable\Generated Files;..\Component\Generated Files;..\Composable;..\Reflection\Generated Files;..\..\; MultiThreaded + Level4 + true 4100;4297;4458 @@ -280,6 +288,8 @@ _HAS_AUTO_PTR_ETC;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) $(OutputPath);..\Composable\Generated Files;..\Component\Generated Files;..\Composable;..\Reflection\Generated Files;..\..\; MultiThreaded + Level4 + true 4100;4297;4458 @@ -299,6 +309,8 @@ _HAS_AUTO_PTR_ETC;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) $(OutputPath);..\Composable\Generated Files;..\Component\Generated Files;..\Composable;..\Reflection\Generated Files;..\..\; MultiThreaded + Level4 + true 4100;4297;4458 diff --git a/test/old_tests/UnitTests/array.cpp b/test/old_tests/UnitTests/array.cpp index f6a7654f3..2b5952004 100644 --- a/test/old_tests/UnitTests/array.cpp +++ b/test/old_tests/UnitTests/array.cpp @@ -17,7 +17,7 @@ using namespace Windows::Security::Cryptography::Certificates; // // This is a helper to create a data reader for use in testing arrays. // -static IAsyncOperation CreateDataReader(std::initializer_list values) +static IAsyncOperation CreateDataReader(std::initializer_list /*values*/) { InMemoryRandomAccessStream stream; DataWriter writer(stream); diff --git a/test/old_tests/UnitTests/produce.cpp b/test/old_tests/UnitTests/produce.cpp index 149466002..9ac76ad18 100644 --- a/test/old_tests/UnitTests/produce.cpp +++ b/test/old_tests/UnitTests/produce.cpp @@ -124,10 +124,17 @@ struct produce_IInspectable_No_RuntimeClassName : implements { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Woverloaded-virtual" +#endif hstring GetRuntimeClassName() { return L"produce_IInspectable_RuntimeClassName"; } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif }; TEST_CASE("produce_IInspectable_RuntimeClassName") diff --git a/test/old_tests/UnitTests/smart_pointers.cpp b/test/old_tests/UnitTests/smart_pointers.cpp index fc760fb48..92dca1396 100644 --- a/test/old_tests/UnitTests/smart_pointers.cpp +++ b/test/old_tests/UnitTests/smart_pointers.cpp @@ -7,6 +7,12 @@ using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; using namespace Component; + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wself-assign-overloaded" +#pragma clang diagnostic ignored "-Wself-move" +#endif + namespace { struct Type : implements diff --git a/test/test/disconnected.cpp b/test/test/disconnected.cpp index 53dfbd142..be356fcb3 100644 --- a/test/test/disconnected.cpp +++ b/test/test/disconnected.cpp @@ -148,7 +148,7 @@ struct non_agile_abandoned_action : implements disconnect) : m_disconnect(disconnect) {} - static fire_and_forget final_release(std::unique_ptr self) + static fire_and_forget final_release(std::unique_ptr /*self*/) { // The C++/WinRT m_handler is agile but not context-aware, // so we need to make sure to release it from the context it diff --git a/test/test/event_deferral.cpp b/test/test/event_deferral.cpp index 9b83a2602..e5b538ca2 100644 --- a/test/test/event_deferral.cpp +++ b/test/test/event_deferral.cpp @@ -38,7 +38,7 @@ namespace // This exercises the short-circuit logic in deferrable_event_args. auto NoDeferralHandler() { - return [=](Class const& sender, DeferrableEventArgs const& args) + return [this](Class const& sender, DeferrableEventArgs const& args) { REQUIRE(sender == c); args.IncrementCounter(); @@ -50,7 +50,7 @@ namespace // deferrable_event_args. auto PointlessDeferralHandler() { - return [=](Class const& sender, DeferrableEventArgs const& args) + return [this](Class const& sender, DeferrableEventArgs const& args) { REQUIRE(sender == c); auto deferral = args.GetDeferral(); @@ -61,15 +61,19 @@ namespace auto TakeDeferralHandler(int startState, int finishState) { - return [=](Class sender, DeferrableEventArgs args) -> fire_and_forget + return [this, startState, finishState](Class sender, DeferrableEventArgs args) -> fire_and_forget { + // Captures will go out of scope after the first co_await call. Copy anything needed after that point. + const auto startStateCopy = startState; + const auto finishStateCopy = finishState; + REQUIRE(sender == c); auto deferral = args.GetDeferral(); co_await resume_background(); - wait_for_state(startState); + wait_for_state(startStateCopy); args.IncrementCounter(); deferral.Complete(); - go_to_state(finishState); + go_to_state(finishStateCopy); }; } }; diff --git a/test/test/inspectable_interop.cpp b/test/test/inspectable_interop.cpp index e9094ca77..6a8db907a 100644 --- a/test/test/inspectable_interop.cpp +++ b/test/test/inspectable_interop.cpp @@ -41,11 +41,18 @@ namespace #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Woverloaded-virtual" +#endif +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Woverloaded-virtual" #endif Windows::Foundation::TrustLevel GetTrustLevel() const noexcept { return Windows::Foundation::TrustLevel::PartialTrust; } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif #ifdef __GNUC__ #pragma GCC diagnostic pop #endif diff --git a/test/test/multi_threaded_map.cpp b/test/test/multi_threaded_map.cpp index b2b143f11..d0f68c1e2 100644 --- a/test/test/multi_threaded_map.cpp +++ b/test/test/multi_threaded_map.cpp @@ -90,7 +90,7 @@ namespace using const_reverse_iterator = std::reverse_iterator; using node_type = typename inner::node_type; - mapped_type& operator[](const key_type& key) + mapped_type& operator[](const key_type& /*key*/) { auto guard = concurrency_guard::lock_nonconst(); concurrency_guard::call_hook(collection_action::at); diff --git a/test/test/out_params.cpp b/test/test/out_params.cpp index 7aafb63ae..7fd2f536e 100644 --- a/test/test/out_params.cpp +++ b/test/test/out_params.cpp @@ -134,7 +134,7 @@ TEST_CASE("out_params") REQUIRE(value[3] == nullptr); } { - std::array value{ {L"First", L"Second"} }; + std::array value{ { { L"First" }, { L"Second"} } }; object.RefStructArray(value); REQUIRE(value[0].First == L"1"); REQUIRE(value[0].Second == L"2"); @@ -260,7 +260,7 @@ TEST_CASE("out_params") REQUIRE(value[3] == nullptr); } { - std::array value{ {L"First", L"Second"} }; + std::array value{ { { L"First" }, { L"Second"} } }; REQUIRE_THROWS_AS(object.RefStructArray(value), hresult_invalid_argument); REQUIRE(value[0].First == L""); REQUIRE(value[0].Second == L""); diff --git a/test/test/return_params_abi.cpp b/test/test/return_params_abi.cpp index 1d4af9a9f..5e7c11cd3 100644 --- a/test/test/return_params_abi.cpp +++ b/test/test/return_params_abi.cpp @@ -12,12 +12,19 @@ using namespace winrt; namespace { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +#endif hstring to_hstring(::IInspectable* raw) { winrt::IInspectable object; copy_from_abi(object, raw); return object.as().ToString(); } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif } TEST_CASE("return_params_abi") diff --git a/test/test/struct_delegate.cpp b/test/test/struct_delegate.cpp index 26fcd9e64..785a0fb0a 100644 --- a/test/test/struct_delegate.cpp +++ b/test/test/struct_delegate.cpp @@ -1,5 +1,5 @@ #include "pch.h" -#include "winrt/test_component.delegates.h" +#include "winrt/test_component.Delegates.h" using namespace winrt; using namespace test_component; diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index f1035ab6c..7840f17eb 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -92,6 +92,8 @@ $(OutputPath);Generated Files;..;..\..\cppwinrt _MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -112,6 +114,8 @@ $(OutputPath);Generated Files;..;..\..\cppwinrt _MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -130,6 +134,8 @@ $(OutputPath);Generated Files;..;..\..\cppwinrt _MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -148,6 +154,8 @@ $(OutputPath);Generated Files;..;..\..\cppwinrt _MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -168,6 +176,8 @@ $(OutputPath);Generated Files;..;..\..\cppwinrt _MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -190,6 +200,8 @@ $(OutputPath);Generated Files;..;..\..\cppwinrt _MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console diff --git a/test/test_component/Class.cpp b/test/test_component/Class.cpp index 4f36df5c1..3f68d96c3 100644 --- a/test/test_component/Class.cpp +++ b/test/test_component/Class.cpp @@ -519,7 +519,14 @@ namespace winrt::test_component::implementation namespace { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +#endif void ValidateStaticEventAutoRevoke() { auto x = winrt::test_component::Simple::StaticEvent(winrt::auto_revoke, [](auto&&, auto&&) {}); } +#ifdef __clang__ +#pragma clang diagnostic pop +#endif } \ No newline at end of file diff --git a/test/test_component/test_component.vcxproj b/test/test_component/test_component.vcxproj index 9751fb5a2..3ffdb8f97 100644 --- a/test/test_component/test_component.vcxproj +++ b/test/test_component/test_component.vcxproj @@ -114,6 +114,8 @@ .;$(OutputPath);Generated Files /Zc:threadSafeInit- /we4640 %(AdditionalOptions) MultiThreadedDebug + Level4 + true exports.def @@ -150,6 +152,8 @@ .;$(OutputPath);Generated Files /Zc:threadSafeInit- /we4640 %(AdditionalOptions) MultiThreadedDebug + Level4 + true exports.def @@ -199,6 +203,8 @@ .;$(OutputPath);Generated Files /Zc:threadSafeInit- /we4640 %(AdditionalOptions) MultiThreadedDebug + Level4 + true exports.def @@ -237,6 +243,8 @@ .;$(OutputPath);Generated Files /Zc:threadSafeInit- /we4640 %(AdditionalOptions) MultiThreaded + Level4 + true true @@ -277,6 +285,8 @@ .;$(OutputPath);Generated Files /Zc:threadSafeInit- /we4640 %(AdditionalOptions) MultiThreaded + Level4 + true true @@ -330,6 +340,8 @@ .;$(OutputPath);Generated Files /Zc:threadSafeInit- /we4640 %(AdditionalOptions) MultiThreaded + Level4 + true true diff --git a/test/test_component_base/HierarchyA.cpp b/test/test_component_base/HierarchyA.cpp index 887b31bc9..45b3e6098 100644 --- a/test/test_component_base/HierarchyA.cpp +++ b/test/test_component_base/HierarchyA.cpp @@ -3,11 +3,11 @@ namespace winrt::test_component_base::implementation { - HierarchyA::HierarchyA(hstring const& name) + HierarchyA::HierarchyA(hstring const& /*name*/) { throw hresult_not_implemented(); } - HierarchyA::HierarchyA(int32_t dummy, hstring const& name) + HierarchyA::HierarchyA(int32_t /*dummy*/, hstring const& /*name*/) { throw hresult_not_implemented(); } diff --git a/test/test_component_base/HierarchyB.cpp b/test/test_component_base/HierarchyB.cpp index 30b9f09ff..b56988f73 100644 --- a/test/test_component_base/HierarchyB.cpp +++ b/test/test_component_base/HierarchyB.cpp @@ -5,7 +5,7 @@ namespace winrt::test_component_base::implementation { - HierarchyB::HierarchyB(hstring const& name) + HierarchyB::HierarchyB(hstring const& /*name*/) { throw hresult_not_implemented(); } diff --git a/test/test_component_base/test_component_base.vcxproj b/test/test_component_base/test_component_base.vcxproj index 947c53e8f..90577a2c5 100644 --- a/test/test_component_base/test_component_base.vcxproj +++ b/test/test_component_base/test_component_base.vcxproj @@ -114,6 +114,8 @@ $(ProjectDir);$(OutputPath);Generated Files 4100 MultiThreadedDebug + Level4 + true exports.def @@ -162,6 +164,8 @@ $(ProjectDir);$(OutputPath);Generated Files 4100 MultiThreadedDebug + Level4 + true exports.def @@ -224,6 +228,8 @@ $(ProjectDir);$(OutputPath);Generated Files 4100 MultiThreadedDebug + Level4 + true exports.def @@ -274,6 +280,8 @@ $(ProjectDir);$(OutputPath);Generated Files 4100 MultiThreaded + Level4 + true true @@ -326,6 +334,8 @@ $(ProjectDir);$(OutputPath);Generated Files 4100 MultiThreaded + Level4 + true true @@ -392,6 +402,8 @@ $(ProjectDir);$(OutputPath);Generated Files 4100 MultiThreaded + Level4 + true true diff --git a/test/test_component_derived/Nested.HierarchyD.cpp b/test/test_component_derived/Nested.HierarchyD.cpp index bad2cf1ce..8011e73e6 100644 --- a/test/test_component_derived/Nested.HierarchyD.cpp +++ b/test/test_component_derived/Nested.HierarchyD.cpp @@ -3,7 +3,7 @@ namespace winrt::test_component_derived::Nested::implementation { - HierarchyD::HierarchyD(hstring const& name) + HierarchyD::HierarchyD(hstring const& /*name*/) { throw hresult_not_implemented(); } diff --git a/test/test_component_derived/test_component_derived.vcxproj b/test/test_component_derived/test_component_derived.vcxproj index a1c856c90..837d8821e 100644 --- a/test/test_component_derived/test_component_derived.vcxproj +++ b/test/test_component_derived/test_component_derived.vcxproj @@ -112,6 +112,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files + Level4 + true 4100 MultiThreadedDebug @@ -161,6 +163,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files + Level4 + true 4100 MultiThreadedDebug @@ -224,6 +228,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files + Level4 + true 4100 MultiThreadedDebug @@ -275,6 +281,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files + Level4 + true 4100 MultiThreaded @@ -328,6 +336,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files + Level4 + true 4100 MultiThreaded @@ -395,6 +405,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files;..\test_component_base\Generated Files + Level4 + true 4100 MultiThreaded diff --git a/test/test_component_fast/test_component_fast.vcxproj b/test/test_component_fast/test_component_fast.vcxproj index 5d646cf78..ed5a36222 100644 --- a/test/test_component_fast/test_component_fast.vcxproj +++ b/test/test_component_fast/test_component_fast.vcxproj @@ -114,6 +114,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) + Level4 + true 4100 MultiThreadedDebug @@ -163,6 +165,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) + Level4 + true 4100 MultiThreadedDebug @@ -226,6 +230,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) + Level4 + true 4100 MultiThreadedDebug @@ -277,6 +283,8 @@ true $(ProjectDir);$(OutputPath);Generated Files /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) + Level4 + true 4100 MultiThreaded @@ -330,6 +338,8 @@ true $(ProjectDir);$(OutputPath);Generated Files /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) + Level4 + true 4100 MultiThreaded @@ -397,6 +407,8 @@ true $(ProjectDir);$(OutputPath);Generated Files /DWINRT_FAST_ABI_SIZE=50 %(AdditionalOptions) + Level4 + true 4100 MultiThreaded diff --git a/test/test_component_folders/test_component_folders.vcxproj b/test/test_component_folders/test_component_folders.vcxproj index 6d642096f..14c12f8f9 100644 --- a/test/test_component_folders/test_component_folders.vcxproj +++ b/test/test_component_folders/test_component_folders.vcxproj @@ -112,6 +112,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 MultiThreadedDebug @@ -160,6 +162,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 MultiThreadedDebug @@ -222,6 +226,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 MultiThreadedDebug @@ -272,6 +278,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 MultiThreaded @@ -324,6 +332,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 MultiThreaded @@ -390,6 +400,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 MultiThreaded diff --git a/test/test_component_no_pch/test_component_no_pch.vcxproj b/test/test_component_no_pch/test_component_no_pch.vcxproj index 0b1a98271..117be2d00 100644 --- a/test/test_component_no_pch/test_component_no_pch.vcxproj +++ b/test/test_component_no_pch/test_component_no_pch.vcxproj @@ -112,6 +112,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 NotUsing MultiThreadedDebug @@ -161,6 +163,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 NotUsing MultiThreadedDebug @@ -224,6 +228,8 @@ Disabled $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 NotUsing MultiThreadedDebug @@ -275,6 +281,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 NotUsing MultiThreaded @@ -328,6 +336,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 NotUsing MultiThreaded @@ -395,6 +405,8 @@ true true $(ProjectDir);$(OutputPath);Generated Files + Level4 + true 4100 NotUsing MultiThreaded diff --git a/test/test_cpp20/array_span.cpp b/test/test_cpp20/array_span.cpp index dff5a2ec5..8cebc4a1e 100644 --- a/test/test_cpp20/array_span.cpp +++ b/test/test_cpp20/array_span.cpp @@ -10,7 +10,7 @@ using namespace Windows::Data::Json; // // This is a helper to create a data reader for use in testing arrays. // -static IAsyncOperation CreateDataReader(std::initializer_list values) +static IAsyncOperation CreateDataReader(std::initializer_list /*values*/) { InMemoryRandomAccessStream stream; DataWriter writer(stream); diff --git a/test/test_cpp20/clang_only.cpp b/test/test_cpp20/clang_only.cpp new file mode 100644 index 000000000..45aa4b380 --- /dev/null +++ b/test/test_cpp20/clang_only.cpp @@ -0,0 +1,23 @@ +#include "pch.h" +#include + +#ifdef __clang__ + +using namespace winrt; +using namespace Windows::Foundation; +using namespace Windows::Storage::Pickers; + +TEST_CASE("clang_lto_visibility") +{ + // A previous bug report (https://github.com/microsoft/cppwinrt/pull/1482) represented a problem when some linker + // options (-O3 -flto -fwhole-program-vtables) were used with cppwinrt generated code. The lack of public annotation + // caused methods to be removed from the binary, leading to a crash. This test case aims to be a regression test for + // that problem. + FileOpenPicker picker{}; + picker.ViewMode(PickerViewMode::Thumbnail); + picker.FileTypeFilter().Append(L".png"); // This line would trigger the crash. + + REQUIRE(true); +} + +#endif // __clang__ \ No newline at end of file diff --git a/test/test_cpp20/test_cpp20.vcxproj b/test/test_cpp20/test_cpp20.vcxproj index 832297f7f..4eaee0a18 100644 --- a/test/test_cpp20/test_cpp20.vcxproj +++ b/test/test_cpp20/test_cpp20.vcxproj @@ -93,6 +93,9 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true + %(AdditionalOptions) -O3 -flto -fwhole-program-vtables Console @@ -114,6 +117,9 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true + %(AdditionalOptions) -flto -fwhole-program-vtables Console @@ -133,6 +139,9 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true + %(AdditionalOptions) -flto -fwhole-program-vtables Console @@ -152,6 +161,9 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true + %(AdditionalOptions) -flto -fwhole-program-vtables Console @@ -173,6 +185,9 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true + %(AdditionalOptions) -O3 -flto -fwhole-program-vtables Console @@ -196,6 +211,9 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true + %(AdditionalOptions) -O3 -flto -fwhole-program-vtables Console @@ -217,6 +235,7 @@ + diff --git a/test/test_cpp20_no_sourcelocation/custom_error.cpp b/test/test_cpp20_no_sourcelocation/custom_error.cpp index 43e5f16d9..d9905ea04 100644 --- a/test/test_cpp20_no_sourcelocation/custom_error.cpp +++ b/test/test_cpp20_no_sourcelocation/custom_error.cpp @@ -53,7 +53,7 @@ TEST_CASE("custom_error_logger") REQUIRE(s_loggerArgs.functionName == nullptr); REQUIRE(s_loggerArgs.returnAddress); - REQUIRE(s_loggerArgs.result == 0x80000018); // E_ILLEGAL_DELEGATE_ASSIGNMENT) + REQUIRE(s_loggerArgs.result == static_cast(0x80000018)); // E_ILLEGAL_DELEGATE_ASSIGNMENT) // Remove global handler winrt_throw_hresult_handler = nullptr; diff --git a/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj b/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj index 86a56a3b9..85c3e1532 100644 --- a/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj +++ b/test/test_cpp20_no_sourcelocation/test_cpp20_no_sourcelocation.vcxproj @@ -89,6 +89,8 @@ WINRT_NO_SOURCE_LOCATION;%(PreprocessorDefinitions) + Level4 + true diff --git a/test/test_fast/Nomadic.cpp b/test/test_fast/Nomadic.cpp index 98753c06d..c29150e17 100644 --- a/test/test_fast/Nomadic.cpp +++ b/test/test_fast/Nomadic.cpp @@ -11,7 +11,15 @@ hstring invoke_by_interface_vtable_offset(Nomadic const& nomadic, ptrdiff_t offs // that IInspectable has 6 functions in total (including those inherited from IUnknown) auto insp = static_cast<::IInspectable*>(get_abi(nomadic)); auto vtable = *reinterpret_cast(insp); + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wmicrosoft-cast" +#endif auto fn_ptr = static_cast(vtable[6 + offset]); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif HSTRING hstr; check_hresult(fn_ptr(insp, &hstr)); diff --git a/test/test_fast/test_fast.vcxproj b/test/test_fast/test_fast.vcxproj index 27a7ea350..c01907348 100644 --- a/test/test_fast/test_fast.vcxproj +++ b/test/test_fast/test_fast.vcxproj @@ -92,6 +92,8 @@ $(OutputPath);Generated Files;..\; WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -113,6 +115,8 @@ $(OutputPath);Generated Files;..\; WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -132,6 +136,8 @@ $(OutputPath);Generated Files;..\; WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -151,6 +157,8 @@ $(OutputPath);Generated Files;..\; WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -172,6 +180,8 @@ $(OutputPath);Generated Files;..\; WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -195,6 +205,8 @@ $(OutputPath);Generated Files;..\; WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console diff --git a/test/test_fast_fwd/test_fast_fwd.vcxproj b/test/test_fast_fwd/test_fast_fwd.vcxproj index d4b63c3fb..6d049b1a9 100644 --- a/test/test_fast_fwd/test_fast_fwd.vcxproj +++ b/test/test_fast_fwd/test_fast_fwd.vcxproj @@ -59,6 +59,8 @@ true $(CppWinRTDir);$(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) + Level4 + true Console @@ -86,6 +88,8 @@ pch.h true WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) + Level4 + true Console @@ -106,6 +110,8 @@ Disabled $(CppWinRTDir);$(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) + Level4 + true Console @@ -123,6 +129,8 @@ Disabled $(CppWinRTDir);$(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) + Level4 + true Console @@ -146,6 +154,8 @@ pch.h true WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) + Level4 + true Console @@ -166,6 +176,8 @@ true $(CppWinRTDir);$(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) + Level4 + true Console diff --git a/test/test_module_lock_custom/test_module_lock_custom.vcxproj b/test/test_module_lock_custom/test_module_lock_custom.vcxproj index 6671a1156..64da0d8bc 100644 --- a/test/test_module_lock_custom/test_module_lock_custom.vcxproj +++ b/test/test_module_lock_custom/test_module_lock_custom.vcxproj @@ -92,6 +92,8 @@ $(OutputPath);Generated Files;..\; NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -113,6 +115,8 @@ $(OutputPath);Generated Files;..\; NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -132,6 +136,8 @@ $(OutputPath);Generated Files;..\; NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -151,6 +157,8 @@ $(OutputPath);Generated Files;..\; NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -172,6 +180,8 @@ $(OutputPath);Generated Files;..\; NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -195,6 +205,8 @@ $(OutputPath);Generated Files;..\; NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console diff --git a/test/test_module_lock_none/main.cpp b/test/test_module_lock_none/main.cpp index ca8eab7ac..9648ad8be 100644 --- a/test/test_module_lock_none/main.cpp +++ b/test/test_module_lock_none/main.cpp @@ -57,11 +57,18 @@ TEST_CASE("module_lock_none") // Validates that test_component_base is pinned by virtue of it defining WINRT_NO_MODULE_LOCK. +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wcast-function-type-mismatch" +#endif auto can_unload = reinterpret_cast(GetProcAddress(LoadLibraryA("test_component_base.dll"), "DllCanUnloadNow")); REQUIRE(can_unload() == S_FALSE); auto cannot_unload = reinterpret_cast(GetProcAddress(LoadLibraryA("test_component_derived.dll"), "DllCanUnloadNow")); REQUIRE(cannot_unload() == S_OK); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif } int main(int const argc, char** argv) diff --git a/test/test_module_lock_none/test_module_lock_none.vcxproj b/test/test_module_lock_none/test_module_lock_none.vcxproj index 381edbdfe..d9242a281 100644 --- a/test/test_module_lock_none/test_module_lock_none.vcxproj +++ b/test/test_module_lock_none/test_module_lock_none.vcxproj @@ -92,6 +92,8 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -113,6 +115,8 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -132,6 +136,8 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -151,6 +157,8 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -172,6 +180,8 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -195,6 +205,8 @@ $(OutputPath);Generated Files;..\ NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console diff --git a/test/test_slow/test_slow.vcxproj b/test/test_slow/test_slow.vcxproj index eb6c7fc60..5b753a17a 100644 --- a/test/test_slow/test_slow.vcxproj +++ b/test/test_slow/test_slow.vcxproj @@ -92,6 +92,8 @@ $(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -112,6 +114,8 @@ $(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -130,6 +134,8 @@ $(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -148,6 +154,8 @@ $(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreadedDebug + Level4 + true Console @@ -168,6 +176,8 @@ $(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console @@ -190,6 +200,8 @@ $(OutputPath);Generated Files;..\ WINRT_DIAGNOSTICS;NOMINMAX;_MBCS;%(PreprocessorDefinitions) MultiThreaded + Level4 + true Console diff --git a/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj b/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj index f82376473..f205306b8 100644 --- a/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Desktop/ConsoleApplication/ConsoleApplication.vcxproj @@ -67,6 +67,7 @@ $(IntDir)pch.pch _CONSOLE;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) Level4 + true %(AdditionalOptions) /permissive- /bigobj diff --git a/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj b/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj index 8b8cb03ce..e4a05cdc7 100644 --- a/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Desktop/WindowsApplication/WindowsApplication.vcxproj @@ -67,6 +67,7 @@ $(IntDir)pch.pch _CONSOLE;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) Level4 + true %(AdditionalOptions) /permissive- /bigobj diff --git a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj index 30630610e..ae3d074f2 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/BlankApp/BlankApp.vcxproj @@ -76,6 +76,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) diff --git a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj index 841ff85c9..2d891ef11 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/CoreApp/CoreApp.vcxproj @@ -75,6 +75,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) diff --git a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj index ec8126558..2afea1c00 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/StaticLibrary/StaticLibrary.vcxproj @@ -81,6 +81,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) diff --git a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj index 78c477177..da87bf2fb 100644 --- a/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj +++ b/vsix/ProjectTemplates/VC/Windows Universal/WindowsRuntimeComponent/WindowsRuntimeComponent.vcxproj @@ -80,6 +80,7 @@ pch.h $(IntDir)pch.pch Level4 + true %(AdditionalOptions) /bigobj _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) From 4c9e03fe1e3d7cbfbf742ec237e9af5b30add68a Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sun, 4 May 2025 13:51:28 -0500 Subject: [PATCH 47/91] fix indent in generated code (#1489) Fix a line that was indented too much in the generated code. --- cppwinrt/code_writers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index ae2920d56..ffc0ee948 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1868,7 +1868,7 @@ namespace cppwinrt { auto param_name = param.Name(); - w.write("\n if (%) *% = detach_abi(winrt_impl_%);", param_name, param_name, param_name); + w.write("\n if (%) *% = detach_abi(winrt_impl_%);", param_name, param_name, param_name); } } } From 1a678d68b9e3ad25722318127d15057d377dac16 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 09:06:52 -0700 Subject: [PATCH 48/91] Bump actions/checkout from 4 to 5 (#1502) Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8544bcf77..11fc05c26 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: config: Release runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Download nuget run: | @@ -102,7 +102,7 @@ jobs: config: Release runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' @@ -250,7 +250,7 @@ jobs: CMAKE_COLOR_DIAGNOSTICS: 1 CLICOLOR_FORCE: 1 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Install cross compiler run: | @@ -283,7 +283,7 @@ jobs: Deployment: [Component, Standalone] runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Download nuget run: | @@ -323,7 +323,7 @@ jobs: config: [Release] runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Fetch cppwinrt executables uses: actions/download-artifact@v4 @@ -368,7 +368,7 @@ jobs: name: Build nuget package with MSVC runs-on: windows-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Package run: | From a338c862c43e16ee8c3ba77bcae92d821be2deb5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 09:35:09 -0700 Subject: [PATCH 49/91] Bump actions/download-artifact from 4 to 5 (#1501) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 5. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 11fc05c26..866fddd7d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,14 +106,14 @@ jobs: - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: msvc-build-${{ matrix.compiler}}-x86-Release-bin path: _build/x86/Release/ @@ -326,7 +326,7 @@ jobs: - uses: actions/checkout@v5 - name: Fetch cppwinrt executables - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ From 34fba98b48cc4cf98e069f7f2c1f7f51122894cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 13:59:36 -0500 Subject: [PATCH 50/91] Bump actions/stale from 9 to 10 (#1507) --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index c081bdf43..b686df568 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -13,7 +13,7 @@ jobs: pull-requests: write steps: - - uses: actions/stale@v9 + - uses: actions/stale@v10 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 10 From ebace4abb8f48b6b9a612e8b84667e6044976a47 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Thu, 16 Oct 2025 09:33:43 -0700 Subject: [PATCH 51/91] Fix CI build by using latest Windows SDK in C# project (#1516) * Attempt "latest SDK" setting * Update TargetPlatformVersion to use WindowsSDKVersion * Fix TargetPlatformVersion trimming in project file --- .../TestRuntimeComponentCSharp.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj b/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj index d756e19b7..167b32ad9 100644 --- a/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj +++ b/test/nuget/TestRuntimeComponentCSharp/TestRuntimeComponentCSharp.csproj @@ -11,7 +11,7 @@ TestRuntimeComponentCSharp en-US UAP - 10.0.22621.0 + $(WindowsSDKVersion.TrimEnd('\')) 10.0.18362.0 14 512 @@ -93,4 +93,4 @@ --> - \ No newline at end of file + From dcaa98c8d2abeb47ab5ce9ef1f96171e93d0ff9b Mon Sep 17 00:00:00 2001 From: antmor <43587397+antmor@users.noreply.github.com> Date: Thu, 30 Oct 2025 10:59:16 -0700 Subject: [PATCH 52/91] Remove throwing/originating errors in expected scenarios (Lookup/TryLookup and Cancel) (#1512) * non-originating error compiles * fix with test cases * and remove ignore * add runsettings to run tests from visual studio tester, modified readme, make shouldOrigiante a template param. * change map shouldOriginate to template parameter. Note, could be a breakig change for usages of map that are not default (i.e. custom std::less) if so, might need to split up templates into separate template, or spin out into separate pr. changed bool to template parameter in hresult_error, as the char*-to-bool decaying conversion failed the old tests. also fixed runsettings, added note in readme. * settle on avoid_originate as naming scheme * add a printf only to Lookup so we can add SFINAE or something like that. * weird templating magic required... still not working, has error 1>G:\source\repos\cppwinrt\_build\x64\Debug\winrt\Windows.Foundation.Collections.h(868,51): error C3878: syntax error: unexpected token '>' following 'simple-type-specifier' 1>(compiling source file '/Class.cpp') 1> G:\source\repos\cppwinrt\_build\x64\Debug\winrt\Windows.Foundation.Collections.h(868,51): 1> missing one of: '(' '{' ? * trylookup exists to avoid throwing an error, and let's avoid avoid_originate now. * remove test. * cleaned up and correctness. * undo changes to untouched files * spacing changes , change do declval. * added special tag to parameter list to make sure not to break existing TryLookup impls, added test to verify this. * address avoid_oritinate comment, no need for a different name, resuse existing hresult_cancelled * change out async to a new name, with it being true by default. add new unittest to test nullable lookup. * Address hresult comments by adding tests and removing source_locatoin, special-cased further by checking the typename. * add unittest without specialization, make sure that the behaviour is opt-in --------- Co-authored-by: Chris Guzak --- .runsettings | 24 +++++ README.md | 5 + cppwinrt/code_writers.h | 80 ++++++++++++++-- strings/base_collections_base.h | 15 +++ strings/base_coroutine_foundation.h | 22 ++++- strings/base_coroutine_threadpool.h | 11 +++ strings/base_error.h | 8 ++ strings/base_meta.h | 16 ++++ test/old_tests/UnitTests/Errors.cpp | 1 + test/old_tests/UnitTests/TryLookup.cpp | 127 ++++++++++++++++++++++++- test/test/async_check_cancel.cpp | 80 +++++++++++++++- test/test_cpp20/custom_error.cpp | 63 +++++++++++- 12 files changed, 437 insertions(+), 15 deletions(-) create mode 100644 .runsettings diff --git a/.runsettings b/.runsettings new file mode 100644 index 000000000..5f10e44f8 --- /dev/null +++ b/.runsettings @@ -0,0 +1,24 @@ + + + + .\TestResults + 60000 + true + + + + + + + Single + (?i:Test) + true + on + true + Verbose + AdditionalInfo + ShortInfo + , + 20000 + + \ No newline at end of file diff --git a/README.md b/README.md index 1749fea0c..19e1493dc 100644 --- a/README.md +++ b/README.md @@ -34,3 +34,8 @@ a dev command prompt at the root of the repo _after_ following the above build i * Run `build_prior_projection.cmd` in the dev command prompt as well * Run `prepare_versionless_diffs.cmd` which removes version stamps on both current and prior projection * Use a directory-level differencing tool to compare `_build\$(arch)\$(flavor)\winrt` and `_reference\$(arch)\$(flavor)\winrt` + +## Testing +This repository uses the [Catch2](https://github.com/catchorg/Catch2) testing framework. +- From a Visual Studio command line, you should run `build_tests_all.cmd` to build and run the tests. To Debug the tests, you can debug the associated `_build\$(arch)\$(flavor)\.exe` under the debugger of your choice. +- Optionally, you can install the [Catch2Adapter](https://marketplace.visualstudio.com/items?itemName=JohnnyHendriks.ext01) to run the tests from Visual Studio. \ No newline at end of file diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index ffc0ee948..35e9935d0 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1873,7 +1873,37 @@ namespace cppwinrt } } - static void write_produce_method(writer& w, MethodDef const& method) + static void write_produce_upcall_TryLookup(writer& w, std::string_view const& upcall, method_signature const& method_signature) + { + auto name = method_signature.return_param_name(); + + w.write("auto out_param_val = %(%, trylookup_from_abi);", + upcall, + bind(method_signature)); + w.write(R"( + if (out_param_val.has_value()) + { + *% = detach_from<%>(std::move(*out_param_val)); + } + else + { + return impl::error_out_of_bounds; + } +)", + name, method_signature.return_signature()); + + for (auto&& [param, param_signature] : method_signature.params()) + { + if (param.Flags().Out() && !param_signature->Type().is_szarray() && is_object(param_signature->Type())) + { + auto param_name = param.Name(); + + w.write("\n if (%) *% = detach_abi(winrt_impl_%);", param_name, param_name, param_name); + } + } + } + + static void write_produce_method(writer& w, MethodDef const& method, TypeDef const& type) { std::string_view format; @@ -1902,13 +1932,45 @@ namespace cppwinrt method_signature signature{ method }; auto async_types_guard = w.push_async_types(signature.is_async()); std::string upcall = "this->shim()."; - upcall += get_name(method); + auto name = get_name(method); + upcall += name; - w.write(format, - get_abi_name(method), - bind(signature), - bind(signature), - bind(upcall, signature)); + auto typeName = type.TypeName(); + if (((typeName == "IMapView`2") || (typeName == "IMap`2")) + && (name == "Lookup")) + { + // Special-case IMap*::Lookup to look for a TryLookup here, to avoid extranous throw/originates + std::string tryLookupUpCall = "this->shim().TryLookup"; + format = R"( int32_t __stdcall %(%) noexcept final try + { +% typename D::abi_guard guard(this->shim()); + if constexpr (has_TryLookup_v) + { + % + } + else + { + % + } + return 0; + } + catch (...) { return to_hresult(); } +)"; + w.write(format, + get_abi_name(method), + bind(signature), + bind(signature), // clear_abi + bind(tryLookupUpCall, signature), + bind(upcall, signature)); + } + else + { + w.write(format, + get_abi_name(method), + bind(signature), + bind(signature), + bind(upcall, signature)); + } } static void write_fast_produce_methods(writer& w, TypeDef const& default_interface) @@ -1951,7 +2013,7 @@ namespace cppwinrt break; } - w.write_each(info.type.MethodList()); + w.write_each(info.type.MethodList(), info.type); } } @@ -1973,7 +2035,7 @@ namespace cppwinrt bind(generics), type, type, - bind_each(type.MethodList()), + bind_each(type.MethodList(), type), bind(type)); } diff --git a/strings/base_collections_base.h b/strings/base_collections_base.h index f3ede9ed4..fec3de660 100644 --- a/strings/base_collections_base.h +++ b/strings/base_collections_base.h @@ -506,6 +506,20 @@ WINRT_EXPORT namespace winrt template struct map_view_base : iterable_base, Version> { + // specialization of Lookup that avoids throwing the hresult + std::optional TryLookup(K const& key, trylookup_from_abi_t) const + { + [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); + auto pair = static_cast(*this).get_container().find(static_cast(*this).wrap_value(key)); + + if (pair == static_cast(*this).get_container().end()) + { + return std::nullopt; + } + + return static_cast(*this).unwrap_value(pair->second); + } + V Lookup(K const& key) const { [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); @@ -536,6 +550,7 @@ WINRT_EXPORT namespace winrt first = nullptr; second = nullptr; } + }; template diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 670a65403..87aaed24e 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -351,6 +351,10 @@ namespace winrt::impl return m_promise->enable_cancellation_propagation(value); } + bool originate_on_cancel(bool value = true) const noexcept + { + return m_promise->originate_on_cancel(value); + } private: Promise* m_promise; @@ -484,7 +488,14 @@ namespace winrt::impl if (m_status.load(std::memory_order_relaxed) == AsyncStatus::Started) { m_status.store(AsyncStatus::Canceled, std::memory_order_relaxed); - m_exception = std::make_exception_ptr(hresult_canceled()); + if (cancellable_promise::originate_on_cancel()) + { + m_exception = std::make_exception_ptr(hresult_canceled()); + } + else + { + m_exception = std::make_exception_ptr(hresult_canceled(hresult_error::no_originate)); + } cancel = std::move(m_cancel); } } @@ -628,7 +639,14 @@ namespace winrt::impl { if (Status() == AsyncStatus::Canceled) { - throw winrt::hresult_canceled(); + if (cancellable_promise::originate_on_cancel()) + { + throw winrt::hresult_canceled(); + } + else + { + throw winrt::hresult_canceled(hresult_error::no_originate); + } } return std::forward(expression); diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index 0faaa1acd..7fa8789c7 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -180,12 +180,23 @@ WINRT_EXPORT namespace winrt return m_propagate_cancellation; } + bool originate_on_cancel(bool value = true) noexcept + { + return std::exchange(m_originate_on_cancel, value); + } + + bool should_originate_on_cancel() const noexcept + { + return m_originate_on_cancel; + } + private: static inline auto const cancelling_ptr = reinterpret_cast(1); std::atomic m_canceller{ nullptr }; void* m_context{ nullptr }; bool m_propagate_cancellation{ false }; + bool m_originate_on_cancel{ true }; // By default, will call RoOriginateError before throwing a cancel error code. }; template diff --git a/strings/base_error.h b/strings/base_error.h index 85de70f63..41929336b 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -84,6 +84,9 @@ WINRT_EXPORT namespace winrt { struct hresult_error { + struct no_originate_t {}; + static constexpr no_originate_t no_originate{}; + using from_abi_t = take_ownership_from_abi_t; static constexpr auto from_abi{ take_ownership_from_abi }; @@ -109,6 +112,10 @@ WINRT_EXPORT namespace winrt originate(code, nullptr, sourceInformation); } + explicit hresult_error(hresult const code, no_originate_t) noexcept : m_code(verify_error(code)) + { + } + hresult_error(hresult const code, param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : m_code(verify_error(code)) { originate(code, get_abi(message), sourceInformation); @@ -325,6 +332,7 @@ WINRT_EXPORT namespace winrt struct hresult_canceled : hresult_error { hresult_canceled(winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_canceled, sourceInformation) {} + hresult_canceled(hresult_error::no_originate_t) noexcept : hresult_error(impl::error_canceled, hresult_error::no_originate) {} hresult_canceled(param::hstring const& message, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_canceled, message, sourceInformation) {} hresult_canceled(take_ownership_from_abi_t, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) noexcept : hresult_error(impl::error_canceled, take_ownership_from_abi, sourceInformation) {} }; diff --git a/strings/base_meta.h b/strings/base_meta.h index 25deb42ec..7dbb4c386 100644 --- a/strings/base_meta.h +++ b/strings/base_meta.h @@ -10,6 +10,10 @@ WINRT_EXPORT namespace winrt struct take_ownership_from_abi_t {}; inline constexpr take_ownership_from_abi_t take_ownership_from_abi{}; + // Map implementations can implement TryLookup with trylookup_from_abi_t as an optimization + struct trylookup_from_abi_t {}; + inline constexpr trylookup_from_abi_t trylookup_from_abi{}; + template struct com_ptr; @@ -298,4 +302,16 @@ namespace winrt::impl return (func(Types{}) || ...); } }; + + template + struct has_TryLookup + { + template ().TryLookup(std::declval(), trylookup_from_abi))> static constexpr bool get_value(int) { return true; } + template static constexpr bool get_value(...) { return false; } + public: + static constexpr bool value = get_value(0); + }; + + template + inline constexpr bool has_TryLookup_v = has_TryLookup::value; } diff --git a/test/old_tests/UnitTests/Errors.cpp b/test/old_tests/UnitTests/Errors.cpp index 472d633f1..f8656a508 100644 --- a/test/old_tests/UnitTests/Errors.cpp +++ b/test/old_tests/UnitTests/Errors.cpp @@ -233,6 +233,7 @@ TEST_CASE("Errors") // Make sure trimming works. hresult_error e(E_FAIL, L":) is \u263A \n \t "); + auto x = e.message(); REQUIRE(e.message() == L":) is \u263A"); // Make sure delegates propagate correctly. diff --git a/test/old_tests/UnitTests/TryLookup.cpp b/test/old_tests/UnitTests/TryLookup.cpp index 3c6c54580..350fa9006 100644 --- a/test/old_tests/UnitTests/TryLookup.cpp +++ b/test/old_tests/UnitTests/TryLookup.cpp @@ -143,4 +143,129 @@ TEST_CASE("TryLookup TryRemove error") REQUIRE(!map.TryLookup(123)); REQUIRE(!map.TryRemove(123)); -} \ No newline at end of file +} + +TEST_CASE("trylookup_from_abi specialization") +{ + // A map that throws a specific error, used to verify various edge cases. + // and implements tryLookup, to take advantage of an optimization to avoid a throw. + struct map_with_try_lookup : implements> + { + hresult codeToThrow{ S_OK }; + bool shouldThrowOnTryLookup{ false }; + std::optional TryLookup(int, trylookup_from_abi_t) + { + if (shouldThrowOnTryLookup) + { + throw_hresult(codeToThrow); + } + else + { + return { std::nullopt }; + } + } + int Lookup(int) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + int32_t Size() { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + bool HasKey(int) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + void Split(IMapView&, IMapView&) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + }; + + auto self = make_self(); + IMapView map = *self; + + // Make sure that we use the TryLookup specialization, and don't throw an unexpected exception. + self->shouldThrowOnTryLookup = false; + REQUIRE(!map.TryLookup(123)); + // make sure regular lookup stll throws bounds + REQUIRE_THROWS_AS(map.Lookup(123), hresult_out_of_bounds); + + // Simulate a non-agile map that is being accessed from the wrong thread. + // "Try" operations should throw rather than erroneously report "not found". + // Because they didn't even try. The operation never got off the ground. + self->shouldThrowOnTryLookup = true; + self->codeToThrow = RPC_E_WRONG_THREAD; + REQUIRE_THROWS_AS(map.TryLookup(123), hresult_wrong_thread); + // regular lookup should throw the same error + REQUIRE_THROWS_AS(map.Lookup(123), hresult_wrong_thread); +} + +TEST_CASE("trylookup_from_abi NOT opt-in, no special tag") +{ + // Makes sure that an existing TryLookup method is not called without the trylookup_from_abi_t tag. + struct map_without_try_lookup : implements> + { + hresult codeToThrow{ S_OK }; + std::optional TryLookup(int) // notice no trylookup_from_abi_t, so no opt-in + { + // throw an unexpectd hresult, this should not be called. + throw_hresult(RPC_E_WRONG_THREAD); + } + int Lookup(int) { return 42; } // Behave as if the item was found + + int32_t Size() { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + bool HasKey(int) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + void Split(IMapView&, IMapView&) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + }; + + auto self = make_self(); + IMapView map = *self; + + // Make sure that we don't use the TryLookup specialization, we use the Successful Lookup + REQUIRE(map.TryLookup(123).value() == 42); + REQUIRE(map.Lookup(123) == 42); +} + +TEST_CASE("trylookup_from_abi specialization with IInspectable") +{ + // A map that throws a specific error, used to verify various edge cases. + // and implements tryLookup, to take advantage of an optimization to avoid a throw. + struct map_with_try_lookup : implements> + { + hresult codeToThrow{ S_OK }; + bool shouldThrowOnTryLookup{ false }; + bool returnNullptr{ false }; + std::optional TryLookup(int, trylookup_from_abi_t) + { + if (returnNullptr) + { + return { nullptr }; + } + else if (shouldThrowOnTryLookup) + { + throw_hresult(codeToThrow); + } + else + { + return { std::nullopt }; + } + } + IInspectable Lookup(int) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + int32_t Size() { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + bool HasKey(int) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + void Split(IMapView&, IMapView&) { throw_hresult(E_UNEXPECTED); } // shouldn't be called by the test + }; + + auto self = make_self(); + IMapView map = *self; + + // Ensure that we return a value on nullptr, a nullptr is a valid IInspectable in the Map + self->returnNullptr = true; + REQUIRE(map.TryLookup(123) == IInspectable{nullptr}); + REQUIRE(map.Lookup(123) == IInspectable{nullptr}); + + // Make sure that we use the TryLookup specialization, and don't throw an unexpected exception. + self->shouldThrowOnTryLookup = false; + self->returnNullptr = false; + REQUIRE(map.TryLookup(123) == IInspectable{nullptr}); + // make sure regular lookup stll throws bounds + REQUIRE_THROWS_AS(map.Lookup(123), hresult_out_of_bounds); + + // Simulate a non-agile map that is being accessed from the wrong thread. + // "Try" operations should throw rather than erroneously report "not found". + // Because they didn't even try. The operation never got off the ground. + self->shouldThrowOnTryLookup = true; + self->codeToThrow = RPC_E_WRONG_THREAD; + REQUIRE_THROWS_AS(map.TryLookup(123), hresult_wrong_thread); + // regular lookup should throw the same error + REQUIRE_THROWS_AS(map.Lookup(123), hresult_wrong_thread); +} diff --git a/test/test/async_check_cancel.cpp b/test/test/async_check_cancel.cpp index 7547609f6..d88fdcaf0 100644 --- a/test/test/async_check_cancel.cpp +++ b/test/test/async_check_cancel.cpp @@ -11,6 +11,28 @@ namespace using std::experimental::suspend_never; #endif + static bool s_exceptionLoggerCalled = false; + + static struct { + uint32_t lineNumber; + char const* fileName; + char const* functionName; + void* returnAddress; + winrt::hresult result; + } s_exceptionLoggerArgs{}; + + void __stdcall exceptionLogger(uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept + { + s_exceptionLoggerArgs = { + /*.lineNumber =*/ lineNumber, + /*.fileName =*/ fileName, + /*.functionName =*/ functionName, + /*.returnAddress =*/ returnAddress, + /*.result =*/ result, + }; + s_exceptionLoggerCalled = true; + } + // // Checks that manual cancellation checks work. // @@ -61,6 +83,7 @@ namespace co_return 1; } + IAsyncOperationWithProgress OperationWithProgress(HANDLE event, bool& canceled) { co_await resume_on_signal(event); @@ -77,6 +100,59 @@ namespace co_return 1; } + IAsyncAction OperationCancelLogged(HANDLE event, bool& canceled) + { + REQUIRE(!s_exceptionLoggerCalled); + REQUIRE(!winrt_throw_hresult_handler); + winrt_throw_hresult_handler = exceptionLogger; + + co_await resume_on_signal(event); + auto cancel = co_await get_cancellation_token(); + + if (cancel()) + { + REQUIRE(!canceled); + canceled = true; + REQUIRE(s_exceptionLoggerCalled); + REQUIRE(s_exceptionLoggerArgs.result == HRESULT_FROM_WIN32(ERROR_CANCELLED)); + } + + winrt_throw_hresult_handler = nullptr; + s_exceptionLoggerCalled = false; + + co_await suspend_never(); + + REQUIRE(false); + co_return; + } + + IAsyncAction OperationAvoidLoggingCancel(HANDLE event, bool& canceled) + { + REQUIRE(!s_exceptionLoggerCalled); + REQUIRE(!winrt_throw_hresult_handler); + winrt_throw_hresult_handler = exceptionLogger; + + auto cancel = co_await get_cancellation_token(); + cancel.originate_on_cancel(false); + + co_await resume_on_signal(event); + + if (cancel()) + { + REQUIRE(!canceled); + canceled = true; + REQUIRE(!s_exceptionLoggerCalled); + } + + winrt_throw_hresult_handler = nullptr; + s_exceptionLoggerCalled = false; + + co_await suspend_never(); + + REQUIRE(false); + co_return; + } + template void Check(F make) { @@ -96,7 +172,7 @@ namespace async.Cancel(); SetEvent(start.get()); - REQUIRE(WaitForSingleObject(completed.get(), 1000) == WAIT_OBJECT_0); + REQUIRE(WaitForSingleObject(completed.get(), IsDebuggerPresent() ? INFINITE : 1000) == WAIT_OBJECT_0); REQUIRE(async.Status() == AsyncStatus::Canceled); REQUIRE(async.ErrorCode() == HRESULT_FROM_WIN32(ERROR_CANCELLED)); @@ -115,4 +191,6 @@ TEST_CASE("async_check_cancel") Check(ActionWithProgress); Check(Operation); Check(OperationWithProgress); + Check(OperationCancelLogged); + Check(OperationAvoidLoggingCancel); } diff --git a/test/test_cpp20/custom_error.cpp b/test/test_cpp20/custom_error.cpp index d7b055e47..b925628d9 100644 --- a/test/test_cpp20/custom_error.cpp +++ b/test/test_cpp20/custom_error.cpp @@ -37,9 +37,9 @@ namespace #if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 170000 // not available in libc++ before LLVM 16 -TEST_CASE("custom_error_logger", "[!shouldfail]") +TEST_CASE("custom_error_logger_on_throw", "[!shouldfail]") #else -TEST_CASE("custom_error_logger") +TEST_CASE("custom_error_logger_on_throw") #endif { // Set up global handler @@ -72,3 +72,62 @@ TEST_CASE("custom_error_logger") winrt_throw_hresult_handler = nullptr; s_loggerCalled = false; } +template +void HresultOnLine80(Args... args) +{ + // Validate that handler translated on creating an HRESULT +#line 80 // Force next line to be reported as line number 80 + winrt::hresult_canceled(std::forward(args)...); +} + +#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 170000 +// not available in libc++ before LLVM 16 +TEST_CASE("custom_error_logger_on_originate", "[!shouldfail]") +#else +TEST_CASE("custom_error_logger_on_originate") +#endif +{ + // Set up global handler + REQUIRE(!s_loggerCalled); + REQUIRE(!winrt_throw_hresult_handler); + winrt_throw_hresult_handler = logger; + + HresultOnLine80(); + REQUIRE(s_loggerCalled); + // In C++20 these fields should be filled in by std::source_location + REQUIRE(s_loggerArgs.lineNumber == 80); + const auto fileNameSv = std::string_view(s_loggerArgs.fileName); + REQUIRE(!fileNameSv.empty()); + REQUIRE(fileNameSv.find("custom_error.cpp") != std::string::npos); +#ifdef _DEBUG + const auto functionNameSv = std::string_view(s_loggerArgs.functionName); + REQUIRE(!functionNameSv.empty()); + // Every compiler has a slightly different naming approach for this function, and even the same + // compiler can change its mind over time. Instead of matching the entire function name just + // match against the part we care about. + REQUIRE((functionNameSv.find("HresultOnLine80") != std::string_view::npos)); +#else + REQUIRE(s_loggerArgs.functionName == nullptr); +#endif // _DEBUG + + REQUIRE(s_loggerArgs.returnAddress); + REQUIRE(s_loggerArgs.result == HRESULT_FROM_WIN32(ERROR_CANCELLED)); // E_ILLEGAL_DELEGATE_ASSIGNMENT) + + s_loggerCalled = false; + s_loggerArgs.lineNumber = 0; + // verify HRESULT with a custom message + HresultOnLine80(L"with custom message"); + REQUIRE(s_loggerCalled); + REQUIRE(s_loggerArgs.lineNumber == 80); + + s_loggerCalled = false; + s_loggerArgs.lineNumber = 0; + // verify that no_originate does _not_ call the logger. + HresultOnLine80(winrt::hresult_error::no_originate); + REQUIRE(!s_loggerCalled); + REQUIRE(s_loggerArgs.lineNumber == 0); + + // Remove global handler + winrt_throw_hresult_handler = nullptr; + s_loggerCalled = false; +} From 584a0e09b2cce0450bb5b0e2c3ee122c383a34bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 08:49:08 -0600 Subject: [PATCH 53/91] Bump actions/download-artifact from 5 to 6 (#1519) --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 866fddd7d..6f2745772 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,14 +106,14 @@ jobs: - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v6 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v6 with: name: msvc-build-${{ matrix.compiler}}-x86-Release-bin path: _build/x86/Release/ @@ -326,7 +326,7 @@ jobs: - uses: actions/checkout@v5 - name: Fetch cppwinrt executables - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v6 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ From a0fcdc8a6db6283b19c16da04a920bf4de202c32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 10:41:58 -0600 Subject: [PATCH 54/91] Bump actions/upload-artifact from 4 to 5 (#1518) --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6f2745772..37611ce0e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,7 +66,7 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt - name: Upload built executables - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -230,7 +230,7 @@ jobs: - name: Upload arm64 test executables if: matrix.arch == 'arm64' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: msvc-tests-${{ matrix.test_exe }}-${{ matrix.compiler }}-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -269,7 +269,7 @@ jobs: cmake --build build/cross_x64/ --target install -j2 - name: Upload cppwinrt.exe - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: cross-build-${{ matrix.arch }}-bin path: install/bin/cppwinrt.exe @@ -383,7 +383,7 @@ jobs: } - name: Upload nuget package artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: package path: "*.nupkg" From 1ccb7e1494b9c55f45f2a306d9a4dbc62317dc4c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Nov 2025 17:48:07 -0800 Subject: [PATCH 55/91] Bump actions/checkout from 5 to 6 (#1523) Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 37611ce0e..4ece2a7df 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: config: Release runs-on: windows-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Download nuget run: | @@ -102,7 +102,7 @@ jobs: config: Release runs-on: windows-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' @@ -250,7 +250,7 @@ jobs: CMAKE_COLOR_DIAGNOSTICS: 1 CLICOLOR_FORCE: 1 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Install cross compiler run: | @@ -283,7 +283,7 @@ jobs: Deployment: [Component, Standalone] runs-on: windows-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Download nuget run: | @@ -323,7 +323,7 @@ jobs: config: [Release] runs-on: windows-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Fetch cppwinrt executables uses: actions/download-artifact@v6 @@ -368,7 +368,7 @@ jobs: name: Build nuget package with MSVC runs-on: windows-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Package run: | From ac422060b70014180021d73974fc99ed0676ee3a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jan 2026 11:18:32 -0600 Subject: [PATCH 56/91] Bump actions/upload-artifact from 5 to 6 (#1525) --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ece2a7df..d0b327169 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,7 +66,7 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt - name: Upload built executables - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -230,7 +230,7 @@ jobs: - name: Upload arm64 test executables if: matrix.arch == 'arm64' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: msvc-tests-${{ matrix.test_exe }}-${{ matrix.compiler }}-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -269,7 +269,7 @@ jobs: cmake --build build/cross_x64/ --target install -j2 - name: Upload cppwinrt.exe - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: cross-build-${{ matrix.arch }}-bin path: install/bin/cppwinrt.exe @@ -383,7 +383,7 @@ jobs: } - name: Upload nuget package artifact - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: name: package path: "*.nupkg" From 6d87b8463a5608aca62b3f439f30dbe38dc11620 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jan 2026 11:45:29 -0600 Subject: [PATCH 57/91] Bump actions/download-artifact from 6 to 7 (#1526) --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0b327169..aeed4106c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,14 +106,14 @@ jobs: - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' - uses: actions/download-artifact@v6 + uses: actions/download-artifact@v7 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' - uses: actions/download-artifact@v6 + uses: actions/download-artifact@v7 with: name: msvc-build-${{ matrix.compiler}}-x86-Release-bin path: _build/x86/Release/ @@ -326,7 +326,7 @@ jobs: - uses: actions/checkout@v6 - name: Fetch cppwinrt executables - uses: actions/download-artifact@v6 + uses: actions/download-artifact@v7 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ From a7a5cd97ccc16bf606a20108bc9bda33f09bdb7f Mon Sep 17 00:00:00 2001 From: Vineeth Thomas Alex Date: Tue, 3 Feb 2026 13:48:20 -0600 Subject: [PATCH 58/91] Enable PreFast for build stage in OneBranch pipeline (#1533) Re-enable PreFast for build stage in pipeline. --- .pipelines/OneBranch.Official.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 552ec761b..56fada628 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -45,8 +45,6 @@ extends: compiled: enabled: true tsaEnabled: true - prefast: - enabled: true stages: - stage: build @@ -59,6 +57,8 @@ extends: BuildConfiguration: $(BuildConfiguration) BuildVersion: $(BuildVersion) OfficialBuild: true + ob_sdl_prefast_enabled: true + ob_sdl_prefast_runDuring: "Guardian" # Enabling PreFast only for build stage - stage: vpack dependsOn: build From 3a596b513eb14d374c55d8f79a15906fbdfafc3f Mon Sep 17 00:00:00 2001 From: Vineeth Thomas Alex Date: Tue, 3 Feb 2026 16:57:59 -0600 Subject: [PATCH 59/91] Update PreFast run stage in OneBranchBuild.yml to "Guardian" to avoid race condition with build. (#1534) * Remove PreFast settings from OneBranch pipeline Removed PreFast parameters from build configuration. * Update PreFast run stage in OneBranchBuild.yml Changed PreFast run stage from 'Build' to 'Guardian' to enable it only during the Guardian stage. * Correct indentation for PreFast configuration Fix indentation for ob_sdl_prefast_runDuring in OneBranchBuild.yml --- .pipelines/OneBranch.Official.yml | 3 --- .pipelines/jobs/OneBranchBuild.yml | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 56fada628..996f2a607 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -57,8 +57,6 @@ extends: BuildConfiguration: $(BuildConfiguration) BuildVersion: $(BuildVersion) OfficialBuild: true - ob_sdl_prefast_enabled: true - ob_sdl_prefast_runDuring: "Guardian" # Enabling PreFast only for build stage - stage: vpack dependsOn: build @@ -68,7 +66,6 @@ extends: type: windows variables: ob_outputDirectory: '$(Build.SourcesDirectory)\out' - ob_createvpack_enabled: true ob_createvpack_packagename: CppWinRT.Compiler ob_createvpack_owneralias: cpp4uwpt diff --git a/.pipelines/jobs/OneBranchBuild.yml b/.pipelines/jobs/OneBranchBuild.yml index b5c060cb9..dfee85edf 100644 --- a/.pipelines/jobs/OneBranchBuild.yml +++ b/.pipelines/jobs/OneBranchBuild.yml @@ -32,7 +32,7 @@ jobs: ob_sdl_codeSignValidation_excludes: '-|**\*.exe;-|**\*.dll' ob_sdl_prefast_enabled: true - ob_sdl_prefast_runDuring: 'Build' + ob_sdl_prefast_runDuring: "Guardian" ob_sdl_checkCompliantCompilerWarnings: true ob_symbolsPublishing_enabled: ${{ parameters.OfficialBuild }} From 0f3e9f7b8d80a86f2ab3e9f8da47e217c5736ad1 Mon Sep 17 00:00:00 2001 From: Vineeth Thomas Alex Date: Thu, 5 Feb 2026 13:06:33 -0600 Subject: [PATCH 60/91] Remove Windows pool from build stage (#1535) * Remove Windows pool from build stage Removed Windows pool configuration from build stage, since template job defines pool * Remove prefast in OneBranch.PullRequest.yml Prefast is enabled in the build stage template job * Add -SkipDuplicate option to NuGet push arguments * Update .pipelines/jobs/OneBranchNuGet.yml Co-authored-by: Ryan Shepherd * Update NuGet push command arguments Removed the -SkipDuplicate option from the NuGet push command. * Set pre-release NuGet version in VSIX build * Change ob_sdl_prefast_runDuring to 'Guardian' --------- Co-authored-by: Ryan Shepherd --- .pipelines/OneBranch.Official.yml | 3 --- .pipelines/OneBranch.PullRequest.yml | 2 -- .pipelines/jobs/OneBranchNuGet.yml | 9 ++++++--- .pipelines/jobs/OneBranchVsix.yml | 7 ++++++- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 996f2a607..cf2928151 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -48,9 +48,6 @@ extends: stages: - stage: build - pool: - type: windows - jobs: - template: .pipelines/jobs/OneBranchBuild.yml@self parameters: diff --git a/.pipelines/OneBranch.PullRequest.yml b/.pipelines/OneBranch.PullRequest.yml index bc08bbddf..ea4884329 100644 --- a/.pipelines/OneBranch.PullRequest.yml +++ b/.pipelines/OneBranch.PullRequest.yml @@ -41,8 +41,6 @@ extends: enabled: false sbom: enabled: true - prefast: - enabled: true stages: - stage: build diff --git a/.pipelines/jobs/OneBranchNuGet.yml b/.pipelines/jobs/OneBranchNuGet.yml index 02133ee03..867202891 100644 --- a/.pipelines/jobs/OneBranchNuGet.yml +++ b/.pipelines/jobs/OneBranchNuGet.yml @@ -15,10 +15,13 @@ jobs: variables: ob_outputDirectory: '$(Build.SourcesDirectory)\out' - PackageVersion: ${{ parameters.BuildVersion }} + ${{ if eq(parameters.OfficialBuild, true) }}: + PackageVersion: ${{ parameters.BuildVersion }} + ${{ else }}: + PackageVersion: ${{ parameters.BuildVersion }}-unofficial ob_sdl_prefast_enabled: true - ob_sdl_prefast_runDuring: 'Build' + ob_sdl_prefast_runDuring: 'Guardian' ob_sdl_checkCompliantCompilerWarnings: true steps: @@ -72,4 +75,4 @@ jobs: displayName: 'Publish NuGet package' inputs: command: 'custom' - arguments: 'push $(ob_outputDirectory)\packages\Microsoft.Windows.CppWinRT.$(PackageVersion).nupkg -NonInteractive -Source https://microsoft.pkgs.visualstudio.com/_packaging/CppWinRT/nuget/v3/index.json -ApiKey VSTS' \ No newline at end of file + arguments: 'push $(ob_outputDirectory)\packages\Microsoft.Windows.CppWinRT.$(PackageVersion).nupkg -NonInteractive -Source https://microsoft.pkgs.visualstudio.com/_packaging/CppWinRT/nuget/v3/index.json -ApiKey VSTS' diff --git a/.pipelines/jobs/OneBranchVsix.yml b/.pipelines/jobs/OneBranchVsix.yml index 18b74403b..1b03f71d0 100644 --- a/.pipelines/jobs/OneBranchVsix.yml +++ b/.pipelines/jobs/OneBranchVsix.yml @@ -27,6 +27,11 @@ jobs: VsixFilename: Microsoft.Windows.CppWinRT variables: + ${{ if eq(parameters.OfficialBuild, true) }}: + PackageVersion: ${{ parameters.BuildVersion }} + ${{ else }}: + PackageVersion: ${{ parameters.BuildVersion }}-unofficial + ob_outputDirectory: $(Build.SourcesDirectory)\out ob_artifactSuffix: $(VsVersion)_$(Deployment) @@ -91,7 +96,7 @@ jobs: displayName: Build VSIX inputs: solution: $(Build.SourcesDirectory)\vsix\vsix.sln - msbuildArgs: /t:vsix_$(VsVersion) /m /p:CppWinRTVersion=${{ parameters.BuildVersion }},clean_intermediate_files=true,Deployment=$(Deployment),NatvisDirx86=$(Build.SourcesDirectory)\x86\$(Deployment)\,NatvisDirx64=$(Build.SourcesDirectory)\x64\$(Deployment)\,NatvisDirarm64=$(Build.SourcesDirectory)\arm64\$(Deployment)\,NupkgDir=$(Pipeline.Workspace)\nuget\packages /bl:$(ob_outputDirectory)\output.binlog + msbuildArgs: /t:vsix_$(VsVersion) /m /p:CppWinRTVersion=$(PackageVersion),clean_intermediate_files=true,Deployment=$(Deployment),NatvisDirx86=$(Build.SourcesDirectory)\x86\$(Deployment)\,NatvisDirx64=$(Build.SourcesDirectory)\x64\$(Deployment)\,NatvisDirarm64=$(Build.SourcesDirectory)\arm64\$(Deployment)\,NupkgDir=$(Pipeline.Workspace)\nuget\packages /bl:$(ob_outputDirectory)\output.binlog platform: 'Any CPU' configuration: ${{ parameters.BuildConfiguration }} From 1a5cd652058cb2e3162732da42c7a478c2b8ccc8 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Tue, 10 Feb 2026 11:59:31 -0800 Subject: [PATCH 61/91] Only sign the VSIX contents instead of the entire temp directory (#1537) --- .pipelines/jobs/OneBranchVsix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pipelines/jobs/OneBranchVsix.yml b/.pipelines/jobs/OneBranchVsix.yml index 1b03f71d0..8c49ccf5b 100644 --- a/.pipelines/jobs/OneBranchVsix.yml +++ b/.pipelines/jobs/OneBranchVsix.yml @@ -114,7 +114,7 @@ jobs: command: sign signing_profile: external_distribution files_to_sign: '**\*.dll' - search_root: '$(Agent.TempDirectory)' + search_root: '$(Agent.TempDirectory)\$(VsixFilename)' - task: ArchiveFiles@2 displayName: 'Repack signed VSIX contents' From da8a3761306c037e6ba5b0d29e6e2a4923c4488c Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Tue, 10 Feb 2026 12:00:40 -0800 Subject: [PATCH 62/91] Fix handling of NuGet package version in VSIX (#1536) * Allow vsix to have prerelease nupkg * Fix nuget template invocation * Missed one case of NuGet vs VSIX version --- .pipelines/OneBranch.Official.yml | 6 ++++-- .pipelines/OneBranch.PullRequest.yml | 3 ++- .pipelines/jobs/OneBranchNuGet.yml | 7 ++----- .pipelines/jobs/OneBranchVsix.yml | 9 +++------ .pipelines/variables/version.yml | 12 +++++++++++- build_vsix.cmd | 4 ++-- vsix/Dev16/Component/source.extension.vsixmanifest | 2 +- vsix/Dev16/Standalone/source.extension.vsixmanifest | 2 +- vsix/Dev16/vsix.Dev16.csproj | 4 ++-- vsix/Dev17/Component/source.extension.vsixmanifest | 2 +- vsix/Dev17/Standalone/source.extension.vsixmanifest | 2 +- vsix/Dev17/vsix.Dev17.csproj | 4 ++-- vsix/Extension.targets | 4 +++- 13 files changed, 35 insertions(+), 26 deletions(-) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index cf2928151..64f762d81 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -6,6 +6,8 @@ parameters: # parameters are shown up in ADO UI in a build queue time variables: - template: variables/version.yml + parameters: + OfficialBuild: true - template: variables/OneBranchVariables.yml parameters: debug: ${{ parameters.debug }} @@ -132,8 +134,7 @@ extends: jobs: - template: .pipelines/jobs/OneBranchNuGet.yml@self parameters: - BuildConfiguration: $(BuildConfiguration) - BuildVersion: $(BuildVersion) + NugetPackageVersion: $(NugetPackageVersion) OfficialBuild: true - stage: Test @@ -151,4 +152,5 @@ extends: parameters: BuildConfiguration: $(BuildConfiguration) BuildVersion: $(BuildVersion) + NugetPackageVersion: $(NugetPackageVersion) OfficialBuild: true diff --git a/.pipelines/OneBranch.PullRequest.yml b/.pipelines/OneBranch.PullRequest.yml index ea4884329..9e18821b4 100644 --- a/.pipelines/OneBranch.PullRequest.yml +++ b/.pipelines/OneBranch.PullRequest.yml @@ -56,7 +56,7 @@ extends: - template: .pipelines/jobs/OneBranchNuGet.yml@self parameters: BuildConfiguration: $(BuildConfiguration) - BuildVersion: $(BuildVersion) + NugetPackageVersion: $(NugetPackageVersion) - stage: Test dependsOn: build @@ -73,3 +73,4 @@ extends: parameters: BuildConfiguration: $(BuildConfiguration) BuildVersion: $(BuildVersion) + NugetPackageVersion: $(NugetPackageVersion) diff --git a/.pipelines/jobs/OneBranchNuGet.yml b/.pipelines/jobs/OneBranchNuGet.yml index 867202891..36ec3144b 100644 --- a/.pipelines/jobs/OneBranchNuGet.yml +++ b/.pipelines/jobs/OneBranchNuGet.yml @@ -2,7 +2,7 @@ parameters: - name: BuildConfiguration type: string - - name: BuildVersion + - name: NugetPackageVersion type: string - name: OfficialBuild type: boolean @@ -15,10 +15,7 @@ jobs: variables: ob_outputDirectory: '$(Build.SourcesDirectory)\out' - ${{ if eq(parameters.OfficialBuild, true) }}: - PackageVersion: ${{ parameters.BuildVersion }} - ${{ else }}: - PackageVersion: ${{ parameters.BuildVersion }}-unofficial + PackageVersion: ${{ parameters.NugetPackageVersion }} ob_sdl_prefast_enabled: true ob_sdl_prefast_runDuring: 'Guardian' diff --git a/.pipelines/jobs/OneBranchVsix.yml b/.pipelines/jobs/OneBranchVsix.yml index 8c49ccf5b..696b7e292 100644 --- a/.pipelines/jobs/OneBranchVsix.yml +++ b/.pipelines/jobs/OneBranchVsix.yml @@ -3,6 +3,8 @@ parameters: type: string - name: BuildVersion type: string + - name: NugetPackageVersion + type: string - name: OfficialBuild type: boolean default: false @@ -27,11 +29,6 @@ jobs: VsixFilename: Microsoft.Windows.CppWinRT variables: - ${{ if eq(parameters.OfficialBuild, true) }}: - PackageVersion: ${{ parameters.BuildVersion }} - ${{ else }}: - PackageVersion: ${{ parameters.BuildVersion }}-unofficial - ob_outputDirectory: $(Build.SourcesDirectory)\out ob_artifactSuffix: $(VsVersion)_$(Deployment) @@ -96,7 +93,7 @@ jobs: displayName: Build VSIX inputs: solution: $(Build.SourcesDirectory)\vsix\vsix.sln - msbuildArgs: /t:vsix_$(VsVersion) /m /p:CppWinRTVersion=$(PackageVersion),clean_intermediate_files=true,Deployment=$(Deployment),NatvisDirx86=$(Build.SourcesDirectory)\x86\$(Deployment)\,NatvisDirx64=$(Build.SourcesDirectory)\x64\$(Deployment)\,NatvisDirarm64=$(Build.SourcesDirectory)\arm64\$(Deployment)\,NupkgDir=$(Pipeline.Workspace)\nuget\packages /bl:$(ob_outputDirectory)\output.binlog + msbuildArgs: /t:vsix_$(VsVersion) /m /p:CppWinRTVersion=${{ parameters.BuildVersion }},NugetPackageVersion=${{ parameters.NugetPackageVersion }},clean_intermediate_files=true,Deployment=$(Deployment),NatvisDirx86=$(Build.SourcesDirectory)\x86\$(Deployment)\,NatvisDirx64=$(Build.SourcesDirectory)\x64\$(Deployment)\,NatvisDirarm64=$(Build.SourcesDirectory)\arm64\$(Deployment)\,NupkgDir=$(Pipeline.Workspace)\nuget\packages /bl:$(ob_outputDirectory)\output.binlog platform: 'Any CPU' configuration: ${{ parameters.BuildConfiguration }} diff --git a/.pipelines/variables/version.yml b/.pipelines/variables/version.yml index 576d896eb..15382e7df 100644 --- a/.pipelines/variables/version.yml +++ b/.pipelines/variables/version.yml @@ -1,7 +1,17 @@ +parameters: + - name: OfficialBuild + type: boolean + default: false + variables: MajorVersion: "2" MinorVersion: "0" VersionDate: $[format('{0:yyMMdd}', pipeline.startTime)] VersionCounter: $[counter(variables['VersionDate'], 1)] BuildVersion: $(MajorVersion).$(MinorVersion).$(VersionDate).$(VersionCounter) - PatchVersion: $(VersionDate)$(VersionCounter) \ No newline at end of file + PatchVersion: $(VersionDate)$(VersionCounter) + + ${{ if eq(parameters.OfficialBuild, true) }}: + NugetPackageVersion: $(BuildVersion) + ${{ else }}: + NugetPackageVersion: $(BuildVersion)-unofficial diff --git a/build_vsix.cmd b/build_vsix.cmd index 9908462ef..aefc84df1 100644 --- a/build_vsix.cmd +++ b/build_vsix.cmd @@ -30,7 +30,7 @@ call msbuild /p:Configuration=%target_configuration%,Platform=x86,Deployment=%ta call msbuild /p:Configuration=%target_configuration%,Platform=arm64,Deployment=%target_deployment%,CppWinRTBuildVersion=%target_version% natvis\cppwinrtvisualizer.sln rem Build nuget -.nuget\nuget.exe pack nuget\Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory %this_dir%_build -Properties Configuration=%target_configuration%;cppwinrt_exe=%this_dir%_build\x86\%target_configuration%\cppwinrt.exe;cppwinrt_fast_fwd_x86=%this_dir%_build\x86\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%this_dir%_build\x64\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%this_dir%_build\arm64\%target_configuration%\cppwinrt_fast_forwarder.lib -version %target_version% -Verbosity Detailed +.nuget\nuget.exe pack nuget\Microsoft.Windows.CppWinRT.nuspec -NonInteractive -OutputDirectory %this_dir%_build -Properties Configuration=%target_configuration%;cppwinrt_exe=%this_dir%_build\x86\%target_configuration%\cppwinrt.exe;cppwinrt_fast_fwd_x86=%this_dir%_build\x86\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_x64=%this_dir%_build\x64\%target_configuration%\cppwinrt_fast_forwarder.lib;cppwinrt_fast_fwd_arm64=%this_dir%_build\arm64\%target_configuration%\cppwinrt_fast_forwarder.lib;target_version=%target_version% -version %target_version% -Verbosity Detailed rem Build vsix -call msbuild /restore /p:Configuration=%target_configuration%,Platform="Any CPU",Deployment=%target_deployment%,CppWinRTVersion=%target_version%,NatvisDirx86=%this_dir%natvis\x86\%target_configuration%\%target_deployment%,NatvisDirx64=%this_dir%natvis\x64\%target_configuration%\%target_deployment%,NatvisDirarm64=%this_dir%natvis\arm64\%target_configuration%\%target_deployment%,NupkgDir=%this_dir%_build vsix\vsix.sln +call msbuild /restore /p:Configuration=%target_configuration%,Platform="Any CPU",Deployment=%target_deployment%,CppWinRTVersion=%target_version%,NugetPackageVersion=%target_version%,NatvisDirx86=%this_dir%natvis\x86\%target_configuration%\%target_deployment%,NatvisDirx64=%this_dir%natvis\x64\%target_configuration%\%target_deployment%,NatvisDirarm64=%this_dir%natvis\arm64\%target_configuration%\%target_deployment%,NupkgDir=%this_dir%_build vsix\vsix.sln diff --git a/vsix/Dev16/Component/source.extension.vsixmanifest b/vsix/Dev16/Component/source.extension.vsixmanifest index afd96cf1f..a7ab21972 100644 --- a/vsix/Dev16/Component/source.extension.vsixmanifest +++ b/vsix/Dev16/Component/source.extension.vsixmanifest @@ -29,7 +29,7 @@ - + diff --git a/vsix/Dev16/Standalone/source.extension.vsixmanifest b/vsix/Dev16/Standalone/source.extension.vsixmanifest index e3c2ac995..b38c06cf8 100644 --- a/vsix/Dev16/Standalone/source.extension.vsixmanifest +++ b/vsix/Dev16/Standalone/source.extension.vsixmanifest @@ -29,7 +29,7 @@ - + diff --git a/vsix/Dev16/vsix.Dev16.csproj b/vsix/Dev16/vsix.Dev16.csproj index 72b9b4098..94a6836c3 100644 --- a/vsix/Dev16/vsix.Dev16.csproj +++ b/vsix/Dev16/vsix.Dev16.csproj @@ -41,8 +41,8 @@ %(Filename)%(Extension) true - - Packages\Microsoft.Windows.CppWinRT.$(CppWinRTVersion).nupkg + + Packages\Microsoft.Windows.CppWinRT.$(NugetPackageVersion).nupkg true diff --git a/vsix/Dev17/Component/source.extension.vsixmanifest b/vsix/Dev17/Component/source.extension.vsixmanifest index bcbfa9c8b..063dfcbc7 100644 --- a/vsix/Dev17/Component/source.extension.vsixmanifest +++ b/vsix/Dev17/Component/source.extension.vsixmanifest @@ -35,7 +35,7 @@ - + diff --git a/vsix/Dev17/Standalone/source.extension.vsixmanifest b/vsix/Dev17/Standalone/source.extension.vsixmanifest index 56ea4b86f..89e178c82 100644 --- a/vsix/Dev17/Standalone/source.extension.vsixmanifest +++ b/vsix/Dev17/Standalone/source.extension.vsixmanifest @@ -35,7 +35,7 @@ - + diff --git a/vsix/Dev17/vsix.Dev17.csproj b/vsix/Dev17/vsix.Dev17.csproj index 3326ce6fa..02f3e0bb8 100644 --- a/vsix/Dev17/vsix.Dev17.csproj +++ b/vsix/Dev17/vsix.Dev17.csproj @@ -44,8 +44,8 @@ %(Filename)%(Extension) true - - Packages\Microsoft.Windows.CppWinRT.$(CppWinRTVersion).nupkg + + Packages\Microsoft.Windows.CppWinRT.$(NugetPackageVersion).nupkg true diff --git a/vsix/Extension.targets b/vsix/Extension.targets index 7a7b6c2b8..442f03a53 100644 --- a/vsix/Extension.targets +++ b/vsix/Extension.targets @@ -1,8 +1,10 @@ + + @@ -27,7 +29,7 @@ - + From 129c9258fedbae96a0155f634bf56b68f6f75053 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 11 Feb 2026 11:55:11 -0800 Subject: [PATCH 63/91] Fix accidentally deleted parameter (#1538) --- .pipelines/OneBranch.Official.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 64f762d81..7a73b263b 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -134,6 +134,7 @@ extends: jobs: - template: .pipelines/jobs/OneBranchNuGet.yml@self parameters: + BuildConfiguration: $(BuildConfiguration) NugetPackageVersion: $(NugetPackageVersion) OfficialBuild: true From dcbdcc856f43be2f119a7b83005387894959e0db Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 1 Mar 2026 08:15:25 -0800 Subject: [PATCH 64/91] Delete stale.yml (#1543) --- .github/workflows/stale.yml | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 .github/workflows/stale.yml diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml deleted file mode 100644 index b686df568..000000000 --- a/.github/workflows/stale.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Mark stale issues and pull requests - -on: - schedule: - - cron: '0 0 * * *' - -jobs: - stale: - - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - - steps: - - uses: actions/stale@v10 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - days-before-stale: 10 - days-before-close: 5 - stale-issue-message: 'This issue is stale because it has been open 10 days with no activity. Remove stale label or comment or this will be closed in 5 days.' - stale-pr-message: 'This pull request is stale because it has been open 10 days with no activity. Remove stale label or comment or this will be closed in 5 days.' - stale-issue-label: 'no-issue-activity' - stale-pr-label: 'no-pr-activity' From 6bf188e1ab4ec5d089f093043f7df34de76bb31f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Mar 2026 08:24:20 -0800 Subject: [PATCH 65/91] Bump actions/download-artifact from 7 to 8 (#1541) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 7 to 8. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v7...v8) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-version: '8' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aeed4106c..eb37051b5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,14 +106,14 @@ jobs: - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: msvc-build-${{ matrix.compiler}}-x86-Release-bin path: _build/x86/Release/ @@ -326,7 +326,7 @@ jobs: - uses: actions/checkout@v6 - name: Fetch cppwinrt executables - uses: actions/download-artifact@v7 + uses: actions/download-artifact@v8 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ From 751a57bd33b92d67ada681d9084fa6a452364317 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Mar 2026 08:34:58 -0800 Subject: [PATCH 66/91] Bump actions/upload-artifact from 6 to 7 (#1542) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eb37051b5..6356b8095 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,7 +66,7 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt - name: Upload built executables - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -230,7 +230,7 @@ jobs: - name: Upload arm64 test executables if: matrix.arch == 'arm64' - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: msvc-tests-${{ matrix.test_exe }}-${{ matrix.compiler }}-${{ matrix.arch }}-${{ matrix.config }}-bin path: | @@ -269,7 +269,7 @@ jobs: cmake --build build/cross_x64/ --target install -j2 - name: Upload cppwinrt.exe - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: cross-build-${{ matrix.arch }}-bin path: install/bin/cppwinrt.exe @@ -383,7 +383,7 @@ jobs: } - name: Upload nuget package artifact - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: package path: "*.nupkg" From bb0a408e7764f6b5ed8ac050459d07896c3f5f91 Mon Sep 17 00:00:00 2001 From: Yexuan Xiao Date: Tue, 10 Mar 2026 07:56:46 +0800 Subject: [PATCH 67/91] Simplify the definition of the consume function (#1544) --- cppwinrt/code_writers.h | 59 +++++++++-------------------------------- strings/base_windows.h | 57 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 47 deletions(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 35e9935d0..1d0f8fe92 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -619,10 +619,15 @@ namespace cppwinrt } } - static void write_abi_args(writer& w, method_signature const& method_signature) + static void write_abi_args(writer& w, method_signature const& method_signature, bool start_comma) { separator s{ w }; + if (start_comma) + { + s(); + } + for (auto&& [param, param_signature] : method_signature.params()) { s(); @@ -1135,19 +1140,7 @@ namespace cppwinrt // immediately while preserving the error code and local variables. format = R"( template auto consume_%::%(%) const noexcept {% - if constexpr (!std::is_same_v) - { - winrt::hresult _winrt_cast_result_code; - auto const _winrt_casted_result = impl::try_as_with_reason<%, D const*>(static_cast(this), _winrt_cast_result_code); - check_hresult(_winrt_cast_result_code); - auto const _winrt_abi_type = *(abi_t<%>**)&_winrt_casted_result; - _winrt_abi_type->%(%); - } - else - { - auto const _winrt_abi_type = *(abi_t<%>**)this; - _winrt_abi_type->%(%); - }% + consume_noexcept_remove_overload<%, D>(static_cast(this), &abi_t<%>::%%);% } )"; } @@ -1155,19 +1148,7 @@ namespace cppwinrt { format = R"( template auto consume_%::%(%) const noexcept {% - if constexpr (!std::is_same_v) - { - winrt::hresult _winrt_cast_result_code; - auto const _winrt_casted_result = impl::try_as_with_reason<%, D const*>(static_cast(this), _winrt_cast_result_code); - check_hresult(_winrt_cast_result_code); - auto const _winrt_abi_type = *(abi_t<%>**)&_winrt_casted_result; - WINRT_VERIFY_(0, _winrt_abi_type->%(%)); - } - else - { - auto const _winrt_abi_type = *(abi_t<%>**)this; - WINRT_VERIFY_(0, _winrt_abi_type->%(%)); - }% + consume_noexcept<%, D>(static_cast(this), &abi_t<%>::%%);% } )"; } @@ -1176,19 +1157,7 @@ namespace cppwinrt { format = R"( template auto consume_%::%(%) const {% - if constexpr (!std::is_same_v) - { - winrt::hresult _winrt_cast_result_code; - auto const _winrt_casted_result = impl::try_as_with_reason<%, D const*>(static_cast(this), _winrt_cast_result_code); - check_hresult(_winrt_cast_result_code); - auto const _winrt_abi_type = *(abi_t<%>**)&_winrt_casted_result; - check_hresult(_winrt_abi_type->%(%)); - } - else - { - auto const _winrt_abi_type = *(abi_t<%>**)this; - check_hresult(_winrt_abi_type->%(%)); - }% + consume_general<%, D>(static_cast(this), &abi_t<%>::%%);% } )"; } @@ -1202,12 +1171,8 @@ namespace cppwinrt bind(signature, false), type, type, - type, - get_abi_name(method), - bind(signature), - type, get_abi_name(method), - bind(signature), + bind(signature, true), bind(signature)); if (is_add_overload(method)) @@ -2750,7 +2715,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable bind(signature, true), type_name, bind_list(", ", generics), - bind(signature), + bind(signature, false), bind(signature)); } else @@ -2822,7 +2787,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable bind(signature), bind(signature, true), type_name, - bind(signature), + bind(signature, false), bind(signature)); } } diff --git a/strings/base_windows.h b/strings/base_windows.h index bf28440ef..831e1b1fe 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -451,3 +451,60 @@ WINRT_EXPORT namespace winrt::Windows::Foundation IInspectable(void* ptr, take_ownership_from_abi_t) noexcept : IUnknown(ptr, take_ownership_from_abi) {} }; } + +WINRT_EXPORT namespace winrt::impl +{ + template + void consume_noexcept_remove_overload(Derive const* d, MemberPointer mptr, Args&&... args) noexcept + { + if constexpr (!std::is_same_v) + { + winrt::hresult _winrt_cast_result_code; + auto const _winrt_casted_result = try_as_with_reason(d, _winrt_cast_result_code); + check_hresult(_winrt_cast_result_code); + auto const _winrt_abi_type = *(abi_t**)&_winrt_casted_result; + (_winrt_abi_type->*mptr)(std::forward(args)...); + } + else + { + auto const _winrt_abi_type = *(abi_t**)d; + (_winrt_abi_type->*mptr)(std::forward(args)...); + } + } + + template + void consume_noexcept(Derive const* d, MemberPointer mptr, Args&&... args) noexcept + { + if constexpr (!std::is_same_v) + { + winrt::hresult _winrt_cast_result_code; + auto const _winrt_casted_result = try_as_with_reason(d, _winrt_cast_result_code); + check_hresult(_winrt_cast_result_code); + auto const _winrt_abi_type = *(abi_t**)&_winrt_casted_result; + WINRT_VERIFY_(0, (_winrt_abi_type->*mptr)(std::forward(args)...)); + } + else + { + auto const _winrt_abi_type = *(abi_t**)d; + WINRT_VERIFY_(0, (_winrt_abi_type->*mptr)(std::forward(args)...)); + } + } + + template + void consume_general(Derive const* d, MemberPointer mptr, Args&&... args) + { + if constexpr (!std::is_same_v) + { + winrt::hresult _winrt_cast_result_code; + auto const _winrt_casted_result = try_as_with_reason(d, _winrt_cast_result_code); + check_hresult(_winrt_cast_result_code); + auto const _winrt_abi_type = *(abi_t**)&_winrt_casted_result; + check_hresult((_winrt_abi_type->*mptr)(std::forward(args)...)); + } + else + { + auto const _winrt_abi_type = *(abi_t**)d; + check_hresult((_winrt_abi_type->*mptr)(std::forward(args)...)); + } + } +} From 8864ac6ef07952e2ed10c3cec1445474b748a332 Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Mon, 16 Mar 2026 00:23:52 -0400 Subject: [PATCH 68/91] Remove experimental coroutines support (#1521) * Remove experimental coroutines support Replace CppWinRTEnableLegacyCoroutines with CppWinRTEnableCpp17Coroutines Remove base_coroutine_system_winui.h, hasn't worked since PR 0.8 Support and test building with no coroutines Remove implementation selection machinery * Fix clang-cl mismatching signedness error * Require coroutine support for C++/WinRT Add error message for missing coroutine support in C++. * Revert "Require coroutine support for C++/WinRT" This reverts commit de710f17fe9b7da34bf228b8b296f34c483e9a33. * Include an error message if /await is used --------- Co-authored-by: Ryan Shepherd --- .github/workflows/ci.yml | 2 +- .pipelines/jobs/OneBranchTest.yml | 4 + Directory.Build.Props | 4 +- build_test_all.cmd | 1 + cppwinrt.sln | 18 ++ cppwinrt/code_writers.h | 4 - nuget/CppWinrtRules.Project.xml | 6 +- nuget/Microsoft.Windows.CppWinRT.targets | 2 +- run_tests.cmd | 1 + strings/base_coroutine_foundation.h | 28 ++- strings/base_coroutine_system.h | 6 +- strings/base_coroutine_system_winui.h | 50 ----- strings/base_coroutine_threadpool.h | 59 +++--- strings/base_coroutine_ui_core.h | 6 +- strings/base_deferral.h | 16 +- strings/base_includes.h | 28 +-- strings/base_macros.h | 2 +- test/CMakeLists.txt | 1 + test/old_tests/UnitTests/async.cpp | 14 +- test/old_tests/UnitTests/weak.cpp | 8 +- test/test/async_auto_cancel.cpp | 16 +- test/test/async_cancel_callback.cpp | 14 +- test/test/async_check_cancel.cpp | 18 +- test/test/when.cpp | 8 +- test/test_nocoro/CMakeLists.txt | 35 ++++ test/test_nocoro/get.cpp | 74 +++++++ test/test_nocoro/main.cpp | 22 +++ test/test_nocoro/pch.cpp | 1 + test/test_nocoro/pch.h | 6 + test/test_nocoro/test_nocoro.vcxproj | 241 +++++++++++++++++++++++ 30 files changed, 489 insertions(+), 206 deletions(-) delete mode 100644 strings/base_coroutine_system_winui.h create mode 100644 test/test_nocoro/CMakeLists.txt create mode 100644 test/test_nocoro/get.cpp create mode 100644 test/test_nocoro/main.cpp create mode 100644 test/test_nocoro/pch.cpp create mode 100644 test/test_nocoro/pch.h create mode 100644 test/test_nocoro/test_nocoro.vcxproj diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6356b8095..a42f2c5b7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -92,7 +92,7 @@ jobs: compiler: [MSVC, clang-cl] arch: [x86, x64, arm64] config: [Debug, Release] - test_exe: [test, test_cpp20, test_cpp20_no_sourcelocation, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] + test_exe: [test, test_nocoro, test_cpp20, test_cpp20_no_sourcelocation, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] exclude: - arch: arm64 config: Debug diff --git a/.pipelines/jobs/OneBranchTest.yml b/.pipelines/jobs/OneBranchTest.yml index 0aa5c934b..2fb3a4bd1 100644 --- a/.pipelines/jobs/OneBranchTest.yml +++ b/.pipelines/jobs/OneBranchTest.yml @@ -17,6 +17,10 @@ jobs: TestExe: 'test' TestProject: 'test' BuildPlatform: 'x86' + test_nocoro.x86: + TestExe: 'test_nocoro' + TestProject: 'test_nocoro' + BuildPlatform: 'x86' test_cpp20.x86: TestExe: 'test_cpp20' TestProject: 'test_cpp20' diff --git a/Directory.Build.Props b/Directory.Build.Props index 9088021c1..5f530da91 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -30,7 +30,7 @@ ClangCL - + 20 false @@ -60,7 +60,7 @@ CATCH_CONFIG_COLOUR_ANSI;%(PreprocessorDefinitions) true /bigobj - /await %(AdditionalOptions) + /await:strict %(AdditionalOptions) -Wno-unused-command-line-argument -fno-delayed-template-parsing -mcx16 diff --git a/build_test_all.cmd b/build_test_all.cmd index 4372acfd5..649f4dc69 100644 --- a/build_test_all.cmd +++ b/build_test_all.cmd @@ -28,6 +28,7 @@ call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platfor call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% test\nuget\NugetTest.sln call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test +call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_nocoro call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_cpp20 call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_cpp20_no_sourcelocation call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_fast diff --git a/cppwinrt.sln b/cppwinrt.sln index 5964f976b..3bcfb33bc 100644 --- a/cppwinrt.sln +++ b/cppwinrt.sln @@ -119,6 +119,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20_no_sourcelocatio {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_nocoro", "test\test_nocoro\test_nocoro.vcxproj", "{9E392830-805A-4AAF-932D-C493143EFACA}" + ProjectSection(ProjectDependencies) = postProject + {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} + EndProjectSection +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D15C8430-A7CD-4616-BD84-243B26A9F1C2}" ProjectSection(SolutionItems) = preProject build_nuget.cmd = build_nuget.cmd @@ -394,6 +399,18 @@ Global {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x64.Build.0 = Release|x64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x86.ActiveCfg = Release|Win32 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x86.Build.0 = Release|Win32 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|ARM64.Build.0 = Debug|ARM64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|x64.ActiveCfg = Debug|x64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|x64.Build.0 = Debug|x64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|x86.ActiveCfg = Debug|Win32 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|x86.Build.0 = Debug|Win32 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|ARM64.ActiveCfg = Release|ARM64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|ARM64.Build.0 = Release|ARM64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x64.ActiveCfg = Release|x64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x64.Build.0 = Release|x64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x86.ActiveCfg = Release|Win32 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -417,6 +434,7 @@ Global {08C40663-B6A3-481E-8755-AE32BAD99501} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} + {9E392830-805A-4AAF-932D-C493143EFACA} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2783B8FD-EA3B-4D6B-9F81-662D289E02AA} diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 1d0f8fe92..e24cfd302 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -3442,10 +3442,6 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable { w.write(strings::base_coroutine_system); } - else if (namespace_name == "Microsoft.System") - { - w.write(strings::base_coroutine_system_winui); - } else if (namespace_name == "Windows.UI.Core") { w.write(strings::base_coroutine_ui_core); diff --git a/nuget/CppWinrtRules.Project.xml b/nuget/CppWinrtRules.Project.xml index 7f69fcd74..73f32c6d3 100644 --- a/nuget/CppWinrtRules.Project.xml +++ b/nuget/CppWinrtRules.Project.xml @@ -81,9 +81,9 @@ Description="Enables or disables the default for copying binaries to the output folder to be false" Category="General" /> - diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index 7fe83b14d..188e56835 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -882,7 +882,7 @@ $(XamlMetaDataProviderPch) %(AdditionalOptions) /bigobj - %(AdditionalOptions) /await + %(AdditionalOptions) /await:strict %(AdditionalIncludeDirectories);$(GeneratedFilesDir) diff --git a/run_tests.cmd b/run_tests.cmd index 77d883642..58e3c5524 100644 --- a/run_tests.cmd +++ b/run_tests.cmd @@ -9,6 +9,7 @@ if "%target_platform%"=="" set target_platform=x64 if "%target_configuration%"=="" set target_configuration=Debug call :run_test test +call :run_test test_nocoro call :run_test test_cpp20 call :run_test test_cpp20_no_sourcelocation call :run_test test_fast diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 87aaed24e..a5816a85b 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -99,12 +99,13 @@ namespace winrt::impl return async.GetResults(); } +#ifdef WINRT_IMPL_COROUTINES struct ignore_apartment_context {}; template struct disconnect_aware_handler : private std::conditional_t { - disconnect_aware_handler(Awaiter* awaiter, coroutine_handle<> handle) noexcept + disconnect_aware_handler(Awaiter* awaiter, std::coroutine_handle<> handle) noexcept : m_awaiter(awaiter), m_handle(handle) { } disconnect_aware_handler(disconnect_aware_handler&& other) = default; @@ -123,7 +124,7 @@ namespace winrt::impl private: movable_primitive m_awaiter; - movable_primitive, nullptr> m_handle; + movable_primitive, nullptr> m_handle; void Complete() { @@ -149,7 +150,6 @@ namespace winrt::impl } }; -#ifdef WINRT_IMPL_COROUTINES template struct await_adapter : cancellable_awaiter> { @@ -175,7 +175,7 @@ namespace winrt::impl } template - bool await_suspend(coroutine_handle handle) + bool await_suspend(std::coroutine_handle handle) { this->set_cancellable_promise_from_handle(handle); return register_completed_callback(handle); @@ -189,7 +189,7 @@ namespace winrt::impl } private: - bool register_completed_callback(coroutine_handle<> handle) + bool register_completed_callback(std::coroutine_handle<> handle) { if constexpr (!preserve_context) { @@ -294,7 +294,6 @@ WINRT_EXPORT namespace winrt::Windows::Foundation return{ async }; } } -#endif WINRT_EXPORT namespace winrt { @@ -327,7 +326,7 @@ namespace winrt::impl return true; } - void await_suspend(coroutine_handle<>) const noexcept + void await_suspend(std::coroutine_handle<>) const noexcept { } @@ -373,7 +372,7 @@ namespace winrt::impl return true; } - void await_suspend(coroutine_handle<>) const noexcept + void await_suspend(std::coroutine_handle<>) const noexcept { } @@ -411,7 +410,7 @@ namespace winrt::impl if (remaining == 0) { std::atomic_thread_fence(std::memory_order_acquire); - coroutine_handle::from_promise(*static_cast(this)).destroy(); + std::coroutine_handle::from_promise(*static_cast(this)).destroy(); } return remaining; @@ -577,7 +576,7 @@ namespace winrt::impl } } - suspend_never initial_suspend() const noexcept + std::suspend_never initial_suspend() const noexcept { return{}; } @@ -595,7 +594,7 @@ namespace winrt::impl { } - bool await_suspend(coroutine_handle<>) const noexcept + bool await_suspend(std::coroutine_handle<>) const noexcept { promise->set_completed(); uint32_t const remaining = promise->subtract_reference(); @@ -705,11 +704,7 @@ namespace winrt::impl }; } -#ifdef __cpp_lib_coroutine namespace std -#else -namespace std::experimental -#endif { template struct coroutine_traits @@ -844,7 +839,6 @@ namespace std::experimental WINRT_EXPORT namespace winrt { -#ifdef WINRT_IMPL_COROUTINES template Windows::Foundation::IAsyncAction when_all(T... async) { @@ -890,5 +884,5 @@ WINRT_EXPORT namespace winrt impl::check_status_canceled(shared->status); co_return shared->result.GetResults(); } -#endif } +#endif diff --git a/strings/base_coroutine_system.h b/strings/base_coroutine_system.h index b893bd1b5..f79fe0671 100644 --- a/strings/base_coroutine_system.h +++ b/strings/base_coroutine_system.h @@ -1,4 +1,5 @@ +#ifdef WINRT_IMPL_COROUTINES WINRT_EXPORT namespace winrt { [[nodiscard]] inline auto resume_foreground( @@ -23,7 +24,7 @@ WINRT_EXPORT namespace winrt return m_queued; } - bool await_suspend(impl::coroutine_handle<> handle) + bool await_suspend(std::coroutine_handle<> handle) { return m_dispatcher.TryEnqueue(m_priority, [handle, this] { @@ -41,10 +42,9 @@ WINRT_EXPORT namespace winrt return awaitable{ dispatcher, priority }; }; -#ifdef WINRT_IMPL_COROUTINES inline auto operator co_await(Windows::System::DispatcherQueue const& dispatcher) { return resume_foreground(dispatcher); } -#endif } +#endif diff --git a/strings/base_coroutine_system_winui.h b/strings/base_coroutine_system_winui.h deleted file mode 100644 index ecb3cf766..000000000 --- a/strings/base_coroutine_system_winui.h +++ /dev/null @@ -1,50 +0,0 @@ - -WINRT_EXPORT namespace winrt -{ - [[nodiscard]] inline auto resume_foreground( - Microsoft::System::DispatcherQueue const& dispatcher, - Microsoft::System::DispatcherQueuePriority const priority = Microsoft::System::DispatcherQueuePriority::Normal) noexcept - { - struct awaitable - { - awaitable(Microsoft::System::DispatcherQueue const& dispatcher, Microsoft::System::DispatcherQueuePriority const priority) noexcept : - m_dispatcher(dispatcher), - m_priority(priority) - { - } - - bool await_ready() const noexcept - { - return false; - } - - bool await_resume() const noexcept - { - return m_queued; - } - - bool await_suspend(impl::coroutine_handle<> handle) - { - return m_dispatcher.TryEnqueue(m_priority, [handle, this] - { - m_queued = true; - handle(); - }); - } - - private: - Microsoft::System::DispatcherQueue const& m_dispatcher; - Microsoft::System::DispatcherQueuePriority const m_priority; - bool m_queued{}; - }; - - return awaitable{ dispatcher, priority }; - }; - -#ifdef WINRT_IMPL_COROUTINES - inline auto operator co_await(Microsoft::System::DispatcherQueue const& dispatcher) - { - return resume_foreground(dispatcher); - } -#endif -} diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index 7fa8789c7..e59fcadb2 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -1,6 +1,7 @@ namespace winrt::impl { +#ifdef WINRT_IMPL_COROUTINES inline auto submit_threadpool_callback(void(__stdcall* callback)(void*, void* context), void* context) { if (!WINRT_IMPL_TrySubmitThreadpoolCallback(callback, context, nullptr)) @@ -11,13 +12,14 @@ namespace winrt::impl inline void __stdcall resume_background_callback(void*, void* context) noexcept { - coroutine_handle<>::from_address(context)(); + std::coroutine_handle<>::from_address(context)(); }; - inline auto resume_background(coroutine_handle<> handle) + inline auto resume_background(std::coroutine_handle<> handle) { submit_threadpool_callback(resume_background_callback, handle.address()); } +#endif inline std::pair get_apartment_type() noexcept { @@ -48,6 +50,7 @@ namespace winrt::impl return false; } +#ifdef WINRT_IMPL_COROUTINES struct resume_apartment_context { resume_apartment_context() = default; @@ -64,11 +67,11 @@ namespace winrt::impl inline int32_t __stdcall resume_apartment_callback(com_callback_args* args) noexcept { - coroutine_handle<>::from_address(args->data)(); + std::coroutine_handle<>::from_address(args->data)(); return 0; }; - [[nodiscard]] inline bool resume_apartment_sync(com_ptr const& context, coroutine_handle<> handle, int32_t* failure) + [[nodiscard]] inline bool resume_apartment_sync(com_ptr const& context, std::coroutine_handle<> handle, int32_t* failure) { com_callback_args args{}; args.data = handle.address(); @@ -85,10 +88,10 @@ namespace winrt::impl struct threadpool_resume { - threadpool_resume(com_ptr const& context, coroutine_handle<> handle, int32_t* failure) : + threadpool_resume(com_ptr const& context, std::coroutine_handle<> handle, int32_t* failure) : m_context(context), m_handle(handle), m_failure(failure) { } com_ptr m_context; - coroutine_handle<> m_handle; + std::coroutine_handle<> m_handle; int32_t* m_failure; }; @@ -101,14 +104,14 @@ namespace winrt::impl } } - inline void resume_apartment_on_threadpool(com_ptr const& context, coroutine_handle<> handle, int32_t* failure) + inline void resume_apartment_on_threadpool(com_ptr const& context, std::coroutine_handle<> handle, int32_t* failure) { auto state = std::make_unique(context, handle, failure); submit_threadpool_callback(fallback_submit_threadpool_callback, state.get()); state.release(); } - [[nodiscard]] inline auto resume_apartment(resume_apartment_context const& context, coroutine_handle<> handle, int32_t* failure) + [[nodiscard]] inline auto resume_apartment(resume_apartment_context const& context, std::coroutine_handle<> handle, int32_t* failure) { WINRT_ASSERT(context.valid()); if ((context.m_context == nullptr) || (context.m_context == try_capture(WINRT_IMPL_CoGetObjectContext))) @@ -130,8 +133,10 @@ namespace winrt::impl return resume_apartment_sync(context.m_context, handle, failure); } } +#endif } +#ifdef WINRT_IMPL_COROUTINES WINRT_EXPORT namespace winrt { struct cancellable_promise @@ -217,7 +222,7 @@ WINRT_EXPORT namespace winrt protected: template - void set_cancellable_promise_from_handle(impl::coroutine_handle const& handle) + void set_cancellable_promise_from_handle(std::coroutine_handle const& handle) { if constexpr (std::is_base_of_v) { @@ -237,10 +242,7 @@ WINRT_EXPORT namespace winrt cancellable_promise* m_promise = nullptr; }; -} -WINRT_EXPORT namespace winrt -{ [[nodiscard]] inline auto resume_background() noexcept { struct awaitable @@ -254,7 +256,7 @@ WINRT_EXPORT namespace winrt { } - void await_suspend(impl::coroutine_handle<> handle) const + void await_suspend(std::coroutine_handle<> handle) const { impl::resume_background(handle); } @@ -281,7 +283,7 @@ WINRT_EXPORT namespace winrt { } - void await_suspend(impl::coroutine_handle<> resume) + void await_suspend(std::coroutine_handle<> resume) { m_resume = resume; @@ -301,7 +303,7 @@ WINRT_EXPORT namespace winrt } T const& m_context; - impl::coroutine_handle<> m_resume{ nullptr }; + std::coroutine_handle<> m_resume{ nullptr }; }; return awaitable{ context }; @@ -336,7 +338,7 @@ namespace winrt::impl check_hresult(failure); } - bool await_suspend(impl::coroutine_handle<> handle) + bool await_suspend(std::coroutine_handle<> handle) { auto context_copy = context; return impl::resume_apartment(context_copy.context, handle, &failure); @@ -381,7 +383,7 @@ namespace winrt::impl } template - void await_suspend(impl::coroutine_handle handle) + void await_suspend(std::coroutine_handle handle) { set_cancellable_promise_from_handle(handle); @@ -445,7 +447,7 @@ namespace winrt::impl handle_type m_timer; Windows::Foundation::TimeSpan m_duration; - impl::coroutine_handle<> m_handle; + std::coroutine_handle<> m_handle; std::atomic m_state{ state::idle }; }; @@ -489,7 +491,7 @@ namespace winrt::impl } template - void await_suspend(impl::coroutine_handle resume) + void await_suspend(std::coroutine_handle resume) { set_cancellable_promise_from_handle(resume); @@ -559,31 +561,27 @@ namespace winrt::impl Windows::Foundation::TimeSpan m_timeout; void* m_handle; uint32_t m_result{}; - impl::coroutine_handle<> m_resume{ nullptr }; + std::coroutine_handle<> m_resume{ nullptr }; std::atomic m_state{ state::idle }; }; } WINRT_EXPORT namespace winrt { -#ifdef WINRT_IMPL_COROUTINES inline impl::apartment_awaiter operator co_await(apartment_context const& context) { return{ context }; } -#endif [[nodiscard]] inline impl::timespan_awaiter resume_after(Windows::Foundation::TimeSpan duration) noexcept { return impl::timespan_awaiter{ duration }; } -#ifdef WINRT_IMPL_COROUTINES inline impl::timespan_awaiter operator co_await(Windows::Foundation::TimeSpan duration) { return resume_after(duration); } -#endif [[nodiscard]] inline impl::signal_awaiter resume_on_signal(void* handle, Windows::Foundation::TimeSpan timeout = {}) noexcept { @@ -613,7 +611,7 @@ WINRT_EXPORT namespace winrt { } - void await_suspend(impl::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { if (!WINRT_IMPL_TrySubmitThreadpoolCallback(callback, handle.address(), &m_environment)) { @@ -625,7 +623,7 @@ WINRT_EXPORT namespace winrt static void __stdcall callback(void*, void* context) noexcept { - impl::coroutine_handle<>::from_address(context)(); + std::coroutine_handle<>::from_address(context)(); } struct pool_traits @@ -673,11 +671,7 @@ WINRT_EXPORT namespace winrt struct fire_and_forget {}; } -#ifdef __cpp_lib_coroutine namespace std -#else -namespace std::experimental -#endif { template struct coroutine_traits @@ -693,12 +687,12 @@ namespace std::experimental { } - suspend_never initial_suspend() const noexcept + std::suspend_never initial_suspend() const noexcept { return{}; } - suspend_never final_suspend() const noexcept + std::suspend_never final_suspend() const noexcept { return{}; } @@ -710,3 +704,4 @@ namespace std::experimental }; }; } +#endif diff --git a/strings/base_coroutine_ui_core.h b/strings/base_coroutine_ui_core.h index dab34c8de..7efed5174 100644 --- a/strings/base_coroutine_ui_core.h +++ b/strings/base_coroutine_ui_core.h @@ -1,4 +1,5 @@ +#ifdef WINRT_IMPL_COROUTINES WINRT_EXPORT namespace winrt { [[nodiscard]] inline auto resume_foreground( @@ -22,7 +23,7 @@ WINRT_EXPORT namespace winrt { } - void await_suspend(impl::coroutine_handle<> handle) const + void await_suspend(std::coroutine_handle<> handle) const { m_dispatcher.RunAsync(m_priority, [handle] { @@ -39,10 +40,9 @@ WINRT_EXPORT namespace winrt return awaitable{ dispatcher, priority }; }; -#ifdef WINRT_IMPL_COROUTINES inline auto operator co_await(Windows::UI::Core::CoreDispatcher const& dispatcher) { return resume_foreground(dispatcher); } -#endif } +#endif diff --git a/strings/base_deferral.h b/strings/base_deferral.h index ceab1cd4b..6976db4a6 100644 --- a/strings/base_deferral.h +++ b/strings/base_deferral.h @@ -1,7 +1,7 @@ +#ifdef WINRT_IMPL_COROUTINES WINRT_EXPORT namespace winrt { -#ifdef WINRT_IMPL_COROUTINES template struct deferrable_event_args { @@ -22,9 +22,9 @@ WINRT_EXPORT namespace winrt [[nodiscard]] Windows::Foundation::IAsyncAction wait_for_deferrals() { - struct awaitable : impl::suspend_always + struct awaitable : std::suspend_always { - bool await_suspend(coroutine_handle handle) + bool await_suspend(std::coroutine_handle<> handle) { return m_deferrable.await_suspend(handle); } @@ -37,11 +37,9 @@ WINRT_EXPORT namespace winrt private: - using coroutine_handle = impl::coroutine_handle<>; - void one_deferral_completed() { - coroutine_handle resume = nullptr; + std::coroutine_handle<> resume = nullptr; { slim_lock_guard const guard(m_lock); @@ -62,7 +60,7 @@ WINRT_EXPORT namespace winrt } } - bool await_suspend(coroutine_handle handle) noexcept + bool await_suspend(std::coroutine_handle<> handle) noexcept { slim_lock_guard const guard(m_lock); m_handle = handle; @@ -71,7 +69,7 @@ WINRT_EXPORT namespace winrt slim_mutex m_lock; int32_t m_outstanding_deferrals = 0; - coroutine_handle m_handle = nullptr; + std::coroutine_handle<> m_handle = nullptr; }; -#endif } +#endif diff --git a/strings/base_includes.h b/strings/base_includes.h index 819e3c98f..a3bf308d1 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -48,31 +48,7 @@ #endif #ifdef __cpp_lib_coroutine - #include - -namespace winrt::impl -{ - template - using coroutine_handle = std::coroutine_handle; - - using suspend_always = std::suspend_always; - using suspend_never = std::suspend_never; -} - -#elif __has_include() - -#include - -namespace winrt::impl -{ - template - using coroutine_handle = std::experimental::coroutine_handle; - - using suspend_always = std::experimental::suspend_always; - using suspend_never = std::experimental::suspend_never; -} - -#else -#error C++/WinRT requires coroutine support, which is currently missing. Try enabling C++20 in your compiler. +#elif defined(_RESUMABLE_FUNCTIONS_SUPPORTED) +#error "C++/WinRT no longer supports pre-standardization coroutines. If you use co_await, switch to /await:strict or upgrade to C++20. If you do not, remove /await from the compiler flags." #endif diff --git a/strings/base_macros.h b/strings/base_macros.h index 0c4357b1e..3dc01fa2d 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -23,7 +23,7 @@ #pragma warning(disable : 4268) #endif -#if defined(__cpp_lib_coroutine) || defined(__cpp_coroutines) || defined(_RESUMABLE_FUNCTIONS_SUPPORTED) +#if defined(__cpp_lib_coroutine) #define WINRT_IMPL_COROUTINES #endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ed1515526..e5ca6e0fb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -105,6 +105,7 @@ set(SKIP_LARGE_PCH FALSE CACHE BOOL "Skip building large precompiled headers.") add_subdirectory(test) +add_subdirectory(test_nocoro) add_subdirectory(test_cpp20) add_subdirectory(test_cpp20_no_sourcelocation) diff --git a/test/old_tests/UnitTests/async.cpp b/test/old_tests/UnitTests/async.cpp index 037e16ab7..7a7382004 100644 --- a/test/old_tests/UnitTests/async.cpp +++ b/test/old_tests/UnitTests/async.cpp @@ -14,12 +14,6 @@ using namespace std::chrono; namespace { -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - IAsyncAction NoSuspend_IAsyncAction() { co_await 0s; @@ -1118,7 +1112,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await suspend_never{}; + co_await std::suspend_never{}; REQUIRE(false); } @@ -1126,7 +1120,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await suspend_never{}; + co_await std::suspend_never{}; REQUIRE(false); } @@ -1134,7 +1128,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await suspend_never{}; + co_await std::suspend_never{}; REQUIRE(false); co_return 0; } @@ -1143,7 +1137,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await suspend_never{}; + co_await std::suspend_never{}; REQUIRE(false); co_return 0; } diff --git a/test/old_tests/UnitTests/weak.cpp b/test/old_tests/UnitTests/weak.cpp index 55c40dbe6..46b89bf6f 100644 --- a/test/old_tests/UnitTests/weak.cpp +++ b/test/old_tests/UnitTests/weak.cpp @@ -99,13 +99,13 @@ namespace // Returns an IAsyncAction that has not completed. // Call the resume() handle to complete it. - winrt::Windows::Foundation::IAsyncAction SuspendAction(impl::coroutine_handle<>& resume) + winrt::Windows::Foundation::IAsyncAction SuspendAction(std::coroutine_handle<>& resume) { struct awaiter { - impl::coroutine_handle<>& resume; + std::coroutine_handle<>& resume; bool await_ready() { return false; } - void await_suspend(impl::coroutine_handle<> handle) { resume = handle; } + void await_suspend(std::coroutine_handle<> handle) { resume = handle; } void await_resume() {} }; @@ -516,7 +516,7 @@ TEST_CASE("weak,coroutine") // Start a coroutine but don't complete it yet. // Confirm that weak references resolve. - impl::coroutine_handle<> resume; + std::coroutine_handle<> resume; weak = winrt::weak_ref(SuspendAction(resume)); REQUIRE(weak.get() != nullptr); // Now complete the coroutine. Confirm that weak references no longer resolve. diff --git a/test/test/async_auto_cancel.cpp b/test/test/async_auto_cancel.cpp index bffcb6e44..b0a541535 100644 --- a/test/test/async_auto_cancel.cpp +++ b/test/test/async_auto_cancel.cpp @@ -5,12 +5,6 @@ using namespace Windows::Foundation; namespace { -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - // // Checks that the coroutine is automatically canceled when reaching a suspension point. // @@ -18,21 +12,21 @@ namespace IAsyncAction Action(HANDLE event) { co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } IAsyncActionWithProgress ActionWithProgress(HANDLE event) { co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } IAsyncOperation Operation(HANDLE event) { co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } @@ -40,7 +34,7 @@ namespace IAsyncOperationWithProgress OperationWithProgress(HANDLE event) { co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } @@ -54,7 +48,7 @@ namespace auto cancel = co_await get_cancellation_token(); cancel.callback(nullptr); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } diff --git a/test/test/async_cancel_callback.cpp b/test/test/async_cancel_callback.cpp index c99e1dad4..75a3aac0c 100644 --- a/test/test/async_cancel_callback.cpp +++ b/test/test/async_cancel_callback.cpp @@ -5,12 +5,6 @@ using namespace Windows::Foundation; namespace { -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - // // Checks that the cancellation callback is invoked. // @@ -29,7 +23,7 @@ namespace }(); co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } @@ -44,7 +38,7 @@ namespace }); co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } @@ -59,7 +53,7 @@ namespace }); co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } @@ -75,7 +69,7 @@ namespace }); co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } diff --git a/test/test/async_check_cancel.cpp b/test/test/async_check_cancel.cpp index d88fdcaf0..c98519f06 100644 --- a/test/test/async_check_cancel.cpp +++ b/test/test/async_check_cancel.cpp @@ -5,12 +5,6 @@ using namespace Windows::Foundation; namespace { -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - static bool s_exceptionLoggerCalled = false; static struct { @@ -48,7 +42,7 @@ namespace canceled = true; } - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } @@ -63,7 +57,7 @@ namespace canceled = true; } - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } @@ -78,7 +72,7 @@ namespace canceled = true; } - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } @@ -95,7 +89,7 @@ namespace canceled = true; } - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } @@ -120,7 +114,7 @@ namespace winrt_throw_hresult_handler = nullptr; s_exceptionLoggerCalled = false; - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return; @@ -147,7 +141,7 @@ namespace winrt_throw_hresult_handler = nullptr; s_exceptionLoggerCalled = false; - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return; diff --git a/test/test/when.cpp b/test/test/when.cpp index 35c9287a8..0b1151abc 100644 --- a/test/test/when.cpp +++ b/test/test/when.cpp @@ -5,13 +5,7 @@ using namespace concurrency; using namespace winrt; using namespace Windows::Foundation; -#ifdef __cpp_lib_coroutine -using std::suspend_never; -#else -using std::experimental::suspend_never; -#endif - -struct CommaStruct : suspend_never +struct CommaStruct : std::suspend_never { // If the comma operator is invoked, we will get a build failure. CommaStruct operator,(CommaStruct) = delete; diff --git a/test/test_nocoro/CMakeLists.txt b/test/test_nocoro/CMakeLists.txt new file mode 100644 index 000000000..ee234f146 --- /dev/null +++ b/test/test_nocoro/CMakeLists.txt @@ -0,0 +1,35 @@ +set(CMAKE_CXX_STANDARD 17) + +file(GLOB TEST_SRCS + LIST_DIRECTORIES false + CONFIGURE_DEPENDS + *.cpp +) +list(FILTER TEST_SRCS EXCLUDE REGEX "/(main|pch)\\.cpp") + + +list(APPEND BROKEN_TESTS + # No broken tests. +) + +# Exclude broken tests +foreach(TEST_SRCS_EXCLUDE_ITEM IN LISTS BROKEN_TESTS) + list(FILTER TEST_SRCS EXCLUDE REGEX "/${TEST_SRCS_EXCLUDE_ITEM}\\.cpp") +endforeach() + +add_executable(test_nocoro main.cpp ${TEST_SRCS}) + +target_compile_definitions(test_nocoro PRIVATE WINRT_NO_SOURCE_LOCATION) + +target_precompile_headers(test_nocoro PRIVATE pch.h) +set_source_files_properties( + main.cpp + PROPERTIES SKIP_PRECOMPILE_HEADERS true +) + +add_dependencies(test_nocoro build-cppwinrt-projection) + +add_test( + NAME test_nocoro + COMMAND "$" ${TEST_COLOR_ARG} +) diff --git a/test/test_nocoro/get.cpp b/test/test_nocoro/get.cpp new file mode 100644 index 000000000..11339e10b --- /dev/null +++ b/test/test_nocoro/get.cpp @@ -0,0 +1,74 @@ +#include "pch.h" + +using namespace winrt; +using namespace Windows::Foundation; + +template +struct async_completion_source : implements, IAsyncOperation, IAsyncInfo> +{ + void set_result(TResult result) + { + m_result = std::move(result); + m_status = AsyncStatus::Completed; + m_completed(*this, m_status); + } + + void Completed(AsyncOperationCompletedHandler completed) + { + m_completed = completed; + } + + AsyncOperationCompletedHandler Completed() const noexcept + { + return m_completed; + } + + TResult GetResults() + { + return m_result.value(); + } + + uint32_t Id() const + { + return 1; + } + + AsyncStatus Status() const + { + return m_status; + } + + hresult ErrorCode() const + { + return hresult(0); // S_OK + } + + void Cancel() const + { + throw hresult_error(0x80070032); // E_NOT_SUPPORTED + } + + void Close() const + { + } + +private: + AsyncStatus m_status = AsyncStatus::Started; + AsyncOperationCompletedHandler m_completed; + std::optional m_result; +}; + +TEST_CASE("get") +{ + auto acs = winrt::make_self>(); + + std::thread worker([acs] + { + std::this_thread::sleep_for(1s); + acs->set_result(0xDEADBEEF); + }); + + worker.detach(); + + REQUIRE(acs.as>().get() == 0xDEADBEEF); +} diff --git a/test/test_nocoro/main.cpp b/test/test_nocoro/main.cpp new file mode 100644 index 000000000..7590df7e1 --- /dev/null +++ b/test/test_nocoro/main.cpp @@ -0,0 +1,22 @@ +#include +#define CATCH_CONFIG_RUNNER +#include "catch.hpp" +#include "winrt/base.h" + +using namespace winrt; + +int main(int const argc, char** argv) +{ + init_apartment(); + std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + return Catch::Session().run(argc, argv); +} + +CATCH_TRANSLATE_EXCEPTION(hresult_error const& e) +{ + return to_string(e.message()); +} diff --git a/test/test_nocoro/pch.cpp b/test/test_nocoro/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/test_nocoro/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/test_nocoro/pch.h b/test/test_nocoro/pch.h new file mode 100644 index 000000000..7ff48a37c --- /dev/null +++ b/test/test_nocoro/pch.h @@ -0,0 +1,6 @@ +#pragma once + +#include "catch.hpp" +#include "winrt/Windows.Foundation.h" + +using namespace std::literals; diff --git a/test/test_nocoro/test_nocoro.vcxproj b/test/test_nocoro/test_nocoro.vcxproj new file mode 100644 index 000000000..7efc28066 --- /dev/null +++ b/test/test_nocoro/test_nocoro.vcxproj @@ -0,0 +1,241 @@ + + + + + Debug + ARM64 + + + Debug + Win32 + + + Release + ARM64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {9E392830-805A-4AAF-932D-C493143EFACA} + unittests + test_nocoro + false + + + + Application + true + + + Application + true + + + Application + false + true + + + Application + false + true + + + Application + true + + + Application + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + Level4 + true + + + Console + true + true + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + Level4 + true + + + Console + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + Level4 + true + + + Console + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + Level4 + true + + + Console + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + Level4 + true + + + Console + true + true + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + Level4 + true + + + Console + true + true + + + + + + + + + + + + + + + + + NotUsing + + + Create + + + + + + \ No newline at end of file From 481f8f40816dd7c49a073de4b5d09191e5140e7f Mon Sep 17 00:00:00 2001 From: Yexuan Xiao Date: Tue, 17 Mar 2026 13:54:27 +0800 Subject: [PATCH 69/91] =?UTF-8?q?Add=20missing=20headers=20and=20std=20qua?= =?UTF-8?q?lification,=20use=20std::numeric=5Flimits=20in=E2=80=A6=20(#154?= =?UTF-8?q?6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add missing headers and std qualification, use std::numeric_limits instead of macros, and use std::memcpy/std::swprintf instead of the non-standard memcpy_s/swprintf_s * Remove a accidentally added redundant comment * Add some headers as suggested by Copilot * Use std::copy_n instead of std::memcpy, and protect std::numeric_limits::max from the max macro --- cppwinrt/cmd_reader.h | 31 +-- cppwinrt/code_writers.h | 84 +++--- cppwinrt/component_writers.h | 20 +- cppwinrt/helpers.h | 30 +-- cppwinrt/text_writer.h | 27 +- cppwinrt/type_writers.h | 22 +- strings/base_abi.h | 96 +++---- strings/base_activation.h | 74 +++--- strings/base_agile_ref.h | 4 +- strings/base_array.h | 64 ++--- strings/base_chrono.h | 10 +- strings/base_collections.h | 6 +- strings/base_collections_base.h | 50 ++-- strings/base_collections_map.h | 6 +- strings/base_collections_vector.h | 18 +- strings/base_com_ptr.h | 8 +- strings/base_coroutine_foundation.h | 14 +- strings/base_coroutine_threadpool.h | 52 ++-- strings/base_deferral.h | 2 +- strings/base_delegate.h | 18 +- strings/base_error.h | 22 +- strings/base_events.h | 26 +- strings/base_extern.h | 98 +++---- strings/base_fast_forward.h | 42 +-- strings/base_identity.h | 240 +++++++++--------- strings/base_implements.h | 150 +++++------ strings/base_includes.h | 5 + strings/base_iterator.h | 10 +- strings/base_lock.h | 2 +- strings/base_marshaler.h | 20 +- strings/base_natvis.h | 34 +-- strings/base_reference_produce.h | 126 ++++----- strings/base_security.h | 2 +- strings/base_std_hash.h | 22 +- strings/base_string.h | 84 +++--- strings/base_string_input.h | 8 +- strings/base_string_operators.h | 6 +- strings/base_types.h | 52 ++-- strings/base_version.h | 4 +- strings/base_windows.h | 6 +- strings/base_xaml_component_connector.h | 4 +- strings/base_xaml_component_connector_winui.h | 4 +- strings/base_xaml_typename.h | 16 +- 43 files changed, 814 insertions(+), 805 deletions(-) diff --git a/cppwinrt/cmd_reader.h b/cppwinrt/cmd_reader.h index 7faf49e4f..e2787b7d4 100644 --- a/cppwinrt/cmd_reader.h +++ b/cppwinrt/cmd_reader.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -203,7 +204,7 @@ namespace cppwinrt while (true) { - DWORD actual_size = GetModuleFileNameA(nullptr, path.data(), 1 + static_cast(path.size())); + DWORD actual_size = GetModuleFileNameA(nullptr, path.data(), 1 + static_cast(path.size())); if (actual_size < 1 + path.size()) { @@ -237,12 +238,12 @@ namespace cppwinrt } auto key = open_sdk(); - uint32_t index{}; + std::uint32_t index{}; std::array subkey; std::array version_parts{}; std::string result; - while (0 == RegEnumKeyA(key.handle, index++, subkey.data(), static_cast(subkey.size()))) + while (0 == RegEnumKeyA(key.handle, index++, subkey.data(), static_cast(subkey.size()))) { if (!std::regex_match(subkey.data(), match, rx)) { @@ -258,7 +259,7 @@ namespace cppwinrt char* next_part = subkey.data(); bool force_newer = false; - for (size_t i = 0; ; ++i) + for (std::size_t i = 0; ; ++i) { auto version_part = strtoul(next_part, &next_part, 10); @@ -312,19 +313,19 @@ namespace cppwinrt struct option { - static constexpr uint32_t no_min = 0; - static constexpr uint32_t no_max = UINT_MAX; + static constexpr std::uint32_t no_min = 0; + static constexpr std::uint32_t no_max = (std::numeric_limits::max)(); std::string_view name; - uint32_t min{ no_min }; - uint32_t max{ no_max }; + std::uint32_t min{ no_min }; + std::uint32_t max{ no_max }; std::string_view arg{}; std::string_view desc{}; }; struct reader { - template + template reader(C const argc, V const argv, const option(& options)[numOptions]) { #ifdef _DEBUG @@ -449,9 +450,9 @@ namespace cppwinrt #if defined(_WIN32) || defined(_WIN64) std::array local{}; #ifdef _WIN64 - ExpandEnvironmentStringsA("%windir%\\System32\\WinMetadata", local.data(), static_cast(local.size())); + ExpandEnvironmentStringsA("%windir%\\System32\\WinMetadata", local.data(), static_cast(local.size())); #else - ExpandEnvironmentStringsA("%windir%\\SysNative\\WinMetadata", local.data(), static_cast(local.size())); + ExpandEnvironmentStringsA("%windir%\\SysNative\\WinMetadata", local.data(), static_cast(local.size())); #endif add_directory(local.data()); #else /* defined(_WIN32) || defined(_WIN64) */ @@ -586,7 +587,7 @@ namespace cppwinrt std::filesystem::path response_path{ std::string{ arg } }; std::string extension = response_path.extension().generic_string(); std::transform(extension.begin(), extension.end(), extension.begin(), - [](auto c) { return static_cast(::tolower(c)); }); + [](auto c) { return static_cast(std::tolower(c)); }); // Check if misuse of @ prefix, so if directory or metadata file instead of response file. if (is_directory(response_path) || extension == ".winmd") @@ -597,12 +598,12 @@ namespace cppwinrt std::ifstream response_file(absolute(response_path)); while (getline(response_file, line_buf)) { - size_t argc = 0; + std::size_t argc = 0; std::vector argv; parse_command_line(line_buf.data(), argv, &argc); - for (size_t i = 0; i < argc; i++) + for (std::size_t i = 0; i < argc; i++) { extract_option(argv[i], options, last); } @@ -610,7 +611,7 @@ namespace cppwinrt } template - static void parse_command_line(Character* cmdstart, std::vector& argv, size_t* argument_count) + static void parse_command_line(Character* cmdstart, std::vector& argv, std::size_t* argument_count) { std::string arg; diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index e24cfd302..0a4c4638e 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -359,17 +359,17 @@ namespace cppwinrt using std::get; w.write_printf("0x%08X,0x%04X,0x%04X,{ 0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X }", - get(get(args[0].value).value), - get(get(args[1].value).value), - get(get(args[2].value).value), - get(get(args[3].value).value), - get(get(args[4].value).value), - get(get(args[5].value).value), - get(get(args[6].value).value), - get(get(args[7].value).value), - get(get(args[8].value).value), - get(get(args[9].value).value), - get(get(args[10].value).value)); + get(get(args[0].value).value), + get(get(args[1].value).value), + get(get(args[2].value).value), + get(get(args[3].value).value), + get(get(args[4].value).value), + get(get(args[5].value).value), + get(get(args[6].value).value), + get(get(args[7].value).value), + get(get(args[8].value).value), + get(get(args[9].value).value), + get(get(args[10].value).value)); } static void write_guid_comment(writer& w, std::vector const& args) @@ -377,17 +377,17 @@ namespace cppwinrt using std::get; w.write_printf("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", - get(get(args[0].value).value), - get(get(args[1].value).value), - get(get(args[2].value).value), - get(get(args[3].value).value), - get(get(args[4].value).value), - get(get(args[5].value).value), - get(get(args[6].value).value), - get(get(args[7].value).value), - get(get(args[8].value).value), - get(get(args[9].value).value), - get(get(args[10].value).value)); + get(get(args[0].value).value), + get(get(args[1].value).value), + get(get(args[2].value).value), + get(get(args[3].value).value), + get(get(args[4].value).value), + get(get(args[5].value).value), + get(get(args[6].value).value), + get(get(args[7].value).value), + get(get(args[8].value).value), + get(get(args[9].value).value), + get(get(args[10].value).value)); } static void write_category(writer& w, TypeDef const& type, std::string_view const& category) @@ -561,15 +561,15 @@ namespace cppwinrt if (param.Flags().In()) { - format = "uint32_t%, %"; + format = "std::uint32_t%, %"; } else if (param_signature->ByRef()) { - format = "uint32_t*%, %*"; + format = "std::uint32_t*%, %*"; } else { - format = "uint32_t%, %"; + format = "std::uint32_t%, %"; } w.write(format, bind(param), bind(param_signature->Type())); @@ -605,7 +605,7 @@ namespace cppwinrt if (type.is_szarray()) { - w.write("uint32_t* __%Size, %**", method_signature.return_param_name(), type); + w.write("std::uint32_t* __%Size, %**", method_signature.return_param_name(), type); } else { @@ -748,7 +748,7 @@ namespace cppwinrt break; } - auto format = R"( virtual int32_t __stdcall %(%) noexcept = 0; + auto format = R"( virtual std::int32_t __stdcall %(%) noexcept = 0; )"; for (auto&& method : info.type.MethodList()) @@ -788,7 +788,7 @@ namespace cppwinrt } - auto format = R"( virtual int32_t __stdcall %(%) noexcept = 0; + auto format = R"( virtual std::int32_t __stdcall %(%) noexcept = 0; )"; auto abi_guard = w.push_abi_types(true); @@ -821,7 +821,7 @@ namespace cppwinrt { struct WINRT_IMPL_ABI_DECL type : unknown_abi { - virtual int32_t __stdcall Invoke(%) noexcept = 0; + virtual std::int32_t __stdcall Invoke(%) noexcept = 0; }; }; )"; @@ -1054,7 +1054,7 @@ namespace cppwinrt if (category == param_category::array_type) { auto format = R"( - uint32_t %_impl_size{}; + std::uint32_t %_impl_size{}; %* %{};)"; auto abi_guard = w.push_abi_types(true); @@ -1317,7 +1317,7 @@ namespace cppwinrt w.write(R"( auto data() const { - uint8_t* data{}; + std::uint8_t* data{}; static_cast(*this).template as()->Buffer(&data); return data; } @@ -1328,8 +1328,8 @@ namespace cppwinrt w.write(R"( auto data() const { - uint8_t* data{}; - uint32_t capacity{}; + std::uint8_t* data{}; + std::uint32_t capacity{}; check_hresult(static_cast(*this).template as()->GetBuffer(&data, &capacity)); return data; } @@ -1480,7 +1480,7 @@ namespace cppwinrt using iterator_concept = std::input_iterator_tag; using iterator_category = std::input_iterator_tag; using value_type = T; - using difference_type = ptrdiff_t; + using difference_type = std::ptrdiff_t; using pointer = void; using reference = T; )"); @@ -1491,7 +1491,7 @@ namespace cppwinrt using iterator_concept = std::input_iterator_tag; using iterator_category = std::input_iterator_tag; using value_type = Windows::Foundation::IInspectable; - using difference_type = ptrdiff_t; + using difference_type = std::ptrdiff_t; using pointer = void; using reference = Windows::Foundation::IInspectable; )"); @@ -1874,7 +1874,7 @@ namespace cppwinrt if (is_noexcept(method)) { - format = R"( int32_t __stdcall %(%) noexcept final + format = R"( std::int32_t __stdcall %(%) noexcept final { % typename D::abi_guard guard(this->shim()); % @@ -1884,7 +1884,7 @@ namespace cppwinrt } else { - format = R"( int32_t __stdcall %(%) noexcept final try + format = R"( std::int32_t __stdcall %(%) noexcept final try { % typename D::abi_guard guard(this->shim()); % @@ -1906,7 +1906,7 @@ namespace cppwinrt { // Special-case IMap*::Lookup to look for a TryLookup here, to avoid extranous throw/originates std::string tryLookupUpCall = "this->shim().TryLookup"; - format = R"( int32_t __stdcall %(%) noexcept final try + format = R"( std::int32_t __stdcall %(%) noexcept final try { % typename D::abi_guard guard(this->shim()); if constexpr (has_TryLookup_v) @@ -2596,7 +2596,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable { delegate(H&& handler) : implements_delegate<%, H>(std::forward(handler)) {} - int32_t __stdcall Invoke(%) noexcept final try + std::int32_t __stdcall Invoke(%) noexcept final try { % % return 0; @@ -2801,7 +2801,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable static void write_struct_equality(writer& w, std::vector> const& fields) { - for (size_t i = 0; i != fields.size(); ++i) + for (std::size_t i = 0; i != fields.size(); ++i) { w.write(" left.% == right.%", fields[i].first, fields[i].first); @@ -2877,9 +2877,9 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable return false; }; - for (size_t left = 0; left < structs.size(); ++left) + for (std::size_t left = 0; left < structs.size(); ++left) { - for (size_t right = left + 1; right < structs.size(); ++right) + for (std::size_t right = left + 1; right < structs.size(); ++right) { if (depends(w, structs[left], structs[right])) { diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index cb748917d..3966cad6c 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -172,7 +172,7 @@ void* __stdcall %_get_activation_factory([[maybe_unused]] std::wstring_view cons } format = R"( -int32_t __stdcall WINRT_CanUnloadNow() noexcept +std::int32_t __stdcall WINRT_CanUnloadNow() noexcept { #ifdef _WRL_MODULE_H_ #ifdef _MSC_VER @@ -187,7 +187,7 @@ int32_t __stdcall WINRT_CanUnloadNow() noexcept return %_can_unload_now() ? 0 : 1; } -int32_t __stdcall WINRT_GetActivationFactory(void* classId, void** factory) noexcept try +std::int32_t __stdcall WINRT_GetActivationFactory(void* classId, void** factory) noexcept try { std::wstring_view const name{ *reinterpret_cast(&classId) }; *factory = %_get_activation_factory(name); @@ -640,7 +640,7 @@ catch (...) { return winrt::to_hresult(); } } )"; - size_t offset = get_bases(type).size(); + std::size_t offset = get_bases(type).size(); auto interfaces = get_interfaces(w, type); for (auto&& [name, info] : interfaces) @@ -685,7 +685,7 @@ catch (...) { return winrt::to_hresult(); } if (has_base) { auto format = R"( - int32_t query_interface_tearoff(guid const& id, void** result) const noexcept override + std::int32_t query_interface_tearoff(guid const& id, void** result) const noexcept override {% return B::query_interface_tearoff(id, result); } @@ -701,7 +701,7 @@ catch (...) { return winrt::to_hresult(); } } auto format = R"( - int32_t query_interface_tearoff(guid const& id, void** result) const noexcept override + std::int32_t query_interface_tearoff(guid const& id, void** result) const noexcept override {% return impl::error_no_interface; } @@ -779,8 +779,8 @@ catch (...) { return winrt::to_hresult(); } { composable_base_name = w.write_temp("using composable_base = %;", base_type); auto base_interfaces = get_interfaces(w, base_type); - uint32_t base_interfaces_count{}; - uint32_t protected_base_interfaces_count{}; + std::uint32_t base_interfaces_count{}; + std::uint32_t protected_base_interfaces_count{}; external_requires = ",\n impl::require(::toupper(c)); }); + std::transform(upper.begin(), upper.end(), upper.begin(), [](char c) {return static_cast(std::toupper(c)); }); auto include_path = get_generated_component_filename(type); @@ -1240,7 +1240,7 @@ namespace winrt::@::implementation static void write_component_fast_abi_thunk(writer& w) { - for (uint32_t slot = 6; slot < 1024; ++slot) + for (std::uint32_t slot = 6; slot < 1024; ++slot) { auto format = R"( extern "C" void __stdcall winrt_ff_thunk%(); )"; @@ -1251,7 +1251,7 @@ namespace winrt::@::implementation static void write_component_fast_abi_vtable(writer& w) { - for (uint32_t slot = 6; slot < 1024; ++slot) + for (std::uint32_t slot = 6; slot < 1024; ++slot) { auto format = R"( #if WINRT_FAST_ABI_SIZE > % diff --git a/cppwinrt/helpers.h b/cppwinrt/helpers.h index 522d0bcd1..2dc152a74 100644 --- a/cppwinrt/helpers.h +++ b/cppwinrt/helpers.h @@ -31,7 +31,7 @@ namespace cppwinrt ++params.first; } - for (uint32_t i{}; i != size(m_signature.Params()); ++i) + for (std::uint32_t i{}; i != size(m_signature.Params()); ++i) { m_params.emplace_back(params.first + i, &m_signature.Params().first[i]); } @@ -193,7 +193,7 @@ namespace cppwinrt } template - auto get_attribute_value(CustomAttribute const& attribute, uint32_t const arg) + auto get_attribute_value(CustomAttribute const& attribute, std::uint32_t const arg) { return get_attribute_value(attribute.Value().FixedArgs()[arg]); } @@ -330,15 +330,15 @@ namespace cppwinrt struct contract_version { std::string_view name; - uint32_t version; + std::uint32_t version; }; struct previous_contract { std::string_view contract_from; std::string_view contract_to; - uint32_t version_low; - uint32_t version_high; + std::uint32_t version_low; + std::uint32_t version_high; }; struct contract_history @@ -359,7 +359,7 @@ namespace cppwinrt assert(args.size() == 2); contract_version result{}; - result.version = get_integer_attribute(args[1]); + result.version = get_integer_attribute(args[1]); call(std::get(args[0].value).value, [&](ElemSig::SystemType t) { @@ -388,8 +388,8 @@ namespace cppwinrt previous_contract result{}; result.contract_from = get_attribute_value(args[0]); - result.version_low = get_integer_attribute(args[1]); - result.version_high = get_integer_attribute(args[2]); + result.version_low = get_integer_attribute(args[1]); + result.version_high = get_integer_attribute(args[2]); if (args.size() == 4) { result.contract_to = get_attribute_value(args[3]); @@ -452,7 +452,7 @@ namespace cppwinrt // is not a contract version if (current_contract.name.empty()) { - current_contract.version = get_attribute_value(attribute, 0); + current_contract.version = get_attribute_value(attribute, 0); } } } @@ -509,7 +509,7 @@ namespace cppwinrt } assert(result.previous_contracts.back().contract_to == result.current_contract.name); - for (size_t size = result.previous_contracts.size() - 1; size; --size) + for (std::size_t size = result.previous_contracts.size() - 1; size; --size) { auto& last = result.previous_contracts[size]; auto itr = std::find_if(result.previous_contracts.begin(), result.previous_contracts.begin() + size, [&](auto const& prev) @@ -537,7 +537,7 @@ namespace cppwinrt // in relative to the contract history of the class. E.g. if a class goes from contract 'A' to 'B' to 'C', // 'relativeContract' would be '0' for an interface introduced in contract 'A', '1' for an interface introduced // in contract 'B', etc. This is only set/valid for 'fastabi' interfaces - std::pair relative_version{}; + std::pair relative_version{}; std::vector> generic_param_stack{}; }; @@ -660,7 +660,7 @@ namespace cppwinrt } auto history = get_contract_history(type); - size_t count = 0; + std::size_t count = 0; for (auto& pair : result) { if (pair.second.exclusive && !pair.second.base && !pair.second.overridable) @@ -676,12 +676,12 @@ namespace cppwinrt }); if (itr != history.previous_contracts.end()) { - pair.second.relative_version.first = static_cast(itr - history.previous_contracts.begin()); + pair.second.relative_version.first = static_cast(itr - history.previous_contracts.begin()); } else { assert(history.current_contract.name == introduced.name); - pair.second.relative_version.first = static_cast(history.previous_contracts.size()); + pair.second.relative_version.first = static_cast(history.previous_contracts.size()); } } } @@ -863,7 +863,7 @@ namespace cppwinrt { if (auto visibility = std::get_if(&std::get(arg.value).value)) { - info.visible = std::get(visibility->value) == 2; + info.visible = std::get(visibility->value) == 2; break; } } diff --git a/cppwinrt/text_writer.h b/cppwinrt/text_writer.h index 0b7c07a4e..a274d11ce 100644 --- a/cppwinrt/text_writer.h +++ b/cppwinrt/text_writer.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -66,7 +67,7 @@ namespace cppwinrt #if defined(_DEBUG) if (debug_trace) { - ::printf("%.*s", static_cast(value.size()), value.data()); + std::printf("%.*s", static_cast(value.size()), value.data()); } #endif } @@ -78,7 +79,7 @@ namespace cppwinrt #if defined(_DEBUG) if (debug_trace) { - ::printf("%c", value); + std::printf("%c", value); } #endif } @@ -139,12 +140,12 @@ namespace cppwinrt { char buffer[128]; #if defined(_WIN32) || defined(_WIN64) - size_t const size = sprintf_s(buffer, format, args...); + std::size_t const size = sprintf_s(buffer, format, args...); #else - size_t size = snprintf(buffer, sizeof(buffer), format, args...); + std::size_t size = std::snprintf(buffer, sizeof(buffer), format, args...); if (size > sizeof(buffer) - 1) { - fprintf(stderr, "\n*** WARNING: writer_base::write_printf -- buffer too small\n"); + std::fprintf(stderr, "\n*** WARNING: writer_base::write_printf -- buffer too small\n"); size = sizeof(buffer) - 1; } #endif @@ -167,8 +168,8 @@ namespace cppwinrt void flush_to_console(bool to_stdout = true) noexcept { - fprintf(to_stdout ? stdout : stderr, "%.*s", static_cast(m_first.size()), m_first.data()); - fprintf(to_stdout ? stdout : stderr, "%.*s", static_cast(m_second.size()), m_second.data()); + std::fprintf(to_stdout ? stdout : stderr, "%.*s", static_cast(m_first.size()), m_first.data()); + std::fprintf(to_stdout ? stdout : stderr, "%.*s", static_cast(m_second.size()), m_second.data()); m_first.clear(); m_second.clear(); } @@ -243,9 +244,9 @@ namespace cppwinrt private: - static constexpr uint32_t count_placeholders(std::string_view const& format) noexcept + static constexpr std::uint32_t count_placeholders(std::string_view const& format) noexcept { - uint32_t count{}; + std::uint32_t count{}; bool escape{}; for (auto c : format) @@ -332,7 +333,7 @@ namespace cppwinrt { struct indent_guard { - indent_guard(indented_writer_base& w, int32_t offset = 1) noexcept : m_writer(w), m_offset(offset) + indent_guard(indented_writer_base& w, std::int32_t offset = 1) noexcept : m_writer(w), m_offset(offset) { m_writer.m_indent += m_offset; } @@ -344,13 +345,13 @@ namespace cppwinrt private: indented_writer_base& m_writer; - int32_t m_offset{}; + std::int32_t m_offset{}; }; void write_indent() { - for (int32_t i = 0; i < m_indent; i++) + for (std::int32_t i = 0; i < m_indent; i++) { writer_base::write_impl(" "); } @@ -418,7 +419,7 @@ namespace cppwinrt return result; } - int32_t m_indent{}; + std::int32_t m_indent{}; }; diff --git a/cppwinrt/type_writers.h b/cppwinrt/type_writers.h index 0fa3e5f8d..df17450f1 100644 --- a/cppwinrt/type_writers.h +++ b/cppwinrt/type_writers.h @@ -232,12 +232,12 @@ namespace cppwinrt return member_value_guard(this, &writer::delegate_types, value); } - void write_value(int32_t value) + void write_value(std::int32_t value) { write_printf("%d", value); } - void write_value(uint32_t value) + void write_value(std::uint32_t value) { write_printf("%#0x", value); } @@ -309,7 +309,7 @@ namespace cppwinrt { if ((name == "DateTime" || name == "TimeSpan") && ns == "Windows.Foundation") { - write("int64_t"); + write("std::int64_t"); } else if ((name == "Point" || name == "Size" || name == "Rect") && ns == "Windows.Foundation") { @@ -473,14 +473,14 @@ namespace cppwinrt { if (type == ElementType::Boolean) { write("bool"); } else if (type == ElementType::Char) { write("char16_t"); } - else if (type == ElementType::I1) { write("int8_t"); } - else if (type == ElementType::U1) { write("uint8_t"); } - else if (type == ElementType::I2) { write("int16_t"); } - else if (type == ElementType::U2) { write("uint16_t"); } - else if (type == ElementType::I4) { write("int32_t"); } - else if (type == ElementType::U4) { write("uint32_t"); } - else if (type == ElementType::I8) { write("int64_t"); } - else if (type == ElementType::U8) { write("uint64_t"); } + else if (type == ElementType::I1) { write("std::int8_t"); } + else if (type == ElementType::U1) { write("std::uint8_t"); } + else if (type == ElementType::I2) { write("std::int16_t"); } + else if (type == ElementType::U2) { write("std::uint16_t"); } + else if (type == ElementType::I4) { write("std::int32_t"); } + else if (type == ElementType::U4) { write("std::uint32_t"); } + else if (type == ElementType::I8) { write("std::int64_t"); } + else if (type == ElementType::U8) { write("std::uint64_t"); } else if (type == ElementType::R4) { write("float"); } else if (type == ElementType::R8) { write("double"); } else if (type == ElementType::String) diff --git a/strings/base_abi.h b/strings/base_abi.h index ec42fefe6..72946a3fa 100644 --- a/strings/base_abi.h +++ b/strings/base_abi.h @@ -5,9 +5,9 @@ namespace winrt::impl { struct WINRT_IMPL_ABI_DECL type { - virtual int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept = 0; - virtual uint32_t __stdcall AddRef() noexcept = 0; - virtual uint32_t __stdcall Release() noexcept = 0; + virtual std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept = 0; + virtual std::uint32_t __stdcall AddRef() noexcept = 0; + virtual std::uint32_t __stdcall Release() noexcept = 0; }; }; @@ -17,9 +17,9 @@ namespace winrt::impl { struct WINRT_IMPL_ABI_DECL type : unknown_abi { - virtual int32_t __stdcall GetIids(uint32_t* count, guid** ids) noexcept = 0; - virtual int32_t __stdcall GetRuntimeClassName(void** name) noexcept = 0; - virtual int32_t __stdcall GetTrustLevel(Windows::Foundation::TrustLevel* level) noexcept = 0; + virtual std::int32_t __stdcall GetIids(std::uint32_t* count, guid** ids) noexcept = 0; + virtual std::int32_t __stdcall GetRuntimeClassName(void** name) noexcept = 0; + virtual std::int32_t __stdcall GetTrustLevel(Windows::Foundation::TrustLevel* level) noexcept = 0; }; }; @@ -29,7 +29,7 @@ namespace winrt::impl { struct WINRT_IMPL_ABI_DECL type : inspectable_abi { - virtual int32_t __stdcall ActivateInstance(void** instance) noexcept = 0; + virtual std::int32_t __stdcall ActivateInstance(void** instance) noexcept = 0; }; }; @@ -37,109 +37,109 @@ namespace winrt::impl struct WINRT_IMPL_ABI_DECL IAgileReference : unknown_abi { - virtual int32_t __stdcall Resolve(guid const& id, void** object) noexcept = 0; + virtual std::int32_t __stdcall Resolve(guid const& id, void** object) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IMarshal : unknown_abi { - virtual int32_t __stdcall GetUnmarshalClass(guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, guid* pCid) noexcept = 0; - virtual int32_t __stdcall GetMarshalSizeMax(guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, uint32_t* pSize) noexcept = 0; - virtual int32_t __stdcall MarshalInterface(void* pStm, guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags) noexcept = 0; - virtual int32_t __stdcall UnmarshalInterface(void* pStm, guid const& riid, void** ppv) noexcept = 0; - virtual int32_t __stdcall ReleaseMarshalData(void* pStm) noexcept = 0; - virtual int32_t __stdcall DisconnectObject(uint32_t dwReserved) noexcept = 0; + virtual std::int32_t __stdcall GetUnmarshalClass(guid const& riid, void* pv, std::uint32_t dwDestContext, void* pvDestContext, std::uint32_t mshlflags, guid* pCid) noexcept = 0; + virtual std::int32_t __stdcall GetMarshalSizeMax(guid const& riid, void* pv, std::uint32_t dwDestContext, void* pvDestContext, std::uint32_t mshlflags, std::uint32_t* pSize) noexcept = 0; + virtual std::int32_t __stdcall MarshalInterface(void* pStm, guid const& riid, void* pv, std::uint32_t dwDestContext, void* pvDestContext, std::uint32_t mshlflags) noexcept = 0; + virtual std::int32_t __stdcall UnmarshalInterface(void* pStm, guid const& riid, void** ppv) noexcept = 0; + virtual std::int32_t __stdcall ReleaseMarshalData(void* pStm) noexcept = 0; + virtual std::int32_t __stdcall DisconnectObject(std::uint32_t dwReserved) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IGlobalInterfaceTable : unknown_abi { - virtual int32_t __stdcall RegisterInterfaceInGlobal(void* object, guid const& iid, uint32_t* cookie) noexcept = 0; - virtual int32_t __stdcall RevokeInterfaceFromGlobal(uint32_t cookie) noexcept = 0; - virtual int32_t __stdcall GetInterfaceFromGlobal(uint32_t cookie, guid const& iid, void** object) noexcept = 0; + virtual std::int32_t __stdcall RegisterInterfaceInGlobal(void* object, guid const& iid, std::uint32_t* cookie) noexcept = 0; + virtual std::int32_t __stdcall RevokeInterfaceFromGlobal(std::uint32_t cookie) noexcept = 0; + virtual std::int32_t __stdcall GetInterfaceFromGlobal(std::uint32_t cookie, guid const& iid, void** object) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IStaticLifetime : inspectable_abi { - virtual int32_t __stdcall unused() noexcept = 0; - virtual int32_t __stdcall GetCollection(void** value) noexcept = 0; + virtual std::int32_t __stdcall unused() noexcept = 0; + virtual std::int32_t __stdcall GetCollection(void** value) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IStaticLifetimeCollection : inspectable_abi { - virtual int32_t __stdcall Lookup(void*, void**) noexcept = 0; - virtual int32_t __stdcall unused() noexcept = 0; - virtual int32_t __stdcall unused2() noexcept = 0; - virtual int32_t __stdcall unused3() noexcept = 0; - virtual int32_t __stdcall Insert(void*, void*, bool*) noexcept = 0; - virtual int32_t __stdcall Remove(void*) noexcept = 0; - virtual int32_t __stdcall unused4() noexcept = 0; + virtual std::int32_t __stdcall Lookup(void*, void**) noexcept = 0; + virtual std::int32_t __stdcall unused() noexcept = 0; + virtual std::int32_t __stdcall unused2() noexcept = 0; + virtual std::int32_t __stdcall unused3() noexcept = 0; + virtual std::int32_t __stdcall Insert(void*, void*, bool*) noexcept = 0; + virtual std::int32_t __stdcall Remove(void*) noexcept = 0; + virtual std::int32_t __stdcall unused4() noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IWeakReference : unknown_abi { - virtual int32_t __stdcall Resolve(guid const& iid, void** objectReference) noexcept = 0; + virtual std::int32_t __stdcall Resolve(guid const& iid, void** objectReference) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IWeakReferenceSource : unknown_abi { - virtual int32_t __stdcall GetWeakReference(IWeakReference** weakReference) noexcept = 0; + virtual std::int32_t __stdcall GetWeakReference(IWeakReference** weakReference) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IRestrictedErrorInfo : unknown_abi { - virtual int32_t __stdcall GetErrorDetails(bstr* description, int32_t* error, bstr* restrictedDescription, bstr* capabilitySid) noexcept = 0; - virtual int32_t __stdcall GetReference(bstr* reference) noexcept = 0; + virtual std::int32_t __stdcall GetErrorDetails(bstr* description, std::int32_t* error, bstr* restrictedDescription, bstr* capabilitySid) noexcept = 0; + virtual std::int32_t __stdcall GetReference(bstr* reference) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IErrorInfo : unknown_abi { - virtual int32_t __stdcall GetGUID(guid* value) noexcept = 0; - virtual int32_t __stdcall GetSource(bstr* value) noexcept = 0; - virtual int32_t __stdcall GetDescription(bstr* value) noexcept = 0; - virtual int32_t __stdcall GetHelpFile(bstr* value) noexcept = 0; - virtual int32_t __stdcall GetHelpContext(uint32_t* value) noexcept = 0; + virtual std::int32_t __stdcall GetGUID(guid* value) noexcept = 0; + virtual std::int32_t __stdcall GetSource(bstr* value) noexcept = 0; + virtual std::int32_t __stdcall GetDescription(bstr* value) noexcept = 0; + virtual std::int32_t __stdcall GetHelpFile(bstr* value) noexcept = 0; + virtual std::int32_t __stdcall GetHelpContext(std::uint32_t* value) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL ILanguageExceptionErrorInfo2 : unknown_abi { - virtual int32_t __stdcall GetLanguageException(void** exception) noexcept = 0; - virtual int32_t __stdcall GetPreviousLanguageExceptionErrorInfo(ILanguageExceptionErrorInfo2** previous) noexcept = 0; - virtual int32_t __stdcall CapturePropagationContext(void* exception) noexcept = 0; - virtual int32_t __stdcall GetPropagationContextHead(ILanguageExceptionErrorInfo2** head) noexcept = 0; + virtual std::int32_t __stdcall GetLanguageException(void** exception) noexcept = 0; + virtual std::int32_t __stdcall GetPreviousLanguageExceptionErrorInfo(ILanguageExceptionErrorInfo2** previous) noexcept = 0; + virtual std::int32_t __stdcall CapturePropagationContext(void* exception) noexcept = 0; + virtual std::int32_t __stdcall GetPropagationContextHead(ILanguageExceptionErrorInfo2** head) noexcept = 0; }; struct ICallbackWithNoReentrancyToApplicationSTA; struct WINRT_IMPL_ABI_DECL IContextCallback : unknown_abi { - virtual int32_t __stdcall ContextCallback(int32_t(__stdcall* callback)(com_callback_args*), com_callback_args* args, guid const& iid, int method, void* reserved) noexcept = 0; + virtual std::int32_t __stdcall ContextCallback(std::int32_t(__stdcall* callback)(com_callback_args*), com_callback_args* args, guid const& iid, int method, void* reserved) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IServerSecurity : unknown_abi { - virtual int32_t __stdcall QueryBlanket(uint32_t*, uint32_t*, wchar_t**, uint32_t*, uint32_t*, void**, uint32_t*) noexcept = 0; - virtual int32_t __stdcall ImpersonateClient() noexcept = 0; - virtual int32_t __stdcall RevertToSelf() noexcept = 0; - virtual int32_t __stdcall IsImpersonating() noexcept = 0; + virtual std::int32_t __stdcall QueryBlanket(std::uint32_t*, std::uint32_t*, wchar_t**, std::uint32_t*, std::uint32_t*, void**, std::uint32_t*) noexcept = 0; + virtual std::int32_t __stdcall ImpersonateClient() noexcept = 0; + virtual std::int32_t __stdcall RevertToSelf() noexcept = 0; + virtual std::int32_t __stdcall IsImpersonating() noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IBufferByteAccess : unknown_abi { - virtual int32_t __stdcall Buffer(uint8_t** value) noexcept = 0; + virtual std::int32_t __stdcall Buffer(std::uint8_t** value) noexcept = 0; }; struct WINRT_IMPL_ABI_DECL IMemoryBufferByteAccess : unknown_abi { - virtual int32_t __stdcall GetBuffer(uint8_t** value, uint32_t* capacity) noexcept = 0; + virtual std::int32_t __stdcall GetBuffer(std::uint8_t** value, std::uint32_t* capacity) noexcept = 0; }; template <> struct abi { - using type = int64_t; + using type = std::int64_t; }; template <> struct abi { - using type = int64_t; + using type = std::int64_t; }; template <> inline constexpr guid guid_v{ 0x00000000, 0x0000, 0x0000, { 0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 } }; diff --git a/strings/base_activation.h b/strings/base_activation.h index 586df32e9..1a195d865 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -30,7 +30,7 @@ namespace winrt::impl if (hr == impl::error_not_initialized) { - auto usage = reinterpret_cast(WINRT_IMPL_GetProcAddress(load_library(L"combase.dll"), "CoIncrementMTAUsage")); + auto usage = reinterpret_cast(WINRT_IMPL_GetProcAddress(load_library(L"combase.dll"), "CoIncrementMTAUsage")); if (!usage) { @@ -65,7 +65,7 @@ namespace winrt::impl continue; } - auto library_call = reinterpret_cast(WINRT_IMPL_GetProcAddress(library.get(), "DllGetActivationFactory")); + auto library_call = reinterpret_cast(WINRT_IMPL_GetProcAddress(library.get(), "DllGetActivationFactory")); if (!library_call) { @@ -127,17 +127,17 @@ WINRT_EXPORT namespace winrt namespace winrt::impl { - inline int32_t interlocked_read_32(int32_t const volatile* target) noexcept + inline std::int32_t interlocked_read_32(std::int32_t const volatile* target) noexcept { #if defined _M_IX86 || defined _M_X64 - int32_t const result = *target; + std::int32_t const result = *target; _ReadWriteBarrier(); return result; #elif defined _M_ARM64 #if defined(__GNUC__) - int32_t const result = *target; + std::int32_t const result = *target; #else - int32_t const result = __iso_volatile_load32(reinterpret_cast(target)); + std::int32_t const result = __iso_volatile_load32(reinterpret_cast(target)); #endif WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER return result; @@ -147,17 +147,17 @@ namespace winrt::impl } #if defined _WIN64 - inline int64_t interlocked_read_64(int64_t const volatile* target) noexcept + inline std::int64_t interlocked_read_64(std::int64_t const volatile* target) noexcept { #if defined _M_X64 - int64_t const result = *target; + std::int64_t const result = *target; _ReadWriteBarrier(); return result; #elif defined _M_ARM64 #if defined(__GNUC__) - int64_t const result = *target; + std::int64_t const result = *target; #else - int64_t const result = __iso_volatile_load64(target); + std::int64_t const result = __iso_volatile_load64(target); #endif WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER return result; @@ -177,14 +177,14 @@ namespace winrt::impl T* interlocked_read_pointer(T* const volatile* target) noexcept { #ifdef _WIN64 - return (T*)interlocked_read_64((int64_t*)target); + return (T*)interlocked_read_64((std::int64_t*)target); #else - return (T*)interlocked_read_32((int32_t*)target); + return (T*)interlocked_read_32((std::int32_t*)target); #endif } #ifdef _WIN64 - inline constexpr uint32_t memory_allocation_alignment{ 16 }; + inline constexpr std::uint32_t memory_allocation_alignment{ 16 }; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4324) // structure was padded due to alignment specifier @@ -197,34 +197,34 @@ namespace winrt::impl { struct { - uint64_t reserved1; - uint64_t reserved2; + std::uint64_t reserved1; + std::uint64_t reserved2; } reserved1; struct { - uint64_t reserved1 : 16; - uint64_t reserved2 : 48; - uint64_t reserved3 : 4; - uint64_t reserved4 : 60; + std::uint64_t reserved1 : 16; + std::uint64_t reserved2 : 48; + std::uint64_t reserved3 : 4; + std::uint64_t reserved4 : 60; } reserved2; }; #ifdef _MSC_VER #pragma warning(pop) #endif #else - inline constexpr uint32_t memory_allocation_alignment{ 8 }; + inline constexpr std::uint32_t memory_allocation_alignment{ 8 }; struct slist_entry { slist_entry* next; }; union slist_header { - uint64_t reserved1; + std::uint64_t reserved1; struct { slist_entry reserved1; - uint16_t reserved2; - uint16_t reserved3; + std::uint16_t reserved2; + std::uint16_t reserved3; } reserved2; }; #endif @@ -234,11 +234,11 @@ namespace winrt::impl factory_count_guard(factory_count_guard const&) = delete; factory_count_guard& operator=(factory_count_guard const&) = delete; - explicit factory_count_guard(size_t& count) noexcept : m_count(count) + explicit factory_count_guard(std::size_t& count) noexcept : m_count(count) { #ifndef WINRT_NO_MODULE_LOCK #ifdef _WIN64 - _InterlockedIncrement64((int64_t*)&m_count); + _InterlockedIncrement64((std::int64_t*)&m_count); #else _InterlockedIncrement((long*)&m_count); #endif @@ -249,7 +249,7 @@ namespace winrt::impl { #ifndef WINRT_NO_MODULE_LOCK #ifdef _WIN64 - _InterlockedDecrement64((int64_t*)&m_count); + _InterlockedDecrement64((std::int64_t*)&m_count); #else _InterlockedDecrement((long*)&m_count); #endif @@ -257,7 +257,7 @@ namespace winrt::impl } private: - [[maybe_unused]] size_t& m_count; // Field is unused when WINRT_NO_MODULE_LOCK is defined. + [[maybe_unused]] std::size_t& m_count; // Field is unused when WINRT_NO_MODULE_LOCK is defined. }; struct factory_cache_entry_base @@ -265,7 +265,7 @@ namespace winrt::impl struct alignas(sizeof(void*) * 2) object_and_count { unknown_abi* object; - size_t count; + std::size_t count; }; object_and_count m_value; @@ -286,16 +286,16 @@ namespace winrt::impl #if defined(__GNUC__) bool exchanged = __sync_bool_compare_and_swap((__int128*)this, *(__int128*)¤t_value, (__int128)0); #else - bool exchanged = 1 == _InterlockedCompareExchange128((int64_t*)this, 0, 0, (int64_t*)¤t_value); + bool exchanged = 1 == _InterlockedCompareExchange128((std::int64_t*)this, 0, 0, (std::int64_t*)¤t_value); #endif if (exchanged) { pointer_value->Release(); } #else - int64_t const result = _InterlockedCompareExchange64((int64_t*)this, 0, *(int64_t*)¤t_value); + std::int64_t const result = _InterlockedCompareExchange64((std::int64_t*)this, 0, *(std::int64_t*)¤t_value); - if (result == *(int64_t*)¤t_value) + if (result == *(std::int64_t*)¤t_value) { pointer_value->Release(); } @@ -330,7 +330,7 @@ namespace winrt::impl // entry->next must be read before entry->clear() is called since the InterlockedCompareExchange // inside clear() will allow another thread to add the entry back to the cache. slist_entry* next = entry->next; - reinterpret_cast(reinterpret_cast(entry) - offsetof(factory_cache_entry_base, m_next))->clear(); + reinterpret_cast(reinterpret_cast(entry) - offsetof(factory_cache_entry_base, m_next))->clear(); entry = next; } } @@ -443,7 +443,7 @@ namespace winrt::impl template struct produce : produce_base { - int32_t __stdcall ActivateInstance(void** instance) noexcept final try + std::int32_t __stdcall ActivateInstance(void** instance) noexcept final try { *instance = nullptr; typename D::abi_guard guard(this->shim()); @@ -456,7 +456,7 @@ namespace winrt::impl WINRT_EXPORT namespace winrt { - enum class apartment_type : int32_t + enum class apartment_type : std::int32_t { multi_threaded = 0, single_threaded = 2, @@ -464,7 +464,7 @@ WINRT_EXPORT namespace winrt inline void init_apartment(apartment_type const type = apartment_type::multi_threaded) { - hresult const result = WINRT_IMPL_CoInitializeEx(nullptr, static_cast(type)); + hresult const result = WINRT_IMPL_CoInitializeEx(nullptr, static_cast(type)); if (result < 0) { @@ -519,13 +519,13 @@ WINRT_EXPORT namespace winrt } template - auto try_create_instance(guid const& clsid, uint32_t context = 0x1 /*CLSCTX_INPROC_SERVER*/, void* outer = nullptr) + auto try_create_instance(guid const& clsid, std::uint32_t context = 0x1 /*CLSCTX_INPROC_SERVER*/, void* outer = nullptr) { return try_capture(WINRT_IMPL_CoCreateInstance, clsid, outer, context); } template - auto create_instance(guid const& clsid, uint32_t context = 0x1 /*CLSCTX_INPROC_SERVER*/, void* outer = nullptr) + auto create_instance(guid const& clsid, std::uint32_t context = 0x1 /*CLSCTX_INPROC_SERVER*/, void* outer = nullptr) { return capture(WINRT_IMPL_CoCreateInstance, clsid, outer, context); } diff --git a/strings/base_agile_ref.h b/strings/base_agile_ref.h index b85cb7e61..88fbea065 100644 --- a/strings/base_agile_ref.h +++ b/strings/base_agile_ref.h @@ -10,12 +10,12 @@ WINRT_EXPORT namespace winrt { struct lock { - constexpr uint32_t operator++() noexcept + constexpr std::uint32_t operator++() noexcept { return 1; } - constexpr uint32_t operator--() noexcept + constexpr std::uint32_t operator--() noexcept { return 0; } diff --git a/strings/base_array.h b/strings/base_array.h index a4f570614..9544dcf8c 100644 --- a/strings/base_array.h +++ b/strings/base_array.h @@ -5,7 +5,7 @@ WINRT_EXPORT namespace winrt struct array_view { using value_type = T; - using size_type = uint32_t; + using size_type = std::uint32_t; using reference = value_type&; using const_reference = value_type const&; using pointer = value_type*; @@ -32,11 +32,11 @@ WINRT_EXPORT namespace winrt {} #ifdef __cpp_lib_span - template + template array_view(std::span span) noexcept : array_view(span.data(), static_cast(span.size())) { - WINRT_ASSERT(span.size() <= UINT_MAX); + WINRT_ASSERT(span.size() <= (std::numeric_limits::max)()); } operator std::span() const noexcept @@ -62,12 +62,12 @@ WINRT_EXPORT namespace winrt { } - template + template array_view(std::array& value) noexcept : array_view(value.data(), static_cast(value.size())) {} - template + template array_view(std::array const& value) noexcept : array_view(value.data(), static_cast(value.size())) {} @@ -231,15 +231,15 @@ WINRT_EXPORT namespace winrt } }; - template array_view(C(&value)[N]) -> array_view; + template array_view(C(&value)[N]) -> array_view; template array_view(std::vector& value) -> array_view; template array_view(std::vector const& value) -> array_view; - template array_view(std::array& value) -> array_view; - template array_view(std::array const& value) -> array_view; + template array_view(std::array& value) -> array_view; + template array_view(std::array const& value) -> array_view; #ifdef __cpp_lib_span - template array_view(std::span& value) -> array_view; - template array_view(std::span const& value) -> array_view; + template array_view(std::span& value) -> array_view; + template array_view(std::span const& value) -> array_view; #endif template @@ -265,7 +265,7 @@ WINRT_EXPORT namespace winrt com_array(count, value_type()) {} - com_array(void* ptr, uint32_t const count, take_ownership_from_abi_t) noexcept : + com_array(void* ptr, std::uint32_t const count, take_ownership_from_abi_t) noexcept : array_view(static_cast(ptr), static_cast(ptr) + count) { } @@ -288,21 +288,21 @@ WINRT_EXPORT namespace winrt com_array(value.begin(), value.end()) {} - template + template explicit com_array(std::array const& value) : com_array(value.begin(), value.end()) {} #ifdef __cpp_lib_span - template + template explicit com_array(std::span span) noexcept : com_array(span.data(), span.data() + span.size()) { - WINRT_ASSERT(span.size() <= UINT_MAX); + WINRT_ASSERT(span.size() <= (std::numeric_limits::max)()); } #endif - template + template explicit com_array(U const(&value)[N]) : com_array(value, value + N) {} @@ -374,17 +374,17 @@ WINRT_EXPORT namespace winrt } } - std::pair> detach_abi() noexcept + std::pair> detach_abi() noexcept { #ifdef _MSC_VER // https://github.com/microsoft/cppwinrt/pull/1165 - std::pair> result; - memset(&result, 0, sizeof(result)); + std::pair> result; + std::memset(&result, 0, sizeof(result)); result.first = this->size(); result.second = *reinterpret_cast*>(this); - memset(this, 0, sizeof(com_array)); + std::memset(this, 0, sizeof(com_array)); #else - std::pair> result(this->size(), *reinterpret_cast*>(this)); + std::pair> result(this->size(), *reinterpret_cast*>(this)); this->m_data = nullptr; this->m_size = 0; #endif @@ -392,19 +392,19 @@ WINRT_EXPORT namespace winrt } template - friend std::pair> detach_abi(com_array& object) noexcept; + friend std::pair> detach_abi(com_array& object) noexcept; }; - template com_array(uint32_t, C const&) -> com_array>; + template com_array(std::uint32_t, C const&) -> com_array>; template ::difference_type>> com_array(InIt, InIt) -> com_array::value_type>>; template com_array(std::vector const&) -> com_array>; - template com_array(std::array const&) -> com_array>; - template com_array(C const(&)[N]) -> com_array>; + template com_array(std::array const&) -> com_array>; + template com_array(C const(&)[N]) -> com_array>; template com_array(std::initializer_list) -> com_array>; #ifdef __cpp_lib_span - template com_array(std::span const& value) -> com_array>; + template com_array(std::span const& value) -> com_array>; #endif @@ -471,7 +471,7 @@ WINRT_EXPORT namespace winrt } template - std::pair> detach_abi(com_array& object) noexcept + std::pair> detach_abi(com_array& object) noexcept { return object.detach_abi(); } @@ -496,10 +496,10 @@ namespace winrt::impl ~array_size_proxy() noexcept { WINRT_ASSERT(m_value.data() || (!m_value.data() && m_size == 0)); - *reinterpret_cast(reinterpret_cast(&m_value) + 1) = m_size; + *reinterpret_cast(reinterpret_cast(&m_value) + 1) = m_size; } - operator uint32_t*() noexcept + operator std::uint32_t*() noexcept { return &m_size; } @@ -512,7 +512,7 @@ namespace winrt::impl private: com_array& m_value; - uint32_t m_size{ 0 }; + std::uint32_t m_size{ 0 }; }; template @@ -524,7 +524,7 @@ namespace winrt::impl template struct com_array_proxy { - com_array_proxy(uint32_t* size, winrt::impl::arg_out* value) noexcept : m_size(size), m_value(value) + com_array_proxy(std::uint32_t* size, winrt::impl::arg_out* value) noexcept : m_size(size), m_value(value) {} ~com_array_proxy() noexcept @@ -545,7 +545,7 @@ namespace winrt::impl private: - uint32_t* m_size; + std::uint32_t* m_size; arg_out* m_value; com_array m_temp; }; @@ -554,7 +554,7 @@ namespace winrt::impl WINRT_EXPORT namespace winrt { template - auto detach_abi(uint32_t* __valueSize, impl::arg_out* value) noexcept + auto detach_abi(std::uint32_t* __valueSize, impl::arg_out* value) noexcept { return impl::com_array_proxy(__valueSize, value); } diff --git a/strings/base_chrono.h b/strings/base_chrono.h index d48cd703b..7934ac5b2 100644 --- a/strings/base_chrono.h +++ b/strings/base_chrono.h @@ -3,17 +3,17 @@ WINRT_EXPORT namespace winrt { struct file_time { - uint64_t value{}; + std::uint64_t value{}; file_time() noexcept = default; - constexpr explicit file_time(uint64_t const value) noexcept : value(value) + constexpr explicit file_time(std::uint64_t const value) noexcept : value(value) { } #ifdef _FILETIME_ constexpr file_time(FILETIME const& value) noexcept - : value(value.dwLowDateTime | (static_cast(value.dwHighDateTime) << 32)) + : value(value.dwLowDateTime | (static_cast(value.dwHighDateTime) << 32)) { } @@ -26,7 +26,7 @@ WINRT_EXPORT namespace winrt struct clock { - using rep = int64_t; + using rep = std::int64_t; using period = impl::filetime_period; using duration = Windows::Foundation::TimeSpan; using time_point = Windows::Foundation::DateTime; @@ -52,7 +52,7 @@ WINRT_EXPORT namespace winrt static file_time to_file_time(time_point const& time) noexcept { - return file_time{ static_cast(time.time_since_epoch().count()) }; + return file_time{ static_cast(time.time_since_epoch().count()) }; } static time_point from_file_time(file_time const& time) noexcept diff --git a/strings/base_collections.h b/strings/base_collections.h index cba0864b3..4e1af51eb 100644 --- a/strings/base_collections.h +++ b/strings/base_collections.h @@ -101,10 +101,10 @@ namespace winrt::impl private: - uint32_t const m_snapshot; + std::uint32_t const m_snapshot; }; - uint32_t get_version() const noexcept + std::uint32_t get_version() const noexcept { return m_version; } @@ -116,7 +116,7 @@ namespace winrt::impl private: - std::atomic m_version{}; + std::atomic m_version{}; }; template diff --git a/strings/base_collections_base.h b/strings/base_collections_base.h index fec3de660..6fe10fa64 100644 --- a/strings/base_collections_base.h +++ b/strings/base_collections_base.h @@ -191,7 +191,7 @@ WINRT_EXPORT namespace winrt return m_current != m_end; } - uint32_t GetMany(array_view values) + std::uint32_t GetMany(array_view values) { [[maybe_unused]] auto guard = m_owner->acquire_exclusive(); this->check_version(*m_owner); @@ -213,15 +213,15 @@ WINRT_EXPORT namespace winrt } } - uint32_t GetMany(array_view values, std::random_access_iterator_tag) + std::uint32_t GetMany(array_view values, std::random_access_iterator_tag) { - uint32_t const actual = (std::min)(static_cast(m_end - m_current), values.size()); + std::uint32_t const actual = (std::min)(static_cast(m_end - m_current), values.size()); m_owner->copy_n(m_current, actual, values.begin()); m_current += actual; return actual; } - uint32_t GetMany(array_view values, std::input_iterator_tag) + std::uint32_t GetMany(array_view values, std::input_iterator_tag) { auto output = values.begin(); @@ -232,7 +232,7 @@ WINRT_EXPORT namespace winrt ++m_current; } - return static_cast(output - values.begin()); + return static_cast(output - values.begin()); } using iterator_type = decltype(std::declval().get_container().begin()); @@ -246,7 +246,7 @@ WINRT_EXPORT namespace winrt template struct vector_view_base : iterable_base { - T GetAt(uint32_t const index) const + T GetAt(std::uint32_t const index) const { [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); if (index >= container_size()) @@ -257,13 +257,13 @@ WINRT_EXPORT namespace winrt return static_cast(*this).unwrap_value(*std::next(static_cast(*this).get_container().begin(), index)); } - uint32_t Size() const noexcept + std::uint32_t Size() const noexcept { [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); return container_size(); } - bool IndexOf(T const& value, uint32_t& index) const noexcept + bool IndexOf(T const& value, std::uint32_t& index) const noexcept { [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); auto first = std::find_if(static_cast(*this).get_container().begin(), static_cast(*this).get_container().end(), [&](auto&& match) @@ -271,11 +271,11 @@ WINRT_EXPORT namespace winrt return value == static_cast(*this).unwrap_value(match); }); - index = static_cast(first - static_cast(*this).get_container().begin()); + index = static_cast(first - static_cast(*this).get_container().begin()); return index < container_size(); } - uint32_t GetMany(uint32_t const startIndex, array_view values) const + std::uint32_t GetMany(std::uint32_t const startIndex, array_view values) const { [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); if (startIndex >= container_size()) @@ -283,16 +283,16 @@ WINRT_EXPORT namespace winrt return 0; } - uint32_t const actual = (std::min)(container_size() - startIndex, values.size()); + std::uint32_t const actual = (std::min)(container_size() - startIndex, values.size()); this->copy_n(static_cast(*this).get_container().begin() + startIndex, actual, values.begin()); return actual; } private: - uint32_t container_size() const noexcept + std::uint32_t container_size() const noexcept { - return static_cast(std::distance(static_cast(*this).get_container().begin(), static_cast(*this).get_container().end())); + return static_cast(std::distance(static_cast(*this).get_container().begin(), static_cast(*this).get_container().end())); } }; @@ -304,7 +304,7 @@ WINRT_EXPORT namespace winrt return static_cast(*this); } - void SetAt(uint32_t const index, T const& value) + void SetAt(std::uint32_t const index, T const& value) { impl::removed_value::value_type> oldValue; @@ -320,7 +320,7 @@ WINRT_EXPORT namespace winrt pos = static_cast(*this).wrap_value(value); } - void InsertAt(uint32_t const index, T const& value) + void InsertAt(std::uint32_t const index, T const& value) { [[maybe_unused]] auto guard = static_cast(*this).acquire_exclusive(); if (index > static_cast(*this).get_container().size()) @@ -332,7 +332,7 @@ WINRT_EXPORT namespace winrt static_cast(*this).get_container().insert(static_cast(*this).get_container().begin() + index, static_cast(*this).wrap_value(value)); } - void RemoveAt(uint32_t const index) + void RemoveAt(std::uint32_t const index) { impl::removed_value::value_type> removedValue; @@ -425,19 +425,19 @@ WINRT_EXPORT namespace winrt m_changed.remove(cookie); } - void SetAt(uint32_t const index, T const& value) + void SetAt(std::uint32_t const index, T const& value) { vector_base::SetAt(index, value); call_changed(Windows::Foundation::Collections::CollectionChange::ItemChanged, index); } - void InsertAt(uint32_t const index, T const& value) + void InsertAt(std::uint32_t const index, T const& value) { vector_base::InsertAt(index, value); call_changed(Windows::Foundation::Collections::CollectionChange::ItemInserted, index); } - void RemoveAt(uint32_t const index) + void RemoveAt(std::uint32_t const index) { vector_base::RemoveAt(index); call_changed(Windows::Foundation::Collections::CollectionChange::ItemRemoved, index); @@ -469,7 +469,7 @@ WINRT_EXPORT namespace winrt protected: - void call_changed(Windows::Foundation::Collections::CollectionChange const change, uint32_t const index) + void call_changed(Windows::Foundation::Collections::CollectionChange const change, std::uint32_t const index) { m_changed(static_cast(*this), make(change, index)); } @@ -480,7 +480,7 @@ WINRT_EXPORT namespace winrt struct args : implements { - args(Windows::Foundation::Collections::CollectionChange const change, uint32_t const index) noexcept : + args(Windows::Foundation::Collections::CollectionChange const change, std::uint32_t const index) noexcept : m_change(change), m_index(index) { @@ -491,7 +491,7 @@ WINRT_EXPORT namespace winrt return m_change; } - uint32_t Index() const noexcept + std::uint32_t Index() const noexcept { return m_index; } @@ -499,7 +499,7 @@ WINRT_EXPORT namespace winrt private: Windows::Foundation::Collections::CollectionChange const m_change; - uint32_t const m_index; + std::uint32_t const m_index; }; }; @@ -533,10 +533,10 @@ WINRT_EXPORT namespace winrt return static_cast(*this).unwrap_value(pair->second); } - uint32_t Size() const noexcept + std::uint32_t Size() const noexcept { [[maybe_unused]] auto guard = static_cast(*this).acquire_shared(); - return static_cast(static_cast(*this).get_container().size()); + return static_cast(static_cast(*this).get_container().size()); } bool HasKey(K const& key) const noexcept diff --git a/strings/base_collections_map.h b/strings/base_collections_map.h index f4bd74baf..fa769fb88 100644 --- a/strings/base_collections_map.h +++ b/strings/base_collections_map.h @@ -120,11 +120,11 @@ namespace std { template struct tuple_size> - : integral_constant + : integral_constant { }; - template + template struct tuple_element> { static_assert(Idx < 2, "key-value pair index out of bounds"); @@ -134,7 +134,7 @@ namespace std namespace winrt::Windows::Foundation::Collections { - template + template std::tuple_element_t> get(IKeyValuePair const& kvp) { static_assert(Idx < 2, "key-value pair index out of bounds"); diff --git a/strings/base_collections_vector.h b/strings/base_collections_vector.h index cef7ef2d3..3e9c1b254 100644 --- a/strings/base_collections_vector.h +++ b/strings/base_collections_vector.h @@ -90,12 +90,12 @@ namespace winrt::impl return result{ this }; } - auto GetAt(uint32_t const index) const + auto GetAt(std::uint32_t const index) const { struct result { base_type const* container; - uint32_t const index; + std::uint32_t const index; operator T() const { @@ -113,7 +113,7 @@ namespace winrt::impl using base_type::IndexOf; - bool IndexOf(Windows::Foundation::IInspectable const& value, uint32_t& index) const + bool IndexOf(Windows::Foundation::IInspectable const& value, std::uint32_t& index) const { if constexpr (is_com_interface_v) { @@ -139,7 +139,7 @@ namespace winrt::impl using base_type::GetMany; - uint32_t GetMany(uint32_t const startIndex, array_view values) const + std::uint32_t GetMany(std::uint32_t const startIndex, array_view values) const { [[maybe_unused]] auto guard = this->acquire_shared(); if (startIndex >= m_values.size()) @@ -147,7 +147,7 @@ namespace winrt::impl return 0; } - uint32_t const actual = (std::min)(static_cast(m_values.size() - startIndex), values.size()); + std::uint32_t const actual = (std::min)(static_cast(m_values.size() - startIndex), values.size()); std::transform(m_values.begin() + startIndex, m_values.begin() + startIndex + actual, values.begin(), [&](auto && value) { @@ -179,14 +179,14 @@ namespace winrt::impl using base_type::SetAt; - void SetAt(uint32_t const index, Windows::Foundation::IInspectable const& value) + void SetAt(std::uint32_t const index, Windows::Foundation::IInspectable const& value) { SetAt(index, unbox_value(value)); } using base_type::InsertAt; - void InsertAt(uint32_t const index, Windows::Foundation::IInspectable const& value) + void InsertAt(std::uint32_t const index, Windows::Foundation::IInspectable const& value) { InsertAt(index, unbox_value(value)); } @@ -268,11 +268,11 @@ namespace winrt::impl return m_current != m_end; } - uint32_t GetMany(array_view values) + std::uint32_t GetMany(array_view values) { [[maybe_unused]] auto guard = m_owner->acquire_exclusive(); check_version(*m_owner); - uint32_t const actual = (std::min)(static_cast(std::distance(m_current, m_end)), values.size()); + std::uint32_t const actual = (std::min)(static_cast(std::distance(m_current, m_end)), values.size()); std::transform(m_current, m_current + actual, values.begin(), [&](auto && value) { diff --git a/strings/base_com_ptr.h b/strings/base_com_ptr.h index 14a9a0851..27496789a 100644 --- a/strings/base_com_ptr.h +++ b/strings/base_com_ptr.h @@ -19,19 +19,19 @@ namespace winrt::impl }; template - int32_t capture_to(void**result, F function, Args&& ...args) + std::int32_t capture_to(void**result, F function, Args&& ...args) { return function(args..., guid_of(), capture_decay{ result }); } template || std::is_union_v, int> = 0> - int32_t capture_to(void** result, O* object, M method, Args&& ...args) + std::int32_t capture_to(void** result, O* object, M method, Args&& ...args) { return (object->*method)(args..., guid_of(), capture_decay{ result }); } template - int32_t capture_to(void** result, com_ptr const& object, M method, Args&& ...args); + std::int32_t capture_to(void** result, com_ptr const& object, M method, Args&& ...args); } WINRT_EXPORT namespace winrt @@ -352,7 +352,7 @@ WINRT_EXPORT namespace winrt namespace winrt::impl { template - int32_t capture_to(void** result, com_ptr const& object, M method, Args&& ...args) + std::int32_t capture_to(void** result, com_ptr const& object, M method, Args&& ...args) { return (object.get()->*(method))(args..., guid_of(), capture_decay{ result }); } diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index a5816a85b..4f1c8d0b6 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -47,7 +47,7 @@ namespace winrt::impl } template - auto wait_for_completed(Async const& async, uint32_t const timeout) + auto wait_for_completed(Async const& async, std::uint32_t const timeout) { struct shared_type { @@ -72,8 +72,8 @@ namespace winrt::impl { check_sta_blocking_wait(); auto const milliseconds = std::chrono::duration_cast(timeout).count(); - WINRT_ASSERT((milliseconds >= 0) && (static_cast(milliseconds) < 0xFFFFFFFFull)); // Within uint32_t range and not INFINITE - return wait_for_completed(async, static_cast(milliseconds)); + WINRT_ASSERT((milliseconds >= 0) && (static_cast(milliseconds) < 0xFFFFFFFFull)); // Within std::uint32_t range and not INFINITE + return wait_for_completed(async, static_cast(milliseconds)); } inline void check_status_canceled(Windows::Foundation::AsyncStatus status) @@ -158,7 +158,7 @@ namespace winrt::impl std::conditional_t async; Windows::Foundation::AsyncStatus status = Windows::Foundation::AsyncStatus::Started; - int32_t failure = 0; + std::int32_t failure = 0; std::atomic suspending = true; void enable_cancellation(cancellable_promise* promise) @@ -405,7 +405,7 @@ namespace winrt::impl unsigned long __stdcall Release() noexcept { - uint32_t const remaining = this->subtract_reference(); + std::uint32_t const remaining = this->subtract_reference(); if (remaining == 0) { @@ -450,7 +450,7 @@ namespace winrt::impl return m_completed; } - uint32_t Id() const noexcept + std::uint32_t Id() const noexcept { return 1; } @@ -597,7 +597,7 @@ namespace winrt::impl bool await_suspend(std::coroutine_handle<>) const noexcept { promise->set_completed(); - uint32_t const remaining = promise->subtract_reference(); + std::uint32_t const remaining = promise->subtract_reference(); if (remaining == 0) { diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index e59fcadb2..6748906ca 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -21,10 +21,10 @@ namespace winrt::impl } #endif - inline std::pair get_apartment_type() noexcept + inline std::pair get_apartment_type() noexcept { - int32_t aptType; - int32_t aptTypeQualifier; + std::int32_t aptType; + std::int32_t aptTypeQualifier; if (0 == WINRT_IMPL_CoGetApartmentType(&aptType, &aptTypeQualifier)) { return { aptType, aptTypeQualifier }; @@ -62,16 +62,16 @@ namespace winrt::impl } com_ptr m_context = try_capture(WINRT_IMPL_CoGetObjectContext); - movable_primitive m_context_type = get_apartment_type().first; + movable_primitive m_context_type = get_apartment_type().first; }; - inline int32_t __stdcall resume_apartment_callback(com_callback_args* args) noexcept + inline std::int32_t __stdcall resume_apartment_callback(com_callback_args* args) noexcept { std::coroutine_handle<>::from_address(args->data)(); return 0; }; - [[nodiscard]] inline bool resume_apartment_sync(com_ptr const& context, std::coroutine_handle<> handle, int32_t* failure) + [[nodiscard]] inline bool resume_apartment_sync(com_ptr const& context, std::coroutine_handle<> handle, std::int32_t* failure) { com_callback_args args{}; args.data = handle.address(); @@ -88,11 +88,11 @@ namespace winrt::impl struct threadpool_resume { - threadpool_resume(com_ptr const& context, std::coroutine_handle<> handle, int32_t* failure) : + threadpool_resume(com_ptr const& context, std::coroutine_handle<> handle, std::int32_t* failure) : m_context(context), m_handle(handle), m_failure(failure) { } com_ptr m_context; std::coroutine_handle<> m_handle; - int32_t* m_failure; + std::int32_t* m_failure; }; inline void __stdcall fallback_submit_threadpool_callback(void*, void* p) noexcept @@ -104,14 +104,14 @@ namespace winrt::impl } } - inline void resume_apartment_on_threadpool(com_ptr const& context, std::coroutine_handle<> handle, int32_t* failure) + inline void resume_apartment_on_threadpool(com_ptr const& context, std::coroutine_handle<> handle, std::int32_t* failure) { auto state = std::make_unique(context, handle, failure); submit_threadpool_callback(fallback_submit_threadpool_callback, state.get()); state.release(); } - [[nodiscard]] inline auto resume_apartment(resume_apartment_context const& context, std::coroutine_handle<> handle, int32_t* failure) + [[nodiscard]] inline auto resume_apartment(resume_apartment_context const& context, std::coroutine_handle<> handle, std::int32_t* failure) { WINRT_ASSERT(context.valid()); if ((context.m_context == nullptr) || (context.m_context == try_capture(WINRT_IMPL_CoGetObjectContext))) @@ -326,7 +326,7 @@ namespace winrt::impl struct apartment_awaiter { apartment_context const& context; - int32_t failure = 0; + std::int32_t failure = 0; bool await_ready() const noexcept { @@ -403,7 +403,7 @@ namespace winrt::impl void create_threadpool_timer() { m_timer.attach(check_pointer(WINRT_IMPL_CreateThreadpoolTimer(callback, this, nullptr))); - int64_t relative_count = -m_duration.count(); + std::int64_t relative_count = -m_duration.count(); WINRT_IMPL_SetThreadpoolTimer(m_timer.get(), &relative_count, 0, 0); state expected = state::idle; @@ -417,7 +417,7 @@ namespace winrt::impl { if (WINRT_IMPL_SetThreadpoolTimerEx(m_timer.get(), nullptr, 0, 0)) { - int64_t now = 0; + std::int64_t now = 0; WINRT_IMPL_SetThreadpoolTimer(m_timer.get(), &now, 0, 0); } } @@ -513,8 +513,8 @@ namespace winrt::impl void create_threadpool_wait() { m_wait.attach(check_pointer(WINRT_IMPL_CreateThreadpoolWait(callback, this, nullptr))); - int64_t relative_count = -m_timeout.count(); - int64_t* file_time = relative_count != 0 ? &relative_count : nullptr; + std::int64_t relative_count = -m_timeout.count(); + std::int64_t* file_time = relative_count != 0 ? &relative_count : nullptr; WINRT_IMPL_SetThreadpoolWait(m_wait.get(), m_handle, file_time); state expected = state::idle; @@ -528,12 +528,12 @@ namespace winrt::impl { if (WINRT_IMPL_SetThreadpoolWaitEx(m_wait.get(), nullptr, nullptr, nullptr)) { - int64_t now = 0; + std::int64_t now = 0; WINRT_IMPL_SetThreadpoolWait(m_wait.get(), WINRT_IMPL_GetCurrentProcess(), &now); } } - static void __stdcall callback(void*, void* context, void*, uint32_t result) noexcept + static void __stdcall callback(void*, void* context, void*, std::uint32_t result) noexcept { auto that = static_cast(context); that->m_result = result; @@ -560,7 +560,7 @@ namespace winrt::impl handle_type m_wait; Windows::Foundation::TimeSpan m_timeout; void* m_handle; - uint32_t m_result{}; + std::uint32_t m_result{}; std::coroutine_handle<> m_resume{ nullptr }; std::atomic m_state{ state::idle }; }; @@ -596,7 +596,7 @@ WINRT_EXPORT namespace winrt m_environment.Pool = m_pool.get(); } - void thread_limits(uint32_t const high, uint32_t const low) + void thread_limits(std::uint32_t const high, std::uint32_t const low) { WINRT_IMPL_SetThreadpoolThreadMaximum(m_pool.get(), high); check_bool(WINRT_IMPL_SetThreadpoolThreadMinimum(m_pool.get(), low)); @@ -643,7 +643,7 @@ WINRT_EXPORT namespace winrt struct environment // TP_CALLBACK_ENVIRON { - uint32_t Version{ 3 }; + std::uint32_t Version{ 3 }; void* Pool{}; void* CleanupGroup{}; void* CleanupGroupCancelCallback{}; @@ -652,16 +652,16 @@ WINRT_EXPORT namespace winrt void* FinalizationCallback{}; union { - uint32_t Flags{}; + std::uint32_t Flags{}; struct { - uint32_t LongFunction : 1; - uint32_t Persistent : 1; - uint32_t Private : 30; + std::uint32_t LongFunction : 1; + std::uint32_t Persistent : 1; + std::uint32_t Private : 30; } s; } u; - int32_t CallbackPriority{ 1 }; - uint32_t Size{ sizeof(environment) }; + std::int32_t CallbackPriority{ 1 }; + std::uint32_t Size{ sizeof(environment) }; }; handle_type m_pool; diff --git a/strings/base_deferral.h b/strings/base_deferral.h index 6976db4a6..cc6f724e5 100644 --- a/strings/base_deferral.h +++ b/strings/base_deferral.h @@ -68,7 +68,7 @@ WINRT_EXPORT namespace winrt } slim_mutex m_lock; - int32_t m_outstanding_deferrals = 0; + std::int32_t m_outstanding_deferrals = 0; std::coroutine_handle<> m_handle = nullptr; }; } diff --git a/strings/base_delegate.h b/strings/base_delegate.h index 3d1457c2e..1cfe58710 100644 --- a/strings/base_delegate.h +++ b/strings/base_delegate.h @@ -8,17 +8,17 @@ namespace winrt::impl struct implements_delegate_base { - WINRT_IMPL_NOINLINE uint32_t increment_reference() noexcept + WINRT_IMPL_NOINLINE std::uint32_t increment_reference() noexcept { return ++m_references; } - WINRT_IMPL_NOINLINE uint32_t decrement_reference() noexcept + WINRT_IMPL_NOINLINE std::uint32_t decrement_reference() noexcept { return --m_references; } - WINRT_IMPL_NOINLINE uint32_t query_interface(guid const& id, void** result, unknown_abi* derivedAbiPtr, guid const& derivedId) noexcept + WINRT_IMPL_NOINLINE std::uint32_t query_interface(guid const& id, void** result, unknown_abi* derivedAbiPtr, guid const& derivedId) noexcept { if (id == derivedId || is_guid_of(id) || is_guid_of(id)) { @@ -47,17 +47,17 @@ namespace winrt::impl { } - int32_t __stdcall QueryInterface(guid const& id, void** result) noexcept final + std::int32_t __stdcall QueryInterface(guid const& id, void** result) noexcept final { return query_interface(id, result, static_cast*>(this), guid_of()); } - uint32_t __stdcall AddRef() noexcept final + std::uint32_t __stdcall AddRef() noexcept final { return increment_reference(); } - uint32_t __stdcall Release() noexcept final + std::uint32_t __stdcall Release() noexcept final { auto const remaining = decrement_reference(); @@ -133,17 +133,17 @@ namespace winrt::impl } } - int32_t __stdcall QueryInterface(guid const& id, void** result) noexcept final + std::int32_t __stdcall QueryInterface(guid const& id, void** result) noexcept final { return query_interface(id, result, static_cast(this), guid_of()); } - uint32_t __stdcall AddRef() noexcept final + std::uint32_t __stdcall AddRef() noexcept final { return increment_reference(); } - uint32_t __stdcall Release() noexcept final + std::uint32_t __stdcall Release() noexcept final { auto const remaining = decrement_reference(); diff --git a/strings/base_error.h b/strings/base_error.h index 41929336b..c58635e5d 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -41,11 +41,11 @@ namespace winrt::impl using bstr_handle = handle_type; - inline hstring trim_hresult_message(wchar_t const* const message, uint32_t size) noexcept + inline hstring trim_hresult_message(wchar_t const* const message, std::uint32_t size) noexcept { wchar_t const* back = message + size - 1; - while (size&& iswspace(*back)) + while (size && std::iswspace(*back)) { --size; --back; @@ -58,7 +58,7 @@ namespace winrt::impl { handle_type message; - uint32_t const size = WINRT_IMPL_FormatMessageW(0x00001300, // FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS + std::uint32_t const size = WINRT_IMPL_FormatMessageW(0x00001300, // FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS nullptr, code, 0x00000400, // MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) @@ -69,14 +69,14 @@ namespace winrt::impl return trim_hresult_message(message.get(), size); } - constexpr int32_t hresult_from_win32(uint32_t const x) noexcept + constexpr std::int32_t hresult_from_win32(std::uint32_t const x) noexcept { - return (int32_t)(x) <= 0 ? (int32_t)(x) : (int32_t)(((x) & 0x0000FFFF) | (7 << 16) | 0x80000000); + return (std::int32_t)(x) <= 0 ? (std::int32_t)(x) : (std::int32_t)(((x) & 0x0000FFFF) | (7 << 16) | 0x80000000); } - constexpr int32_t hresult_from_nt(uint32_t const x) noexcept + constexpr std::int32_t hresult_from_nt(std::uint32_t const x) noexcept { - return ((int32_t)((x) | 0x10000000)); + return ((std::int32_t)((x) | 0x10000000)); } } @@ -164,7 +164,7 @@ WINRT_EXPORT namespace winrt { if (m_info) { - int32_t code{}; + std::int32_t code{}; impl::bstr_handle fallback; impl::bstr_handle message; impl::bstr_handle unused; @@ -236,7 +236,7 @@ WINRT_EXPORT namespace winrt #endif impl::bstr_handle m_debug_reference; - uint32_t m_debug_magic{ 0xAABBCCDD }; + std::uint32_t m_debug_magic{ 0xAABBCCDD }; hresult m_code{ impl::error_fail }; com_ptr m_info; @@ -471,7 +471,7 @@ WINRT_EXPORT namespace winrt } catch (...) { - abort(); + std::abort(); } } @@ -532,7 +532,7 @@ WINRT_EXPORT namespace winrt [[noreturn]] inline void terminate() noexcept { WINRT_IMPL_RoFailFastWithErrorContext(to_hresult()); - abort(); + std::abort(); } } diff --git a/strings/base_events.h b/strings/base_events.h index 77952474e..f7e2e6976 100644 --- a/strings/base_events.h +++ b/strings/base_events.h @@ -3,7 +3,7 @@ WINRT_EXPORT namespace winrt { struct event_token { - int64_t value{}; + std::int64_t value{}; explicit operator bool() const noexcept { @@ -22,7 +22,7 @@ WINRT_EXPORT namespace winrt template struct event_revoker { - using method_type = int32_t(__stdcall impl::abi_t::*)(winrt::event_token); + using method_type = std::int32_t(__stdcall impl::abi_t::*)(winrt::event_token); event_revoker() noexcept = default; event_revoker(event_revoker const&) = delete; @@ -77,7 +77,7 @@ WINRT_EXPORT namespace winrt template struct factory_event_revoker { - using method_type = int32_t(__stdcall impl::abi_t::*)(winrt::event_token); + using method_type = std::int32_t(__stdcall impl::abi_t::*)(winrt::event_token); factory_event_revoker() noexcept = default; factory_event_revoker(factory_event_revoker const&) = delete; @@ -267,7 +267,7 @@ namespace winrt::impl using pointer = value_type*; using iterator = value_type*; - explicit event_array(uint32_t const count) noexcept : m_size(count) + explicit event_array(std::uint32_t const count) noexcept : m_size(count) { std::uninitialized_fill_n(data(), count, value_type()); } @@ -306,7 +306,7 @@ namespace winrt::impl return data() + m_size; } - uint32_t size() const noexcept + std::uint32_t size() const noexcept { return m_size; } @@ -324,11 +324,11 @@ namespace winrt::impl } atomic_ref_count m_references{ 1 }; - uint32_t m_size{ 0 }; + std::uint32_t m_size{ 0 }; }; template - com_ptr> make_event_array(uint32_t const capacity) + com_ptr> make_event_array(std::uint32_t const capacity) { void* raw = ::operator new(sizeof(event_array) + (sizeof(T)* capacity)); #ifdef _MSC_VER @@ -339,12 +339,12 @@ namespace winrt::impl WINRT_IMPL_NOINLINE inline bool report_failed_invoke() { - int32_t const code = to_hresult(); + std::int32_t const code = to_hresult(); WINRT_IMPL_RoTransformError(code, 0, nullptr); - if (code == static_cast(0x80010108) || // RPC_E_DISCONNECTED - code == static_cast(0x800706BA) || // HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) - code == static_cast(0x89020001)) // JSCRIPT_E_CANTEXECUTE + if (code == static_cast(0x80010108) || // RPC_E_DISCONNECTED + code == static_cast(0x800706BA) || // HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) + code == static_cast(0x89020001)) // JSCRIPT_E_CANTEXECUTE { return false; } @@ -402,7 +402,7 @@ WINRT_EXPORT namespace winrt return; } - uint32_t available_slots = m_targets->size() - 1; + std::uint32_t available_slots = m_targets->size() - 1; delegate_array new_targets; bool removed = false; @@ -516,7 +516,7 @@ WINRT_EXPORT namespace winrt event_token get_token(delegate_type const& delegate) const noexcept { - return event_token{ reinterpret_cast(WINRT_IMPL_EncodePointer(get_abi(delegate))) }; + return event_token{ reinterpret_cast(WINRT_IMPL_EncodePointer(get_abi(delegate))) }; } using delegate_array = com_ptr>; diff --git a/strings/base_extern.h b/strings/base_extern.h index 2412f9f2c..84e2943c4 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -1,8 +1,8 @@ -__declspec(selectany) int32_t(__stdcall* winrt_to_hresult_handler)(void* address) noexcept {}; +__declspec(selectany) std::int32_t(__stdcall* winrt_to_hresult_handler)(void* address) noexcept {}; __declspec(selectany) winrt::hstring(__stdcall* winrt_to_message_handler)(void* address) {}; -__declspec(selectany) void(__stdcall* winrt_throw_hresult_handler)(uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept {}; -__declspec(selectany) int32_t(__stdcall* winrt_activation_handler)(void* classId, winrt::guid const& iid, void** factory) noexcept {}; +__declspec(selectany) void(__stdcall* winrt_throw_hresult_handler)(std::uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept {}; +__declspec(selectany) std::int32_t(__stdcall* winrt_activation_handler)(void* classId, winrt::guid const& iid, void** factory) noexcept {}; #if defined(_MSC_VER) #ifdef _M_HYBRID @@ -24,88 +24,88 @@ __declspec(selectany) int32_t(__stdcall* winrt_activation_handler)(void* classId extern "C" { - int32_t __stdcall WINRT_IMPL_RoGetActivationFactory(void* classId, winrt::guid const& iid, void** factory) noexcept WINRT_IMPL_LINK(RoGetActivationFactory, 12); - int32_t __stdcall WINRT_IMPL_RoGetAgileReference(uint32_t options, winrt::guid const& iid, void* object, void** reference) noexcept WINRT_IMPL_LINK(RoGetAgileReference, 16); - int32_t __stdcall WINRT_IMPL_SetThreadpoolTimerEx(winrt::impl::ptp_timer, void*, uint32_t, uint32_t) noexcept WINRT_IMPL_LINK(SetThreadpoolTimerEx, 16); - int32_t __stdcall WINRT_IMPL_SetThreadpoolWaitEx(winrt::impl::ptp_wait, void*, void*, void*) noexcept WINRT_IMPL_LINK(SetThreadpoolWaitEx, 16); - int32_t __stdcall WINRT_IMPL_RoOriginateLanguageException(int32_t error, void* message, void* exception) noexcept WINRT_IMPL_LINK(RoOriginateLanguageException, 12); - int32_t __stdcall WINRT_IMPL_RoCaptureErrorContext(int32_t error) noexcept WINRT_IMPL_LINK(RoCaptureErrorContext, 4); - void __stdcall WINRT_IMPL_RoFailFastWithErrorContext(int32_t) noexcept WINRT_IMPL_LINK(RoFailFastWithErrorContext, 4); - int32_t __stdcall WINRT_IMPL_RoTransformError(int32_t, int32_t, void*) noexcept WINRT_IMPL_LINK(RoTransformError, 12); + std::int32_t __stdcall WINRT_IMPL_RoGetActivationFactory(void* classId, winrt::guid const& iid, void** factory) noexcept WINRT_IMPL_LINK(RoGetActivationFactory, 12); + std::int32_t __stdcall WINRT_IMPL_RoGetAgileReference(std::uint32_t options, winrt::guid const& iid, void* object, void** reference) noexcept WINRT_IMPL_LINK(RoGetAgileReference, 16); + std::int32_t __stdcall WINRT_IMPL_SetThreadpoolTimerEx(winrt::impl::ptp_timer, void*, std::uint32_t, std::uint32_t) noexcept WINRT_IMPL_LINK(SetThreadpoolTimerEx, 16); + std::int32_t __stdcall WINRT_IMPL_SetThreadpoolWaitEx(winrt::impl::ptp_wait, void*, void*, void*) noexcept WINRT_IMPL_LINK(SetThreadpoolWaitEx, 16); + std::int32_t __stdcall WINRT_IMPL_RoOriginateLanguageException(std::int32_t error, void* message, void* exception) noexcept WINRT_IMPL_LINK(RoOriginateLanguageException, 12); + std::int32_t __stdcall WINRT_IMPL_RoCaptureErrorContext(std::int32_t error) noexcept WINRT_IMPL_LINK(RoCaptureErrorContext, 4); + void __stdcall WINRT_IMPL_RoFailFastWithErrorContext(std::int32_t) noexcept WINRT_IMPL_LINK(RoFailFastWithErrorContext, 4); + std::int32_t __stdcall WINRT_IMPL_RoTransformError(std::int32_t, std::int32_t, void*) noexcept WINRT_IMPL_LINK(RoTransformError, 12); - void* __stdcall WINRT_IMPL_LoadLibraryExW(wchar_t const* name, void* unused, uint32_t flags) noexcept WINRT_IMPL_LINK(LoadLibraryExW, 12); - int32_t __stdcall WINRT_IMPL_FreeLibrary(void* library) noexcept WINRT_IMPL_LINK(FreeLibrary, 4); + void* __stdcall WINRT_IMPL_LoadLibraryExW(wchar_t const* name, void* unused, std::uint32_t flags) noexcept WINRT_IMPL_LINK(LoadLibraryExW, 12); + std::int32_t __stdcall WINRT_IMPL_FreeLibrary(void* library) noexcept WINRT_IMPL_LINK(FreeLibrary, 4); void* __stdcall WINRT_IMPL_GetProcAddress(void* library, char const* name) noexcept WINRT_IMPL_LINK(GetProcAddress, 8); - int32_t __stdcall WINRT_IMPL_SetErrorInfo(uint32_t reserved, void* info) noexcept WINRT_IMPL_LINK(SetErrorInfo, 8); - int32_t __stdcall WINRT_IMPL_GetErrorInfo(uint32_t reserved, void** info) noexcept WINRT_IMPL_LINK(GetErrorInfo, 8); - int32_t __stdcall WINRT_IMPL_CoInitializeEx(void*, uint32_t type) noexcept WINRT_IMPL_LINK(CoInitializeEx, 8); + std::int32_t __stdcall WINRT_IMPL_SetErrorInfo(std::uint32_t reserved, void* info) noexcept WINRT_IMPL_LINK(SetErrorInfo, 8); + std::int32_t __stdcall WINRT_IMPL_GetErrorInfo(std::uint32_t reserved, void** info) noexcept WINRT_IMPL_LINK(GetErrorInfo, 8); + std::int32_t __stdcall WINRT_IMPL_CoInitializeEx(void*, std::uint32_t type) noexcept WINRT_IMPL_LINK(CoInitializeEx, 8); void __stdcall WINRT_IMPL_CoUninitialize() noexcept WINRT_IMPL_LINK(CoUninitialize, 0); - int32_t __stdcall WINRT_IMPL_CoCreateFreeThreadedMarshaler(void* outer, void** marshaler) noexcept WINRT_IMPL_LINK(CoCreateFreeThreadedMarshaler, 8); - int32_t __stdcall WINRT_IMPL_CoCreateInstance(winrt::guid const& clsid, void* outer, uint32_t context, winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoCreateInstance, 20); - int32_t __stdcall WINRT_IMPL_CoGetCallContext(winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoGetCallContext, 8); - int32_t __stdcall WINRT_IMPL_CoGetObjectContext(winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoGetObjectContext, 8); - int32_t __stdcall WINRT_IMPL_CoGetApartmentType(int32_t* type, int32_t* qualifier) noexcept WINRT_IMPL_LINK(CoGetApartmentType, 8); + std::int32_t __stdcall WINRT_IMPL_CoCreateFreeThreadedMarshaler(void* outer, void** marshaler) noexcept WINRT_IMPL_LINK(CoCreateFreeThreadedMarshaler, 8); + std::int32_t __stdcall WINRT_IMPL_CoCreateInstance(winrt::guid const& clsid, void* outer, std::uint32_t context, winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoCreateInstance, 20); + std::int32_t __stdcall WINRT_IMPL_CoGetCallContext(winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoGetCallContext, 8); + std::int32_t __stdcall WINRT_IMPL_CoGetObjectContext(winrt::guid const& iid, void** object) noexcept WINRT_IMPL_LINK(CoGetObjectContext, 8); + std::int32_t __stdcall WINRT_IMPL_CoGetApartmentType(std::int32_t* type, std::int32_t* qualifier) noexcept WINRT_IMPL_LINK(CoGetApartmentType, 8); void* __stdcall WINRT_IMPL_CoTaskMemAlloc(std::size_t size) noexcept WINRT_IMPL_LINK(CoTaskMemAlloc, 4); void __stdcall WINRT_IMPL_CoTaskMemFree(void* ptr) noexcept WINRT_IMPL_LINK(CoTaskMemFree, 4); winrt::impl::bstr __stdcall WINRT_IMPL_SysAllocString(wchar_t const* value) noexcept WINRT_IMPL_LINK(SysAllocString, 4); void __stdcall WINRT_IMPL_SysFreeString(winrt::impl::bstr string) noexcept WINRT_IMPL_LINK(SysFreeString, 4); - uint32_t __stdcall WINRT_IMPL_SysStringLen(winrt::impl::bstr string) noexcept WINRT_IMPL_LINK(SysStringLen, 4); - int32_t __stdcall WINRT_IMPL_IIDFromString(wchar_t const* string, winrt::guid* iid) noexcept WINRT_IMPL_LINK(IIDFromString, 8); - int32_t __stdcall WINRT_IMPL_MultiByteToWideChar(uint32_t codepage, uint32_t flags, char const* in_string, int32_t in_size, wchar_t* out_string, int32_t out_size) noexcept WINRT_IMPL_LINK(MultiByteToWideChar, 24); - int32_t __stdcall WINRT_IMPL_WideCharToMultiByte(uint32_t codepage, uint32_t flags, wchar_t const* int_string, int32_t in_size, char* out_string, int32_t out_size, char const* default_char, int32_t* default_used) noexcept WINRT_IMPL_LINK(WideCharToMultiByte, 32); - void* __stdcall WINRT_IMPL_HeapAlloc(void* heap, uint32_t flags, size_t bytes) noexcept WINRT_IMPL_LINK(HeapAlloc, 12); - int32_t __stdcall WINRT_IMPL_HeapFree(void* heap, uint32_t flags, void* value) noexcept WINRT_IMPL_LINK(HeapFree, 12); + std::uint32_t __stdcall WINRT_IMPL_SysStringLen(winrt::impl::bstr string) noexcept WINRT_IMPL_LINK(SysStringLen, 4); + std::int32_t __stdcall WINRT_IMPL_IIDFromString(wchar_t const* string, winrt::guid* iid) noexcept WINRT_IMPL_LINK(IIDFromString, 8); + std::int32_t __stdcall WINRT_IMPL_MultiByteToWideChar(std::uint32_t codepage, std::uint32_t flags, char const* in_string, std::int32_t in_size, wchar_t* out_string, std::int32_t out_size) noexcept WINRT_IMPL_LINK(MultiByteToWideChar, 24); + std::int32_t __stdcall WINRT_IMPL_WideCharToMultiByte(std::uint32_t codepage, std::uint32_t flags, wchar_t const* int_string, std::int32_t in_size, char* out_string, std::int32_t out_size, char const* default_char, std::int32_t* default_used) noexcept WINRT_IMPL_LINK(WideCharToMultiByte, 32); + void* __stdcall WINRT_IMPL_HeapAlloc(void* heap, std::uint32_t flags, std::size_t bytes) noexcept WINRT_IMPL_LINK(HeapAlloc, 12); + std::int32_t __stdcall WINRT_IMPL_HeapFree(void* heap, std::uint32_t flags, void* value) noexcept WINRT_IMPL_LINK(HeapFree, 12); void* __stdcall WINRT_IMPL_GetProcessHeap() noexcept WINRT_IMPL_LINK(GetProcessHeap, 0); - uint32_t __stdcall WINRT_IMPL_FormatMessageW(uint32_t flags, void const* source, uint32_t code, uint32_t language, wchar_t* buffer, uint32_t size, va_list* arguments) noexcept WINRT_IMPL_LINK(FormatMessageW, 28); - uint32_t __stdcall WINRT_IMPL_GetLastError() noexcept WINRT_IMPL_LINK(GetLastError, 0); + std::uint32_t __stdcall WINRT_IMPL_FormatMessageW(std::uint32_t flags, void const* source, std::uint32_t code, std::uint32_t language, wchar_t* buffer, std::uint32_t size, va_list* arguments) noexcept WINRT_IMPL_LINK(FormatMessageW, 28); + std::uint32_t __stdcall WINRT_IMPL_GetLastError() noexcept WINRT_IMPL_LINK(GetLastError, 0); void __stdcall WINRT_IMPL_GetSystemTimePreciseAsFileTime(void* result) noexcept WINRT_IMPL_LINK(GetSystemTimePreciseAsFileTime, 4); - uintptr_t __stdcall WINRT_IMPL_VirtualQuery(void* address, void* buffer, uintptr_t length) noexcept WINRT_IMPL_LINK(VirtualQuery, 12); + std::uintptr_t __stdcall WINRT_IMPL_VirtualQuery(void* address, void* buffer, std::uintptr_t length) noexcept WINRT_IMPL_LINK(VirtualQuery, 12); void* __stdcall WINRT_IMPL_EncodePointer(void* ptr) noexcept WINRT_IMPL_LINK(EncodePointer, 4); - int32_t __stdcall WINRT_IMPL_OpenProcessToken(void* process, uint32_t access, void** token) noexcept WINRT_IMPL_LINK(OpenProcessToken, 12); + std::int32_t __stdcall WINRT_IMPL_OpenProcessToken(void* process, std::uint32_t access, void** token) noexcept WINRT_IMPL_LINK(OpenProcessToken, 12); void* __stdcall WINRT_IMPL_GetCurrentProcess() noexcept WINRT_IMPL_LINK(GetCurrentProcess, 0); - int32_t __stdcall WINRT_IMPL_DuplicateToken(void* existing, uint32_t level, void** duplicate) noexcept WINRT_IMPL_LINK(DuplicateToken, 12); - int32_t __stdcall WINRT_IMPL_OpenThreadToken(void* thread, uint32_t access, int32_t self, void** token) noexcept WINRT_IMPL_LINK(OpenThreadToken, 16); + std::int32_t __stdcall WINRT_IMPL_DuplicateToken(void* existing, std::uint32_t level, void** duplicate) noexcept WINRT_IMPL_LINK(DuplicateToken, 12); + std::int32_t __stdcall WINRT_IMPL_OpenThreadToken(void* thread, std::uint32_t access, std::int32_t self, void** token) noexcept WINRT_IMPL_LINK(OpenThreadToken, 16); void* __stdcall WINRT_IMPL_GetCurrentThread() noexcept WINRT_IMPL_LINK(GetCurrentThread, 0); - int32_t __stdcall WINRT_IMPL_SetThreadToken(void** thread, void* token) noexcept WINRT_IMPL_LINK(SetThreadToken, 8); + std::int32_t __stdcall WINRT_IMPL_SetThreadToken(void** thread, void* token) noexcept WINRT_IMPL_LINK(SetThreadToken, 8); void __stdcall WINRT_IMPL_AcquireSRWLockExclusive(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(AcquireSRWLockExclusive, 4); void __stdcall WINRT_IMPL_AcquireSRWLockShared(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(AcquireSRWLockShared, 4); - uint8_t __stdcall WINRT_IMPL_TryAcquireSRWLockExclusive(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(TryAcquireSRWLockExclusive, 4); - uint8_t __stdcall WINRT_IMPL_TryAcquireSRWLockShared(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(TryAcquireSRWLockShared, 4); + std::uint8_t __stdcall WINRT_IMPL_TryAcquireSRWLockExclusive(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(TryAcquireSRWLockExclusive, 4); + std::uint8_t __stdcall WINRT_IMPL_TryAcquireSRWLockShared(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(TryAcquireSRWLockShared, 4); void __stdcall WINRT_IMPL_ReleaseSRWLockExclusive(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(ReleaseSRWLockExclusive, 4); void __stdcall WINRT_IMPL_ReleaseSRWLockShared(winrt::impl::srwlock* lock) noexcept WINRT_IMPL_LINK(ReleaseSRWLockShared, 4); - int32_t __stdcall WINRT_IMPL_SleepConditionVariableSRW(winrt::impl::condition_variable* cv, winrt::impl::srwlock* lock, uint32_t milliseconds, uint32_t flags) noexcept WINRT_IMPL_LINK(SleepConditionVariableSRW, 16); + std::int32_t __stdcall WINRT_IMPL_SleepConditionVariableSRW(winrt::impl::condition_variable* cv, winrt::impl::srwlock* lock, std::uint32_t milliseconds, std::uint32_t flags) noexcept WINRT_IMPL_LINK(SleepConditionVariableSRW, 16); void __stdcall WINRT_IMPL_WakeConditionVariable(winrt::impl::condition_variable* cv) noexcept WINRT_IMPL_LINK(WakeConditionVariable, 4); void __stdcall WINRT_IMPL_WakeAllConditionVariable(winrt::impl::condition_variable* cv) noexcept WINRT_IMPL_LINK(WakeAllConditionVariable, 4); void* __stdcall WINRT_IMPL_InterlockedPushEntrySList(void* head, void* entry) noexcept WINRT_IMPL_LINK(InterlockedPushEntrySList, 8); void* __stdcall WINRT_IMPL_InterlockedFlushSList(void* head) noexcept WINRT_IMPL_LINK(InterlockedFlushSList, 4); - void* __stdcall WINRT_IMPL_CreateEventW(void*, int32_t, int32_t, void*) noexcept WINRT_IMPL_LINK(CreateEventW, 16); - int32_t __stdcall WINRT_IMPL_SetEvent(void*) noexcept WINRT_IMPL_LINK(SetEvent, 4); - int32_t __stdcall WINRT_IMPL_CloseHandle(void* hObject) noexcept WINRT_IMPL_LINK(CloseHandle, 4); - uint32_t __stdcall WINRT_IMPL_WaitForSingleObject(void* handle, uint32_t milliseconds) noexcept WINRT_IMPL_LINK(WaitForSingleObject, 8); + void* __stdcall WINRT_IMPL_CreateEventW(void*, std::int32_t, std::int32_t, void*) noexcept WINRT_IMPL_LINK(CreateEventW, 16); + std::int32_t __stdcall WINRT_IMPL_SetEvent(void*) noexcept WINRT_IMPL_LINK(SetEvent, 4); + std::int32_t __stdcall WINRT_IMPL_CloseHandle(void* hObject) noexcept WINRT_IMPL_LINK(CloseHandle, 4); + std::uint32_t __stdcall WINRT_IMPL_WaitForSingleObject(void* handle, std::uint32_t milliseconds) noexcept WINRT_IMPL_LINK(WaitForSingleObject, 8); - int32_t __stdcall WINRT_IMPL_TrySubmitThreadpoolCallback(void(__stdcall *callback)(void*, void* context), void* context, void*) noexcept WINRT_IMPL_LINK(TrySubmitThreadpoolCallback, 12); + std::int32_t __stdcall WINRT_IMPL_TrySubmitThreadpoolCallback(void(__stdcall *callback)(void*, void* context), void* context, void*) noexcept WINRT_IMPL_LINK(TrySubmitThreadpoolCallback, 12); winrt::impl::ptp_timer __stdcall WINRT_IMPL_CreateThreadpoolTimer(void(__stdcall *callback)(void*, void* context, void*), void* context, void*) noexcept WINRT_IMPL_LINK(CreateThreadpoolTimer, 12); - void __stdcall WINRT_IMPL_SetThreadpoolTimer(winrt::impl::ptp_timer timer, void* time, uint32_t period, uint32_t window) noexcept WINRT_IMPL_LINK(SetThreadpoolTimer, 16); + void __stdcall WINRT_IMPL_SetThreadpoolTimer(winrt::impl::ptp_timer timer, void* time, std::uint32_t period, std::uint32_t window) noexcept WINRT_IMPL_LINK(SetThreadpoolTimer, 16); void __stdcall WINRT_IMPL_CloseThreadpoolTimer(winrt::impl::ptp_timer timer) noexcept WINRT_IMPL_LINK(CloseThreadpoolTimer, 4); - winrt::impl::ptp_wait __stdcall WINRT_IMPL_CreateThreadpoolWait(void(__stdcall *callback)(void*, void* context, void*, uint32_t result), void* context, void*) noexcept WINRT_IMPL_LINK(CreateThreadpoolWait, 12); + winrt::impl::ptp_wait __stdcall WINRT_IMPL_CreateThreadpoolWait(void(__stdcall *callback)(void*, void* context, void*, std::uint32_t result), void* context, void*) noexcept WINRT_IMPL_LINK(CreateThreadpoolWait, 12); void __stdcall WINRT_IMPL_SetThreadpoolWait(winrt::impl::ptp_wait wait, void* handle, void* timeout) noexcept WINRT_IMPL_LINK(SetThreadpoolWait, 12); void __stdcall WINRT_IMPL_CloseThreadpoolWait(winrt::impl::ptp_wait wait) noexcept WINRT_IMPL_LINK(CloseThreadpoolWait, 4); - winrt::impl::ptp_io __stdcall WINRT_IMPL_CreateThreadpoolIo(void* object, void(__stdcall *callback)(void*, void* context, void* overlapped, uint32_t result, std::size_t bytes, void*) noexcept, void* context, void*) noexcept WINRT_IMPL_LINK(CreateThreadpoolIo, 16); + winrt::impl::ptp_io __stdcall WINRT_IMPL_CreateThreadpoolIo(void* object, void(__stdcall *callback)(void*, void* context, void* overlapped, std::uint32_t result, std::size_t bytes, void*) noexcept, void* context, void*) noexcept WINRT_IMPL_LINK(CreateThreadpoolIo, 16); void __stdcall WINRT_IMPL_StartThreadpoolIo(winrt::impl::ptp_io io) noexcept WINRT_IMPL_LINK(StartThreadpoolIo, 4); void __stdcall WINRT_IMPL_CancelThreadpoolIo(winrt::impl::ptp_io io) noexcept WINRT_IMPL_LINK(CancelThreadpoolIo, 4); void __stdcall WINRT_IMPL_CloseThreadpoolIo(winrt::impl::ptp_io io) noexcept WINRT_IMPL_LINK(CloseThreadpoolIo, 4); winrt::impl::ptp_pool __stdcall WINRT_IMPL_CreateThreadpool(void* reserved) noexcept WINRT_IMPL_LINK(CreateThreadpool, 4); - void __stdcall WINRT_IMPL_SetThreadpoolThreadMaximum(winrt::impl::ptp_pool pool, uint32_t value) noexcept WINRT_IMPL_LINK(SetThreadpoolThreadMaximum, 8); - int32_t __stdcall WINRT_IMPL_SetThreadpoolThreadMinimum(winrt::impl::ptp_pool pool, uint32_t value) noexcept WINRT_IMPL_LINK(SetThreadpoolThreadMinimum, 8); + void __stdcall WINRT_IMPL_SetThreadpoolThreadMaximum(winrt::impl::ptp_pool pool, std::uint32_t value) noexcept WINRT_IMPL_LINK(SetThreadpoolThreadMaximum, 8); + std::int32_t __stdcall WINRT_IMPL_SetThreadpoolThreadMinimum(winrt::impl::ptp_pool pool, std::uint32_t value) noexcept WINRT_IMPL_LINK(SetThreadpoolThreadMinimum, 8); void __stdcall WINRT_IMPL_CloseThreadpool(winrt::impl::ptp_pool pool) noexcept WINRT_IMPL_LINK(CloseThreadpool, 4); - int32_t __stdcall WINRT_CanUnloadNow() noexcept; - int32_t __stdcall WINRT_GetActivationFactory(void* classId, void** factory) noexcept; + std::int32_t __stdcall WINRT_CanUnloadNow() noexcept; + std::int32_t __stdcall WINRT_GetActivationFactory(void* classId, void** factory) noexcept; } #undef WINRT_IMPL_LINK diff --git a/strings/base_fast_forward.h b/strings/base_fast_forward.h index 3ca34dba7..dc89fe6ce 100644 --- a/strings/base_fast_forward.h +++ b/strings/base_fast_forward.h @@ -1,5 +1,7 @@ #include #include +#include +#include #define WINRT_IMPL_STRING_1(expression) #expression #define WINRT_IMPL_STRING(expression) WINRT_IMPL_STRING_1(expression) @@ -36,31 +38,31 @@ namespace winrt::impl { struct guid { - uint32_t Data1; - uint16_t Data2; - uint16_t Data3; - uint8_t Data4[8]; + std::uint32_t Data1; + std::uint16_t Data2; + std::uint16_t Data3; + std::uint8_t Data4[8]; inline bool operator!=(guid const& right) const noexcept { - return memcmp(this, &right, sizeof(guid)); + return std::memcmp(this, &right, sizeof(guid)); } }; struct WINRT_IMPL_FF_NOVTABLE WINRT_IMPL_FF_PUBLIC inspectable { - virtual int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept = 0; - virtual uint32_t __stdcall AddRef() noexcept = 0; - virtual uint32_t __stdcall Release() noexcept = 0; - virtual int32_t __stdcall GetIids(uint32_t* count, guid** ids) noexcept = 0; - virtual int32_t __stdcall GetRuntimeClassName(void** name) noexcept = 0; - virtual int32_t __stdcall GetTrustLevel(uint32_t* level) noexcept = 0; + virtual std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept = 0; + virtual std::uint32_t __stdcall AddRef() noexcept = 0; + virtual std::uint32_t __stdcall Release() noexcept = 0; + virtual std::int32_t __stdcall GetIids(std::uint32_t* count, guid** ids) noexcept = 0; + virtual std::int32_t __stdcall GetRuntimeClassName(void** name) noexcept = 0; + virtual std::int32_t __stdcall GetTrustLevel(std::uint32_t* level) noexcept = 0; }; void* const* m_vfptr; inspectable* m_owner; std::size_t m_offset; guid m_iid; - std::atomic m_references{ 1 }; + std::atomic m_references{ 1 }; fast_abi_forwarder(void* owner, guid const& iid, std::size_t offset) noexcept : m_vfptr(s_vtable), m_owner(static_cast(owner)), m_offset(offset), m_iid(iid) @@ -73,7 +75,7 @@ namespace winrt::impl m_owner->Release(); } - static int32_t __stdcall QueryInterface(fast_abi_forwarder* self, guid const& iid, void** object) noexcept + static std::int32_t __stdcall QueryInterface(fast_abi_forwarder* self, guid const& iid, void** object) noexcept { if (iid != self->m_iid) { @@ -85,14 +87,14 @@ namespace winrt::impl } // Note: COM interfaces use stdcall, not thiscall, ('this' gets no special treatment), permitting static implementations - static uint32_t __stdcall AddRef(fast_abi_forwarder* self) noexcept + static std::uint32_t __stdcall AddRef(fast_abi_forwarder* self) noexcept { return 1 + self->m_references.fetch_add(1, std::memory_order_relaxed); } - static uint32_t __stdcall Release(fast_abi_forwarder* self) noexcept + static std::uint32_t __stdcall Release(fast_abi_forwarder* self) noexcept { - uint32_t const remaining = self->m_references.fetch_sub(1, std::memory_order_release) - 1; + std::uint32_t const remaining = self->m_references.fetch_sub(1, std::memory_order_release) - 1; if (remaining == 0) { std::atomic_thread_fence(std::memory_order_acquire); @@ -101,17 +103,17 @@ namespace winrt::impl return remaining; } - static uint32_t __stdcall GetIids(fast_abi_forwarder* self, uint32_t* count, guid** iids) noexcept + static std::uint32_t __stdcall GetIids(fast_abi_forwarder* self, std::uint32_t* count, guid** iids) noexcept { return self->m_owner->GetIids(count, iids); } - static uint32_t __stdcall GetRuntimeClassName(fast_abi_forwarder* self, void** name) noexcept + static std::uint32_t __stdcall GetRuntimeClassName(fast_abi_forwarder* self, void** name) noexcept { return self->m_owner->GetRuntimeClassName(name); } - static uint32_t __stdcall GetTrustLevel(fast_abi_forwarder* self, uint32_t* level) noexcept + static std::uint32_t __stdcall GetTrustLevel(fast_abi_forwarder* self, std::uint32_t* level) noexcept { return self->m_owner->GetTrustLevel(level); } @@ -144,7 +146,7 @@ namespace winrt::impl namespace winrt { template - auto make_fast_abi_forwarder(void* owner, TGuid const& guid, size_t offset) + auto make_fast_abi_forwarder(void* owner, TGuid const& guid, std::size_t offset) { using ff_guid = impl::fast_abi_forwarder::guid; static_assert(sizeof(ff_guid) == sizeof(TGuid)); diff --git a/strings/base_identity.h b/strings/base_identity.h index 0f4a163b6..30830bc5a 100644 --- a/strings/base_identity.h +++ b/strings/base_identity.h @@ -19,31 +19,31 @@ WINRT_EXPORT namespace winrt namespace winrt::impl { - template + template constexpr std::array to_array(T const* value, std::index_sequence const) noexcept { return { value[Index]... }; } - template + template constexpr auto to_array(std::array const& value) noexcept { return value; } - template + template constexpr auto to_array(char const(&value)[Size]) noexcept { return to_array(value, std::make_index_sequence()); } - template + template constexpr auto to_array(wchar_t const(&value)[Size]) noexcept { return to_array(value, std::make_index_sequence()); } - template + template constexpr std::array concat( [[maybe_unused]] std::array const& left, [[maybe_unused]] std::array const& right, @@ -53,31 +53,31 @@ namespace winrt::impl return { left[LeftIndex]..., right[RightIndex]... }; } - template + template constexpr auto concat(std::array const& left, std::array const& right) noexcept { return concat(left, right, std::make_index_sequence(), std::make_index_sequence()); } - template + template constexpr auto concat(std::array const& left, T const(&right)[RightSize]) noexcept { return concat(left, to_array(right)); } - template + template constexpr auto concat(T const(&left)[LeftSize], std::array const& right) noexcept { return concat(to_array(left), right); } - template + template constexpr auto concat(std::array const& left, T const right) noexcept { return concat(left, std::array{right}); } - template + template constexpr auto concat(T const left, std::array const& right) noexcept { return concat(std::array{left}, right); @@ -96,31 +96,31 @@ namespace winrt::impl } } - template + template constexpr std::array zconcat_base(std::array const& left, std::array const& right, std::index_sequence const, std::index_sequence const) noexcept { return { left[LI]..., right[RI]..., T{} }; } - template + template constexpr auto zconcat(std::array const& left, std::array const& right) noexcept { return zconcat_base(left, right, std::make_index_sequence(), std::make_index_sequence()); } - template + template constexpr std::array to_zarray_base(T const(&value)[S], std::index_sequence const) noexcept { return { value[I]... }; } - template + template constexpr auto to_zarray(T const(&value)[S]) noexcept { return to_zarray_base(value, std::make_index_sequence()); } - template + template constexpr auto to_zarray(std::array const& value) noexcept { return value; @@ -139,43 +139,43 @@ namespace winrt::impl } } - constexpr std::array to_array(uint32_t value) noexcept + constexpr std::array to_array(std::uint32_t value) noexcept { - return { static_cast(value & 0x000000ff), static_cast((value & 0x0000ff00) >> 8), static_cast((value & 0x00ff0000) >> 16), static_cast((value & 0xff000000) >> 24) }; + return { static_cast(value & 0x000000ff), static_cast((value & 0x0000ff00) >> 8), static_cast((value & 0x00ff0000) >> 16), static_cast((value & 0xff000000) >> 24) }; } - constexpr std::array to_array(uint16_t value) noexcept + constexpr std::array to_array(std::uint16_t value) noexcept { - return { static_cast(value & 0x00ff), static_cast((value & 0xff00) >> 8) }; + return { static_cast(value & 0x00ff), static_cast((value & 0xff00) >> 8) }; } constexpr auto to_array(guid const& value) noexcept { return combine(to_array(value.Data1), to_array(value.Data2), to_array(value.Data3), - std::array{ value.Data4[0], value.Data4[1], value.Data4[2], value.Data4[3], value.Data4[4], value.Data4[5], value.Data4[6], value.Data4[7] }); + std::array{ value.Data4[0], value.Data4[1], value.Data4[2], value.Data4[3], value.Data4[4], value.Data4[5], value.Data4[6], value.Data4[7] }); } template - constexpr T to_hex_digit(uint8_t value) noexcept + constexpr T to_hex_digit(std::uint8_t value) noexcept { value &= 0xF; return value < 10 ? static_cast('0') + value : static_cast('a') + (value - 10); } template - constexpr std::array uint8_to_hex(uint8_t const value) noexcept + constexpr std::array uint8_to_hex(std::uint8_t const value) noexcept { return { to_hex_digit(value >> 4), to_hex_digit(value & 0xF) }; } template - constexpr auto uint16_to_hex(uint16_t value) noexcept + constexpr auto uint16_to_hex(std::uint16_t value) noexcept { - return combine(uint8_to_hex(static_cast(value >> 8)), uint8_to_hex(value & 0xFF)); + return combine(uint8_to_hex(static_cast(value >> 8)), uint8_to_hex(value & 0xFF)); } template - constexpr auto uint32_to_hex(uint32_t const value) noexcept + constexpr auto uint32_to_hex(std::uint32_t const value) noexcept { return combine(uint16_to_hex(value >> 16), uint16_to_hex(value & 0xFFFF)); } @@ -197,18 +197,18 @@ namespace winrt::impl ); } - constexpr uint32_t to_guid(uint8_t a, uint8_t b, uint8_t c, uint8_t d) noexcept + constexpr std::uint32_t to_guid(std::uint8_t a, std::uint8_t b, std::uint8_t c, std::uint8_t d) noexcept { - return (static_cast(d) << 24) | (static_cast(c) << 16) | (static_cast(b) << 8) | static_cast(a); + return (static_cast(d) << 24) | (static_cast(c) << 16) | (static_cast(b) << 8) | static_cast(a); } - constexpr uint16_t to_guid(uint8_t a, uint8_t b) noexcept + constexpr std::uint16_t to_guid(std::uint8_t a, std::uint8_t b) noexcept { - return (static_cast(b) << 8) | static_cast(a); + return (static_cast(b) << 8) | static_cast(a); } - template - constexpr guid to_guid(std::array const& arr) noexcept + template + constexpr guid to_guid(std::array const& arr) noexcept { return { @@ -219,12 +219,12 @@ namespace winrt::impl }; } - constexpr uint32_t endian_swap(uint32_t value) noexcept + constexpr std::uint32_t endian_swap(std::uint32_t value) noexcept { return (value & 0xFF000000) >> 24 | (value & 0x00FF0000) >> 8 | (value & 0x0000FF00) << 8 | (value & 0x000000FF) << 24; } - constexpr uint16_t endian_swap(uint16_t value) noexcept + constexpr std::uint16_t endian_swap(std::uint16_t value) noexcept { return (value & 0xFF00) >> 8 | (value & 0x00FF) << 8; } @@ -239,51 +239,51 @@ namespace winrt::impl constexpr guid set_named_guid_fields(guid value) noexcept { - value.Data3 = static_cast((value.Data3 & 0x0fff) | (5 << 12)); - value.Data4[0] = static_cast((value.Data4[0] & 0x3f) | 0x80); + value.Data3 = static_cast((value.Data3 & 0x0fff) | (5 << 12)); + value.Data4[0] = static_cast((value.Data4[0] & 0x3f) | 0x80); return value; } - template - constexpr std::array char_to_byte_array(std::array const& value, std::index_sequence const) noexcept + template + constexpr std::array char_to_byte_array(std::array const& value, std::index_sequence const) noexcept { - return { static_cast(value[Index])... }; + return { static_cast(value[Index])... }; } - constexpr auto sha1_rotl(uint8_t bits, uint32_t word) noexcept + constexpr auto sha1_rotl(std::uint8_t bits, std::uint32_t word) noexcept { return (word << bits) | (word >> (32 - bits)); } - constexpr auto sha_ch(uint32_t x, uint32_t y, uint32_t z) noexcept + constexpr auto sha_ch(std::uint32_t x, std::uint32_t y, std::uint32_t z) noexcept { return (x & y) ^ ((~x) & z); } - constexpr auto sha_parity(uint32_t x, uint32_t y, uint32_t z) noexcept + constexpr auto sha_parity(std::uint32_t x, std::uint32_t y, std::uint32_t z) noexcept { return x ^ y ^ z; } - constexpr auto sha_maj(uint32_t x, uint32_t y, uint32_t z) noexcept + constexpr auto sha_maj(std::uint32_t x, std::uint32_t y, std::uint32_t z) noexcept { return (x & y) ^ (x & z) ^ (y & z); } - constexpr std::array process_msg_block(uint8_t const* input, size_t start_pos, std::array const& intermediate_hash) noexcept + constexpr std::array process_msg_block(std::uint8_t const* input, std::size_t start_pos, std::array const& intermediate_hash) noexcept { - uint32_t const K[4] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; - std::array W = {}; + std::uint32_t const K[4] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; + std::array W = {}; - size_t t = 0; - uint32_t temp = 0; + std::size_t t = 0; + std::uint32_t temp = 0; for (t = 0; t < 16; t++) { - W[t] = static_cast(input[start_pos + t * 4]) << 24; - W[t] = W[t] | static_cast(input[start_pos + t * 4 + 1]) << 16; - W[t] = W[t] | static_cast(input[start_pos + t * 4 + 2]) << 8; - W[t] = W[t] | static_cast(input[start_pos + t * 4 + 3]); + W[t] = static_cast(input[start_pos + t * 4]) << 24; + W[t] = W[t] | static_cast(input[start_pos + t * 4 + 1]) << 16; + W[t] = W[t] | static_cast(input[start_pos + t * 4 + 2]) << 8; + W[t] = W[t] | static_cast(input[start_pos + t * 4 + 3]); } for (t = 16; t < 80; t++) @@ -291,11 +291,11 @@ namespace winrt::impl W[t] = sha1_rotl(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]); } - uint32_t A = intermediate_hash[0]; - uint32_t B = intermediate_hash[1]; - uint32_t C = intermediate_hash[2]; - uint32_t D = intermediate_hash[3]; - uint32_t E = intermediate_hash[4]; + std::uint32_t A = intermediate_hash[0]; + std::uint32_t B = intermediate_hash[1]; + std::uint32_t C = intermediate_hash[2]; + std::uint32_t D = intermediate_hash[3]; + std::uint32_t E = intermediate_hash[4]; for (t = 0; t < 20; t++) { @@ -340,54 +340,54 @@ namespace winrt::impl return { intermediate_hash[0] + A, intermediate_hash[1] + B, intermediate_hash[2] + C, intermediate_hash[3] + D, intermediate_hash[4] + E }; } - template - constexpr std::array process_msg_block(std::array const& input, size_t start_pos, std::array const& intermediate_hash) noexcept + template + constexpr std::array process_msg_block(std::array const& input, std::size_t start_pos, std::array const& intermediate_hash) noexcept { return process_msg_block(input.data(), start_pos, intermediate_hash); } - constexpr std::array size_to_bytes(size_t size) noexcept + constexpr std::array size_to_bytes(std::size_t size) noexcept { return { - static_cast((size & 0xff00000000000000) >> 56), - static_cast((size & 0x00ff000000000000) >> 48), - static_cast((size & 0x0000ff0000000000) >> 40), - static_cast((size & 0x000000ff00000000) >> 32), - static_cast((size & 0x00000000ff000000) >> 24), - static_cast((size & 0x0000000000ff0000) >> 16), - static_cast((size & 0x000000000000ff00) >> 8), - static_cast((size & 0x00000000000000ff) >> 0) + static_cast((size & 0xff00000000000000) >> 56), + static_cast((size & 0x00ff000000000000) >> 48), + static_cast((size & 0x0000ff0000000000) >> 40), + static_cast((size & 0x000000ff00000000) >> 32), + static_cast((size & 0x00000000ff000000) >> 24), + static_cast((size & 0x0000000000ff0000) >> 16), + static_cast((size & 0x000000000000ff00) >> 8), + static_cast((size & 0x00000000000000ff) >> 0) }; } - template - constexpr std::array make_remaining([[maybe_unused]] std::array const& input, [[maybe_unused]] size_t start_pos, std::index_sequence) noexcept + template + constexpr std::array make_remaining([[maybe_unused]] std::array const& input, [[maybe_unused]] std::size_t start_pos, std::index_sequence) noexcept { return { input[Index + start_pos]..., 0x80 }; } - template - constexpr auto make_remaining(std::array const& input, size_t start_pos) noexcept + template + constexpr auto make_remaining(std::array const& input, std::size_t start_pos) noexcept { constexpr auto remaining_size = Size % 64; return make_remaining(input, start_pos, std::make_index_sequence()); } - template - constexpr auto make_buffer(std::array const& remaining_buffer) noexcept + template + constexpr auto make_buffer(std::array const& remaining_buffer) noexcept { constexpr auto message_length = (RemainderSize + 8 <= 64) ? 64 : 64 * 2; constexpr auto padding_length = message_length - RemainderSize - 8; - auto padding_buffer = std::array{}; + auto padding_buffer = std::array{}; auto length_buffer = size_to_bytes(InputSize * 8); return combine(remaining_buffer, padding_buffer, length_buffer); } - template - constexpr std::array finalize_remaining_buffer(std::array const& input, std::array const& intermediate_hash) noexcept + template + constexpr std::array finalize_remaining_buffer(std::array const& input, std::array const& intermediate_hash) noexcept { if constexpr (Size == 64) { @@ -399,22 +399,22 @@ namespace winrt::impl } } - template - constexpr std::array get_result(std::array const& intermediate_hash, std::index_sequence) noexcept + template + constexpr std::array get_result(std::array const& intermediate_hash, std::index_sequence) noexcept { - return { static_cast(intermediate_hash[Index >> 2] >> (8 * (3 - (Index & 0x03))))... }; + return { static_cast(intermediate_hash[Index >> 2] >> (8 * (3 - (Index & 0x03))))... }; } - constexpr auto get_result(std::array const& intermediate_hash) noexcept + constexpr auto get_result(std::array const& intermediate_hash) noexcept { return get_result(intermediate_hash, std::make_index_sequence<20>{}); } - template - constexpr auto calculate_sha1(std::array const& input) noexcept + template + constexpr auto calculate_sha1(std::array const& input) noexcept { - std::array intermediate_hash{ 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }; - size_t i = 0; + std::array intermediate_hash{ 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }; + std::size_t i = 0; while (i + 64 <= Size) { @@ -426,7 +426,7 @@ namespace winrt::impl return get_result(intermediate_hash); } - template + template constexpr guid generate_guid(std::array const& value) noexcept { guid namespace_guid = { 0xd57af411, 0x737b, 0xc042,{ 0xab, 0xae, 0x87, 0x8b, 0x1e, 0x16, 0xad, 0xee } }; @@ -472,7 +472,7 @@ namespace winrt::impl ) }; - constexpr size_t to_utf8_size(wchar_t const value) noexcept + constexpr std::size_t to_utf8_size(wchar_t const value) noexcept { if (value <= 0x7F) { @@ -487,7 +487,7 @@ namespace winrt::impl return 3; } - constexpr size_t to_utf8(wchar_t const value, char* buffer) noexcept + constexpr std::size_t to_utf8(wchar_t const value, char* buffer) noexcept { if (value <= 0x7F) { @@ -509,10 +509,10 @@ namespace winrt::impl } template - constexpr size_t to_utf8_size() noexcept + constexpr std::size_t to_utf8_size() noexcept { auto input = to_array(name_v); - size_t length = 0; + std::size_t length = 0; for (wchar_t const element : input) { @@ -527,7 +527,7 @@ namespace winrt::impl { auto input = to_array(name_v); std::array()> output{}; - size_t offset{}; + std::size_t offset{}; for (wchar_t const element : input) { @@ -544,14 +544,14 @@ namespace winrt::impl constexpr auto& basic_signature_v = ""; template <> inline constexpr auto& basic_signature_v = "b1"; - template <> inline constexpr auto& basic_signature_v = "i1"; - template <> inline constexpr auto& basic_signature_v = "i2"; - template <> inline constexpr auto& basic_signature_v = "i4"; - template <> inline constexpr auto& basic_signature_v = "i8"; - template <> inline constexpr auto& basic_signature_v = "u1"; - template <> inline constexpr auto& basic_signature_v = "u2"; - template <> inline constexpr auto& basic_signature_v = "u4"; - template <> inline constexpr auto& basic_signature_v = "u8"; + template <> inline constexpr auto& basic_signature_v = "i1"; + template <> inline constexpr auto& basic_signature_v = "i2"; + template <> inline constexpr auto& basic_signature_v = "i4"; + template <> inline constexpr auto& basic_signature_v = "i8"; + template <> inline constexpr auto& basic_signature_v = "u1"; + template <> inline constexpr auto& basic_signature_v = "u2"; + template <> inline constexpr auto& basic_signature_v = "u4"; + template <> inline constexpr auto& basic_signature_v = "u8"; template <> inline constexpr auto& basic_signature_v = "f4"; template <> inline constexpr auto& basic_signature_v = "f8"; template <> inline constexpr auto& basic_signature_v = "c2"; @@ -560,14 +560,14 @@ namespace winrt::impl template <> inline constexpr auto& basic_signature_v = "cinterface(IInspectable)"; template <> inline constexpr auto& name_v = L"Boolean"; - template <> inline constexpr auto& name_v = L"Int8"; - template <> inline constexpr auto& name_v = L"Int16"; - template <> inline constexpr auto& name_v = L"Int32"; - template <> inline constexpr auto& name_v = L"Int64"; - template <> inline constexpr auto& name_v = L"UInt8"; - template <> inline constexpr auto& name_v = L"UInt16"; - template <> inline constexpr auto& name_v = L"UInt32"; - template <> inline constexpr auto& name_v = L"UInt64"; + template <> inline constexpr auto& name_v = L"Int8"; + template <> inline constexpr auto& name_v = L"Int16"; + template <> inline constexpr auto& name_v = L"Int32"; + template <> inline constexpr auto& name_v = L"Int64"; + template <> inline constexpr auto& name_v = L"UInt8"; + template <> inline constexpr auto& name_v = L"UInt16"; + template <> inline constexpr auto& name_v = L"UInt32"; + template <> inline constexpr auto& name_v = L"UInt64"; template <> inline constexpr auto& name_v = L"Single"; template <> inline constexpr auto& name_v = L"Double"; template <> inline constexpr auto& name_v = L"Char16"; @@ -581,23 +581,23 @@ namespace winrt::impl template <> inline constexpr auto& name_v = L"IAgileObject"; template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; - template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; + template <> struct category { using type = basic_category; }; template <> struct category { using type = basic_category; }; template <> struct category { using type = basic_category; }; template <> struct category { using type = basic_category; }; template <> struct category { using type = basic_category; }; - template <> struct category { using type = struct_category; }; - template <> struct category { using type = struct_category; }; + template <> struct category { using type = struct_category; }; + template <> struct category { using type = struct_category; }; template <> struct category { using type = basic_category; }; - template <> struct category { using type = struct_category; }; - template <> struct category { using type = struct_category; }; + template <> struct category { using type = struct_category; }; + template <> struct category { using type = struct_category; }; template struct category_signature @@ -642,13 +642,13 @@ namespace winrt::impl constexpr static auto data{ combine("delegate(", to_array(guid_of()), ")") }; }; - template + template constexpr std::wstring_view to_wstring_view(std::array const& value) noexcept { return { value.data(), Size - 1 }; } - template + template constexpr std::wstring_view to_wstring_view(wchar_t const (&value)[Size]) noexcept { return { value, Size - 1 }; diff --git a/strings/base_implements.h b/strings/base_implements.h index b943c1d96..7edf32149 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -216,11 +216,11 @@ namespace winrt::impl } template - void zero_abi([[maybe_unused]] void* ptr, [[maybe_unused]] uint32_t const capacity) noexcept + void zero_abi([[maybe_unused]] void* ptr, [[maybe_unused]] std::uint32_t const capacity) noexcept { if constexpr (!std::is_trivially_destructible_v) { - memset(ptr, 0, sizeof(T) * capacity); + std::memset(ptr, 0, sizeof(T) * capacity); } } @@ -229,7 +229,7 @@ namespace winrt::impl { if constexpr (!std::is_trivially_destructible_v) { - memset(ptr, 0, sizeof(T)); + std::memset(ptr, 0, sizeof(T)); } } } @@ -522,32 +522,32 @@ namespace winrt::impl return*static_cast(reinterpret_cast*>(this)); } - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept override + std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept override { return shim().QueryInterface(id, object); } - uint32_t __stdcall AddRef() noexcept override + std::uint32_t __stdcall AddRef() noexcept override { return shim().AddRef(); } - uint32_t __stdcall Release() noexcept override + std::uint32_t __stdcall Release() noexcept override { return shim().Release(); } - int32_t __stdcall GetIids(uint32_t* count, guid** array) noexcept override + std::int32_t __stdcall GetIids(std::uint32_t* count, guid** array) noexcept override { return shim().GetIids(reinterpret_cast(count), reinterpret_cast(array)); } - int32_t __stdcall GetRuntimeClassName(void** name) noexcept override + std::int32_t __stdcall GetRuntimeClassName(void** name) noexcept override { return shim().abi_GetRuntimeClassName(name); } - int32_t __stdcall GetTrustLevel(Windows::Foundation::TrustLevel* trustLevel) noexcept final + std::int32_t __stdcall GetTrustLevel(Windows::Foundation::TrustLevel* trustLevel) noexcept final { return shim().abi_GetTrustLevel(trustLevel); } @@ -579,27 +579,27 @@ namespace winrt::impl template struct produce : produce_base { - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final + std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final { return this->shim().NonDelegatingQueryInterface(id, object); } - uint32_t __stdcall AddRef() noexcept final + std::uint32_t __stdcall AddRef() noexcept final { return this->shim().NonDelegatingAddRef(); } - uint32_t __stdcall Release() noexcept final + std::uint32_t __stdcall Release() noexcept final { return this->shim().NonDelegatingRelease(); } - int32_t __stdcall GetIids(uint32_t* count, guid** array) noexcept final + std::int32_t __stdcall GetIids(std::uint32_t* count, guid** array) noexcept final { return this->shim().NonDelegatingGetIids(count, array); } - int32_t __stdcall GetRuntimeClassName(void** name) noexcept final + std::int32_t __stdcall GetRuntimeClassName(void** name) noexcept final { return this->shim().NonDelegatingGetRuntimeClassName(name); } @@ -619,7 +619,7 @@ namespace winrt::impl return static_cast*>(reinterpret_cast*>(this)); } - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final + std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final { if (is_guid_of(id)) { @@ -631,17 +631,17 @@ namespace winrt::impl return that()->m_object->QueryInterface(id, object); } - uint32_t __stdcall AddRef() noexcept final + std::uint32_t __stdcall AddRef() noexcept final { return that()->increment_strong(); } - uint32_t __stdcall Release() noexcept final + std::uint32_t __stdcall Release() noexcept final { return that()->m_object->Release(); } - int32_t __stdcall GetWeakReference(IWeakReference** weakReference) noexcept final + std::int32_t __stdcall GetWeakReference(IWeakReference** weakReference) noexcept final { *weakReference = that(); that()->AddRef(); @@ -659,14 +659,14 @@ namespace winrt::impl template struct weak_ref final : IWeakReference, weak_source_producer { - weak_ref(unknown_abi* object, uint32_t const strong) noexcept : + weak_ref(unknown_abi* object, std::uint32_t const strong) noexcept : m_object(object), m_strong(strong) { WINRT_ASSERT(object); } - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final + std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final { if (is_guid_of(id) || is_guid_of(id)) { @@ -694,14 +694,14 @@ namespace winrt::impl return error_no_interface; } - uint32_t __stdcall AddRef() noexcept final + std::uint32_t __stdcall AddRef() noexcept final { return 1 + m_weak.fetch_add(1, std::memory_order_relaxed); } - uint32_t __stdcall Release() noexcept final + std::uint32_t __stdcall Release() noexcept final { - uint32_t const target = m_weak.fetch_sub(1, std::memory_order_relaxed) - 1; + std::uint32_t const target = m_weak.fetch_sub(1, std::memory_order_relaxed) - 1; if (target == 0) { @@ -711,9 +711,9 @@ namespace winrt::impl return target; } - int32_t __stdcall Resolve(guid const& id, void** objectReference) noexcept final + std::int32_t __stdcall Resolve(guid const& id, void** objectReference) noexcept final { - uint32_t target = m_strong.load(std::memory_order_relaxed); + std::uint32_t target = m_strong.load(std::memory_order_relaxed); while (true) { @@ -725,26 +725,26 @@ namespace winrt::impl if (m_strong.compare_exchange_weak(target, target + 1, std::memory_order_acquire, std::memory_order_relaxed)) { - int32_t hr = m_object->QueryInterface(id, objectReference); + std::int32_t hr = m_object->QueryInterface(id, objectReference); m_strong.fetch_sub(1, std::memory_order_relaxed); return hr; } } } - void set_strong(uint32_t const count) noexcept + void set_strong(std::uint32_t const count) noexcept { m_strong = count; } - uint32_t increment_strong() noexcept + std::uint32_t increment_strong() noexcept { return 1 + m_strong.fetch_add(1, std::memory_order_relaxed); } - uint32_t decrement_strong() noexcept + std::uint32_t decrement_strong() noexcept { - uint32_t const target = m_strong.fetch_sub(1, std::memory_order_release) - 1; + std::uint32_t const target = m_strong.fetch_sub(1, std::memory_order_release) - 1; if (target == 0) { @@ -767,8 +767,8 @@ namespace winrt::impl static_assert(sizeof(weak_source_producer) == sizeof(weak_source)); unknown_abi* m_object{}; - std::atomic m_strong{ 1 }; - std::atomic m_weak{ 1 }; + std::atomic m_strong{ 1 }; + std::atomic m_weak{ 1 }; }; template @@ -842,14 +842,14 @@ namespace winrt::impl using IInspectable = Windows::Foundation::IInspectable; using root_implements_type = root_implements; - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept + std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept { if (this->outer()) { return this->outer()->QueryInterface(id, object); } - int32_t result = query_interface(id, object); + std::int32_t result = query_interface(id, object); if (result == error_no_interface && this->m_inner) { @@ -859,7 +859,7 @@ namespace winrt::impl return result; } - uint32_t __stdcall AddRef() noexcept + std::uint32_t __stdcall AddRef() noexcept { if (this->outer()) { @@ -869,7 +869,7 @@ namespace winrt::impl return NonDelegatingAddRef(); } - uint32_t __stdcall Release() noexcept + std::uint32_t __stdcall Release() noexcept { if (this->outer()) { @@ -907,7 +907,7 @@ namespace winrt::impl protected: - virtual int32_t query_interface_tearoff(guid const&, void**) const noexcept + virtual std::int32_t query_interface_tearoff(guid const&, void**) const noexcept { return error_no_interface; } @@ -922,7 +922,7 @@ namespace winrt::impl subtract_final_reference(); } - int32_t __stdcall GetIids(uint32_t* count, guid** array) noexcept + std::int32_t __stdcall GetIids(std::uint32_t* count, guid** array) noexcept { if (this->outer()) { @@ -932,7 +932,7 @@ namespace winrt::impl return NonDelegatingGetIids(count, array); } - int32_t __stdcall abi_GetRuntimeClassName(void** name) noexcept + std::int32_t __stdcall abi_GetRuntimeClassName(void** name) noexcept { if (this->outer()) { @@ -942,7 +942,7 @@ namespace winrt::impl return NonDelegatingGetRuntimeClassName(name); } - int32_t __stdcall abi_GetTrustLevel(Windows::Foundation::TrustLevel* trustLevel) noexcept + std::int32_t __stdcall abi_GetTrustLevel(Windows::Foundation::TrustLevel* trustLevel) noexcept { if (this->outer()) { @@ -952,11 +952,11 @@ namespace winrt::impl return NonDelegatingGetTrustLevel(trustLevel); } - uint32_t __stdcall NonDelegatingAddRef() noexcept + std::uint32_t __stdcall NonDelegatingAddRef() noexcept { if constexpr (is_weak_ref_source::value) { - uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); + std::uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); while (true) { @@ -965,11 +965,11 @@ namespace winrt::impl return decode_weak_ref(count_or_pointer)->increment_strong(); } - uintptr_t const target = count_or_pointer + 1; + std::uintptr_t const target = count_or_pointer + 1; if (m_references.compare_exchange_weak(count_or_pointer, target, std::memory_order_relaxed)) { - return static_cast(target); + return static_cast(target); } } } @@ -979,9 +979,9 @@ namespace winrt::impl } } - uint32_t __stdcall NonDelegatingRelease() noexcept + std::uint32_t __stdcall NonDelegatingRelease() noexcept { - uint32_t const target = subtract_reference(); + std::uint32_t const target = subtract_reference(); if (target == 0) { @@ -998,7 +998,7 @@ namespace winrt::impl return target; } - int32_t __stdcall NonDelegatingQueryInterface(guid const& id, void** object) noexcept + std::int32_t __stdcall NonDelegatingQueryInterface(guid const& id, void** object) noexcept { if (is_guid_of(id) || is_guid_of(id)) { @@ -1008,7 +1008,7 @@ namespace winrt::impl return 0; } - int32_t result = query_interface(id, object); + std::int32_t result = query_interface(id, object); if (result == error_no_interface && this->m_inner) { @@ -1018,10 +1018,10 @@ namespace winrt::impl return result; } - int32_t __stdcall NonDelegatingGetIids(uint32_t* count, guid** array) noexcept + std::int32_t __stdcall NonDelegatingGetIids(std::uint32_t* count, guid** array) noexcept { auto const& local_iids = static_cast(this)->get_local_iids(); - uint32_t const& local_count = local_iids.first; + std::uint32_t const& local_count = local_iids.first; if constexpr (root_implements_type::is_composing) { if (local_count > 0) @@ -1062,25 +1062,25 @@ namespace winrt::impl return 0; } - int32_t __stdcall NonDelegatingGetRuntimeClassName(void** name) noexcept try + std::int32_t __stdcall NonDelegatingGetRuntimeClassName(void** name) noexcept try { *name = detach_abi(static_cast(this)->GetRuntimeClassName()); return 0; } catch (...) { return to_hresult(); } - int32_t __stdcall NonDelegatingGetTrustLevel(Windows::Foundation::TrustLevel* trustLevel) noexcept try + std::int32_t __stdcall NonDelegatingGetTrustLevel(Windows::Foundation::TrustLevel* trustLevel) noexcept try { *trustLevel = static_cast(this)->GetTrustLevel(); return 0; } catch (...) { return to_hresult(); } - uint32_t subtract_final_reference() noexcept + std::uint32_t subtract_final_reference() noexcept { if constexpr (is_weak_ref_source::value) { - uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); + std::uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); while (true) { @@ -1089,11 +1089,11 @@ namespace winrt::impl return decode_weak_ref(count_or_pointer)->decrement_strong(); } - uintptr_t const target = count_or_pointer - 1; + std::uintptr_t const target = count_or_pointer - 1; if (m_references.compare_exchange_weak(count_or_pointer, target, std::memory_order_release, std::memory_order_relaxed)) { - return static_cast(target); + return static_cast(target); } } } @@ -1103,9 +1103,9 @@ namespace winrt::impl } } - uint32_t subtract_reference() noexcept + std::uint32_t subtract_reference() noexcept { - uint32_t result = subtract_final_reference(); + std::uint32_t result = subtract_final_reference(); if (result == 0) { @@ -1155,9 +1155,9 @@ namespace winrt::impl using use_module_lock = std::negation...>>; using weak_ref_t = impl::weak_ref; - std::atomic> m_references{ 1 }; + std::atomic> m_references{ 1 }; - int32_t query_interface(guid const& id, void** object) noexcept + std::int32_t query_interface(guid const& id, void** object) noexcept { *object = static_cast(this)->find_interface(id); @@ -1170,7 +1170,7 @@ namespace winrt::impl return query_interface_common(id, object); } - WINRT_IMPL_NOINLINE int32_t query_interface_common(guid const& id, void** object) noexcept + WINRT_IMPL_NOINLINE std::int32_t query_interface_common(guid const& id, void** object) noexcept { if (is_guid_of(id)) { @@ -1220,21 +1220,21 @@ namespace winrt::impl { if constexpr (is_weak_ref_source::value) { - uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); + std::uintptr_t count_or_pointer = m_references.load(std::memory_order_relaxed); if (is_weak_ref(count_or_pointer)) { return decode_weak_ref(count_or_pointer)->get_source(); } - com_ptr weak_ref(new (std::nothrow) weak_ref_t(get_unknown(), static_cast(count_or_pointer)), take_ownership_from_abi); + com_ptr weak_ref(new (std::nothrow) weak_ref_t(get_unknown(), static_cast(count_or_pointer)), take_ownership_from_abi); if (!weak_ref) { return nullptr; } - uintptr_t const encoding = encode_weak_ref(weak_ref.get()); + std::uintptr_t const encoding = encode_weak_ref(weak_ref.get()); while (true) { @@ -1250,7 +1250,7 @@ namespace winrt::impl return decode_weak_ref(count_or_pointer)->get_source(); } - weak_ref->set_strong(static_cast(count_or_pointer)); + weak_ref->set_strong(static_cast(count_or_pointer)); } } else @@ -1260,28 +1260,28 @@ namespace winrt::impl } } - static bool is_weak_ref(intptr_t const value) noexcept + static bool is_weak_ref(std::intptr_t const value) noexcept { static_assert(is_weak_ref_source::value, "Weak references are not supported because no_weak_ref was specified."); return value < 0; } - static weak_ref_t* decode_weak_ref(uintptr_t const value) noexcept + static weak_ref_t* decode_weak_ref(std::uintptr_t const value) noexcept { static_assert(is_weak_ref_source::value, "Weak references are not supported because no_weak_ref was specified."); return reinterpret_cast(value << 1); } - static uintptr_t encode_weak_ref(weak_ref_t* value) noexcept + static std::uintptr_t encode_weak_ref(weak_ref_t* value) noexcept { static_assert(is_weak_ref_source::value, "Weak references are not supported because no_weak_ref was specified."); - constexpr uintptr_t pointer_flag = static_cast(1) << ((sizeof(uintptr_t) * 8) - 1); - WINRT_ASSERT((reinterpret_cast(value) & 1) == 0); - return (reinterpret_cast(value) >> 1) | pointer_flag; + constexpr std::uintptr_t pointer_flag = static_cast(1) << ((sizeof(std::uintptr_t) * 8) - 1); + WINRT_ASSERT((reinterpret_cast(value) & 1) == 0); + return (reinterpret_cast(value) >> 1) | pointer_flag; } virtual unknown_abi* get_unknown() const noexcept = 0; - virtual std::pair get_local_iids() const noexcept = 0; + virtual std::pair get_local_iids() const noexcept = 0; virtual hstring GetRuntimeClassName() const = 0; virtual void* find_interface(guid const&) const noexcept = 0; virtual inspectable_abi* find_inspectable() const noexcept = 0; @@ -1528,7 +1528,7 @@ WINRT_EXPORT namespace winrt impl::hresult_type __stdcall GetIids(impl::count_type* count, impl::guid_type** iids) noexcept { - return root_implements_type::GetIids(reinterpret_cast(count), reinterpret_cast(iids)); + return root_implements_type::GetIids(reinterpret_cast(count), reinterpret_cast(iids)); } impl::hresult_type __stdcall GetRuntimeClassName(impl::hstring_type* value) noexcept @@ -1556,11 +1556,11 @@ WINRT_EXPORT namespace winrt return impl::find_inspectable(static_cast(this)); } - std::pair get_local_iids() const noexcept override + std::pair get_local_iids() const noexcept override { using interfaces = impl::uncloaked_interfaces; using local_iids = impl::uncloaked_iids; - return { static_cast(local_iids::value.size()), local_iids::value.data() }; + return { static_cast(local_iids::value.size()), local_iids::value.data() }; } private: diff --git a/strings/base_includes.h b/strings/base_includes.h index a3bf308d1..d6808792b 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -6,9 +6,14 @@ #include #include #include +#include +#include #include +#include +#include #include #include +#include #include #include #include diff --git a/strings/base_iterator.h b/strings/base_iterator.h index b0ad7836d..acb0ebd42 100644 --- a/strings/base_iterator.h +++ b/strings/base_iterator.h @@ -7,13 +7,13 @@ namespace winrt::impl using iterator_concept = std::random_access_iterator_tag; using iterator_category = std::input_iterator_tag; using value_type = decltype(std::declval().GetAt(0)); - using difference_type = ptrdiff_t; + using difference_type = std::ptrdiff_t; using pointer = void; using reference = value_type; fast_iterator() noexcept = default; - fast_iterator(T const& collection, uint32_t const index) noexcept : + fast_iterator(T const& collection, std::uint32_t const index) noexcept : m_collection(&collection), m_index(index) {} @@ -46,7 +46,7 @@ namespace winrt::impl fast_iterator& operator+=(difference_type n) noexcept { - m_index += static_cast(n); + m_index += static_cast(n); return *this; } @@ -78,7 +78,7 @@ namespace winrt::impl reference operator[](difference_type n) const { - return m_collection->GetAt(m_index + static_cast(n)); + return m_collection->GetAt(m_index + static_cast(n)); } bool operator==(fast_iterator const& other) const noexcept @@ -127,7 +127,7 @@ namespace winrt::impl private: T const* m_collection = nullptr; - uint32_t m_index = 0; + std::uint32_t m_index = 0; }; template diff --git a/strings/base_lock.h b/strings/base_lock.h index cf70a001a..a0d6261e4 100644 --- a/strings/base_lock.h +++ b/strings/base_lock.h @@ -117,7 +117,7 @@ WINRT_EXPORT namespace winrt return false; } - if (!WINRT_IMPL_SleepConditionVariableSRW(&m_cv, x.get(), static_cast(milliseconds), 0)) + if (!WINRT_IMPL_SleepConditionVariableSRW(&m_cv, x.get(), static_cast(milliseconds), 0)) { return predicate(); } diff --git a/strings/base_marshaler.h b/strings/base_marshaler.h index 359cf3b47..526f4d4c3 100644 --- a/strings/base_marshaler.h +++ b/strings/base_marshaler.h @@ -1,7 +1,7 @@ namespace winrt::impl { - inline int32_t make_marshaler(unknown_abi* outer, void** result) noexcept + inline std::int32_t make_marshaler(unknown_abi* outer, void** result) noexcept { struct marshaler final : IMarshal { @@ -10,7 +10,7 @@ namespace winrt::impl m_object.copy_from(object); } - int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final + std::int32_t __stdcall QueryInterface(guid const& id, void** object) noexcept final { if (is_guid_of(id)) { @@ -22,12 +22,12 @@ namespace winrt::impl return m_object->QueryInterface(id, object); } - uint32_t __stdcall AddRef() noexcept final + std::uint32_t __stdcall AddRef() noexcept final { return ++m_references; } - uint32_t __stdcall Release() noexcept final + std::uint32_t __stdcall Release() noexcept final { auto const remaining = --m_references; @@ -39,7 +39,7 @@ namespace winrt::impl return remaining; } - int32_t __stdcall GetUnmarshalClass(guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, guid* pCid) noexcept final + std::int32_t __stdcall GetUnmarshalClass(guid const& riid, void* pv, std::uint32_t dwDestContext, void* pvDestContext, std::uint32_t mshlflags, guid* pCid) noexcept final { if (m_marshaler) { @@ -49,7 +49,7 @@ namespace winrt::impl return error_bad_alloc; } - int32_t __stdcall GetMarshalSizeMax(guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags, uint32_t* pSize) noexcept final + std::int32_t __stdcall GetMarshalSizeMax(guid const& riid, void* pv, std::uint32_t dwDestContext, void* pvDestContext, std::uint32_t mshlflags, std::uint32_t* pSize) noexcept final { if (m_marshaler) { @@ -59,7 +59,7 @@ namespace winrt::impl return error_bad_alloc; } - int32_t __stdcall MarshalInterface(void* pStm, guid const& riid, void* pv, uint32_t dwDestContext, void* pvDestContext, uint32_t mshlflags) noexcept final + std::int32_t __stdcall MarshalInterface(void* pStm, guid const& riid, void* pv, std::uint32_t dwDestContext, void* pvDestContext, std::uint32_t mshlflags) noexcept final { if (m_marshaler) { @@ -69,7 +69,7 @@ namespace winrt::impl return error_bad_alloc; } - int32_t __stdcall UnmarshalInterface(void* pStm, guid const& riid, void** ppv) noexcept final + std::int32_t __stdcall UnmarshalInterface(void* pStm, guid const& riid, void** ppv) noexcept final { if (m_marshaler) { @@ -80,7 +80,7 @@ namespace winrt::impl return error_bad_alloc; } - int32_t __stdcall ReleaseMarshalData(void* pStm) noexcept final + std::int32_t __stdcall ReleaseMarshalData(void* pStm) noexcept final { if (m_marshaler) { @@ -90,7 +90,7 @@ namespace winrt::impl return error_bad_alloc; } - int32_t __stdcall DisconnectObject(uint32_t dwReserved) noexcept final + std::int32_t __stdcall DisconnectObject(std::uint32_t dwReserved) noexcept final { if (m_marshaler) { diff --git a/strings/base_natvis.h b/strings/base_natvis.h index 8ff4bd145..60c5f5548 100644 --- a/strings/base_natvis.h +++ b/strings/base_natvis.h @@ -15,19 +15,19 @@ namespace winrt::impl { bool b; wchar_t c; - int8_t i1; - int16_t i2; - int32_t i4; - int64_t i8; - uint8_t u1; - uint16_t u2; - uint32_t u4; - uint64_t u8; + std::int8_t i1; + std::int16_t i2; + std::int32_t i4; + std::int64_t i8; + std::uint8_t u1; + std::uint16_t u2; + std::uint32_t u4; + std::uint64_t u8; float r4; double r8; guid g; void* s; - uint8_t v[1024]; + std::uint8_t v[1024]; } value; value.s = 0; @@ -38,16 +38,16 @@ namespace winrt::impl { void* base_address; void* allocation_base; - uint32_t allocation_protect; + std::uint32_t allocation_protect; #ifdef _WIN64 - uint32_t __alignment1; + std::uint32_t __alignment1; #endif - uintptr_t region_size; - uint32_t state; - uint32_t protect; - uint32_t type; + std::uintptr_t region_size; + std::uint32_t state; + std::uint32_t protect; + std::uint32_t type; #ifdef _WIN64 - uint32_t __alignment2; + std::uint32_t __alignment2; #endif }; memory_basic_information info; @@ -66,7 +66,7 @@ namespace winrt::impl // validate method pointer is executable if ((WINRT_IMPL_VirtualQuery(vfunc, &info, sizeof(info)) != 0) && ((info.protect & 0xF0) != 0)) { - typedef int32_t(__stdcall inspectable_abi:: * PropertyAccessor)(void*); + typedef std::int32_t(__stdcall inspectable_abi:: * PropertyAccessor)(void*); (pinsp->**(PropertyAccessor*)&vfunc)(&value); pinsp->Release(); } diff --git a/strings/base_reference_produce.h b/strings/base_reference_produce.h index 8ea2de5b9..570ba42e0 100644 --- a/strings/base_reference_produce.h +++ b/strings/base_reference_produce.h @@ -23,39 +23,39 @@ namespace winrt::impl return std::is_arithmetic_v || std::is_enum_v; } - uint8_t GetUInt8() const + std::uint8_t GetUInt8() const { - return to_scalar(); + return to_scalar(); } - int16_t GetInt16() const + std::int16_t GetInt16() const { - return to_scalar(); + return to_scalar(); } - uint16_t GetUInt16() const + std::uint16_t GetUInt16() const { - return to_scalar(); + return to_scalar(); } - int32_t GetInt32() const + std::int32_t GetInt32() const { - return to_scalar(); + return to_scalar(); } - uint32_t GetUInt32() const + std::uint32_t GetUInt32() const { - return to_scalar(); + return to_scalar(); } - int64_t GetInt64() const + std::int64_t GetInt64() const { - return to_scalar(); + return to_scalar(); } - uint64_t GetUInt64() const + std::uint64_t GetUInt64() const { - return to_scalar(); + return to_scalar(); } float GetSingle() { throw hresult_not_implemented(); } @@ -69,13 +69,13 @@ namespace winrt::impl Windows::Foundation::Point GetPoint() { throw hresult_not_implemented(); } Windows::Foundation::Size GetSize() { throw hresult_not_implemented(); } Windows::Foundation::Rect GetRect() { throw hresult_not_implemented(); } - void GetUInt8Array(com_array &) { throw hresult_not_implemented(); } - void GetInt16Array(com_array &) { throw hresult_not_implemented(); } - void GetUInt16Array(com_array &) { throw hresult_not_implemented(); } - void GetInt32Array(com_array &) { throw hresult_not_implemented(); } - void GetUInt32Array(com_array &) { throw hresult_not_implemented(); } - void GetInt64Array(com_array &) { throw hresult_not_implemented(); } - void GetUInt64Array(com_array &) { throw hresult_not_implemented(); } + void GetUInt8Array(com_array &) { throw hresult_not_implemented(); } + void GetInt16Array(com_array &) { throw hresult_not_implemented(); } + void GetUInt16Array(com_array &) { throw hresult_not_implemented(); } + void GetInt32Array(com_array &) { throw hresult_not_implemented(); } + void GetUInt32Array(com_array &) { throw hresult_not_implemented(); } + void GetInt64Array(com_array &) { throw hresult_not_implemented(); } + void GetUInt64Array(com_array &) { throw hresult_not_implemented(); } void GetSingleArray(com_array &) { throw hresult_not_implemented(); } void GetDoubleArray(com_array &) { throw hresult_not_implemented(); } void GetChar16Array(com_array &) { throw hresult_not_implemented(); } @@ -115,52 +115,52 @@ namespace winrt::impl }; template <> - struct reference_traits + struct reference_traits { - static auto make(uint8_t value) { return Windows::Foundation::PropertyValue::CreateUInt8(value); } - using itf = Windows::Foundation::IReference; + static auto make(std::uint8_t value) { return Windows::Foundation::PropertyValue::CreateUInt8(value); } + using itf = Windows::Foundation::IReference; }; template <> - struct reference_traits + struct reference_traits { - static auto make(uint16_t value) { return Windows::Foundation::PropertyValue::CreateUInt16(value); } - using itf = Windows::Foundation::IReference; + static auto make(std::uint16_t value) { return Windows::Foundation::PropertyValue::CreateUInt16(value); } + using itf = Windows::Foundation::IReference; }; template <> - struct reference_traits + struct reference_traits { - static auto make(int16_t value) { return Windows::Foundation::PropertyValue::CreateInt16(value); } - using itf = Windows::Foundation::IReference; + static auto make(std::int16_t value) { return Windows::Foundation::PropertyValue::CreateInt16(value); } + using itf = Windows::Foundation::IReference; }; template <> - struct reference_traits + struct reference_traits { - static auto make(uint32_t value) { return Windows::Foundation::PropertyValue::CreateUInt32(value); } - using itf = Windows::Foundation::IReference; + static auto make(std::uint32_t value) { return Windows::Foundation::PropertyValue::CreateUInt32(value); } + using itf = Windows::Foundation::IReference; }; template <> - struct reference_traits + struct reference_traits { - static auto make(int32_t value) { return Windows::Foundation::PropertyValue::CreateInt32(value); } - using itf = Windows::Foundation::IReference; + static auto make(std::int32_t value) { return Windows::Foundation::PropertyValue::CreateInt32(value); } + using itf = Windows::Foundation::IReference; }; template <> - struct reference_traits + struct reference_traits { - static auto make(uint64_t value) { return Windows::Foundation::PropertyValue::CreateUInt64(value); } - using itf = Windows::Foundation::IReference; + static auto make(std::uint64_t value) { return Windows::Foundation::PropertyValue::CreateUInt64(value); } + using itf = Windows::Foundation::IReference; }; template <> - struct reference_traits + struct reference_traits { - static auto make(int64_t value) { return Windows::Foundation::PropertyValue::CreateInt64(value); } - using itf = Windows::Foundation::IReference; + static auto make(std::int64_t value) { return Windows::Foundation::PropertyValue::CreateInt64(value); } + using itf = Windows::Foundation::IReference; }; template <> @@ -255,52 +255,52 @@ namespace winrt::impl }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt8Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt8Array(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt16Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt16Array(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt16Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt16Array(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt32Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt32Array(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(com_array const& value) { return Windows::Foundation::PropertyValue::CreateUInt32Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(com_array const& value) { return Windows::Foundation::PropertyValue::CreateUInt32Array(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt64Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt64Array(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> - struct reference_traits> + struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt64Array(value); } - using itf = Windows::Foundation::IReferenceArray; + static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt64Array(value); } + using itf = Windows::Foundation::IReferenceArray; }; template <> diff --git a/strings/base_security.h b/strings/base_security.h index 8160f11ad..a912487e4 100644 --- a/strings/base_security.h +++ b/strings/base_security.h @@ -18,7 +18,7 @@ WINRT_EXPORT namespace winrt if (!WINRT_IMPL_OpenThreadToken(WINRT_IMPL_GetCurrentThread(), 0x0004 /*TOKEN_IMPERSONATE*/, 1, token.put())) { - uint32_t const error = WINRT_IMPL_GetLastError(); + std::uint32_t const error = WINRT_IMPL_GetLastError(); if (error != 1008 /*ERROR_NO_TOKEN*/) { diff --git a/strings/base_std_hash.h b/strings/base_std_hash.h index eb97db0e9..864c31b13 100644 --- a/strings/base_std_hash.h +++ b/strings/base_std_hash.h @@ -1,19 +1,19 @@ namespace winrt::impl { - inline size_t hash_data(void const* ptr, size_t const bytes) noexcept + inline std::size_t hash_data(void const* ptr, std::size_t const bytes) noexcept { #ifdef _WIN64 - constexpr size_t fnv_offset_basis = 14695981039346656037ULL; - constexpr size_t fnv_prime = 1099511628211ULL; + constexpr std::size_t fnv_offset_basis = 14695981039346656037ULL; + constexpr std::size_t fnv_prime = 1099511628211ULL; #else - constexpr size_t fnv_offset_basis = 2166136261U; - constexpr size_t fnv_prime = 16777619U; + constexpr std::size_t fnv_offset_basis = 2166136261U; + constexpr std::size_t fnv_prime = 16777619U; #endif - size_t result = fnv_offset_basis; - uint8_t const* const buffer = static_cast(ptr); + std::size_t result = fnv_offset_basis; + std::uint8_t const* const buffer = static_cast(ptr); - for (size_t next = 0; next < bytes; ++next) + for (std::size_t next = 0; next < bytes; ++next) { result ^= buffer[next]; result *= fnv_prime; @@ -24,7 +24,7 @@ namespace winrt::impl struct hash_base { - size_t operator()(Windows::Foundation::IUnknown const& value) const noexcept + std::size_t operator()(Windows::Foundation::IUnknown const& value) const noexcept { void* const abi_value = get_abi(value.try_as()); return std::hash{}(abi_value); @@ -36,7 +36,7 @@ namespace std { template<> struct hash { - size_t operator()(winrt::hstring const& value) const noexcept + std::size_t operator()(winrt::hstring const& value) const noexcept { return std::hash{}(value); } @@ -48,7 +48,7 @@ namespace std template<> struct hash { - size_t operator()(winrt::guid const& value) const noexcept + std::size_t operator()(winrt::guid const& value) const noexcept { return winrt::impl::hash_data(&value, sizeof(value)); } diff --git a/strings/base_string.h b/strings/base_string.h index 81229e3d5..c2ba6c742 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -5,21 +5,21 @@ namespace winrt::impl { atomic_ref_count() noexcept = default; - explicit atomic_ref_count(uint32_t count) noexcept : m_count(count) + explicit atomic_ref_count(std::uint32_t count) noexcept : m_count(count) { } - uint32_t operator=(uint32_t count) noexcept + std::uint32_t operator=(std::uint32_t count) noexcept { return m_count = count; } - uint32_t operator++() noexcept + std::uint32_t operator++() noexcept { - return static_cast(m_count.fetch_add(1, std::memory_order_relaxed) + 1); + return static_cast(m_count.fetch_add(1, std::memory_order_relaxed) + 1); } - uint32_t operator--() noexcept + std::uint32_t operator--() noexcept { auto const remaining = m_count.fetch_sub(1, std::memory_order_release) - 1; @@ -29,30 +29,30 @@ namespace winrt::impl } else if (remaining < 0) { - abort(); + std::abort(); } - return static_cast(remaining); + return static_cast(remaining); } - operator uint32_t() const noexcept + operator std::uint32_t() const noexcept { - return static_cast(m_count); + return static_cast(m_count); } private: - std::atomic m_count; + std::atomic m_count; }; - constexpr uint32_t hstring_reference_flag{ 1 }; + constexpr std::uint32_t hstring_reference_flag{ 1 }; struct hstring_header { - uint32_t flags; - uint32_t length; - uint32_t padding1; - uint32_t padding2; + std::uint32_t flags; + std::uint32_t length; + std::uint32_t padding1; + std::uint32_t padding2; wchar_t const* ptr; }; @@ -72,12 +72,12 @@ namespace winrt::impl } } - inline shared_hstring_header* precreate_hstring_on_heap(uint32_t length) + inline shared_hstring_header* precreate_hstring_on_heap(std::uint32_t length) { WINRT_ASSERT(length != 0); - uint64_t bytes_required = static_cast(sizeof(shared_hstring_header)) + static_cast(sizeof(wchar_t)) * static_cast(length); + std::uint64_t bytes_required = static_cast(sizeof(shared_hstring_header)) + static_cast(sizeof(wchar_t)) * static_cast(length); - if (bytes_required > UINT_MAX) + if (bytes_required > (std::numeric_limits::max)()) { throw std::invalid_argument("length"); } @@ -97,7 +97,7 @@ namespace winrt::impl return header; } - inline hstring_header* create_hstring_on_heap(wchar_t const* value, uint32_t length) + inline hstring_header* create_hstring_on_heap(wchar_t const* value, std::uint32_t length) { if (!length) { @@ -105,18 +105,18 @@ namespace winrt::impl } auto header = precreate_hstring_on_heap(length); - memcpy_s(header->buffer, sizeof(wchar_t) * length, value, sizeof(wchar_t) * length); + std::copy_n(value, length, header->buffer); return header; } - inline void create_hstring_on_stack(hstring_header& header, wchar_t const* value, uint32_t length) noexcept + inline void create_hstring_on_stack(hstring_header& header, wchar_t const* value, std::uint32_t length) noexcept { WINRT_ASSERT(value); WINRT_ASSERT(length != 0); if (value[length] != 0) { - abort(); + std::abort(); } header.flags = hstring_reference_flag; @@ -162,7 +162,7 @@ WINRT_EXPORT namespace winrt struct hstring { using value_type = wchar_t; - using size_type = uint32_t; + using size_type = std::uint32_t; using const_reference = value_type const&; using pointer = value_type*; using const_pointer = value_type const*; @@ -191,7 +191,7 @@ WINRT_EXPORT namespace winrt hstring& operator=(std::nullptr_t) = delete; hstring(std::initializer_list value) : - hstring(value.begin(), static_cast(value.size())) + hstring(value.begin(), static_cast(value.size())) {} hstring(wchar_t const* value) : @@ -428,12 +428,12 @@ WINRT_EXPORT namespace winrt inline void* detach_abi(std::wstring_view const& value) { - return impl::create_hstring_on_heap(value.data(), static_cast(value.size())); + return impl::create_hstring_on_heap(value.data(), static_cast(value.size())); } inline void* detach_abi(wchar_t const* const value) { - return impl::create_hstring_on_heap(value, static_cast(wcslen(value))); + return impl::create_hstring_on_heap(value, static_cast(std::wcslen(value))); } } @@ -459,7 +459,7 @@ namespace winrt::impl hstring_builder(hstring_builder const&) = delete; hstring_builder& operator=(hstring_builder const&) = delete; - explicit hstring_builder(uint32_t const size) : + explicit hstring_builder(std::uint32_t const size) : m_handle(impl::precreate_hstring_on_heap(size)) { } @@ -574,8 +574,8 @@ namespace winrt::impl // when non-const (e.g. ranges::filter_view) so taking a const reference // as parameter wouldn't work for all scenarios. auto const size = std::formatted_size(args...); - WINRT_ASSERT(size < INT_MAX); - auto const size32 = static_cast(size); + WINRT_ASSERT(size < static_cast((std::numeric_limits::max)())); + auto const size32 = static_cast(size); hstring_builder builder(size32); WINRT_VERIFY_(size32, std::format_to_n(builder.data(), size32, args...).size); @@ -608,42 +608,42 @@ WINRT_EXPORT namespace winrt }); } - inline hstring to_hstring(uint8_t value) + inline hstring to_hstring(std::uint8_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(int8_t value) + inline hstring to_hstring(std::int8_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(uint16_t value) + inline hstring to_hstring(std::uint16_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(int16_t value) + inline hstring to_hstring(std::int16_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(uint32_t value) + inline hstring to_hstring(std::uint32_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(int32_t value) + inline hstring to_hstring(std::int32_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(uint64_t value) + inline hstring to_hstring(std::uint64_t value) { return impl::hstring_convert(value); } - inline hstring to_hstring(int64_t value) + inline hstring to_hstring(std::int64_t value) { return impl::hstring_convert(value); } @@ -688,7 +688,7 @@ WINRT_EXPORT namespace winrt { wchar_t buffer[40]; //{00000000-0000-0000-0000-000000000000} - swprintf_s(buffer, L"{%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx}", + std::swprintf(buffer, std::size(buffer), L"{%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx}", value.Data1, value.Data2, value.Data3, value.Data4[0], value.Data4[1], value.Data4[2], value.Data4[3], value.Data4[4], value.Data4[5], value.Data4[6], value.Data4[7]); return hstring{ buffer }; @@ -698,7 +698,7 @@ WINRT_EXPORT namespace winrt hstring to_hstring(T const& value) { std::string_view const view(value); - int const size = WINRT_IMPL_MultiByteToWideChar(65001 /*CP_UTF8*/, 0, view.data(), static_cast(view.size()), nullptr, 0); + int const size = WINRT_IMPL_MultiByteToWideChar(65001 /*CP_UTF8*/, 0, view.data(), static_cast(view.size()), nullptr, 0); if (size == 0) { @@ -706,13 +706,13 @@ WINRT_EXPORT namespace winrt } impl::hstring_builder result(size); - WINRT_VERIFY_(size, WINRT_IMPL_MultiByteToWideChar(65001 /*CP_UTF8*/, 0, view.data(), static_cast(view.size()), result.data(), size)); + WINRT_VERIFY_(size, WINRT_IMPL_MultiByteToWideChar(65001 /*CP_UTF8*/, 0, view.data(), static_cast(view.size()), result.data(), size)); return result.to_hstring(); } inline std::string to_string(std::wstring_view value) { - int const size = WINRT_IMPL_WideCharToMultiByte(65001 /*CP_UTF8*/, 0, value.data(), static_cast(value.size()), nullptr, 0, nullptr, nullptr); + int const size = WINRT_IMPL_WideCharToMultiByte(65001 /*CP_UTF8*/, 0, value.data(), static_cast(value.size()), nullptr, 0, nullptr, nullptr); if (size == 0) { @@ -720,7 +720,7 @@ WINRT_EXPORT namespace winrt } std::string result(size, '?'); - WINRT_VERIFY_(size, WINRT_IMPL_WideCharToMultiByte(65001 /*CP_UTF8*/, 0, value.data(), static_cast(value.size()), result.data(), size, nullptr, nullptr)); + WINRT_VERIFY_(size, WINRT_IMPL_WideCharToMultiByte(65001 /*CP_UTF8*/, 0, value.data(), static_cast(value.size()), result.data(), size, nullptr, nullptr)); return result; } } diff --git a/strings/base_string_input.h b/strings/base_string_input.h index 8cfea212b..5ac0221f6 100644 --- a/strings/base_string_input.h +++ b/strings/base_string_input.h @@ -30,7 +30,7 @@ WINRT_EXPORT namespace winrt::param hstring(wchar_t const* const value) noexcept { - create_string_reference(value, wcslen(value)); + create_string_reference(value, std::wcslen(value)); } operator winrt::hstring const&() const noexcept @@ -39,10 +39,10 @@ WINRT_EXPORT namespace winrt::param } private: - void create_string_reference(wchar_t const* const data, size_t size) noexcept + void create_string_reference(wchar_t const* const data, std::size_t size) noexcept { - WINRT_ASSERT(size < UINT_MAX); - auto size32 = static_cast(size); + WINRT_ASSERT(size < (std::numeric_limits::max)()); + auto size32 = static_cast(size); if (size32 == 0) { diff --git a/strings/base_string_operators.h b/strings/base_string_operators.h index b00150f92..25e2eccce 100644 --- a/strings/base_string_operators.h +++ b/strings/base_string_operators.h @@ -98,14 +98,14 @@ namespace winrt::impl { inline hstring concat_hstring(std::wstring_view const& left, std::wstring_view const& right) { - auto size = static_cast(left.size() + right.size()); + auto size = static_cast(left.size() + right.size()); if (size == 0) { return{}; } hstring_builder text(size); - memcpy_s(text.data(), left.size() * sizeof(wchar_t), left.data(), left.size() * sizeof(wchar_t)); - memcpy_s(text.data() + left.size(), right.size() * sizeof(wchar_t), right.data(), right.size() * sizeof(wchar_t)); + std::copy_n(left.data(), left.size(), text.data()); + std::copy_n(right.data(), right.size(), text.data() + left.size()); return text.to_hstring(); } } diff --git a/strings/base_types.h b/strings/base_types.h index 84cf22f5d..18529e116 100644 --- a/strings/base_types.h +++ b/strings/base_types.h @@ -14,25 +14,25 @@ namespace winrt::impl struct com_callback_args { - uint32_t reserved1; - uint32_t reserved2; + std::uint32_t reserved1; + std::uint32_t reserved2; void* data; }; template - constexpr uint8_t hex_to_uint(T const c) + constexpr std::uint8_t hex_to_uint(T const c) { if (c >= '0' && c <= '9') { - return static_cast(c - '0'); + return static_cast(c - '0'); } else if (c >= 'A' && c <= 'F') { - return static_cast(10 + c - 'A'); + return static_cast(10 + c - 'A'); } else if (c >= 'a' && c <= 'f') { - return static_cast(10 + c - 'a'); + return static_cast(10 + c - 'a'); } else { @@ -41,20 +41,20 @@ namespace winrt::impl } template - constexpr uint8_t hex_to_uint8(T const a, T const b) + constexpr std::uint8_t hex_to_uint8(T const a, T const b) { return (hex_to_uint(a) << 4) | hex_to_uint(b); } - constexpr uint16_t uint8_to_uint16(uint8_t a, uint8_t b) + constexpr std::uint16_t uint8_to_uint16(std::uint8_t a, std::uint8_t b) { - return (static_cast(a) << 8) | static_cast(b); + return (static_cast(a) << 8) | static_cast(b); } - constexpr uint32_t uint8_to_uint32(uint8_t a, uint8_t b, uint8_t c, uint8_t d) + constexpr std::uint32_t uint8_to_uint32(std::uint8_t a, std::uint8_t b, std::uint8_t c, std::uint8_t d) { - return (static_cast(uint8_to_uint16(a, b)) << 16) | - static_cast(uint8_to_uint16(c, d)); + return (static_cast(uint8_to_uint16(a, b)) << 16) | + static_cast(uint8_to_uint16(c, d)); } } @@ -66,15 +66,15 @@ WINRT_EXPORT namespace winrt struct hresult { - int32_t value{}; + std::int32_t value{}; constexpr hresult() noexcept = default; - constexpr hresult(int32_t const value) noexcept : value(value) + constexpr hresult(std::int32_t const value) noexcept : value(value) { } - constexpr operator int32_t() const noexcept + constexpr operator std::int32_t() const noexcept { return value; } @@ -133,14 +133,14 @@ WINRT_EXPORT namespace winrt public: - uint32_t Data1; - uint16_t Data2; - uint16_t Data3; - uint8_t Data4[8]; + std::uint32_t Data1; + std::uint16_t Data2; + std::uint16_t Data3; + std::uint8_t Data4[8]; guid() noexcept = default; - constexpr guid(uint32_t const Data1, uint16_t const Data2, uint16_t const Data3, std::array const& Data4) noexcept : + constexpr guid(std::uint32_t const Data1, std::uint16_t const Data2, std::uint16_t const Data3, std::array const& Data4) noexcept : Data1(Data1), Data2(Data2), Data3(Data3), @@ -178,7 +178,7 @@ WINRT_EXPORT namespace winrt inline bool operator==(guid const& left, guid const& right) noexcept { - return !memcmp(&left, &right, sizeof(left)); + return !std::memcmp(&left, &right, sizeof(left)); } inline bool operator!=(guid const& left, guid const& right) noexcept @@ -188,13 +188,13 @@ WINRT_EXPORT namespace winrt inline bool operator<(guid const& left, guid const& right) noexcept { - return memcmp(&left, &right, sizeof(left)) < 0; + return std::memcmp(&left, &right, sizeof(left)) < 0; } } WINRT_EXPORT namespace winrt::Windows::Foundation { - enum class TrustLevel : int32_t + enum class TrustLevel : std::int32_t { BaseTrust, PartialTrust, @@ -204,7 +204,7 @@ WINRT_EXPORT namespace winrt::Windows::Foundation struct IUnknown; struct IInspectable; struct IActivationFactory; - using TimeSpan = std::chrono::duration; + using TimeSpan = std::chrono::duration; using DateTime = std::chrono::time_point; } @@ -215,8 +215,8 @@ namespace winrt::impl using count_type = unsigned long; using guid_type = GUID; #else - using hresult_type = int32_t; - using count_type = uint32_t; + using hresult_type = std::int32_t; + using count_type = std::uint32_t; using guid_type = guid; #endif diff --git a/strings/base_version.h b/strings/base_version.h index adb3608da..4a6b68e66 100644 --- a/strings/base_version.h +++ b/strings/base_version.h @@ -16,7 +16,7 @@ char const * const WINRT_version = "C++/WinRT version:" CPPWINRT_VERSION; WINRT_EXPORT namespace winrt { - template + template constexpr bool check_version(char const(&base)[BaseSize], char const(&component)[ComponentSize]) noexcept { if constexpr (BaseSize != ComponentSize) @@ -24,7 +24,7 @@ WINRT_EXPORT namespace winrt return false; } - for (size_t i = 0; i != BaseSize - 1; ++i) + for (std::size_t i = 0; i != BaseSize - 1; ++i) { if (base[i] != component[i]) { diff --git a/strings/base_windows.h b/strings/base_windows.h index 831e1b1fe..21c4163e5 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -6,12 +6,12 @@ namespace winrt::impl struct factory_diagnostics_info { bool is_agile{ true }; - uint32_t requests{ 0 }; + std::uint32_t requests{ 0 }; }; struct diagnostics_info { - std::map queries; + std::map queries; std::map factories; }; @@ -163,7 +163,7 @@ WINRT_EXPORT namespace winrt::Windows::Foundation { IUnknown() noexcept = default; IUnknown(std::nullptr_t) noexcept {} - void* operator new(size_t) = delete; + void* operator new(std::size_t) = delete; IUnknown(void* ptr, take_ownership_from_abi_t) noexcept : m_ptr(static_cast(ptr)) { diff --git a/strings/base_xaml_component_connector.h b/strings/base_xaml_component_connector.h index 366e18e22..092944613 100644 --- a/strings/base_xaml_component_connector.h +++ b/strings/base_xaml_component_connector.h @@ -17,7 +17,7 @@ WINRT_EXPORT namespace winrt::Windows::UI::Xaml::Markup D::InitializeComponent(); } - void Connect(int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) + void Connect(std::int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) { if constexpr (m_has_connectable_base) { @@ -30,7 +30,7 @@ WINRT_EXPORT namespace winrt::Windows::UI::Xaml::Markup D::Connect(connectionId, target); } - auto GetBindingConnector(int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) + auto GetBindingConnector(std::int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) { if constexpr (m_has_connectable_base) { diff --git a/strings/base_xaml_component_connector_winui.h b/strings/base_xaml_component_connector_winui.h index 4a1f0326a..312f5af29 100644 --- a/strings/base_xaml_component_connector_winui.h +++ b/strings/base_xaml_component_connector_winui.h @@ -17,7 +17,7 @@ WINRT_EXPORT namespace winrt::Microsoft::UI::Xaml::Markup D::InitializeComponent(); } - void Connect(int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) + void Connect(std::int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) { if constexpr (m_has_connectable_base) { @@ -30,7 +30,7 @@ WINRT_EXPORT namespace winrt::Microsoft::UI::Xaml::Markup D::Connect(connectionId, target); } - auto GetBindingConnector(int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) + auto GetBindingConnector(std::int32_t connectionId, winrt::Windows::Foundation::IInspectable const& target) { if constexpr (m_has_connectable_base) { diff --git a/strings/base_xaml_typename.h b/strings/base_xaml_typename.h index 4a782fc72..b7b3a954a 100644 --- a/strings/base_xaml_typename.h +++ b/strings/base_xaml_typename.h @@ -66,42 +66,42 @@ namespace winrt::impl static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; template<> - struct xaml_typename_kind + struct xaml_typename_kind { static constexpr Windows::UI::Xaml::Interop::TypeKind value = Windows::UI::Xaml::Interop::TypeKind::Primitive; }; From b9553a9f0faf9a1395ac98aea65716c6f44e9fca Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Thu, 19 Mar 2026 11:27:29 -0700 Subject: [PATCH 70/91] Fix race condition in multi_threaded_observable_map test (#1550) * Fix race condition in multi_threaded_observable_map test * Hook the other iterator movement methods. --- test/test/multi_threaded_common.h | 15 +++++++++++++-- test/test/multi_threaded_map.cpp | 4 ++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/test/test/multi_threaded_common.h b/test/test/multi_threaded_common.h index 026cb3264..3ed687743 100644 --- a/test/test/multi_threaded_common.h +++ b/test/test/multi_threaded_common.h @@ -45,7 +45,7 @@ namespace concurrent_collections // for the first time on the background thread. enum class collection_action { - none, push_back, insert, erase, at, lookup + none, push_back, insert, erase, at, lookup, advance }; // All of our concurrency tests consists of starting an @@ -165,16 +165,23 @@ namespace concurrent_collections return owner->dereference_iterator(inner()); } - // inherited: pointer operator->() const; + pointer operator->() const + { + auto guard = owner->lock_const(); + owner->call_hook(collection_action::at); + return iterator::operator->(); + } concurrency_checked_random_access_iterator& operator++() { + owner->call_hook(collection_action::advance); ++inner(); return *this; } concurrency_checked_random_access_iterator& operator++(int) { + owner->call_hook(collection_action::advance); auto prev = *this; ++inner(); return prev; @@ -182,12 +189,14 @@ namespace concurrent_collections concurrency_checked_random_access_iterator& operator--() { + owner->call_hook(collection_action::advance); --inner(); return *this; } concurrency_checked_random_access_iterator& operator--(int) { + owner->call_hook(collection_action::advance); auto prev = *this; --inner(); return prev; @@ -195,6 +204,7 @@ namespace concurrent_collections concurrency_checked_random_access_iterator& operator+=(difference_type offset) { + owner->call_hook(collection_action::advance); inner() += offset; return *this; } @@ -206,6 +216,7 @@ namespace concurrent_collections concurrency_checked_random_access_iterator& operator-=(difference_type offset) { + owner->call_hook(collection_action::advance); inner() -= offset; return *this; } diff --git a/test/test/multi_threaded_map.cpp b/test/test/multi_threaded_map.cpp index d0f68c1e2..ffa9988ba 100644 --- a/test/test/multi_threaded_map.cpp +++ b/test/test/multi_threaded_map.cpp @@ -237,7 +237,7 @@ namespace { // MoveNext vs Remove bool moved = false; - race(collection_action::at, [&] + race(collection_action::advance, [&] { try { @@ -273,7 +273,7 @@ namespace { // MoveNext vs Insert bool moved = false; - race(collection_action::at, [&] + race(collection_action::advance, [&] { try { From 16a1c29b5351ca5212f4235d1db5776bdd13ae78 Mon Sep 17 00:00:00 2001 From: Charles Milette Date: Mon, 23 Mar 2026 12:46:53 -0400 Subject: [PATCH 71/91] Fix integer fields causing impl promotion (#1551) --- cppwinrt/code_writers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 0a4c4638e..fc5081bef 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -2916,7 +2916,7 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable for (auto&& field : type.fields) { - if (field.second.find(':') == std::string::npos) + if (field.second.find(':') == std::string::npos || starts_with(field.second, "std::")) { continue; } From 3893ce8c3d0af7676c36f5f933707d442c53050b Mon Sep 17 00:00:00 2001 From: justanotheranonymoususer Date: Thu, 2 Apr 2026 02:00:22 +0300 Subject: [PATCH 72/91] box_value constructor: Replace param::hstring with hstring (#1530) * box_value constructor: Replace param::hstring with hstring * Update base_reference_produce.h * Fix and add tests * Fix github.dev bug --- strings/base_reference_produce.h | 7 +++-- test/test/box_string.cpp | 53 ++++++++++++++++++++++++++++++++ test/test/test.vcxproj | 1 + 3 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 test/test/box_string.cpp diff --git a/strings/base_reference_produce.h b/strings/base_reference_produce.h index 570ba42e0..2820aff50 100644 --- a/strings/base_reference_produce.h +++ b/strings/base_reference_produce.h @@ -509,12 +509,13 @@ namespace winrt::impl WINRT_EXPORT namespace winrt { - inline Windows::Foundation::IInspectable box_value(param::hstring const& value) + template , int> = 0> + Windows::Foundation::IInspectable box_value(T&& value) { - return Windows::Foundation::IReference(*(hstring*)(&value)); + return Windows::Foundation::IReference(hstring(std::forward(value))); } - template , int> = 0> + template , int> = 0> Windows::Foundation::IInspectable box_value(T const& value) { if constexpr (std::is_base_of_v) diff --git a/test/test/box_string.cpp b/test/test/box_string.cpp new file mode 100644 index 000000000..efff92160 --- /dev/null +++ b/test/test/box_string.cpp @@ -0,0 +1,53 @@ +#include "pch.h" + +TEST_CASE("box_string") +{ + // hstring + { + winrt::hstring value = L"hstring"; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"hstring"); + } + + // wchar_t const* (string literal) + { + auto boxed = winrt::box_value(L"literal"); + REQUIRE(winrt::unbox_value(boxed) == L"literal"); + } + + // std::wstring + { + std::wstring value = L"wstring"; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"wstring"); + } + + // std::wstring_view (null-terminated) + { + std::wstring_view value = L"view"; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"view"); + } + + // std::wstring_view (not null-terminated) + // Regression test for https://github.com/microsoft/cppwinrt/issues/1527 + { + std::wstring source = L"ABCDE"; + std::wstring_view value(source.data(), 3); // "ABC" + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"ABC"); + } + + // Empty string + { + auto boxed = winrt::box_value(winrt::hstring{}); + REQUIRE(winrt::unbox_value(boxed) == L""); + } + + // Empty wstring_view + { + std::wstring_view value; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L""); + } +} diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index 7840f17eb..43928dab2 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -233,6 +233,7 @@ + NotUsing From d254f72ed6d4060f0028221e3e59ee1b2f5e6efc Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 16:23:17 -0700 Subject: [PATCH 73/91] fix: normalize CRLF to LF in test/test/box_string.cpp (#1557) * Initial plan * fix: convert CRLF to LF in test/test/box_string.cpp Agent-Logs-Url: https://github.com/microsoft/cppwinrt/sessions/9b31d4ec-f1c5-4859-89a1-3249eb553c5c Co-authored-by: DefaultRyan <26174284+DefaultRyan@users.noreply.github.com> * Add workflow to check line endings in pull requests --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: DefaultRyan <26174284+DefaultRyan@users.noreply.github.com> Co-authored-by: Ryan Shepherd --- .github/workflows/check-line-endings.yml | 32 +++++++ test/test/box_string.cpp | 106 +++++++++++------------ 2 files changed, 85 insertions(+), 53 deletions(-) create mode 100644 .github/workflows/check-line-endings.yml diff --git a/.github/workflows/check-line-endings.yml b/.github/workflows/check-line-endings.yml new file mode 100644 index 000000000..a0705cf58 --- /dev/null +++ b/.github/workflows/check-line-endings.yml @@ -0,0 +1,32 @@ +name: Check Line Endings + +on: + pull_request: + push: + branches: + - master + +jobs: + check-line-endings: + name: Enforce .gitattributes line endings + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Check for line ending violations + run: | + # Re-normalize all files according to .gitattributes + git add --renormalize . + + # Check if renormalization changed anything + if git diff --cached --name-only | grep -q .; then + echo "::error::The following files have line endings that don't match .gitattributes settings:" + git diff --cached --name-only + echo "" + echo "To fix, run:" + echo " git add --renormalize ." + echo " git commit -m 'Normalize line endings'" + exit 1 + fi + + echo "All files have correct line endings." diff --git a/test/test/box_string.cpp b/test/test/box_string.cpp index efff92160..7294eeb79 100644 --- a/test/test/box_string.cpp +++ b/test/test/box_string.cpp @@ -1,53 +1,53 @@ -#include "pch.h" - -TEST_CASE("box_string") -{ - // hstring - { - winrt::hstring value = L"hstring"; - auto boxed = winrt::box_value(value); - REQUIRE(winrt::unbox_value(boxed) == L"hstring"); - } - - // wchar_t const* (string literal) - { - auto boxed = winrt::box_value(L"literal"); - REQUIRE(winrt::unbox_value(boxed) == L"literal"); - } - - // std::wstring - { - std::wstring value = L"wstring"; - auto boxed = winrt::box_value(value); - REQUIRE(winrt::unbox_value(boxed) == L"wstring"); - } - - // std::wstring_view (null-terminated) - { - std::wstring_view value = L"view"; - auto boxed = winrt::box_value(value); - REQUIRE(winrt::unbox_value(boxed) == L"view"); - } - - // std::wstring_view (not null-terminated) - // Regression test for https://github.com/microsoft/cppwinrt/issues/1527 - { - std::wstring source = L"ABCDE"; - std::wstring_view value(source.data(), 3); // "ABC" - auto boxed = winrt::box_value(value); - REQUIRE(winrt::unbox_value(boxed) == L"ABC"); - } - - // Empty string - { - auto boxed = winrt::box_value(winrt::hstring{}); - REQUIRE(winrt::unbox_value(boxed) == L""); - } - - // Empty wstring_view - { - std::wstring_view value; - auto boxed = winrt::box_value(value); - REQUIRE(winrt::unbox_value(boxed) == L""); - } -} +#include "pch.h" + +TEST_CASE("box_string") +{ + // hstring + { + winrt::hstring value = L"hstring"; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"hstring"); + } + + // wchar_t const* (string literal) + { + auto boxed = winrt::box_value(L"literal"); + REQUIRE(winrt::unbox_value(boxed) == L"literal"); + } + + // std::wstring + { + std::wstring value = L"wstring"; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"wstring"); + } + + // std::wstring_view (null-terminated) + { + std::wstring_view value = L"view"; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"view"); + } + + // std::wstring_view (not null-terminated) + // Regression test for https://github.com/microsoft/cppwinrt/issues/1527 + { + std::wstring source = L"ABCDE"; + std::wstring_view value(source.data(), 3); // "ABC" + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L"ABC"); + } + + // Empty string + { + auto boxed = winrt::box_value(winrt::hstring{}); + REQUIRE(winrt::unbox_value(boxed) == L""); + } + + // Empty wstring_view + { + std::wstring_view value; + auto boxed = winrt::box_value(value); + REQUIRE(winrt::unbox_value(boxed) == L""); + } +} From f23b41e92176052bff519f00d44f6497e0845413 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Thu, 2 Apr 2026 16:46:32 -0700 Subject: [PATCH 74/91] Breaking coroutines means v3.0 (#1547) * Start moving to v3.0 * Set more obvious placeholder version numbers --- .github/workflows/ci.yml | 8 ++++---- .pipelines/OneBranch.Official.yml | 2 +- .pipelines/OneBranch.PullRequest.yml | 2 +- .pipelines/variables/version.yml | 2 +- CMakeLists.txt | 4 ++-- Directory.Build.Props | 2 +- build_nuget.cmd | 2 +- build_test_all.cmd | 2 +- build_vsix.cmd | 2 +- prebuild/main.cpp | 18 ++++++++++++++---- 10 files changed, 27 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a42f2c5b7..cb8cafd2b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,7 @@ jobs: run: | $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" - $target_version = "1.2.3.4" + $target_version = "999.999.999.999" $props = "Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" if ("${{ matrix.compiler }}" -eq "clang-cl") { $props += ",Clang=1,PlatformToolset=ClangCl" @@ -134,7 +134,7 @@ jobs: run: | $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" - $target_version = "1.2.3.4" + $target_version = "999.999.999.999" $props = "Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" if ("${{ matrix.compiler }}" -eq "clang-cl") { $props += ",Clang=1,PlatformToolset=ClangCl" @@ -301,7 +301,7 @@ jobs: run: | $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" - $target_version = "1.2.3.4" + $target_version = "999.999.999.999" Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" - name: Restore nuget packages @@ -347,7 +347,7 @@ jobs: run: | $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" - $target_version = "1.2.3.4" + $target_version = "999.999.999.999" Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" - name: Restore nuget packages diff --git a/.pipelines/OneBranch.Official.yml b/.pipelines/OneBranch.Official.yml index 7a73b263b..158d3bf4e 100644 --- a/.pipelines/OneBranch.Official.yml +++ b/.pipelines/OneBranch.Official.yml @@ -12,7 +12,7 @@ variables: parameters: debug: ${{ parameters.debug }} -name: 2.0.$(date:yyMMdd)$(rev:.r) +name: 3.0.$(date:yyMMdd)$(rev:.r) trigger: none diff --git a/.pipelines/OneBranch.PullRequest.yml b/.pipelines/OneBranch.PullRequest.yml index 9e18821b4..d92dccaa2 100644 --- a/.pipelines/OneBranch.PullRequest.yml +++ b/.pipelines/OneBranch.PullRequest.yml @@ -10,7 +10,7 @@ variables: parameters: debug: ${{ parameters.debug }} -name: PullRequest_2.0.$(date:yyMMdd)$(rev:.r) +name: PullRequest_3.0.$(date:yyMMdd)$(rev:.r) trigger: none diff --git a/.pipelines/variables/version.yml b/.pipelines/variables/version.yml index 15382e7df..46a535ee0 100644 --- a/.pipelines/variables/version.yml +++ b/.pipelines/variables/version.yml @@ -4,7 +4,7 @@ parameters: default: false variables: - MajorVersion: "2" + MajorVersion: "3" MinorVersion: "0" VersionDate: $[format('{0:yyMMdd}', pipeline.startTime)] VersionCounter: $[counter(variables['VersionDate'], 1)] diff --git a/CMakeLists.txt b/CMakeLists.txt index 139da8379..b0089e7ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,8 +13,8 @@ project(cppwinrt LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) -set(CPPWINRT_BUILD_VERSION "2.3.4.5" CACHE STRING "The version string used for cppwinrt.") -if(CPPWINRT_BUILD_VERSION STREQUAL "2.3.4.5" OR CPPWINRT_BUILD_VERSION STREQUAL "0.0.0.0") +set(CPPWINRT_BUILD_VERSION "999.999.999.999" CACHE STRING "The version string used for cppwinrt.") +if(CPPWINRT_BUILD_VERSION STREQUAL "999.999.999.999" OR CPPWINRT_BUILD_VERSION STREQUAL "0.0.0.0") message(WARNING "CPPWINRT_BUILD_VERSION has been set to a dummy version string. Do not use in production!") endif() message(STATUS "Using version string: ${CPPWINRT_BUILD_VERSION}") diff --git a/Directory.Build.Props b/Directory.Build.Props index 5f530da91..c98cd5dd0 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -37,7 +37,7 @@ - 2.3.4.5 + 999.999.999.999 $(Platform) x86 $(SolutionDir)_build\$(CppWinRTPlatform)\$(Configuration)\ diff --git a/build_nuget.cmd b/build_nuget.cmd index 3926e4d0b..99e193311 100644 --- a/build_nuget.cmd +++ b/build_nuget.cmd @@ -1,7 +1,7 @@ rem @echo off set target_version=%1 -if "%target_version%"=="" set target_version=3.0.0.0 +if "%target_version%"=="" set target_version=999.999.999.999 call msbuild /m /p:Configuration=Release,Platform=x86,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd call msbuild /m /p:Configuration=Release,Platform=x64,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:fast_fwd diff --git a/build_test_all.cmd b/build_test_all.cmd index 649f4dc69..c9beb852c 100644 --- a/build_test_all.cmd +++ b/build_test_all.cmd @@ -7,7 +7,7 @@ set clean_intermediate_files=%4 if "%target_platform%"=="" set target_platform=x64 if "%target_configuration%"=="" set target_configuration=Release -if "%target_version%"=="" set target_version=1.2.3.4 +if "%target_version%"=="" set target_version=999.999.999.999 if not exist ".\.nuget" mkdir ".\.nuget" if not exist ".\.nuget\nuget.exe" powershell -Command "$ProgressPreference = 'SilentlyContinue' ; Invoke-WebRequest https://dist.nuget.org/win-x86-commandline/latest/nuget.exe -OutFile .\.nuget\nuget.exe" diff --git a/build_vsix.cmd b/build_vsix.cmd index aefc84df1..0a47f6bd6 100644 --- a/build_vsix.cmd +++ b/build_vsix.cmd @@ -6,7 +6,7 @@ set target_version=%2 set target_deployment=%3 if "%target_configuration%"=="" set target_configuration=Release -if "%target_version%"=="" set target_version=1.2.3.4 +if "%target_version%"=="" set target_version=999.999.999.999 if "%target_deployment%"=="" set target_deployment=Standalone if not exist ".\.nuget" mkdir ".\.nuget" diff --git a/prebuild/main.cpp b/prebuild/main.cpp index 3e427d32b..1295f8f69 100644 --- a/prebuild/main.cpp +++ b/prebuild/main.cpp @@ -77,12 +77,19 @@ namespace cppwinrt::strings { writer version_rc; + // Extract major.minor substrings from CPPWINRT_VERSION_STRING (e.g. "3.0.250316.1") + std::string_view const full_version{ CPPWINRT_VERSION_STRING }; + auto const first_dot = full_version.find('.'); + auto const second_dot = full_version.find('.', first_dot + 1); + auto const ver_major = full_version.substr(0, first_dot); + auto const ver_minor = full_version.substr(first_dot + 1, second_dot - first_dot - 1); + version_rc.write(R"( #include "winres.h" VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,0,0,0 - PRODUCTVERSION 2,0,0,0 + FILEVERSION %,%,0,0 + PRODUCTVERSION %,%,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -99,7 +106,7 @@ BEGIN BEGIN VALUE "CompanyName", "Microsoft Corporation" VALUE "FileDescription", "C++/WinRT" - VALUE "FileVersion", "2.0.0.0" + VALUE "FileVersion", "%.%.0.0" VALUE "LegalCopyright", "Microsoft Corporation. All rights reserved." VALUE "OriginalFilename", "cppwinrt.exe" VALUE "ProductName", "C++/WinRT" @@ -112,7 +119,10 @@ BEGIN END END )", - CPPWINRT_VERSION_STRING); + ver_major, ver_minor, // FILEVERSION + ver_major, ver_minor, // PRODUCTVERSION + ver_major, ver_minor, // FileVersion string + CPPWINRT_VERSION_STRING); // ProductVersion string std::filesystem::create_directories(argv[2]); auto const output = std::filesystem::canonical(argv[2]); From 748d1e0876cf64a512dccbedd6ca72ee3bcda813 Mon Sep 17 00:00:00 2001 From: Yexuan Xiao Date: Tue, 21 Apr 2026 03:55:48 +0800 Subject: [PATCH 75/91] Add inline for hstring_reference_flag (#1571) --- strings/base_string.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strings/base_string.h b/strings/base_string.h index c2ba6c742..92295e81c 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -45,7 +45,7 @@ namespace winrt::impl std::atomic m_count; }; - constexpr std::uint32_t hstring_reference_flag{ 1 }; + inline constexpr std::uint32_t hstring_reference_flag{ 1 }; struct hstring_header { From a5e9452e6858849496e61c166ab8510d3acaec2a Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Apr 2026 16:01:47 -0700 Subject: [PATCH 76/91] CI: test against VS2022 (v143) and VS2026 (v145) in parallel (#1573) * Run Windows CI matrix on 2025 and 2025-vs2026 toolsets Agent-Logs-Url: https://github.com/microsoft/cppwinrt/sessions/b78f8378-0fed-463c-97ac-e16f18e532a9 Co-authored-by: DefaultRyan <26174284+DefaultRyan@users.noreply.github.com> * Simplify CI: drop vswhere version/prerelease fields, keep platform_toolset Agent-Logs-Url: https://github.com/microsoft/cppwinrt/sessions/d084d7e4-1d03-4234-a219-7b58887d42d5 Co-authored-by: DefaultRyan <26174284+DefaultRyan@users.noreply.github.com> * Fix clang-cl v145 build: exclude clang from memset path in com_array::detach_abi Clang 19+ (VS2026/v145) treats memset on non-trivially-copyable types as a hard error. clang-cl defines _MSC_VER, so it was taking the memset workaround path meant only for MSVC. Guard with !defined(__clang__) so clang-cl uses the safe member-assignment branch instead. Agent-Logs-Url: https://github.com/microsoft/cppwinrt/sessions/d433cd66-3565-4257-9c9d-23ec477f8c4d Co-authored-by: DefaultRyan <26174284+DefaultRyan@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: DefaultRyan <26174284+DefaultRyan@users.noreply.github.com> --- .github/workflows/ci.yml | 43 +++++++++++++++++++++++++++++----------- strings/base_array.h | 2 +- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cb8cafd2b..d660400a0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,12 +8,17 @@ on: jobs: test-msvc-cppwinrt-build: - name: '${{ matrix.compiler }}: Build (${{ matrix.arch }}, ${{ matrix.config }})' + name: '${{ matrix.compiler }}: Build (${{ matrix.arch }}, ${{ matrix.config }}, ${{ matrix.toolchain.platform_toolset }})' strategy: matrix: compiler: [MSVC, clang-cl] arch: [x86, x64, arm64] config: [Debug, Release] + toolchain: + - image: windows-2025 + platform_toolset: v143 + - image: windows-2025-vs2026 + platform_toolset: v145 exclude: - arch: arm64 config: Debug @@ -21,7 +26,7 @@ jobs: arch: arm64 - compiler: clang-cl config: Release - runs-on: windows-latest + runs-on: ${{ matrix.toolchain.image }} steps: - uses: actions/checkout@v6 @@ -45,6 +50,8 @@ jobs: $props = "Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" if ("${{ matrix.compiler }}" -eq "clang-cl") { $props += ",Clang=1,PlatformToolset=ClangCl" + } else { + $props += ",PlatformToolset=${{ matrix.toolchain.platform_toolset }}" } Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:$props" @@ -68,7 +75,7 @@ jobs: - name: Upload built executables uses: actions/upload-artifact@v7 with: - name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: | _build/${{ matrix.arch }}/${{ matrix.config }}/*.exe _build/${{ matrix.arch }}/${{ matrix.config }}/*.dll @@ -84,7 +91,7 @@ jobs: & "_build\$target_platform\$target_configuration\cppwinrt.exe" -in local -out _build\$target_platform\$target_configuration -verbose test-msvc-cppwinrt-test: - name: '${{ matrix.compiler }}: Test [${{ matrix.test_exe }}] (${{ matrix.arch }}, ${{ matrix.config }})' + name: '${{ matrix.compiler }}: Test [${{ matrix.test_exe }}] (${{ matrix.arch }}, ${{ matrix.config }}, ${{ matrix.toolchain.platform_toolset }})' needs: test-msvc-cppwinrt-build strategy: fail-fast: false @@ -93,6 +100,11 @@ jobs: arch: [x86, x64, arm64] config: [Debug, Release] test_exe: [test, test_nocoro, test_cpp20, test_cpp20_no_sourcelocation, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] + toolchain: + - image: windows-2025 + platform_toolset: v143 + - image: windows-2025-vs2026 + platform_toolset: v145 exclude: - arch: arm64 config: Debug @@ -100,7 +112,7 @@ jobs: arch: arm64 - compiler: clang-cl config: Release - runs-on: windows-latest + runs-on: ${{ matrix.toolchain.image }} steps: - uses: actions/checkout@v6 @@ -108,14 +120,14 @@ jobs: if: matrix.arch != 'arm64' uses: actions/download-artifact@v8 with: - name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' uses: actions/download-artifact@v8 with: - name: msvc-build-${{ matrix.compiler}}-x86-Release-bin + name: msvc-build-${{ matrix.compiler}}-x86-Release-${{ matrix.toolchain.platform_toolset }}-bin path: _build/x86/Release/ - name: Download nuget @@ -138,6 +150,8 @@ jobs: $props = "Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" if ("${{ matrix.compiler }}" -eq "clang-cl") { $props += ",Clang=1,PlatformToolset=ClangCl" + } else { + $props += ",PlatformToolset=${{ matrix.toolchain.platform_toolset }}" } Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:$props" @@ -232,7 +246,7 @@ jobs: if: matrix.arch == 'arm64' uses: actions/upload-artifact@v7 with: - name: msvc-tests-${{ matrix.test_exe }}-${{ matrix.compiler }}-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-tests-${{ matrix.test_exe }}-${{ matrix.compiler }}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: | _build/${{ matrix.arch }}/${{ matrix.config }}/*.exe _build/${{ matrix.arch }}/${{ matrix.config }}/*.dll @@ -313,7 +327,7 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" /p:Deployment=${{ matrix.Deployment }} natvis\cppwinrtvisualizer.sln build-msvc-nuget-test: - name: 'Build nuget test (${{ matrix.arch }})' + name: 'Build nuget test (${{ matrix.arch }}, ${{ matrix.toolchain.platform_toolset }})' needs: test-msvc-cppwinrt-build strategy: matrix: @@ -321,14 +335,19 @@ jobs: - MSVC arch: [x86, x64] config: [Release] - runs-on: windows-latest + toolchain: + - image: windows-2025 + platform_toolset: v143 + - image: windows-2025-vs2026 + platform_toolset: v145 + runs-on: ${{ matrix.toolchain.image }} steps: - uses: actions/checkout@v6 - name: Fetch cppwinrt executables uses: actions/download-artifact@v8 with: - name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-bin + name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Download nuget @@ -348,7 +367,7 @@ jobs: $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" $target_version = "999.999.999.999" - Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" + Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version,PlatformToolset=${{ matrix.toolchain.platform_toolset }}" - name: Restore nuget packages run: | diff --git a/strings/base_array.h b/strings/base_array.h index 9544dcf8c..48d10c6ce 100644 --- a/strings/base_array.h +++ b/strings/base_array.h @@ -376,7 +376,7 @@ WINRT_EXPORT namespace winrt std::pair> detach_abi() noexcept { -#ifdef _MSC_VER +#if defined(_MSC_VER) && !defined(__clang__) // https://github.com/microsoft/cppwinrt/pull/1165 std::pair> result; std::memset(&result, 0, sizeof(result)); From 58811e1efe1589b0d022137c3246fc5e703df3a4 Mon Sep 17 00:00:00 2001 From: Yexuan Xiao Date: Fri, 15 May 2026 00:27:24 +0800 Subject: [PATCH 77/91] Move operator<< to winrt::Windows::Foundation (#1576) --- strings/base_stringable_streams.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/strings/base_stringable_streams.h b/strings/base_stringable_streams.h index 52b481d6f..fa17b0f3e 100644 --- a/strings/base_stringable_streams.h +++ b/strings/base_stringable_streams.h @@ -1,8 +1,11 @@ #ifndef WINRT_LEAN_AND_MEAN -inline std::wostream& operator<<(std::wostream& stream, winrt::Windows::Foundation::IStringable const& stringable) +namespace winrt::Windows::Foundation { - stream << stringable.ToString(); - return stream; + inline std::wostream& operator<<(std::wostream& stream, winrt::Windows::Foundation::IStringable const& stringable) + { + stream << stringable.ToString(); + return stream; + } } #endif From 55f1b452aca069d6ac7eaad3e05cc1058fc39d27 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 20 May 2026 13:17:10 -0700 Subject: [PATCH 78/91] C++20 module support v2 (#1575) * Initial implementation of vs modules based on cppwinrtplus fork * Rename WINRT_MODULE -> WINRT_IMPL_BUILD_MODULE; WINRT_CONSUME_MODULE -> WINRT_IMPORT_MODULE * Namespace modules are winrt.Namespace. Non-namespace modules are winrt_base/winrt_numerics Co-authored-by: Copilot * Bootstrap basic unit test Co-authored-by: Copilot * Fix coroutine export. A few more unit tests. Co-authored-by: Copilot * module_include, module_exclude Co-authored-by: Copilot * Rename test_module to test_cpp20_module * Nuget test project with module include/exclude Co-authored-by: Copilot * Refine generated files in component. Co-authored-by: Copilot * Added a type deriving from DependencyObject Co-authored-by: Copilot * Basic module build/consume support Co-authored-by: Copilot * Prefix namespace ixx files with "winrt." for consistency with module names and built ifc files. Co-authored-by: Copilot * IFC needs better per-project scoping. Now it fully works end to end. * Minor fix to TestModuleComponent2 * Documentation and polish. Co-authored-by: YexuanXiao Co-authored-by: Copilot * Fix CI failures Co-authored-by: Copilot * Try for better std hygiene * Address some PR feedback * Better automation of AdditionalBMIDirectories Co-authored-by: Copilot * Missed fallback definition of WINRT_IMPL_STD_EXPORT * Wrap base.h and extern the handler pointers * Uniform namespace filtering * Write trailing comments for #endif * Clarify language version requirement * Add source_location test Co-authored-by: Copilot * Refactor/cleanup some string writers Co-authored-by: Copilot * Add arm64 configs and replace bogus project guids with real guids. Co-authored-by: Copilot * More cleanup of strings. Collected common macros into base_macros.h, generates into winrt/macros.h Co-authored-by: Copilot * More strings cleanup. Emit a canonical winrt/base_macros.h Co-authored-by: Copilot * More clarifications about guidance when sharing pre-built modules Co-authored-by: Copilot * Ensure structured bindings are exported for IKeyValuePair Co-authored-by: Copilot * Fix up module namespace exclude logic so it still generates import statements. * intrin.h and only needed by base, not namespace modules * Tidy up a few codegen bits * Fix sln config on test_cpp20_module project * Namespace modules now check version against imported winrt_base Co-authored-by: Copilot * PR feedback: Test format, hash, natvis hook visibility, message on old compiler Co-authored-by: Copilot * Clean up some handling of numerics-related code and add some numerics smoke tests * De-duplicate windowsnumerics.impl.h logic * A little more WINRT_IMPORT_MODULE cleanup * Use write_depends in SCC writers --------- Co-authored-by: Copilot Co-authored-by: YexuanXiao --- .github/instructions/cppwinrt.instructions.md | 58 +++ .github/instructions/modules.instructions.md | 40 ++ .github/workflows/ci.yml | 9 + cppwinrt.sln | 18 + cppwinrt/code_writers.h | 57 ++- cppwinrt/component_writers.h | 5 +- cppwinrt/file_writers.h | 374 ++++++++++++++++-- cppwinrt/main.cpp | 203 +++++++++- cppwinrt/settings.h | 6 + docs/modules-design.md | 190 +++++++++ natvis/pch.h | 1 + nuget/Microsoft.Windows.CppWinRT.targets | 95 ++++- nuget/modules.md | 179 +++++++++ nuget/readme.md | 12 + strings/base_abi.h | 2 +- strings/base_activation.h | 6 +- strings/base_agile_ref.h | 2 +- strings/base_array.h | 2 +- strings/base_collections.h | 2 +- strings/base_collections_base.h | 2 +- strings/base_collections_input_iterable.h | 2 +- strings/base_collections_input_map.h | 2 +- strings/base_collections_input_map_view.h | 2 +- strings/base_collections_input_vector.h | 2 +- strings/base_collections_input_vector_view.h | 2 +- strings/base_collections_map.h | 6 +- strings/base_collections_vector.h | 2 +- strings/base_com_ptr.h | 4 +- strings/base_composable.h | 2 +- strings/base_coroutine_foundation.h | 6 +- strings/base_coroutine_threadpool.h | 6 +- strings/base_delegate.h | 2 +- strings/base_detect_numerics.h | 4 + strings/base_error.h | 4 +- strings/base_events.h | 2 +- strings/base_extern.h | 11 +- strings/base_fast_forward.h | 6 +- strings/base_foundation.h | 2 +- strings/base_identity.h | 2 +- strings/base_implements.h | 6 +- strings/base_include_numerics.h | 19 + strings/base_includes.h | 5 - strings/base_iterator.h | 2 +- strings/base_macros.h | 146 ++----- strings/base_marshaler.h | 2 +- strings/base_meta.h | 2 +- strings/base_module_base_ixx.h | 13 + strings/base_module_ixx_preamble.h | 11 + strings/base_module_numerics_ixx.h | 6 + strings/base_natvis.h | 2 +- strings/base_reference_produce.h | 4 +- strings/base_source_location.h | 97 +++++ strings/base_std_hash.h | 4 +- strings/base_string.h | 4 +- strings/base_string_input.h | 2 +- strings/base_string_operators.h | 2 +- strings/base_types.h | 4 +- strings/base_version.h | 2 + strings/base_windows.h | 2 +- strings/base_xaml_typename.h | 2 +- test/nuget/NuGetTest.sln | 69 +++- .../TestModuleApp/CustomDependencyObject.cpp | 8 + .../TestModuleApp/CustomDependencyObject.h | 23 ++ test/nuget/TestModuleApp/ModuleTestHelper.cpp | 7 + test/nuget/TestModuleApp/ModuleTestHelper.h | 27 ++ test/nuget/TestModuleApp/PropertySheet.props | 7 + test/nuget/TestModuleApp/TestModuleApp.def | 3 + test/nuget/TestModuleApp/TestModuleApp.idl | 20 + .../nuget/TestModuleApp/TestModuleApp.vcxproj | 127 ++++++ test/nuget/TestModuleApp/main.cpp | 42 ++ test/nuget/TestModuleApp/pch.cpp | 1 + test/nuget/TestModuleApp/pch.h | 1 + .../TestModuleBuilder/PropertySheet.props | 7 + .../TestModuleBuilder.vcxproj | 67 ++++ test/nuget/TestModuleBuilder/pch.cpp | 1 + test/nuget/TestModuleBuilder/pch.h | 1 + test/nuget/TestModuleComponent1/Greeter.cpp | 8 + test/nuget/TestModuleComponent1/Greeter.h | 25 ++ .../TestModuleComponent1/PropertySheet.props | 7 + .../TestModuleComponent1.def | 3 + .../TestModuleComponent1.idl | 12 + .../TestModuleComponent1.vcxproj | 92 +++++ test/nuget/TestModuleComponent1/pch.cpp | 1 + test/nuget/TestModuleComponent1/pch.h | 1 + .../TestModuleComponent2/GreeterGroup.cpp | 9 + .../nuget/TestModuleComponent2/GreeterGroup.h | 36 ++ .../TestModuleComponent2/PropertySheet.props | 7 + .../TestModuleComponent2.def | 3 + .../TestModuleComponent2.idl | 10 + .../TestModuleComponent2.vcxproj | 93 +++++ test/nuget/TestModuleComponent2/pch.cpp | 1 + test/nuget/TestModuleComponent2/pch.h | 1 + .../TestModuleConsumerApp/PropertySheet.props | 7 + .../TestModuleConsumerApp.vcxproj | 76 ++++ test/nuget/TestModuleConsumerApp/main.cpp | 32 ++ test/nuget/TestModuleConsumerApp/pch.cpp | 1 + test/nuget/TestModuleConsumerApp/pch.h | 1 + test/test_cpp20_module/collections.cpp | 57 +++ test/test_cpp20_module/com_interop.cpp | 84 ++++ test/test_cpp20_module/coroutines.cpp | 58 +++ test/test_cpp20_module/format.cpp | 49 +++ test/test_cpp20_module/foundation.cpp | 68 ++++ test/test_cpp20_module/hash.cpp | 73 ++++ test/test_cpp20_module/main.cpp | 24 ++ test/test_cpp20_module/natvis.cpp | 58 +++ test/test_cpp20_module/numerics.cpp | 129 ++++++ test/test_cpp20_module/pch.cpp | 1 + test/test_cpp20_module/pch.h | 3 + test/test_cpp20_module/range_for.cpp | 135 +++++++ test/test_cpp20_module/source_location.cpp | 13 + .../test_cpp20_module.vcxproj | 112 ++++++ 111 files changed, 3146 insertions(+), 224 deletions(-) create mode 100644 .github/instructions/cppwinrt.instructions.md create mode 100644 .github/instructions/modules.instructions.md create mode 100644 docs/modules-design.md create mode 100644 nuget/modules.md create mode 100644 strings/base_detect_numerics.h create mode 100644 strings/base_include_numerics.h create mode 100644 strings/base_module_base_ixx.h create mode 100644 strings/base_module_ixx_preamble.h create mode 100644 strings/base_module_numerics_ixx.h create mode 100644 strings/base_source_location.h create mode 100644 test/nuget/TestModuleApp/CustomDependencyObject.cpp create mode 100644 test/nuget/TestModuleApp/CustomDependencyObject.h create mode 100644 test/nuget/TestModuleApp/ModuleTestHelper.cpp create mode 100644 test/nuget/TestModuleApp/ModuleTestHelper.h create mode 100644 test/nuget/TestModuleApp/PropertySheet.props create mode 100644 test/nuget/TestModuleApp/TestModuleApp.def create mode 100644 test/nuget/TestModuleApp/TestModuleApp.idl create mode 100644 test/nuget/TestModuleApp/TestModuleApp.vcxproj create mode 100644 test/nuget/TestModuleApp/main.cpp create mode 100644 test/nuget/TestModuleApp/pch.cpp create mode 100644 test/nuget/TestModuleApp/pch.h create mode 100644 test/nuget/TestModuleBuilder/PropertySheet.props create mode 100644 test/nuget/TestModuleBuilder/TestModuleBuilder.vcxproj create mode 100644 test/nuget/TestModuleBuilder/pch.cpp create mode 100644 test/nuget/TestModuleBuilder/pch.h create mode 100644 test/nuget/TestModuleComponent1/Greeter.cpp create mode 100644 test/nuget/TestModuleComponent1/Greeter.h create mode 100644 test/nuget/TestModuleComponent1/PropertySheet.props create mode 100644 test/nuget/TestModuleComponent1/TestModuleComponent1.def create mode 100644 test/nuget/TestModuleComponent1/TestModuleComponent1.idl create mode 100644 test/nuget/TestModuleComponent1/TestModuleComponent1.vcxproj create mode 100644 test/nuget/TestModuleComponent1/pch.cpp create mode 100644 test/nuget/TestModuleComponent1/pch.h create mode 100644 test/nuget/TestModuleComponent2/GreeterGroup.cpp create mode 100644 test/nuget/TestModuleComponent2/GreeterGroup.h create mode 100644 test/nuget/TestModuleComponent2/PropertySheet.props create mode 100644 test/nuget/TestModuleComponent2/TestModuleComponent2.def create mode 100644 test/nuget/TestModuleComponent2/TestModuleComponent2.idl create mode 100644 test/nuget/TestModuleComponent2/TestModuleComponent2.vcxproj create mode 100644 test/nuget/TestModuleComponent2/pch.cpp create mode 100644 test/nuget/TestModuleComponent2/pch.h create mode 100644 test/nuget/TestModuleConsumerApp/PropertySheet.props create mode 100644 test/nuget/TestModuleConsumerApp/TestModuleConsumerApp.vcxproj create mode 100644 test/nuget/TestModuleConsumerApp/main.cpp create mode 100644 test/nuget/TestModuleConsumerApp/pch.cpp create mode 100644 test/nuget/TestModuleConsumerApp/pch.h create mode 100644 test/test_cpp20_module/collections.cpp create mode 100644 test/test_cpp20_module/com_interop.cpp create mode 100644 test/test_cpp20_module/coroutines.cpp create mode 100644 test/test_cpp20_module/format.cpp create mode 100644 test/test_cpp20_module/foundation.cpp create mode 100644 test/test_cpp20_module/hash.cpp create mode 100644 test/test_cpp20_module/main.cpp create mode 100644 test/test_cpp20_module/natvis.cpp create mode 100644 test/test_cpp20_module/numerics.cpp create mode 100644 test/test_cpp20_module/pch.cpp create mode 100644 test/test_cpp20_module/pch.h create mode 100644 test/test_cpp20_module/range_for.cpp create mode 100644 test/test_cpp20_module/source_location.cpp create mode 100644 test/test_cpp20_module/test_cpp20_module.vcxproj diff --git a/.github/instructions/cppwinrt.instructions.md b/.github/instructions/cppwinrt.instructions.md new file mode 100644 index 000000000..ba5d66212 --- /dev/null +++ b/.github/instructions/cppwinrt.instructions.md @@ -0,0 +1,58 @@ +# C++/WinRT Codebase — Agent Instructions + +## Repository Structure + +- `cppwinrt/` — The cppwinrt.exe code generator (C++ source) + - `main.cpp` — CLI parsing, namespace iteration, SCC detection, .ixx orchestration + - `file_writers.h` — All file generation functions (headers, .ixx modules, component stubs) + - `code_writers.h` — Code-level writing utilities (guards, namespace wrappers, type writers) + - `type_writers.h` — Type formatting (ABI signatures, names, GUIDs) + - `component_writers.h` — Component authoring code generation + - `helpers.h` — Metadata reading helpers + - `settings.h` — Global settings populated from CLI args + - `text_writer.h` — Core text writer infrastructure +- `strings/` — String literal `.h` files embedded by the prebuild step. Changes require: delete prebuild.exe → rebuild solution +- `nuget/` — MSBuild targets, props, and NuGet packaging + - `Microsoft.Windows.CppWinRT.targets` — Main MSBuild integration (projections, module support) +- `test/` — Test projects + - `test/test_cpp20_module/` — Standalone module test (in main solution) + - `test/nuget/` — NuGet integration tests (multi-project module chain) +- `docs/` — Documentation +- `natvis/` — Visual Studio debug visualizer (includes strings/*.h in its pch.h — add new files there too) + +## Build Process + +- Use VS Developer Shell for correct toolset environment +- `cmake --build build --config Release --target cppwinrt` for cppwinrt.exe (or MSBuild: `msbuild cppwinrt\cppwinrt.vcxproj /p:Configuration=Release /p:Platform=x64`) +- NuGet tests: `msbuild test\nuget\NuGetTest.sln /p:Configuration=Release /p:Platform=x64` +- Module test projects require v145 toolset (VS 2026). Directory.Build.Props sets v143 by default — override with `v145` in Configuration PropertyGroup + +## Key Patterns + +### Prebuild Embedding +The `strings/*.h` files are embedded as string literals by the prebuild step. If you modify any `strings/*.h` file, you must delete `prebuild.exe` and rebuild the entire solution for changes to take effect. + +### Module Guard Macros +- `WINRT_IMPL_BUILD_MODULE` — Defined in .ixx global fragment. Makes `WINRT_EXPORT` expand to `export extern "C++"` and suppresses `#include` of dependencies +- `WINRT_IMPORT_MODULE` — Defined by consumers who import modules. Makes namespace headers and base.h no-op (types come from module import) +- `WINRT_EXPORT` — Empty in header mode, `export extern "C++"` in module mode. Defined in `winrt/base_macros.h` +- `WINRT_IMPL_STD_EXPORT` — Empty in header mode, `extern "C++"` (without export) in module mode. Used for `namespace std` specializations + +### Generated Header Structure +Each namespace produces four header files: +- `impl/.0.h` — Forward declarations, ABIs, GUIDs, categories +- `impl/.1.h` — Interface definitions +- `impl/.2.h` — Delegates, structs, class implementations +- `.h` — Public API surface (consume definitions, class wrappers, operators) + +### Dependency Collection +When generating headers with `-modules`, writer.depends is inspected after each header to build a namespace dependency graph. This graph drives SCC detection and module import lists. + +## Common Gotchas + +- Module IFCs are NOT compatible across toolset versions — always clean rebuild when switching +- PCH and modules can coexist but PCH should NOT include winrt headers when using modules +- `/ifcSearchDir` works for the module dependency scanner to find IFCs, but cross-component modules may need explicit `/reference "name=path.ifc"` flags +- `import std;` requires `BuildStlModules=true` +- `strings/base_macros.h` is the single source of truth for shared macros (generated as `winrt/base_macros.h`). New macros go in `base_macros.h` only +- When adding, removing, or heavily refactoring `strings/*.h` files, always rebuild the natvis project (`natvis/cppwinrtvisualizer.sln`) to verify — it includes strings/*.h directly in its pch.h diff --git a/.github/instructions/modules.instructions.md b/.github/instructions/modules.instructions.md new file mode 100644 index 000000000..3deee2955 --- /dev/null +++ b/.github/instructions/modules.instructions.md @@ -0,0 +1,40 @@ +# C++/WinRT Modules — Agent Instructions + +## Module Architecture (v2 — Per-Namespace) + +Each WinRT namespace gets its own C++20 named module (`winrt.`). Base infrastructure is in `winrt_base` and `winrt_numerics`. + +### Code Generator Flow + +1. `-modules` flag enables .ixx generation in cppwinrt.exe +2. `-module_include`/`-module_exclude` filter which namespaces get modules +3. Headers are generated with dependency tracking (deps_ptr parameter) +4. Tarjan's SCC algorithm detects cyclic namespace groups +5. Standalone namespaces get individual .ixx; cyclic groups get consolidated SCC owner + re-export stubs + +### MSBuild Flow + +1. `CppWinRTBuildModule=true` adds `-modules` to cppwinrt.exe invocations +2. `CppWinRTAddModuleInterfaces` discovers `$(GeneratedFilesDir)winrt\*.ixx` and adds to ClCompile +3. `CppWinRTConsumeModule` metadata on ProjectReference controls per-reference IFC sharing +4. `CppWinRTResolveModuleReferences` calls `CppWinRTGetModuleOutputs` on tagged references +5. Platform projection suppresses `-modules` when consuming pre-built IFCs + +### Critical Invariants + +- Module guards are unconditional in codegen — `-modules` controls .ixx generation and component codegen (module.g.cpp, stub .cpp) +- SCC owner is alphabetically first namespace in the cycle +- All .ixx filenames use `winrt` prefix: `winrt.Windows.Foundation.ixx`, `winrt_base.ixx` +- Shared macros live in `strings/base_module.h` → generates `winrt/macros.h`. `base_macros.h` includes it via `#include "winrt/macros.h"` + +### Testing Changes + +After modifying cppwinrt.exe code: +1. Rebuild cppwinrt.exe: `msbuild cppwinrt\cppwinrt.vcxproj /p:Configuration=Release /p:Platform=x64` +2. Run standalone test: build `test_cpp20_module` in main solution +3. Run NuGet tests: `msbuild test\nuget\NuGetTest.sln /p:Configuration=Release /p:Platform=x64` + +After modifying targets: +1. Clean NuGet test obj dirs +2. Build with `/v:normal` and check "Module providers:" diagnostic messages +3. Inspect `.rsp` files in `obj/` to verify correct `-modules` flag placement diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d660400a0..6c2a04353 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -379,6 +379,15 @@ jobs: $target_platform = "${{ matrix.arch }}" & "_build\$target_platform\$target_configuration\cppwinrt.exe" -in local -out _build\$target_platform\$target_configuration -verbose + - name: Remove module test projects on v143 + if: matrix.toolchain.platform_toolset == 'v143' + run: | + # Module test projects require v145 toolset + mv test\nuget\NugetTest.sln test\nuget\NugetTest.sln.orig + Get-Content test\nuget\NugetTest.sln.orig | + Where-Object { -not ($_ -match 'TestModule') } | + Set-Content test\nuget\NugetTest.sln + - name: Run nuget test run: | cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" test\nuget\NugetTest.sln diff --git a/cppwinrt.sln b/cppwinrt.sln index 3bcfb33bc..700e9f5ea 100644 --- a/cppwinrt.sln +++ b/cppwinrt.sln @@ -124,6 +124,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_nocoro", "test\test_no {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20_module", "test\test_cpp20_module\test_cpp20_module.vcxproj", "{B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}" + ProjectSection(ProjectDependencies) = postProject + {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} + EndProjectSection +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D15C8430-A7CD-4616-BD84-243B26A9F1C2}" ProjectSection(SolutionItems) = preProject build_nuget.cmd = build_nuget.cmd @@ -411,6 +416,18 @@ Global {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x64.Build.0 = Release|x64 {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x86.ActiveCfg = Release|Win32 {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x86.Build.0 = Release|Win32 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Debug|ARM64.Build.0 = Debug|ARM64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Debug|x64.ActiveCfg = Debug|x64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Debug|x64.Build.0 = Debug|x64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Debug|x86.ActiveCfg = Debug|Win32 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Debug|x86.Build.0 = Debug|Win32 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Release|ARM64.ActiveCfg = Release|ARM64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Release|ARM64.Build.0 = Release|ARM64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Release|x64.ActiveCfg = Release|x64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Release|x64.Build.0 = Release|x64 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Release|x86.ActiveCfg = Release|Win32 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -435,6 +452,7 @@ Global {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {9E392830-805A-4AAF-932D-C493143EFACA} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2783B8FD-EA3B-4D6B-9F81-662D289E02AA} diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index fc5081bef..ab119ae89 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -5,9 +5,9 @@ namespace cppwinrt struct finish_with { writer& w; - void (*finisher)(writer&); + std::function finisher; - finish_with(writer& w, void (*finisher)(writer&)) : w(w), finisher(finisher) {} + finish_with(writer& w, std::function finisher) : w(w), finisher(std::move(finisher)) {} finish_with(finish_with const&)= delete; void operator=(finish_with const&) = delete; @@ -35,6 +35,35 @@ namespace cppwinrt } } + static void write_endif(writer& w, std::string_view macro = {}) + { + if (macro.empty()) + { + w.write("#endif\n"); + } + else + { + w.write("#endif // %\n", macro); + } + } + + // When modules are enabled, wraps a block of #include directives in + // #ifndef WINRT_IMPL_BUILD_MODULE ... #endif so that in module builds (where + // WINRT_IMPL_BUILD_MODULE is defined in the global module fragment), textual + // includes are suppressed — dependencies come via import instead. + [[nodiscard]] static finish_with wrap_module_aware_includes_guard(writer& w, bool modules_enabled) + { + if (modules_enabled) + { + w.write("#ifndef WINRT_IMPL_BUILD_MODULE\n"); + return { w, [](writer& w) { write_endif(w, "WINRT_IMPL_BUILD_MODULE"); } }; + } + else + { + return { w, write_nothing }; + } + } + static void write_version_assert(writer& w) { w.write_root_include("base"); @@ -52,14 +81,6 @@ namespace cppwinrt w.write(format); } - static void write_endif(writer& w) - { - auto format = R"(#endif -)"; - - w.write(format); - } - static void write_close_file_guard(writer& w) { write_endif(w); @@ -105,7 +126,7 @@ namespace cppwinrt w.write(format); - return { w, write_endif }; + return { w, [](writer& w) { write_endif(w, "WINRT_LEAN_AND_MEAN"); } }; } else { @@ -120,7 +141,17 @@ namespace cppwinrt w.write(format, macro); - return { w, write_endif }; + return { w, [macro = std::string(macro)](writer& w) { write_endif(w, macro); } }; + } + + [[nodiscard]] static finish_with wrap_ifndef(writer& w, std::string_view macro) + { + auto format = R"(#ifndef % +)"; + + w.write(format, macro); + + return { w, [macro = std::string(macro)](writer& w) { write_endif(w, macro); } }; } static void write_parent_depends(writer& w, cache const& c, std::string_view const& type_namespace) @@ -166,7 +197,7 @@ namespace cppwinrt [[nodiscard]] static finish_with wrap_impl_namespace(writer& w) { - auto format = R"(namespace winrt::impl + auto format = R"(WINRT_EXPORT namespace winrt::impl { )"; diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index 3966cad6c..af5626d14 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -136,7 +136,10 @@ namespace cppwinrt static void write_module_g_cpp(writer& w, std::vector const& classes) { - w.write_root_include("base"); + if (!settings.modules) + { + w.write_root_include("base"); + } auto format = R"(% bool __stdcall %_can_unload_now() noexcept { diff --git a/cppwinrt/file_writers.h b/cppwinrt/file_writers.h index ed9386b4e..fd9833cb1 100644 --- a/cppwinrt/file_writers.h +++ b/cppwinrt/file_writers.h @@ -9,9 +9,16 @@ namespace cppwinrt w.write(strings::base_version_odr, CPPWINRT_VERSION_STRING); { auto wrap_file_guard = wrap_open_file_guard(w, "BASE"); + auto wrap_import = wrap_ifndef(w, "WINRT_IMPORT_MODULE"); - w.write(strings::base_includes); - w.write(strings::base_macros); + { + auto wrap_includes = wrap_module_aware_includes_guard(w, true); + w.write(strings::base_includes); + w.write(strings::base_detect_numerics); + w.write(strings::base_include_numerics); + } + w.write_root_include("base_macros"); + w.write(strings::base_source_location); w.write(strings::base_types); w.write(strings::base_extern); w.write(strings::base_meta); @@ -65,7 +72,15 @@ namespace cppwinrt w.flush_to_file(settings.output_folder + "winrt/fast_forward.h"); } - static void write_namespace_0_h(std::string_view const& ns, cache::namespace_members const& members) + static void collect_writer_deps(writer const& w, std::set& out) + { + for (auto&& [dep_ns, _] : w.depends) + { + out.insert(std::string(dep_ns)); + } + } + + static void write_namespace_0_h(std::string_view const& ns, cache::namespace_members const& members, std::set* out_deps = nullptr) { writer w; w.type_namespace = ns; @@ -118,10 +133,11 @@ namespace cppwinrt w.write_each(depends.second); } + if (out_deps) collect_writer_deps(w, *out_deps); w.save_header('0'); } - static void write_namespace_1_h(std::string_view const& ns, cache::namespace_members const& members) + static void write_namespace_1_h(std::string_view const& ns, cache::namespace_members const& members, std::set* out_deps = nullptr) { writer w; w.type_namespace = ns; @@ -137,16 +153,20 @@ namespace cppwinrt write_preamble(w); write_open_file_guard(w, ns, '1'); - for (auto&& depends : w.depends) { - w.write_depends(depends.first, '0'); - } + auto wrap_includes = wrap_module_aware_includes_guard(w, true); + for (auto&& depends : w.depends) + { + w.write_depends(depends.first, '0'); + } - w.write_depends(w.type_namespace, '0'); + w.write_depends(w.type_namespace, '0'); + } + if (out_deps) collect_writer_deps(w, *out_deps); w.save_header('1'); } - static void write_namespace_2_h(std::string_view const& ns, cache::namespace_members const& members) + static void write_namespace_2_h(std::string_view const& ns, cache::namespace_members const& members, std::set* out_deps = nullptr) { writer w; w.type_namespace = ns; @@ -167,16 +187,20 @@ namespace cppwinrt char const impl = promote ? '2' : '1'; - for (auto&& depends : w.depends) { - w.write_depends(depends.first, impl); - } + auto wrap_includes = wrap_module_aware_includes_guard(w, true); + for (auto&& depends : w.depends) + { + w.write_depends(depends.first, impl); + } - w.write_depends(w.type_namespace, '1'); + w.write_depends(w.type_namespace, '1'); + } + if (out_deps) collect_writer_deps(w, *out_deps); w.save_header('2'); } - static void write_namespace_h(cache const& c, std::string_view const& ns, cache::namespace_members const& members) + static void write_namespace_h(cache const& c, std::string_view const& ns, cache::namespace_members const& members, std::set* out_deps = nullptr) { writer w; w.type_namespace = ns; @@ -216,18 +240,28 @@ namespace cppwinrt write_namespace_special(w, ns); write_close_file_guard(w); + // The #ifndef WINRT_IMPORT_MODULE / #endif pair spans across w.swap(). + // The body is written first (above), then swap() prepends the header prefix (below). + // In the final output, #ifndef opens before the includes and #endif closes after + // the file guard, mirroring the write_open_file_guard / write_close_file_guard pair. + w.write("#endif // WINRT_IMPORT_MODULE\n"); w.swap(); write_preamble(w); write_open_file_guard(w, ns); - write_version_assert(w); - write_parent_depends(w, c, ns); - - for (auto&& depends : w.depends) + w.write("#ifndef WINRT_IMPORT_MODULE\n\n"); { - w.write_depends(depends.first, '2'); - } + auto wrap_includes = wrap_module_aware_includes_guard(w, true); + write_version_assert(w); + write_parent_depends(w, c, ns); - w.write_depends(w.type_namespace, '2'); + for (auto&& depends : w.depends) + { + w.write_depends(depends.first, '2'); + } + + w.write_depends(w.type_namespace, '2'); + } + if (out_deps) collect_writer_deps(w, *out_deps); w.save_header(); } @@ -236,6 +270,28 @@ namespace cppwinrt writer w; write_preamble(w); write_pch(w); + + if (settings.modules) + { + // In module builds, import std and winrt_base instead of #include "winrt/base.h". + // std is needed for std::wstring_view, std::equal, std::int32_t used in + // the activation factory lookup code. + w.write("\nimport std;\n"); + w.write("import winrt_base;\n"); + + // Collect all unique namespaces from the component classes + std::set namespaces; + for (auto&& type : classes) + { + namespaces.insert(std::string(type.TypeNamespace())); + } + for (auto&& ns : namespaces) + { + w.write("import winrt.%;\n", ns); + } + w.write("\n"); + } + write_module_g_cpp(w, classes); w.flush_to_file(settings.output_folder + "module.g.cpp"); } @@ -250,9 +306,19 @@ namespace cppwinrt write_preamble(w); write_include_guard(w); - for (auto&& depends : w.depends) { - w.write_depends(depends.first); + auto wrap = wrap_ifdef(w, "WINRT_IMPORT_MODULE"); + w.write_root_include("base_macros"); + for (auto&& depends : w.depends) + { + w.write("import winrt.%;\n", depends.first); + } + w.write("#else // WINRT_IMPORT_MODULE\n"); + + for (auto&& depends : w.depends) + { + w.write_depends(depends.first); + } } auto filename = settings.output_folder + get_generated_component_filename(type) + ".g.h"; @@ -316,7 +382,269 @@ namespace cppwinrt writer w; write_pch(w); + + if (settings.modules) + { + // The .g.h handles its own imports, but the implementation .h + // needs the types available in scope, so we import them here. + writer dep_scanner; + dep_scanner.add_depends(type); + write_component_g_h(dep_scanner, type); + + w.write("\n#define WINRT_IMPORT_MODULE\n"); + for (auto&& depends : dep_scanner.depends) + { + w.write("import winrt.%;\n", depends.first); + } + w.write("\n"); + } + write_component_cpp(w, type); w.flush_to_file(path); } + + // --- Per-namespace C++20 module interface unit (.ixx) writers --- + + // Emits the common global module fragment used by all generated .ixx files. + // Defines WINRT_IMPL_BUILD_MODULE so generated headers switch WINRT_EXPORT + // to 'export extern "C++"' and suppress textual #includes of dependencies + // (dependencies arrive via module imports instead). + // Includes minimal headers needed for macros, intrinsics, and debug assertions. + static void write_module_preamble(writer& w) + { + write_preamble(w); + w.write(strings::base_module_ixx_preamble); + w.write_root_include("base_macros"); + } + + // Emits $(out)/winrt/base_macros.h + // This header provides the core macros shared between header and module builds. + // In header builds, base.h includes base_macros.h inline (via the prebuild-embedded string). + // In module builds, each .ixx file includes this in its global module fragment. + static void write_macros_h() + { + writer w; + write_preamble(w); + w.write(strings::base_macros, CPPWINRT_VERSION_STRING); + w.flush_to_file(settings.output_folder + "winrt/base_macros.h"); + } + + static void write_base_ixx() + { + writer w; + write_module_preamble(w); + w.write(strings::base_module_base_ixx); + w.write(strings::base_detect_numerics); + w.write("\n"); + w.write_root_include("base"); + w.flush_to_file(settings.output_folder + "winrt/winrt_base.ixx"); + } + + static void write_numerics_ixx() + { + writer w; + write_module_preamble(w); + // GMF: detect numerics and pre-include directxmath so it's not pulled + // into the module purview by windowsnumerics.impl.h + w.write(strings::base_detect_numerics); + { + auto wrap = wrap_ifdef(w, "WINRT_IMPL_NUMERICS"); + w.write("#include \n"); + } + w.write(strings::base_module_numerics_ixx); + // Module declaration + w.write("\nexport module winrt_numerics;\n"); + // Include windowsnumerics.impl.h in the module purview (exports the types). + // directxmath.h is already included in the GMF above, so the #include inside + // base_include_numerics is a no-op (header guard). + { + auto wrap = wrap_ifdef(w, "_MSC_VER"); + w.write("#pragma warning(push)\n"); + w.write("#pragma warning(disable : 5244)\n"); + } + w.write(strings::base_include_numerics); + { + auto wrap = wrap_ifdef(w, "_MSC_VER"); + w.write("#pragma warning(pop)\n"); + } + w.flush_to_file(settings.output_folder + "winrt/winrt_numerics.ixx"); + } + + // Emits a per-namespace module interface unit for namespaces that are NOT + // part of a dependency cycle (standalone module). + // Output: $(out)/winrt/winrt..ixx (export module winrt.;) + // + // The generated .ixx: + // 1. Starts with the global module fragment (WINRT_IMPL_BUILD_MODULE, minimal includes) + // 2. Declares 'export module winrt.;' + // 3. Imports std and re-exports winrt_base + // 4. Imports each dependent namespace module (computed from type references in headers) + // 5. Includes the impl headers (*.0.h, *.1.h, *.2.h) and public header (.h) + // in the module purview, where WINRT_EXPORT causes declarations to be exported + static void write_namespace_ixx( + std::string_view const& ns, + std::set const& deps) + { + writer w; + write_module_preamble(w); + + // Module declaration + w.write("export module winrt.%;\n\n", ns); + + // Document dependencies + w.write("// Module dependencies:\n"); + w.write("// - std\n"); + w.write("// - winrt_base (re-exported)\n"); + if (deps.empty()) + { + w.write("// - (no additional namespace imports)\n"); + } + else + { + for (auto& dep : deps) + { + w.write("// - winrt.%\n", dep); + } + } + w.write("\n"); + + // Import std and base + w.write("import std;\n"); + w.write("export import winrt_base;\n"); + + // Import dependency namespace modules + for (auto& dep : deps) + { + w.write("import winrt.%;\n", dep); + } + + // Version mismatch check: ensure this namespace module was generated by the + // same version of cppwinrt.exe as the winrt_base module it imports. + // winrt::cppwinrt_version is exported from winrt_base; CPPWINRT_VERSION is + // the macro from this module's own base_macros.h in the global module fragment. + w.write("\nstatic_assert(winrt::check_version(winrt::cppwinrt_version, CPPWINRT_VERSION), \"Mismatched C++/WinRT headers.\");\n\n"); + + // Include namespace headers in module purview + w.write_depends(ns, '0'); + w.write_depends(ns, '1'); + w.write_depends(ns, '2'); + w.write_root_include(ns); + + w.flush_to_file(settings.output_folder + "winrt/winrt." + std::string(ns) + ".ixx"); + } + + // Emits the SCC (Strongly Connected Component) owner module interface unit. + // When multiple namespaces form a dependency cycle, they cannot each have their + // own independent module (circular imports are illegal in C++20 modules). + // Instead, one namespace is chosen as the "owner" (alphabetically first in the SCC), + // and ALL cyclic namespaces' declarations are consolidated into this single module. + // The other namespaces in the SCC get thin re-export stubs (see write_namespace_reexport_ixx). + // + // Output: $(out)/winrt/winrt..ixx (export module winrt.;) + // + // The owner module: + // 1. Imports external dependencies (deps outside the SCC) + // 2. Forward-declares all projected types for ALL SCC namespaces before any + // impl headers — this breaks the type reference cycles + // 3. Includes impl headers in stable phase order: all *.0.h, then all *.1.h, + // then all *.2.h, then all public headers — preserving the original header + // layering while keeping SCC compilation deterministic + static void write_namespace_scc_owner_ixx( + cache const& c, + std::string_view const& owner, + std::vector const& scc_members, + std::set const& external_deps) + { + writer w; + write_module_preamble(w); + + // Module declaration (owner namespace) + w.write("// This module is an SCC owner (cycle breaker). The following namespaces\n"); + w.write("// form a dependency cycle and are consolidated into this single module:\n"); + for (auto& ns : scc_members) + { + w.write("// - %\n", ns); + } + w.write("// Other SCC namespaces are emitted as re-export stubs.\n\n"); + w.write("export module winrt.%;\n\n", owner); + + // Import std and base + w.write("import std;\n"); + w.write("export import winrt_base;\n"); + + // Import external dependency modules (outside the SCC) + for (auto& dep : external_deps) + { + w.write("import winrt.%;\n", dep); + } + + // Version mismatch check: ensure this namespace module was generated by the + // same version of cppwinrt.exe as the winrt_base module it imports. + // winrt::cppwinrt_version is exported from winrt_base; CPPWINRT_VERSION is + // the macro from this module's own base_macros.h in the global module fragment. + w.write("\nstatic_assert(winrt::check_version(winrt::cppwinrt_version, CPPWINRT_VERSION), \"Mismatched C++/WinRT headers.\");\n"); + + // Forward declarations for all projected types in this SCC. + // This is required because SCC members have cyclic type references, + // and generated headers suppress dependent #includes when WINRT_IMPL_BUILD_MODULE + // is defined. Forward declarations provide the names needed before definitions. + for (auto& ns : scc_members) + { + auto found = c.namespaces().find(ns); + if (found == c.namespaces().end()) + { + continue; + } + auto& members = found->second; + + auto wrap_type = wrap_type_namespace(w, ns); + w.write_each(members.enums); + w.write_each(members.interfaces); + w.write_each(members.classes); + w.write_each(members.structs); + w.write_each(members.delegates); + w.write_each(members.contracts); + } + + // Include all SCC members' headers in stable phase order. + // All *.0.h (forward decls + ABIs), then all *.1.h (interfaces), + // then all *.2.h (delegates/structs/classes), then all public headers. + // This preserves the original header layering while keeping compilation deterministic. + for (auto& ns : scc_members) + { + w.write_depends(ns, '0'); + } + for (auto& ns : scc_members) + { + w.write_depends(ns, '1'); + } + for (auto& ns : scc_members) + { + w.write_depends(ns, '2'); + } + for (auto& ns : scc_members) + { + w.write_root_include(ns); + } + + w.flush_to_file(settings.output_folder + "winrt/winrt." + std::string(owner) + ".ixx"); + } + + // Emits a thin re-export stub module for SCC non-owner namespaces. + // This allows 'import winrt.;' to work even though the actual declarations + // live in the SCC owner module. The stub simply re-exports the owner. + // Output: $(out)/winrt/winrt..ixx (export module winrt.; export import winrt.;) + static void write_namespace_reexport_ixx( + std::string_view const& ns, + std::string_view const& owner) + { + writer w; + write_preamble(w); + w.write("\n// NOTE: This module does not define declarations of its own.\n"); + w.write("// It re-exports all declarations from the 'winrt.%' module. This is used to break cycles in the\n", owner); + w.write("// WinRT namespace module dependency graph (SCC owner consolidation).\n\n"); + w.write("export module winrt.%;\n", ns); + w.write("export import winrt.%;\n", owner); + w.flush_to_file(settings.output_folder + "winrt/winrt." + std::string(ns) + ".ixx"); + } } diff --git a/cppwinrt/main.cpp b/cppwinrt/main.cpp index 70a55b076..33bb9248e 100644 --- a/cppwinrt/main.cpp +++ b/cppwinrt/main.cpp @@ -1,5 +1,6 @@ #include "pch.h" #include +#include #include "strings.h" #include "settings.h" #include "type_writers.h" @@ -39,6 +40,9 @@ namespace cppwinrt { "fastabi", 0, 0 }, // Enable support for the Fast ABI { "ignore_velocity", 0, 0 }, // Ignore feature staging metadata and always include implementations { "synchronous", 0, 0 }, // Instructs cppwinrt to run on a single thread to avoid file system issues in batch builds + { "modules", 0, 0, {}, "Generate per-namespace C++20 module interface units (.ixx)" }, + { "module_include", 0, option::no_max, "", "Filter which namespaces are included in module .ixx generation" }, + { "module_exclude", 0, option::no_max, "", "Filter which namespaces are excluded from module .ixx generation" }, }; static void print_usage(writer& w) @@ -85,6 +89,7 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder { settings.verbose = args.exists("verbose"); settings.fastabi = args.exists("fastabi"); + settings.modules = args.exists("modules"); settings.input = args.files("input", database::is_database); settings.reference = args.files("reference", database::is_database); @@ -92,6 +97,15 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder settings.component = args.exists("component"); settings.base = args.exists("base"); + for (auto&& ns : args.values("module_include")) + { + settings.module_include.insert(ns); + } + for (auto&& ns : args.values("module_exclude")) + { + settings.module_exclude.insert(ns); + } + settings.license = args.exists("license"); settings.brackets = args.exists("brackets"); @@ -199,6 +213,13 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder static void build_filters(cache const& c) { + // Build module_filter from -module_include / -module_exclude args. + // This controls which namespaces get .ixx files without affecting header generation. + if (!settings.module_include.empty() || !settings.module_exclude.empty()) + { + settings.module_filter = { settings.module_include, settings.module_exclude }; + } + if (settings.reference.empty()) { return; @@ -281,6 +302,79 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder c.remove_type("Windows.Foundation.Numerics", "Vector4"); } + // Tarjan's algorithm for finding strongly connected components in the + // namespace dependency graph. Namespaces in an SCC have cyclic deps and + // must be combined into a single module. + static std::vector> find_sccs( + std::map, std::less<>> const& graph) + { + struct context + { + std::map index_of; + std::map lowlink; + std::map on_stack; + std::vector stack; + int next_index = 0; + std::vector> result; + + void strongconnect(std::string const& v, + std::map, std::less<>> const& g) + { + index_of[v] = next_index; + lowlink[v] = next_index; + next_index++; + stack.push_back(v); + on_stack[v] = true; + + auto it = g.find(v); + if (it != g.end()) + { + for (auto& w : it->second) + { + if (g.find(w) == g.end()) + { + continue; // dep not in graph (not a projected namespace) + } + + if (index_of.find(w) == index_of.end()) + { + strongconnect(w, g); + lowlink[v] = (std::min)(lowlink[v], lowlink[w]); + } + else if (on_stack[w]) + { + lowlink[v] = (std::min)(lowlink[v], index_of[w]); + } + } + } + + if (lowlink[v] == index_of[v]) + { + std::vector scc; + std::string w; + do + { + w = stack.back(); + stack.pop_back(); + on_stack[w] = false; + scc.push_back(std::move(w)); + } while (scc.back() != v); + result.push_back(std::move(scc)); + } + } + }; + + context ctx; + for (auto& [node, _] : graph) + { + if (ctx.index_of.find(node) == ctx.index_of.end()) + { + ctx.strongconnect(node, graph); + } + } + return std::move(ctx.result); + } + static int run(int const argc, char** argv) { int result{}; @@ -342,11 +436,30 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder w.flush_to_console(); task_group group; group.synchronous(args.exists("synchronous")); - writer ixx; - write_preamble(ixx); - ixx.write("module;\n"); - ixx.write(strings::base_includes); - ixx.write("\nexport module winrt;\n#define WINRT_EXPORT export\n\n"); + + // Dependency collection for per-namespace modules (v2) + std::map, std::less<>> ns_deps_map; + std::set projected_namespaces; + std::mutex ns_deps_mutex; + + // First pass: determine which namespaces will be in the module. + // This includes namespaces from this invocation AND those from other invocations + // (e.g., platform namespaces when building a component). The module_filter + // tells us which namespaces have modules across all invocations. + if (settings.modules) + { + for (auto&& [ns, members] : c.namespaces()) + { + if (!has_projected_types(members)) + { + continue; + } + if (settings.module_filter.empty() || settings.module_filter.includes(members)) + { + projected_namespaces.insert(std::string(ns)); + } + } + } for (auto&&[ns, members] : c.namespaces()) { @@ -355,21 +468,29 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder continue; } - ixx.write("#include \"winrt/%.h\"\n", ns); - group.add([&, &ns = ns, &members = members] { - write_namespace_0_h(ns, members); - write_namespace_1_h(ns, members); - write_namespace_2_h(ns, members); - write_namespace_h(c, ns, members); + bool in_module = projected_namespaces.count(std::string(ns)) > 0; + std::set ns_deps; + auto* deps_ptr = (settings.modules && in_module) ? &ns_deps : nullptr; + + write_namespace_0_h(ns, members, deps_ptr); + write_namespace_1_h(ns, members, deps_ptr); + write_namespace_2_h(ns, members, deps_ptr); + write_namespace_h(c, ns, members, deps_ptr); + + if (settings.modules && in_module) + { + std::lock_guard lock(ns_deps_mutex); + ns_deps_map[std::string(ns)] = std::move(ns_deps); + } }); } if (settings.base) { write_base_h(); - ixx.flush_to_file(settings.output_folder + "winrt/winrt.ixx"); + write_macros_h(); } if (settings.component) @@ -404,6 +525,64 @@ R"( local Local ^%WinDir^%\System32\WinMetadata folder group.get(); + // Generate per-namespace module interface files (.ixx) + // + // Each projected namespace gets its own C++20 named module (winrt.). + // Namespaces that form dependency cycles are detected using Tarjan's SCC algorithm + // and consolidated: one namespace "owns" the SCC module (containing all declarations), + // while others get thin re-export stubs so 'import winrt.;' always works. + // + // Base infrastructure modules (winrt_base, winrt_numerics) are only generated + // for platform projection builds (-base flag). + if (settings.modules) + { + if (settings.base) + { + write_numerics_ixx(); + write_base_ixx(); + } + + // Tarjan's SCC algorithm for cyclic namespace dependencies + auto sccs = find_sccs(ns_deps_map); + + for (auto& scc : sccs) + { + if (scc.size() == 1) + { + // Standalone namespace module + auto& ns = scc[0]; + write_namespace_ixx(ns, ns_deps_map[ns]); + } + else + { + // SCC: choose owner (alphabetically first), others re-export + std::sort(scc.begin(), scc.end()); + auto& owner = scc[0]; + + // External deps = union of all SCC members' deps, minus SCC members themselves + std::set external_deps; + std::set scc_set(scc.begin(), scc.end()); + for (auto& ns : scc) + { + for (auto& dep : ns_deps_map[ns]) + { + if (!scc_set.count(dep)) + { + external_deps.insert(dep); + } + } + } + + write_namespace_scc_owner_ixx(c, owner, scc, external_deps); + + for (size_t i = 1; i < scc.size(); ++i) + { + write_namespace_reexport_ixx(scc[i], owner); + } + } + } + } + if (settings.verbose) { w.write(" time: %ms\n", get_elapsed_time(start)); diff --git a/cppwinrt/settings.h b/cppwinrt/settings.h index e07df4ea2..110e64917 100644 --- a/cppwinrt/settings.h +++ b/cppwinrt/settings.h @@ -31,6 +31,12 @@ namespace cppwinrt bool fastabi{}; std::map fastabi_cache; + + bool modules{}; // Generate per-namespace C++20 module interface units (.ixx) + + std::set module_include; + std::set module_exclude; + winmd::reader::filter module_filter; }; extern settings_type settings; diff --git a/docs/modules-design.md b/docs/modules-design.md new file mode 100644 index 000000000..8327231a7 --- /dev/null +++ b/docs/modules-design.md @@ -0,0 +1,190 @@ +# C++/WinRT Per-Namespace Modules: Design & Internals + +This document describes the design and implementation of per-namespace C++20 module support in C++/WinRT. It is intended for cppwinrt maintainers and contributors. + +## Architecture Overview + +The module system generates one C++20 named module per WinRT namespace. Each module encapsulates the same content as the traditional header files but exports declarations via `WINRT_EXPORT` in module purview. + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ winrt_numerics.ixx ── export module winrt_numerics; │ +│ winrt_base.ixx ── export module winrt_base; │ +│ export import winrt_numerics; │ +│ winrt.Windows.Foundation.ixx │ +│ ── export module winrt.Windows.Foundation; │ +│ import std; export import winrt_base; │ +│ import winrt.Windows.Foundation.Collections; │ +│ #include "winrt/impl/Windows.Foundation.0.h" │ +│ ... │ +│ #include "winrt/Windows.Foundation.h" │ +└─────────────────────────────────────────────────────────────────┘ +``` + +## Key Design Decisions + +### Unconditional Guards + +Module guards (`WINRT_IMPL_BUILD_MODULE`, `WINRT_IMPORT_MODULE`) are emitted unconditionally in generated projection headers — they are always present regardless of whether `-modules` was passed to cppwinrt.exe. The `-modules` flag controls `.ixx` generation and whether generated component files (`module.g.cpp`, stub `.cpp`) use module imports. This means: + +- Projection headers generated without `-modules` still work correctly when later compiled inside a module interface unit +- No regeneration of projection headers needed when switching between header and module consumption + +### WINRT_EXPORT Macro + +`WINRT_EXPORT` is defined in `base_macros.h` (generated as `winrt/base_macros.h`): +- When `WINRT_IMPL_BUILD_MODULE` is defined (inside `.ixx` compilation): `export extern "C++"` +- Otherwise (header mode): empty + +All `namespace winrt::impl` and `namespace std` blocks use `WINRT_EXPORT` so they export correctly from modules. The `extern "C++"` wrapping enables include-before-import compatibility (same technique as MSVC STL). + +### Per-Namespace vs Monolithic + +Unlike the v1 approach (single `import winrt;`), v2 generates one module per namespace. This provides: + +- **Finer granularity**: Import only what you need +- **Better parallelism**: Independent modules compile in parallel +- **Component module support**: Component namespaces get their own modules + +The trade-off is handling dependency cycles between namespaces (see SCC below). + +This is enforced via the MSBuild `CppWinRTConsumeModule` metadata on ProjectReference — it only points at the platform module builder, not at component projects. + +## Code Generator Pipeline + +### Entry Point: `main.cpp` + +1. **Namespace enumeration**: First pass determines which namespaces are module-eligible using `module_filter` (from `-module_include`/`-module_exclude`) + +2. **Header generation**: Standard header generation with optional dependency collection. When `-modules` is active and a namespace is in the module, `write_namespace_*_h()` functions populate `ns_deps` sets via the `deps_ptr` parameter + +3. **Dependency graph construction**: After all headers are generated, `ns_deps_map` contains the full namespace dependency graph + +4. **SCC detection**: Tarjan's algorithm (`find_sccs()`) identifies strongly-connected components + +5. **Module generation**: For each SCC: + - Size 1: `write_namespace_ixx()` — standalone module + - Size > 1: `write_namespace_scc_owner_ixx()` for the owner (alphabetically first) + `write_namespace_reexport_ixx()` for others + +### CLI Options + +| Flag | Description | +|-|-| +| `-modules` | Enable `.ixx` generation | +| `-module_include ...` | Only generate modules for these namespace prefixes | +| `-module_exclude ...` | Skip these namespace prefixes | + +The `module_filter` is populated from these flags and checked against ALL cache namespaces (not just the projection filter). This is important for component builds where the platform namespaces are not being projected but their modules exist from a prior builder invocation. + +### Generated Files + +| File | When Generated | Purpose | +|-|-|-| +| `winrt/base_macros.h` | Always with `-base` | Macros for module builds (WINRT_EXPORT, etc.) | +| `winrt/winrt_base.ixx` | `-modules -base` | Core types module | +| `winrt/winrt_numerics.ixx` | `-modules -base` | Numerics module | +| `winrt/winrt..ixx` | `-modules` | Per-namespace module | + +## SCC (Strongly Connected Components) + +### The Problem + +WinRT namespaces have cyclic dependencies. For example: +- `Windows.Foundation` depends on `Windows.Foundation.Collections` (via `IVector`, `IMap`, etc.) +- `Windows.Foundation.Collections` depends on `Windows.Foundation` (via `IAsyncOperation`, `Uri`, etc.) + +C++20 modules cannot have circular imports. If module A imports module B, then module B cannot import module A. + +### The Solution: SCC Consolidation + +Tarjan's algorithm identifies groups of namespaces that form dependency cycles. These groups (SCCs) are consolidated: + +1. **Owner selection**: The alphabetically first namespace in the SCC becomes the "owner" +2. **Owner module**: Contains ALL declarations from ALL SCC namespaces. Forward-declares all types first, then includes headers in phase order (all `*.0.h`, then `*.1.h`, then `*.2.h`, then public headers) +3. **Re-export stubs**: Other SCC members get thin `.ixx` files that just re-export the owner module + +This means `import winrt.Windows.Foundation;` and `import winrt.Windows.Foundation.Collections;` both work — they resolve to the same underlying module. + +### Example Generated Files + +**Owner** (`winrt.Windows.Foundation.ixx`): +```cpp +module; +#define WINRT_IMPL_BUILD_MODULE +#include "winrt/base_macros.h" +// ... + +// This module is an SCC owner (cycle breaker). The following namespaces +// form a dependency cycle and are consolidated into this single module: +// - Windows.Foundation +// - Windows.Foundation.Collections +// Other SCC namespaces are emitted as re-export stubs. + +export module winrt.Windows.Foundation; + +import std; +export import winrt_base; + +// Forward declarations for all SCC namespaces... +// #include all impl headers in phase order... +``` + +**Re-export stub** (`winrt.Windows.Foundation.Collections.ixx`): +```cpp +// NOTE: This module does not define declarations of its own. +// It re-exports all declarations from the 'winrt.Windows.Foundation' module. +export module winrt.Windows.Foundation.Collections; +export import winrt.Windows.Foundation; +``` + +## MSBuild Integration + +### Targets Flow + +``` +CppWinRTResolveModuleReferences (resolves IFC paths from ProjectReference metadata) + ↓ +CppWinRTMakePlatformProjection (generates headers + .ixx for platform types) +CppWinRTMakeReferenceProjection (generates headers + .ixx for referenced WinMDs) +CppWinRTMakeComponentProjection (generates headers + .ixx for component types) + ↓ +CppWinRTAddModuleInterfaces (discovers .ixx files, adds to ClCompile items) + ↓ +FixupCLCompileOptions (MSVC module dependency scanner processes .ixx) + ↓ +ClCompile (compiles .ixx → .ifc + .obj) +``` + +### Key Properties + +- `CppWinRTBuildModule`: Enables `-modules` for all three projections (platform, reference, component), causing `.ixx` generation and compilation. +- `CppWinRTConsumeModule` (ProjectReference metadata): Per-reference opt-in for IFC consumption. When set, suppresses `-modules` on the platform projection so the consumer uses pre-built IFCs from the referenced project instead of generating its own. +- `_CppWinRTConsumesPlatformModules`: Internal property set by `CppWinRTResolveModuleReferences` when any ProjectReference has `CppWinRTConsumeModule=true`. Controls whether the platform projection receives `-modules`. + +### Cross-Project IFC Resolution + +MSVC's module dependency scanner uses `/ifcSearchDir` for within-project module resolution. For cross-project modules, the scanner generates explicit `/reference "module.name=path.ifc"` entries based on the dependency scan results. The `/ifcSearchDir` pointing to the builder's `$(IntDir)` allows the scanner to find the pre-built IFCs. + +## Dependency Collection + +During header generation, when `-modules` is active, each `write_namespace_*_h()` function receives a `deps_ptr` parameter. The writer's `w.depends` map is inspected to find referenced namespaces. Only namespaces that: +1. Exist in the cache +2. Have projected types +3. Are in the module namespace set (or set is empty) + +are added to the dependency set. Self-references are excluded. The union of dependencies from all four header files (`*.0.h`, `*.1.h`, `*.2.h`, `.h`) gives the complete dependency set for a namespace module. + +## Testing + +### test/test_cpp20_module/ (in-repo) + +Standalone test built by the main solution. Uses a PreBuildEvent to run cppwinrt.exe with `-modules -base -module_include "Windows.Foundation"`. Tests URI, events, collections, and coroutines. + +### test/nuget/ (NuGet integration) + +Multi-project solution: +- **TestModuleBuilder**: Static library that pre-builds platform modules +- **TestModuleComponent1**: Component DLL (Greeter class), consumes builder's modules +- **TestModuleComponent2**: Component DLL (GreeterGroup), depends on Component1 +- **TestModuleConsumerApp**: Console app, consumes builder + both components +- **TestModuleApp**: Single-project that builds and consumes its own modules diff --git a/natvis/pch.h b/natvis/pch.h index 95e561971..3de6807b3 100644 --- a/natvis/pch.h +++ b/natvis/pch.h @@ -12,6 +12,7 @@ #include #include "base_includes.h" #include "base_macros.h" +#include "base_source_location.h" #include "base_types.h" #include "base_extern.h" #include "base_meta.h" diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index 188e56835..a297258f3 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -26,6 +26,10 @@ Copyright (C) Microsoft Corporation. All rights reserved. $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)))..\..\ $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory))) $(CppWinRTParameters) -fastabi + + -modules + -module_include $(CppWinRTModuleInclude.Replace(';', ' ')) + $(CppWinRTCommandModuleFilter) -module_exclude $(CppWinRTModuleExclude.Replace(';', ' ')) "$(CppWinRTPackageDir)bin\" "$(CppWinRTPackageDir)" @@ -651,6 +655,9 @@ $(XamlMetaDataProviderPch) <_CppwinrtParameters>$(CppWinRTCommandVerbosity) $(CppWinRTParameters) + + <_CppwinrtParameters Condition="'$(_CppWinRTConsumesPlatformModules)'!='true'">$(_CppwinrtParameters) $(CppWinRTCommandModules) $(CppWinRTCommandModuleFilter) <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtInputs->'-in "%(WinMDPath)"', ' ') <_CppwinrtParameters>$(_CppwinrtParameters) -out "$(GeneratedFilesDir)." @@ -729,7 +736,7 @@ $(XamlMetaDataProviderPch) <_CppwinrtRefRefs Include="@(CppWinRTPlatformWinMDReferences)"/> - <_CppwinrtParameters>$(CppWinRTCommandVerbosity) $(CppWinRTParameters) + <_CppwinrtParameters>$(CppWinRTCommandVerbosity) $(CppWinRTParameters) $(CppWinRTCommandModules) $(CppWinRTCommandModuleFilter) <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtRefInputs->'-in "%(WinMDPath)"', ' ') <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtRefRefs->'-ref "%(WinMDPath)"', ' ') <_CppwinrtParameters>$(_CppwinrtParameters) -out "$(GeneratedFilesDir)." @@ -835,7 +842,7 @@ $(XamlMetaDataProviderPch) <_CppwinrtCompRefs Include="@(CppWinRTPlatformWinMDReferences)"/> - <_CppwinrtParameters>$(CppWinRTCommandVerbosity) $(CppWinRTParameters) -overwrite -name $(RootNamespace) $(CppWinRTCommandPrecompiledHeader) $(CppWinRTCommandUsePrefixes) -comp "$(GeneratedFilesDir)sources" + <_CppwinrtParameters>$(CppWinRTCommandVerbosity) $(CppWinRTParameters) $(CppWinRTCommandModules) $(CppWinRTCommandModuleFilter) -overwrite -name $(RootNamespace) $(CppWinRTCommandPrecompiledHeader) $(CppWinRTCommandUsePrefixes) -comp "$(GeneratedFilesDir)sources" <_CppwinrtParameters Condition="'$(CppWinRTOptimized)'=='true'">$(_CppwinrtParameters) -opt <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtCompInputs->'-in "%(WinMDPath)"', ' ') <_CppwinrtParameters>$(_CppwinrtParameters) @(_CppwinrtCompRefs->'-ref "%(WinMDPath)"', ' ') @@ -895,4 +902,88 @@ $(XamlMetaDataProviderPch) + + + + + CompileAsCppModule + true + NotUsing + + + + + + + + + $(GeneratedFilesDir) + $(IntDir) + $(OutDir) + + + + + + + + + <_CppWinRTModuleProviders Remove="@(_CppWinRTModuleProviders)" /> + <_CppWinRTModuleProviders Include="@(ProjectReference)" + Condition="'%(ProjectReference.CppWinRTConsumeModule)' == 'true'" /> + + + + + <_CppWinRTConsumesPlatformModules>true + + + + + + + + + + + + + <_CppWinRTModuleIfcSearchDirs>@(_CppWinRTResolvedModuleRefs->'%(CppWinRTModuleIfcDir)') + + + + $(_CppWinRTModuleIfcSearchDirs);%(ClCompile.AdditionalBMIDirectories) + + + + diff --git a/nuget/modules.md b/nuget/modules.md new file mode 100644 index 000000000..479781252 --- /dev/null +++ b/nuget/modules.md @@ -0,0 +1,179 @@ +# C++/WinRT C++20 Modules Guide + +## Overview + +C++/WinRT can generate per-namespace C++20 named modules (`.ixx` files) alongside the traditional projection headers. This allows you to write: + +```cpp +import winrt.Windows.Foundation; +``` + +instead of: + +```cpp +#include +``` + +Modules provide faster builds through pre-compiled module interfaces (IFCs) and better isolation of macro and declaration scopes. + +## Quick Start — Single Project + +For a project that builds and consumes its own modules: + +1. Set `CppWinRTBuildModule` to `true` in your project: + ```xml + + true + + ``` + +2. Optionally limit which namespaces get modules: + ```xml + + Windows.Foundation;Windows.Storage + + ``` + +3. Enable `BuildStlModules` for `import std;` support: + ```xml + + true + + ``` + +4. In your `.cpp` files: + ```cpp + import winrt.Windows.Foundation; + + int main() { + winrt::init_apartment(); + winrt::Windows::Foundation::Uri uri(L"https://example.com"); + } + ``` + +## Quick Start — Multi-Project (Recommended) + +For larger solutions, compile platform modules once in a dedicated "builder" static library, and share the pre-built IFCs with other projects. + +### Module Builder (static library) + +```xml + + StaticLibrary + true + Windows.Foundation + +``` + +### Consumer (exe or dll) + +```xml + + true + + + + true + + +``` + +The `CppWinRTConsumeModule` metadata on the ProjectReference tells the build system to: +- Use the builder's pre-built platform IFCs instead of compiling platform `.ixx` files again +- Skip generating platform `.ixx` files in the consumer's own projection + +### Component DLLs + +WinRT component projects can also use modules. Set `CppWinRTBuildModule=true` and all three projections (platform, reference, component) will generate `.ixx` files. + +```xml + + true + MyComponent + + + + true + + +``` + +### Consuming Components from Other Projects + +If project A references a component DLL from project B, project A builds its own reference projection modules from B's `.winmd`: + +```cpp +// These modules are built locally from the component's .winmd +import winrt.MyComponent; + +auto obj = winrt::MyComponent::MyClass(); +``` + +## MSBuild Properties + +| Property | Default | Description | +|-|-|-| +| `CppWinRTBuildModule` | false | Generate `.ixx` module interface units from projections | +| `CppWinRTModuleInclude` | (all) | Semicolon-delimited namespace prefixes to include in module generation | +| `CppWinRTModuleExclude` | (none) | Semicolon-delimited namespace prefixes to exclude from module generation | + +| ProjectReference Metadata | Default | Description | +|-|-|-| +| `CppWinRTConsumeModule` | false | Consume pre-built platform module IFCs from this project reference | + +## Module Filtering and Transitive Dependencies + +`CppWinRTModuleInclude` and `CppWinRTModuleExclude` control which namespace `.ixx` files are **generated**, but they do not suppress `import` statements for dependencies. If namespace A is included in the filter and depends on namespace B, the generated `winrt.A.ixx` will contain `import winrt.B;` even if B is excluded from the filter. This is by design — the module for B must exist *somewhere* (either from the same project or from a referenced project). + +This has important implications: + +- **Transitive closure must be satisfied.** If you filter to a subset of namespaces, any dependencies that fall outside the filter must be available from another source (e.g., a module builder project referenced via `CppWinRTConsumeModule`, or MSBuild's automatic `ReferencedModuleBMIs` from a static library reference). Otherwise, compilation will fail with "could not find module" errors. + +- **Use `CppWinRTModuleExclude` to avoid generating modules that have unsatisfied dependencies.** For example, `Windows.Foundation.Diagnostics` depends on `Windows.Storage`. If you filter to `CppWinRTModuleInclude=Windows.Foundation`, the Diagnostics `.ixx` will be generated (it matches the prefix) but will fail to compile because `winrt.Windows.Storage` doesn't exist. Add `CppWinRTModuleExclude=Windows.Foundation.Diagnostics` to prevent this. + +- **In multi-project scenarios with static libraries, use `CppWinRTModuleExclude` to avoid duplicate modules.** MSBuild automatically propagates all module IFCs from static library references to consuming projects (via the `AllProjectBMIsArePublic` property, which defaults to `true` for static libraries). If project A is a static library that builds modules for namespace X, and project B references A, then B already has A's IFCs available. If B also has `CppWinRTBuildModule=true`, its reference projection will generate a second `winrt.X.ixx`, causing an ambiguous module error. Set `CppWinRTModuleExclude=X` on project B to prevent this. B's own `.ixx` files will still emit `import winrt.X;`, which resolves to A's IFC via MSBuild's automatic propagation. Note: this issue does not affect DLL references — MSBuild does not propagate module IFCs from DLLs by default. + +## Module Names + +| Module | Contents | +|-|-| +| `winrt_base` | Core C++/WinRT types (`hstring`, `com_ptr`, `IUnknown`, etc.) — re-exported by all namespace modules | +| `winrt_numerics` | `Windows::Foundation::Numerics` types — re-exported by `winrt_base` | +| `winrt.` | Per-namespace projection (e.g., `winrt.Windows.Foundation`) | + +## Requirements + +- MSVC v145 toolset (Visual Studio 2026) or later recommended +- C++20 or later (`/std:c++20` or newer) +- `BuildStlModules=true` for `import std;` support + +## Limitations + +- Module IFCs are not compatible across toolset versions. All projects must use the same toolset. +- Cyclic namespace dependencies (e.g., `Windows.Foundation` ↔ `Windows.Foundation.Collections`) are handled automatically via SCC consolidation, but the resulting module name is chosen alphabetically. Adding new APIs could change SCC groupings. + +## Caution: Module Reuse Across Projects + +Pre-built IFCs (via `CppWinRTConsumeModule`) should only be shared when the builder and consumer use the same compilation context. In particular: + +- **Component modules are project-private.** A component projection built with `CppWinRTOptimized=true` generates modules that bypass activation factories for in-component type instantiation (`-opt`). If a consuming project accidentally imports these modules instead of building its own reference projection, the consumer will attempt direct instantiation across DLL boundaries, resulting in linker errors or incorrect behavior. Each project should build its own modules from the component's `.winmd` — do not tag component ProjectReferences with `CppWinRTConsumeModule`. + +- **`CppWinRTConsumeModule` is intended for platform module builders only.** The builder project is a dedicated static library whose sole purpose is compiling platform SDK modules. Its compilation flags (no `-opt`, no `-comp`) produce modules safe for any consumer. Only tag this builder's ProjectReference with `CppWinRTConsumeModule=true`. + +- **Module filter scope matters.** `CppWinRTModuleInclude` / `CppWinRTModuleExclude` applies to all three projections (platform, reference, component). If you set `CppWinRTModuleInclude=MyComponent`, only `MyComponent` namespaces will get `.ixx` files — platform and reference namespace modules will not be generated. Make sure your filter includes all namespaces you intend to import as modules, or use `CppWinRTConsumeModule` to get platform modules from a builder that was configured with the appropriate filter. + +- **Compilation settings must be compatible between builder and consumer.** Module IFCs encode assumptions about the compilation environment. While the compiler may not always diagnose mismatches, the following differences between the module builder and consumer may cause subtle or hard-to-diagnose issues: + - **Debug vs Release** — Mixing Debug and Release configurations can produce mismatched code generation, iterator debugging levels, and runtime library selections. + - **Preprocessor definitions** — Definitions that affect type layout, conditional compilation, or feature flags should match between builder and consumer. + - **Struct alignment / packing** — Different `/Zp` settings between projects can change struct layout, causing silent ABI mismatches. + - **Language standard** — While C++20 and later are generally compatible, mixing `/std:c++20` and `/std:c++23` and/or `/std:c++latest` if there are language features that affect type definitions. + + As a general rule, the module builder project try to use the same configuration, preprocessor definitions, and compiler options as its consumers. + +## Troubleshooting + +**"could not find module 'winrt.X'"** — Ensure the `.ixx` was generated (check `$(GeneratedFilesDir)winrt\`) and that `CppWinRTBuildModule=true` is set. For cross-project references, verify the consuming project's `ProjectReference` to the builder has `CppWinRTConsumeModule=true`, and that the builder's `IntDir` is accessible via `/ifcSearchDir`. + +**Linker errors for component constructors** — You may be importing a component's internal module instead of building your own reference projection. Remove explicit `/reference` flags for component IFCs and ensure your project has `CppWinRTBuildModule=true` so it builds reference projection modules from the component's `.winmd`. + +**Redefinition errors** — Don't mix `#include` and `import` for the same namespace in the same translation unit. Use `import` consistently. diff --git a/nuget/readme.md b/nuget/readme.md index 9379aa716..c8c0b9537 100644 --- a/nuget/readme.md +++ b/nuget/readme.md @@ -70,6 +70,9 @@ C++/WinRT behavior can be customized with these project properties: | CppWinRTOptimized | true \| *false | Enables component projection [optimization features](https://kennykerr.ca/2019/06/07/cppwinrt-optimizing-components/) | | CppWinRTGenerateWindowsMetadata | true \| *false | Indicates whether this project produces Windows Metadata | | CppWinRTEnableDefaultPrivateFalse | true \| *false | Indicates whether this project uses C++/WinRT optimized default for copying binaries to the output directory | +| CppWinRTBuildModule | true \| *false | Generates per-namespace C++20 module interface units (.ixx) alongside projection headers | +| CppWinRTModuleInclude | namespace list | Semicolon-delimited namespaces to include in module generation (default: all) | +| CppWinRTModuleExclude | namespace list | Semicolon-delimited namespaces to exclude from module generation | \*Default value To customize common C++/WinRT project properties: @@ -132,6 +135,15 @@ void DerivedPage::InitializeComponent() } ``` +## C++20 Modules + +C++/WinRT supports C++20 named modules as an alternative to `#include`-based consumption. Instead of `#include `, you can write `import winrt.Windows.Foundation;`. See [modules.md](modules.md) for the full guide. + +| ProjectReference metadata | Description | +|-|-| +| CppWinRTConsumeModule | true \| *false | When set on a ProjectReference, consumes pre-built platform module IFCs from the referenced project | +\*Default value + ## Troubleshooting The msbuild verbosity level maps to msbuild message importance as follows: diff --git a/strings/base_abi.h b/strings/base_abi.h index 72946a3fa..4b7b8f77f 100644 --- a/strings/base_abi.h +++ b/strings/base_abi.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template <> struct abi { diff --git a/strings/base_activation.h b/strings/base_activation.h index 1a195d865..c657c692d 100644 --- a/strings/base_activation.h +++ b/strings/base_activation.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct library_traits { @@ -125,7 +125,7 @@ WINRT_EXPORT namespace winrt #define WINRT_IMPL_INTERLOCKED_READ_MEMORY_BARRIER (__dmb(_ARM64_BARRIER_ISH)); #endif -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { inline std::int32_t interlocked_read_32(std::int32_t const volatile* target) noexcept { @@ -548,7 +548,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template T fast_activate(Windows::Foundation::IActivationFactory const& factory) diff --git a/strings/base_agile_ref.h b/strings/base_agile_ref.h index 88fbea065..14447706a 100644 --- a/strings/base_agile_ref.h +++ b/strings/base_agile_ref.h @@ -47,7 +47,7 @@ WINRT_EXPORT namespace winrt #endif } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct module_lock_updater; diff --git a/strings/base_array.h b/strings/base_array.h index 48d10c6ce..d29bee883 100644 --- a/strings/base_array.h +++ b/strings/base_array.h @@ -483,7 +483,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct array_size_proxy diff --git a/strings/base_collections.h b/strings/base_collections.h index 4e1af51eb..7d8dc2e77 100644 --- a/strings/base_collections.h +++ b/strings/base_collections.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { namespace wfc = Windows::Foundation::Collections; diff --git a/strings/base_collections_base.h b/strings/base_collections_base.h index 6fe10fa64..d299cc0c8 100644 --- a/strings/base_collections_base.h +++ b/strings/base_collections_base.h @@ -1,4 +1,4 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct nop_lock_guard {}; diff --git a/strings/base_collections_input_iterable.h b/strings/base_collections_input_iterable.h index e75211c30..e9d3af251 100644 --- a/strings/base_collections_input_iterable.h +++ b/strings/base_collections_input_iterable.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct input_iterable : diff --git a/strings/base_collections_input_map.h b/strings/base_collections_input_map.h index b33975fe6..3fe146bf6 100644 --- a/strings/base_collections_input_map.h +++ b/strings/base_collections_input_map.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct map_impl : diff --git a/strings/base_collections_input_map_view.h b/strings/base_collections_input_map_view.h index bfd8d82a9..d79eed61d 100644 --- a/strings/base_collections_input_map_view.h +++ b/strings/base_collections_input_map_view.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct input_map_view : diff --git a/strings/base_collections_input_vector.h b/strings/base_collections_input_vector.h index b5b76de38..a06e73b33 100644 --- a/strings/base_collections_input_vector.h +++ b/strings/base_collections_input_vector.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct vector_impl : diff --git a/strings/base_collections_input_vector_view.h b/strings/base_collections_input_vector_view.h index 3793e239a..30768c18e 100644 --- a/strings/base_collections_input_vector_view.h +++ b/strings/base_collections_input_vector_view.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct input_vector_view : diff --git a/strings/base_collections_map.h b/strings/base_collections_map.h index fa769fb88..6bf884236 100644 --- a/strings/base_collections_map.h +++ b/strings/base_collections_map.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template using multi_threaded_map = map_impl; @@ -116,7 +116,7 @@ WINRT_EXPORT namespace winrt } } -namespace std +WINRT_EXPORT namespace std { template struct tuple_size> @@ -132,7 +132,7 @@ namespace std }; } -namespace winrt::Windows::Foundation::Collections +WINRT_EXPORT namespace winrt::Windows::Foundation::Collections { template std::tuple_element_t> get(IKeyValuePair const& kvp) diff --git a/strings/base_collections_vector.h b/strings/base_collections_vector.h index 3e9c1b254..3388806af 100644 --- a/strings/base_collections_vector.h +++ b/strings/base_collections_vector.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template using multi_threaded_vector = vector_impl; diff --git a/strings/base_com_ptr.h b/strings/base_com_ptr.h index 27496789a..0f02fabeb 100644 --- a/strings/base_com_ptr.h +++ b/strings/base_com_ptr.h @@ -5,7 +5,7 @@ WINRT_EXPORT namespace winrt struct com_ptr; } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct capture_decay { @@ -349,7 +349,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template std::int32_t capture_to(void** result, com_ptr const& object, M method, Args&& ...args) diff --git a/strings/base_composable.h b/strings/base_composable.h index e606d1292..5a7712ef7 100644 --- a/strings/base_composable.h +++ b/strings/base_composable.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct composable_factory diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 4f1c8d0b6..5cefad836 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct async_completed_handler; @@ -312,7 +312,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct cancellation_token @@ -704,7 +704,7 @@ namespace winrt::impl }; } -namespace std +WINRT_IMPL_STD_EXPORT namespace std { template struct coroutine_traits diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index 6748906ca..057d5b548 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { #ifdef WINRT_IMPL_COROUTINES inline auto submit_threadpool_callback(void(__stdcall* callback)(void*, void* context), void* context) @@ -321,7 +321,7 @@ WINRT_EXPORT namespace winrt }; } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct apartment_awaiter { @@ -671,7 +671,7 @@ WINRT_EXPORT namespace winrt struct fire_and_forget {}; } -namespace std +WINRT_IMPL_STD_EXPORT namespace std { template struct coroutine_traits diff --git a/strings/base_delegate.h b/strings/base_delegate.h index 1cfe58710..1fe00ecd1 100644 --- a/strings/base_delegate.h +++ b/strings/base_delegate.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { #if defined(_MSC_VER) #pragma warning(push) diff --git a/strings/base_detect_numerics.h b/strings/base_detect_numerics.h new file mode 100644 index 000000000..6a93a8ffa --- /dev/null +++ b/strings/base_detect_numerics.h @@ -0,0 +1,4 @@ + +#if __has_include() +#define WINRT_IMPL_NUMERICS +#endif diff --git a/strings/base_error.h b/strings/base_error.h index c58635e5d..d42ca516b 100644 --- a/strings/base_error.h +++ b/strings/base_error.h @@ -7,7 +7,7 @@ #define WINRT_IMPL_RETURNADDRESS() nullptr #endif -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct heap_traits { @@ -536,7 +536,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { inline hresult check_hresult_allow_bounds(hresult const result, winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()) { diff --git a/strings/base_events.h b/strings/base_events.h index f7e2e6976..c21124e9c 100644 --- a/strings/base_events.h +++ b/strings/base_events.h @@ -130,7 +130,7 @@ WINRT_EXPORT namespace winrt }; } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct event_revoker diff --git a/strings/base_extern.h b/strings/base_extern.h index 84e2943c4..a17908ac4 100644 --- a/strings/base_extern.h +++ b/strings/base_extern.h @@ -1,8 +1,11 @@ -__declspec(selectany) std::int32_t(__stdcall* winrt_to_hresult_handler)(void* address) noexcept {}; -__declspec(selectany) winrt::hstring(__stdcall* winrt_to_message_handler)(void* address) {}; -__declspec(selectany) void(__stdcall* winrt_throw_hresult_handler)(std::uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept {}; -__declspec(selectany) std::int32_t(__stdcall* winrt_activation_handler)(void* classId, winrt::guid const& iid, void** factory) noexcept {}; +// These global function pointers must use WINRT_EXPORT (which expands to +// 'export extern "C++"' in module builds) so that module and non-module TUs +// in the same binary share the same instances. +WINRT_EXPORT __declspec(selectany) std::int32_t(__stdcall* winrt_to_hresult_handler)(void* address) noexcept {}; +WINRT_EXPORT __declspec(selectany) winrt::hstring(__stdcall* winrt_to_message_handler)(void* address) {}; +WINRT_EXPORT __declspec(selectany) void(__stdcall* winrt_throw_hresult_handler)(std::uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept {}; +WINRT_EXPORT __declspec(selectany) std::int32_t(__stdcall* winrt_activation_handler)(void* classId, winrt::guid const& iid, void** factory) noexcept {}; #if defined(_MSC_VER) #ifdef _M_HYBRID diff --git a/strings/base_fast_forward.h b/strings/base_fast_forward.h index dc89fe6ce..a73e70a04 100644 --- a/strings/base_fast_forward.h +++ b/strings/base_fast_forward.h @@ -30,7 +30,11 @@ static_assert(WINRT_FAST_ABI_SIZE >= %); #pragma detect_mismatch("WINRT_FAST_ABI_SIZE", WINRT_IMPL_STRING(WINRT_FAST_ABI_SIZE)) -namespace winrt::impl +#ifndef WINRT_EXPORT +#define WINRT_EXPORT +#endif // WINRT_EXPORT + +WINRT_EXPORT namespace winrt::impl { // Thunk definitions are in arch-specific assembly sources % diff --git a/strings/base_foundation.h b/strings/base_foundation.h index ea8881edc..083252753 100644 --- a/strings/base_foundation.h +++ b/strings/base_foundation.h @@ -100,7 +100,7 @@ WINRT_EXPORT namespace winrt::Windows::Foundation } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template <> inline constexpr auto& name_v = L"Windows.Foundation.Point"; template <> inline constexpr auto& name_v = L"Windows.Foundation.Size"; diff --git a/strings/base_identity.h b/strings/base_identity.h index 30830bc5a..7c61c83e2 100644 --- a/strings/base_identity.h +++ b/strings/base_identity.h @@ -17,7 +17,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template constexpr std::array to_array(T const* value, std::index_sequence const) noexcept diff --git a/strings/base_implements.h b/strings/base_implements.h index 7edf32149..0eb8db0bd 100644 --- a/strings/base_implements.h +++ b/strings/base_implements.h @@ -6,7 +6,7 @@ #endif #endif -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct marker { @@ -30,7 +30,7 @@ WINRT_EXPORT namespace winrt struct implements; } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template using tuple_cat_t = decltype(std::tuple_cat(std::declval()...)); @@ -267,7 +267,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct interface_list; diff --git a/strings/base_include_numerics.h b/strings/base_include_numerics.h new file mode 100644 index 000000000..4b7658fff --- /dev/null +++ b/strings/base_include_numerics.h @@ -0,0 +1,19 @@ + +// Includes when WINRT_IMPL_NUMERICS is defined. +// Requires to already be included (via base_detect_numerics). +// The types are redirected into winrt::Windows::Foundation::Numerics via macro wrapping. +// Uses WINRT_EXPORT for the namespace declaration, which resolves to 'export extern "C++"' +// in module builds and nothing in header builds. +#ifdef WINRT_IMPL_NUMERICS +#ifndef WINRT_EXPORT +#define WINRT_EXPORT +#endif +#include +#define _WINDOWS_NUMERICS_NAMESPACE_ winrt::Windows::Foundation::Numerics +#define _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ WINRT_EXPORT namespace winrt::Windows::Foundation::Numerics +#define _WINDOWS_NUMERICS_END_NAMESPACE_ +#include +#undef _WINDOWS_NUMERICS_NAMESPACE_ +#undef _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ +#undef _WINDOWS_NUMERICS_END_NAMESPACE_ +#endif // WINRT_IMPL_NUMERICS diff --git a/strings/base_includes.h b/strings/base_includes.h index d6808792b..287a09709 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -31,11 +31,6 @@ #include #endif -#if __has_include() -#define WINRT_IMPL_NUMERICS -#include -#endif - #ifndef WINRT_LEAN_AND_MEAN #include #endif diff --git a/strings/base_iterator.h b/strings/base_iterator.h index acb0ebd42..46c0c6b63 100644 --- a/strings/base_iterator.h +++ b/strings/base_iterator.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct fast_iterator diff --git a/strings/base_macros.h b/strings/base_macros.h index 3dc01fa2d..91b0121d9 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -1,3 +1,6 @@ +#pragma once +#ifndef WINRT_BASE_MACROS_H +#define WINRT_BASE_MACROS_H #ifdef _DEBUG @@ -11,7 +14,11 @@ #define WINRT_VERIFY(expression) (void)(expression) #define WINRT_VERIFY_(result, expression) (void)(expression) -#endif +#endif // _DEBUG + +#if defined(__cpp_lib_coroutine) +#define WINRT_IMPL_COROUTINES +#endif // __cpp_lib_coroutine #define WINRT_IMPL_SHIM(...) (*(abi_t<__VA_ARGS__>**)&static_cast<__VA_ARGS__ const&>(static_cast(*this))) @@ -21,25 +28,30 @@ // Note: this is a workaround for a false-positive warning produced by the Visual C++ 16.3 compiler. #pragma warning(disable : 4268) -#endif -#if defined(__cpp_lib_coroutine) -#define WINRT_IMPL_COROUTINES -#endif +// C++ module warnings by /W4 +#pragma warning(disable : 4499) +#pragma warning(disable : 4630) +#endif // _MSC_VER #ifndef WINRT_EXPORT +#ifdef WINRT_IMPL_BUILD_MODULE +#define WINRT_EXPORT export extern "C++" +#else #define WINRT_EXPORT -#endif - -#ifdef WINRT_IMPL_NUMERICS -#define _WINDOWS_NUMERICS_NAMESPACE_ winrt::Windows::Foundation::Numerics -#define _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ WINRT_EXPORT namespace winrt::Windows::Foundation::Numerics -#define _WINDOWS_NUMERICS_END_NAMESPACE_ -#include -#undef _WINDOWS_NUMERICS_NAMESPACE_ -#undef _WINDOWS_NUMERICS_BEGIN_NAMESPACE_ -#undef _WINDOWS_NUMERICS_END_NAMESPACE_ -#endif +#endif // WINRT_IMPL_BUILD_MODULE +#endif // WINRT_EXPORT + +// Template specializations in namespace std (hash, coroutine_traits) need extern "C++" +// linkage in module builds for proper merging with the std module, but must NOT be +// exported — exporting namespace std would make all of std transitively visible. +#ifndef WINRT_IMPL_STD_EXPORT +#ifdef WINRT_IMPL_BUILD_MODULE +#define WINRT_IMPL_STD_EXPORT extern "C++" +#else +#define WINRT_IMPL_STD_EXPORT +#endif // WINRT_IMPL_BUILD_MODULE +#endif // WINRT_IMPL_STD_EXPORT #if defined(_MSC_VER) #define WINRT_IMPL_NOINLINE __declspec(noinline) @@ -81,7 +93,7 @@ #define WINRT_IMPL_HAS_DECLSPEC_UUID 0 #endif -#ifdef __IUnknown_INTERFACE_DEFINED__ +#if defined(__IUnknown_INTERFACE_DEFINED__) || defined(WINRT_ENABLE_LEGACY_COM) #define WINRT_IMPL_IUNKNOWN_DEFINED #else // Forward declare so we can talk about it. @@ -95,99 +107,11 @@ typedef struct _GUID GUID; #define WINRT_IMPL_CONSTEVAL constexpr #endif -// The intrinsics (such as __builtin_FILE()) that power std::source_location are also used to power winrt:impl::slim_source_location. -// The source location needs to be for the calling code, not cppwinrt itself, so that it is useful to developers building on top of -// this library. As a result any public-facing method that can result in an error needs a default-constructed slim_source_location -// argument so that it will collect source information from the application code that is calling into cppwinrt. -// -// We do not directly use std::source_location for two reasons: -// 1) std::source_location::function_name() is unavoidable. These strings end up in the final binary, bloating their size. This -// is particularly impactful for code bases that use templates heavily. Cases of 50% binary size growth have been observed. -// 2) std::source_location is a cpp20 feature, which is above the cpp17 feature floor for cppwinrt. By defining our own version -// we can avoid ODR violations in mixed cpp17/cpp20 builds. cpp17 callers will have an ABI that matches cpp20 callers (they -// will just not have useful file/line/function information). -// -// Some projects may decide that the source information binary size impact is not worth the benefit. Defining WINRT_NO_SOURCE_LOCATION -// will prevent this feature from activating. The slim_source_location type will be forwarded around but it will not include any -// nonzero data. That eliminates the biggest source of binary size overhead. -// -// To help with debugging the __builtin_FUNCTION() intrinsic will be used in _DEBUG builds. This will provide a bit more diagnostic -// value at the cost of binary size. The assumption is that binary size is considered less important in debug builds so this tradeoff -// is acceptable. -// -// The different behavior of the default parameters to winrt::impl::slim_source_location::current() is technically an ODR violation, -// albeit a minor one. There should be no serious consequence to this violation. In practice it means that mixing cpp17/cpp20, -// or mixing WINRT_NO_SOURCE_LOCATION with undefining it, will lead to inconsistent source location information. It may be missing -// when it is expected to be included, or it may be present when it is not expected. The behavior will depend on the linker's choice -// when there are multiple translation units with different options. This violation is tracked by https://github.com/microsoft/cppwinrt/issues/1445. - -#if !defined(__cpp_lib_source_location) || defined(WINRT_NO_SOURCE_LOCATION) -// Case1: cpp17 mode. The source_location intrinsics are not available. -// Case2: The caller has disabled source_location support. Ensure that there is no binary size overhead for line/file/function. -#define WINRT_IMPL_BUILTIN_LINE 0 -#define WINRT_IMPL_BUILTIN_FILE nullptr -#define WINRT_IMPL_BUILTIN_FUNCTION nullptr -#elif _DEBUG -// cpp20 _DEBUG builds include function information, which has a heavy binary size impact, in addition to file/line. -#define WINRT_IMPL_BUILTIN_LINE __builtin_LINE() -#define WINRT_IMPL_BUILTIN_FILE __builtin_FILE() -#define WINRT_IMPL_BUILTIN_FUNCTION __builtin_FUNCTION() -#else -// Release builds in cpp20 mode get file and line information but NOT function information. Function strings -// quickly add up to a substantial binary size impact, especially when templates are heavily used. -#define WINRT_IMPL_BUILTIN_LINE __builtin_LINE() -#define WINRT_IMPL_BUILTIN_FILE __builtin_FILE() -#define WINRT_IMPL_BUILTIN_FUNCTION nullptr +// CPPWINRT_VERSION is defined here so it is available in module global fragments. +// In header builds, base_version_odr.h defines it first (before base_macros.h is included), +// so the #ifndef guard prevents redefinition. +#ifndef CPPWINRT_VERSION +#define CPPWINRT_VERSION "%" #endif -namespace winrt::impl -{ - // This struct is intended to be highly similar to std::source_location. The key difference is - // that function_name is NOT included. Function names do not fold to identical strings and can - // have heavy binary size overhead when templates cause many permutations to exist. - struct slim_source_location - { - [[nodiscard]] static WINRT_IMPL_CONSTEVAL slim_source_location current( - const std::uint_least32_t line = WINRT_IMPL_BUILTIN_LINE, - const char* const file = WINRT_IMPL_BUILTIN_FILE, - const char* const function = WINRT_IMPL_BUILTIN_FUNCTION) noexcept - { - return slim_source_location{ line, file, function }; - } - - [[nodiscard]] constexpr slim_source_location() noexcept = default; - - [[nodiscard]] constexpr slim_source_location( - const std::uint_least32_t line, - const char* const file, - const char* const function) noexcept : - m_line(line), - m_file(file), - m_function(function) - {} - - [[nodiscard]] constexpr std::uint_least32_t line() const noexcept - { - return m_line; - } - - [[nodiscard]] constexpr const char* file_name() const noexcept - { - return m_file; - } - - [[nodiscard]] constexpr const char* function_name() const noexcept - { - return m_function; - } - - private: - const std::uint_least32_t m_line{}; - const char* const m_file{}; - const char* const m_function{}; - }; -} - -#ifdef _MSC_VER -#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "slim") -#endif // _MSC_VER +#endif // WINRT_BASE_MACROS_H diff --git a/strings/base_marshaler.h b/strings/base_marshaler.h index 526f4d4c3..9be6959c9 100644 --- a/strings/base_marshaler.h +++ b/strings/base_marshaler.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { inline std::int32_t make_marshaler(unknown_abi* outer, void** result) noexcept { diff --git a/strings/base_meta.h b/strings/base_meta.h index 7dbb4c386..6b28640ef 100644 --- a/strings/base_meta.h +++ b/strings/base_meta.h @@ -48,7 +48,7 @@ WINRT_EXPORT namespace winrt } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { using namespace std::literals; diff --git a/strings/base_module_base_ixx.h b/strings/base_module_base_ixx.h new file mode 100644 index 000000000..5930f54ea --- /dev/null +++ b/strings/base_module_base_ixx.h @@ -0,0 +1,13 @@ + +#include +#include + +#ifdef WINRT_ENABLE_LEGACY_COM +#include +#include +#endif + +export module winrt_base; + +import std; +export import winrt_numerics; diff --git a/strings/base_module_ixx_preamble.h b/strings/base_module_ixx_preamble.h new file mode 100644 index 000000000..114873dc7 --- /dev/null +++ b/strings/base_module_ixx_preamble.h @@ -0,0 +1,11 @@ +module; +#define WINRT_IMPL_BUILD_MODULE + +#if defined(_MSC_VER) && _MSC_VER < 1950 +#pragma message("warning: C++/WinRT modules require MSVC toolset v14.50 (v145) or later. Building with an older toolset is not supported and may produce unexpected errors.") +#endif + +#include +#ifdef _DEBUG +#include +#endif // _DEBUG diff --git a/strings/base_module_numerics_ixx.h b/strings/base_module_numerics_ixx.h new file mode 100644 index 000000000..f1ade01ff --- /dev/null +++ b/strings/base_module_numerics_ixx.h @@ -0,0 +1,6 @@ + +#include + +#if defined(_MSC_VER) +#pragma detect_mismatch("C++/WinRT version", CPPWINRT_VERSION) +#endif diff --git a/strings/base_natvis.h b/strings/base_natvis.h index 60c5f5548..9e78563cb 100644 --- a/strings/base_natvis.h +++ b/strings/base_natvis.h @@ -5,7 +5,7 @@ #ifdef WINRT_NATVIS -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct natvis { diff --git a/strings/base_reference_produce.h b/strings/base_reference_produce.h index 2820aff50..abffb3384 100644 --- a/strings/base_reference_produce.h +++ b/strings/base_reference_produce.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct reference : implements, Windows::Foundation::IReference, Windows::Foundation::IPropertyValue> @@ -420,7 +420,7 @@ WINRT_EXPORT namespace winrt::Windows::Foundation } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template T unbox_value_type(From&& value) diff --git a/strings/base_source_location.h b/strings/base_source_location.h new file mode 100644 index 000000000..c0fd81f9f --- /dev/null +++ b/strings/base_source_location.h @@ -0,0 +1,97 @@ + +// The intrinsics (such as __builtin_FILE()) that power std::source_location are also used to power winrt:impl::slim_source_location. +// The source location needs to be for the calling code, not cppwinrt itself, so that it is useful to developers building on top of +// this library. As a result any public-facing method that can result in an error needs a default-constructed slim_source_location +// argument so that it will collect source information from the application code that is calling into cppwinrt. +// +// We do not directly use std::source_location for two reasons: +// 1) std::source_location::function_name() is unavoidable. These strings end up in the final binary, bloating their size. This +// is particularly impactful for code bases that use templates heavily. Cases of 50% binary size growth have been observed. +// 2) std::source_location is a cpp20 feature, which is above the cpp17 feature floor for cppwinrt. By defining our own version +// we can avoid ODR violations in mixed cpp17/cpp20 builds. cpp17 callers will have an ABI that matches cpp20 callers (they +// will just not have useful file/line/function information). +// +// Some projects may decide that the source information binary size impact is not worth the benefit. Defining WINRT_NO_SOURCE_LOCATION +// will prevent this feature from activating. The slim_source_location type will be forwarded around but it will not include any +// nonzero data. That eliminates the biggest source of binary size overhead. +// +// To help with debugging the __builtin_FUNCTION() intrinsic will be used in _DEBUG builds. This will provide a bit more diagnostic +// value at the cost of binary size. The assumption is that binary size is considered less important in debug builds so this tradeoff +// is acceptable. +// +// The different behavior of the default parameters to winrt::impl::slim_source_location::current() is technically an ODR violation, +// albeit a minor one. There should be no serious consequence to this violation. In practice it means that mixing cpp17/cpp20, +// or mixing WINRT_NO_SOURCE_LOCATION with undefining it, will lead to inconsistent source location information. It may be missing +// when it is expected to be included, or it may be present when it is not expected. The behavior will depend on the linker's choice +// when there are multiple translation units with different options. This violation is tracked by https://github.com/microsoft/cppwinrt/issues/1445. + +#if !defined(__cpp_lib_source_location) || defined(WINRT_NO_SOURCE_LOCATION) +// Case1: cpp17 mode. The source_location intrinsics are not available. +// Case2: The caller has disabled source_location support. Ensure that there is no binary size overhead for line/file/function. +#define WINRT_IMPL_BUILTIN_LINE 0 +#define WINRT_IMPL_BUILTIN_FILE nullptr +#define WINRT_IMPL_BUILTIN_FUNCTION nullptr +#elif _DEBUG +// cpp20 _DEBUG builds include function information, which has a heavy binary size impact, in addition to file/line. +#define WINRT_IMPL_BUILTIN_LINE __builtin_LINE() +#define WINRT_IMPL_BUILTIN_FILE __builtin_FILE() +#define WINRT_IMPL_BUILTIN_FUNCTION __builtin_FUNCTION() +#else +// Release builds in cpp20 mode get file and line information but NOT function information. Function strings +// quickly add up to a substantial binary size impact, especially when templates are heavily used. +#define WINRT_IMPL_BUILTIN_LINE __builtin_LINE() +#define WINRT_IMPL_BUILTIN_FILE __builtin_FILE() +#define WINRT_IMPL_BUILTIN_FUNCTION nullptr +#endif + +WINRT_EXPORT namespace winrt::impl +{ + // This struct is intended to be highly similar to std::source_location. The key difference is + // that function_name is NOT included. Function names do not fold to identical strings and can + // have heavy binary size overhead when templates cause many permutations to exist. + struct slim_source_location + { + [[nodiscard]] static WINRT_IMPL_CONSTEVAL slim_source_location current( + const std::uint_least32_t line = WINRT_IMPL_BUILTIN_LINE, + const char* const file = WINRT_IMPL_BUILTIN_FILE, + const char* const function = WINRT_IMPL_BUILTIN_FUNCTION) noexcept + { + return slim_source_location{ line, file, function }; + } + + [[nodiscard]] constexpr slim_source_location() noexcept = default; + + [[nodiscard]] constexpr slim_source_location( + const std::uint_least32_t line, + const char* const file, + const char* const function) noexcept : + m_line(line), + m_file(file), + m_function(function) + {} + + [[nodiscard]] constexpr std::uint_least32_t line() const noexcept + { + return m_line; + } + + [[nodiscard]] constexpr const char* file_name() const noexcept + { + return m_file; + } + + [[nodiscard]] constexpr const char* function_name() const noexcept + { + return m_function; + } + + private: + const std::uint_least32_t m_line{}; + const char* const m_file{}; + const char* const m_function{}; + }; +} + +#ifdef _MSC_VER +#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "slim") +#endif // _MSC_VER diff --git a/strings/base_std_hash.h b/strings/base_std_hash.h index 864c31b13..4777f8082 100644 --- a/strings/base_std_hash.h +++ b/strings/base_std_hash.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { inline std::size_t hash_data(void const* ptr, std::size_t const bytes) noexcept { @@ -32,7 +32,7 @@ namespace winrt::impl }; } -namespace std +WINRT_IMPL_STD_EXPORT namespace std { template<> struct hash { diff --git a/strings/base_string.h b/strings/base_string.h index 92295e81c..6b1fb37b5 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { struct atomic_ref_count { @@ -442,7 +442,7 @@ template<> struct std::formatter : std::formatter {}; #endif -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template <> struct abi { diff --git a/strings/base_string_input.h b/strings/base_string_input.h index 5ac0221f6..71cd5f3c0 100644 --- a/strings/base_string_input.h +++ b/strings/base_string_input.h @@ -65,7 +65,7 @@ WINRT_EXPORT namespace winrt::param } } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template using param_type = std::conditional_t, param::hstring, T>; diff --git a/strings/base_string_operators.h b/strings/base_string_operators.h index 25e2eccce..223769d01 100644 --- a/strings/base_string_operators.h +++ b/strings/base_string_operators.h @@ -94,7 +94,7 @@ WINRT_EXPORT namespace winrt bool operator>=(std::nullptr_t left, hstring const& right) = delete; } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { inline hstring concat_hstring(std::wstring_view const& left, std::wstring_view const& right) { diff --git a/strings/base_types.h b/strings/base_types.h index 18529e116..dc2b13632 100644 --- a/strings/base_types.h +++ b/strings/base_types.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { using ptp_io = struct tp_io*; using ptp_timer = struct tp_timer*; @@ -208,7 +208,7 @@ WINRT_EXPORT namespace winrt::Windows::Foundation using DateTime = std::chrono::time_point; } -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { #ifdef WINRT_IMPL_IUNKNOWN_DEFINED using hresult_type = long; diff --git a/strings/base_version.h b/strings/base_version.h index 4a6b68e66..13d21fb2a 100644 --- a/strings/base_version.h +++ b/strings/base_version.h @@ -16,6 +16,8 @@ char const * const WINRT_version = "C++/WinRT version:" CPPWINRT_VERSION; WINRT_EXPORT namespace winrt { + inline constexpr char cppwinrt_version[] = CPPWINRT_VERSION; + template constexpr bool check_version(char const(&base)[BaseSize], char const(&component)[ComponentSize]) noexcept { diff --git a/strings/base_windows.h b/strings/base_windows.h index 21c4163e5..dcd164574 100644 --- a/strings/base_windows.h +++ b/strings/base_windows.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { #ifdef WINRT_DIAGNOSTICS diff --git a/strings/base_xaml_typename.h b/strings/base_xaml_typename.h index b7b3a954a..2cc45b0bb 100644 --- a/strings/base_xaml_typename.h +++ b/strings/base_xaml_typename.h @@ -1,5 +1,5 @@ -namespace winrt::impl +WINRT_EXPORT namespace winrt::impl { template struct xaml_typename_name diff --git a/test/nuget/NuGetTest.sln b/test/nuget/NuGetTest.sln index 310b0f252..c836b2551 100644 --- a/test/nuget/NuGetTest.sln +++ b/test/nuget/NuGetTest.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.5.33516.290 @@ -47,6 +47,21 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ConsoleApplication1", "Cons EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestProxyStub", "TestProxyStub\TestProxyStub.vcxproj", "{98E28FC8-2EB7-4544-9B6A-941462C6D3E2}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestModuleApp", "TestModuleApp\TestModuleApp.vcxproj", "{8679913F-D38D-468F-A8B7-75B187A7A8BC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestModuleBuilder", "TestModuleBuilder\TestModuleBuilder.vcxproj", "{AEE91B86-AA17-4C22-B0C2-08B2C287E375}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestModuleComponent1", "TestModuleComponent1\TestModuleComponent1.vcxproj", "{F54D9A50-84D7-4953-8350-BEFE73CC36F6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestModuleComponent2", "TestModuleComponent2\TestModuleComponent2.vcxproj", "{126E9412-E861-47C6-8684-C8F9BF32C0BD}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestModuleConsumerApp", "TestModuleConsumerApp\TestModuleConsumerApp.vcxproj", "{FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}" + ProjectSection(ProjectDependencies) = postProject + {AEE91B86-AA17-4C22-B0C2-08B2C287E375} = {AEE91B86-AA17-4C22-B0C2-08B2C287E375} + {F54D9A50-84D7-4953-8350-BEFE73CC36F6} = {F54D9A50-84D7-4953-8350-BEFE73CC36F6} + {126E9412-E861-47C6-8684-C8F9BF32C0BD} = {126E9412-E861-47C6-8684-C8F9BF32C0BD} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM64 = Debug|ARM64 @@ -279,6 +294,58 @@ Global {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|x64.Build.0 = Release|x64 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|x86.ActiveCfg = Release|Win32 {98E28FC8-2EB7-4544-9B6A-941462C6D3E2}.Release|x86.Build.0 = Release|Win32 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Debug|ARM64.Build.0 = Debug|ARM64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Debug|x64.ActiveCfg = Debug|x64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Debug|x64.Build.0 = Debug|x64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Debug|x86.ActiveCfg = Debug|Win32 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Debug|x86.Build.0 = Debug|Win32 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Release|ARM64.ActiveCfg = Release|ARM64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Release|ARM64.Build.0 = Release|ARM64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Release|x64.ActiveCfg = Release|x64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Release|x64.Build.0 = Release|x64 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Release|x86.ActiveCfg = Release|Win32 + {8679913F-D38D-468F-A8B7-75B187A7A8BC}.Release|x86.Build.0 = Release|Win32 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Debug|ARM64.ActiveCfg = Release|ARM64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Debug|x64.ActiveCfg = Release|x64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Debug|x64.Build.0 = Release|x64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Debug|x86.ActiveCfg = Release|Win32 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Release|ARM64.ActiveCfg = Release|ARM64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Release|ARM64.Build.0 = Release|ARM64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Release|x64.ActiveCfg = Release|x64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Release|x64.Build.0 = Release|x64 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Release|x86.ActiveCfg = Release|Win32 + {AEE91B86-AA17-4C22-B0C2-08B2C287E375}.Release|x86.Build.0 = Release|Win32 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Debug|ARM64.ActiveCfg = Release|ARM64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Debug|x64.ActiveCfg = Release|x64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Debug|x64.Build.0 = Release|x64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Debug|x86.ActiveCfg = Release|Win32 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Release|ARM64.ActiveCfg = Release|ARM64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Release|ARM64.Build.0 = Release|ARM64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Release|x64.ActiveCfg = Release|x64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Release|x64.Build.0 = Release|x64 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Release|x86.ActiveCfg = Release|Win32 + {F54D9A50-84D7-4953-8350-BEFE73CC36F6}.Release|x86.Build.0 = Release|Win32 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Debug|ARM64.ActiveCfg = Release|ARM64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Debug|x64.ActiveCfg = Release|x64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Debug|x64.Build.0 = Release|x64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Debug|x86.ActiveCfg = Release|Win32 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Release|ARM64.ActiveCfg = Release|ARM64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Release|ARM64.Build.0 = Release|ARM64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Release|x64.ActiveCfg = Release|x64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Release|x64.Build.0 = Release|x64 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Release|x86.ActiveCfg = Release|Win32 + {126E9412-E861-47C6-8684-C8F9BF32C0BD}.Release|x86.Build.0 = Release|Win32 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Debug|ARM64.ActiveCfg = Release|ARM64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Debug|x64.ActiveCfg = Release|x64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Debug|x64.Build.0 = Release|x64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Debug|x86.ActiveCfg = Release|Win32 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Release|ARM64.ActiveCfg = Release|ARM64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Release|ARM64.Build.0 = Release|ARM64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Release|x64.ActiveCfg = Release|x64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Release|x64.Build.0 = Release|x64 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Release|x86.ActiveCfg = Release|Win32 + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/test/nuget/TestModuleApp/CustomDependencyObject.cpp b/test/nuget/TestModuleApp/CustomDependencyObject.cpp new file mode 100644 index 000000000..81631e387 --- /dev/null +++ b/test/nuget/TestModuleApp/CustomDependencyObject.cpp @@ -0,0 +1,8 @@ +#include "pch.h" + +#define WINRT_IMPORT_MODULE +import winrt.Windows.Foundation; +import winrt.Windows.UI.Xaml; + +#include "CustomDependencyObject.h" +#include "CustomDependencyObject.g.cpp" diff --git a/test/nuget/TestModuleApp/CustomDependencyObject.h b/test/nuget/TestModuleApp/CustomDependencyObject.h new file mode 100644 index 000000000..79fd6b1ff --- /dev/null +++ b/test/nuget/TestModuleApp/CustomDependencyObject.h @@ -0,0 +1,23 @@ +#pragma once +#include "CustomDependencyObject.g.h" + +namespace winrt::TestModuleApp::implementation +{ + struct CustomDependencyObject : CustomDependencyObjectT + { + CustomDependencyObject() = default; + + hstring Name() { return m_name; } + void Name(hstring const& value) { m_name = value; } + + private: + hstring m_name; + }; +} + +namespace winrt::TestModuleApp::factory_implementation +{ + struct CustomDependencyObject : CustomDependencyObjectT + { + }; +} diff --git a/test/nuget/TestModuleApp/ModuleTestHelper.cpp b/test/nuget/TestModuleApp/ModuleTestHelper.cpp new file mode 100644 index 000000000..1e3d7bc1a --- /dev/null +++ b/test/nuget/TestModuleApp/ModuleTestHelper.cpp @@ -0,0 +1,7 @@ +#include "pch.h" + +#define WINRT_IMPORT_MODULE +import winrt.Windows.Foundation; + +#include "ModuleTestHelper.h" +#include "ModuleTestHelper.g.cpp" diff --git a/test/nuget/TestModuleApp/ModuleTestHelper.h b/test/nuget/TestModuleApp/ModuleTestHelper.h new file mode 100644 index 000000000..c5a699c6b --- /dev/null +++ b/test/nuget/TestModuleApp/ModuleTestHelper.h @@ -0,0 +1,27 @@ +#pragma once +#include "ModuleTestHelper.g.h" + +namespace winrt::TestModuleApp::implementation +{ + struct ModuleTestHelper : ModuleTestHelperT + { + ModuleTestHelper() = default; + + Windows::Foundation::Uri CreateUri(hstring const& url) + { + return Windows::Foundation::Uri(url); + } + + Windows::Foundation::IAsyncOperation GetStringAsync() + { + co_return L"hello from module"; + } + }; +} + +namespace winrt::TestModuleApp::factory_implementation +{ + struct ModuleTestHelper : ModuleTestHelperT + { + }; +} diff --git a/test/nuget/TestModuleApp/PropertySheet.props b/test/nuget/TestModuleApp/PropertySheet.props new file mode 100644 index 000000000..379c2c3a2 --- /dev/null +++ b/test/nuget/TestModuleApp/PropertySheet.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/nuget/TestModuleApp/TestModuleApp.def b/test/nuget/TestModuleApp/TestModuleApp.def new file mode 100644 index 000000000..53d2e7cbf --- /dev/null +++ b/test/nuget/TestModuleApp/TestModuleApp.def @@ -0,0 +1,3 @@ +EXPORTS +DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE +DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE diff --git a/test/nuget/TestModuleApp/TestModuleApp.idl b/test/nuget/TestModuleApp/TestModuleApp.idl new file mode 100644 index 000000000..ab3c56707 --- /dev/null +++ b/test/nuget/TestModuleApp/TestModuleApp.idl @@ -0,0 +1,20 @@ +namespace TestModuleApp +{ + // A type that inherits from Windows.UI.Xaml.DependencyObject to exercise + // cross-namespace inheritance in module builds. + [default_interface] + unsealed runtimeclass CustomDependencyObject : Windows.UI.Xaml.DependencyObject + { + CustomDependencyObject(); + String Name{ get; set; }; + } + + // A simple runtime class using platform SDK types. + [default_interface] + runtimeclass ModuleTestHelper + { + ModuleTestHelper(); + Windows.Foundation.Uri CreateUri(String url); + Windows.Foundation.IAsyncOperation GetStringAsync(); + } +} diff --git a/test/nuget/TestModuleApp/TestModuleApp.vcxproj b/test/nuget/TestModuleApp/TestModuleApp.vcxproj new file mode 100644 index 000000000..522e0d911 --- /dev/null +++ b/test/nuget/TestModuleApp/TestModuleApp.vcxproj @@ -0,0 +1,127 @@ + + + + + true + true + true + Windows;TestModuleApp + true + {8679913F-D38D-468F-A8B7-75B187A7A8BC} + TestModuleApp + TestModuleApp + en-US + 14.0 + + + + + Debug + Win32 + + + Debug + x64 + + + Debug + ARM64 + + + Release + Win32 + + + Release + x64 + + + Release + ARM64 + + + + Application + v145 + Unicode + + + true + + + false + true + + + + + + + + + + + + + + + + + Use + pch.h + $(IntDir)pch.pch + stdcpplatest + Level4 + true + %(AdditionalOptions) /bigobj + 5311;28204 + NOMINMAX;%(PreprocessorDefinitions) + true + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + + + Console + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + + + + TestModuleApp.idl + + + TestModuleApp.idl + + + + + Create + + + + TestModuleApp.idl + + + TestModuleApp.idl + + + + + + + + + + + + + diff --git a/test/nuget/TestModuleApp/main.cpp b/test/nuget/TestModuleApp/main.cpp new file mode 100644 index 000000000..907e4afed --- /dev/null +++ b/test/nuget/TestModuleApp/main.cpp @@ -0,0 +1,42 @@ +#include "pch.h" + +#define WINRT_IMPORT_MODULE +import std; +import winrt.Windows.Foundation; +import winrt.Windows.UI.Xaml; + +#include "ModuleTestHelper.h" +#include "CustomDependencyObject.h" + +using namespace winrt; +using namespace Windows::Foundation; + +int main() +{ + init_apartment(); + + // Test ModuleTestHelper + auto helper = TestModuleApp::ModuleTestHelper(); + auto uri = helper.CreateUri(L"https://example.com"); + std::printf("URI: %ls\n", uri.AbsoluteUri().c_str()); + + auto str = helper.GetStringAsync().get(); + std::printf("Async: %ls\n", str.c_str()); + + // Test CustomDependencyObject (inherits from DependencyObject) + // Note: DependencyObject requires XAML runtime, which isn't available in a console app. + // We verify the type compiles and links correctly; runtime creation would need a XAML host. + try + { + auto obj = winrt::make(); + obj.Name(L"test"); + std::printf("Name: %ls\n", obj.Name().c_str()); + } + catch (winrt::hresult_error const& e) + { + std::printf("CustomDependencyObject: expected runtime error (no XAML host): %ls\n", e.message().c_str()); + } + + std::printf("All module tests passed.\n"); + return 0; +} diff --git a/test/nuget/TestModuleApp/pch.cpp b/test/nuget/TestModuleApp/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/nuget/TestModuleApp/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/nuget/TestModuleApp/pch.h b/test/nuget/TestModuleApp/pch.h new file mode 100644 index 000000000..6f70f09be --- /dev/null +++ b/test/nuget/TestModuleApp/pch.h @@ -0,0 +1 @@ +#pragma once diff --git a/test/nuget/TestModuleBuilder/PropertySheet.props b/test/nuget/TestModuleBuilder/PropertySheet.props new file mode 100644 index 000000000..379c2c3a2 --- /dev/null +++ b/test/nuget/TestModuleBuilder/PropertySheet.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/nuget/TestModuleBuilder/TestModuleBuilder.vcxproj b/test/nuget/TestModuleBuilder/TestModuleBuilder.vcxproj new file mode 100644 index 000000000..d2d852240 --- /dev/null +++ b/test/nuget/TestModuleBuilder/TestModuleBuilder.vcxproj @@ -0,0 +1,67 @@ + + + + + true + Windows.Foundation + Windows.Foundation.Diagnostics + true + {AEE91B86-AA17-4C22-B0C2-08B2C287E375} + TestModuleBuilder + TestModuleBuilder + en-US + 14.0 + + + + + Release + Win32 + + + Release + x64 + + + Release + ARM64 + + + + StaticLibrary + v145 + Unicode + + + false + true + + + + + + + + + + Use + pch.h + stdcpplatest + Level4 + true + %(AdditionalOptions) /bigobj + true + NOMINMAX;%(PreprocessorDefinitions) + + + + + + + + Create + + + + + diff --git a/test/nuget/TestModuleBuilder/pch.cpp b/test/nuget/TestModuleBuilder/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/nuget/TestModuleBuilder/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/nuget/TestModuleBuilder/pch.h b/test/nuget/TestModuleBuilder/pch.h new file mode 100644 index 000000000..6f70f09be --- /dev/null +++ b/test/nuget/TestModuleBuilder/pch.h @@ -0,0 +1 @@ +#pragma once diff --git a/test/nuget/TestModuleComponent1/Greeter.cpp b/test/nuget/TestModuleComponent1/Greeter.cpp new file mode 100644 index 000000000..04c668e10 --- /dev/null +++ b/test/nuget/TestModuleComponent1/Greeter.cpp @@ -0,0 +1,8 @@ +#include "pch.h" + +#define WINRT_IMPORT_MODULE +import winrt_base; +import winrt.Windows.Foundation; + +#include "Greeter.h" +#include "Greeter.g.cpp" diff --git a/test/nuget/TestModuleComponent1/Greeter.h b/test/nuget/TestModuleComponent1/Greeter.h new file mode 100644 index 000000000..726fb7d22 --- /dev/null +++ b/test/nuget/TestModuleComponent1/Greeter.h @@ -0,0 +1,25 @@ +#pragma once +#include "Greeter.g.h" + +namespace winrt::TestModuleComponent1::implementation +{ + struct Greeter : GreeterT + { + Greeter() : m_name(L"World") {} + Greeter(hstring const& name) : m_name(name) {} + + hstring Name() { return m_name; } + hstring Greet() { return L"Hello, " + m_name + L"!"; } + Windows::Foundation::Uri Homepage() { return Windows::Foundation::Uri(L"https://example.com/" + m_name); } + + private: + hstring m_name; + }; +} + +namespace winrt::TestModuleComponent1::factory_implementation +{ + struct Greeter : GreeterT + { + }; +} diff --git a/test/nuget/TestModuleComponent1/PropertySheet.props b/test/nuget/TestModuleComponent1/PropertySheet.props new file mode 100644 index 000000000..379c2c3a2 --- /dev/null +++ b/test/nuget/TestModuleComponent1/PropertySheet.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/nuget/TestModuleComponent1/TestModuleComponent1.def b/test/nuget/TestModuleComponent1/TestModuleComponent1.def new file mode 100644 index 000000000..53d2e7cbf --- /dev/null +++ b/test/nuget/TestModuleComponent1/TestModuleComponent1.def @@ -0,0 +1,3 @@ +EXPORTS +DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE +DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE diff --git a/test/nuget/TestModuleComponent1/TestModuleComponent1.idl b/test/nuget/TestModuleComponent1/TestModuleComponent1.idl new file mode 100644 index 000000000..73a983ee2 --- /dev/null +++ b/test/nuget/TestModuleComponent1/TestModuleComponent1.idl @@ -0,0 +1,12 @@ +namespace TestModuleComponent1 +{ + [default_interface] + runtimeclass Greeter + { + Greeter(); + Greeter(String name); + String Name{ get; }; + String Greet(); + Windows.Foundation.Uri Homepage{ get; }; + } +} diff --git a/test/nuget/TestModuleComponent1/TestModuleComponent1.vcxproj b/test/nuget/TestModuleComponent1/TestModuleComponent1.vcxproj new file mode 100644 index 000000000..669b25ff0 --- /dev/null +++ b/test/nuget/TestModuleComponent1/TestModuleComponent1.vcxproj @@ -0,0 +1,92 @@ + + + + + true + true + true + true + {F54D9A50-84D7-4953-8350-BEFE73CC36F6} + TestModuleComponent1 + TestModuleComponent1 + en-US + 14.0 + + + + + Release + Win32 + + + Release + x64 + + + Release + ARM64 + + + + DynamicLibrary + v145 + Unicode + + + false + true + + + + + + + + + + Use + pch.h + stdcpplatest + Level4 + true + %(AdditionalOptions) /bigobj + true + _WINRT_DLL;NOMINMAX;%(PreprocessorDefinitions) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + + + Console + false + TestModuleComponent1.def + + + + + + TestModuleComponent1.idl + + + + + Create + + + TestModuleComponent1.idl + + + + + + + + + + + + + true + + + + + diff --git a/test/nuget/TestModuleComponent1/pch.cpp b/test/nuget/TestModuleComponent1/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/nuget/TestModuleComponent1/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/nuget/TestModuleComponent1/pch.h b/test/nuget/TestModuleComponent1/pch.h new file mode 100644 index 000000000..6f70f09be --- /dev/null +++ b/test/nuget/TestModuleComponent1/pch.h @@ -0,0 +1 @@ +#pragma once diff --git a/test/nuget/TestModuleComponent2/GreeterGroup.cpp b/test/nuget/TestModuleComponent2/GreeterGroup.cpp new file mode 100644 index 000000000..7c6410b44 --- /dev/null +++ b/test/nuget/TestModuleComponent2/GreeterGroup.cpp @@ -0,0 +1,9 @@ +#include "pch.h" + +#define WINRT_IMPORT_MODULE +import std; +import winrt.Windows.Foundation; +import winrt.TestModuleComponent1; + +#include "GreeterGroup.h" +#include "GreeterGroup.g.cpp" diff --git a/test/nuget/TestModuleComponent2/GreeterGroup.h b/test/nuget/TestModuleComponent2/GreeterGroup.h new file mode 100644 index 000000000..461570425 --- /dev/null +++ b/test/nuget/TestModuleComponent2/GreeterGroup.h @@ -0,0 +1,36 @@ +#pragma once +#include "GreeterGroup.g.h" + +namespace winrt::TestModuleComponent2::implementation +{ + struct GreeterGroup : GreeterGroupT + { + GreeterGroup() = default; + + void Add(winrt::TestModuleComponent1::Greeter const& greeter) + { + m_greeters.push_back(greeter); + } + + hstring GreetAll() + { + hstring result; + for (auto const& g : m_greeters) + { + if (!result.empty()) result = result + L", "; + result = result + g.Greet(); + } + return result; + } + + private: + std::vector m_greeters; + }; +} + +namespace winrt::TestModuleComponent2::factory_implementation +{ + struct GreeterGroup : GreeterGroupT + { + }; +} diff --git a/test/nuget/TestModuleComponent2/PropertySheet.props b/test/nuget/TestModuleComponent2/PropertySheet.props new file mode 100644 index 000000000..379c2c3a2 --- /dev/null +++ b/test/nuget/TestModuleComponent2/PropertySheet.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/nuget/TestModuleComponent2/TestModuleComponent2.def b/test/nuget/TestModuleComponent2/TestModuleComponent2.def new file mode 100644 index 000000000..53d2e7cbf --- /dev/null +++ b/test/nuget/TestModuleComponent2/TestModuleComponent2.def @@ -0,0 +1,3 @@ +EXPORTS +DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE +DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE diff --git a/test/nuget/TestModuleComponent2/TestModuleComponent2.idl b/test/nuget/TestModuleComponent2/TestModuleComponent2.idl new file mode 100644 index 000000000..e45eed438 --- /dev/null +++ b/test/nuget/TestModuleComponent2/TestModuleComponent2.idl @@ -0,0 +1,10 @@ +namespace TestModuleComponent2 +{ + [default_interface] + runtimeclass GreeterGroup + { + GreeterGroup(); + void Add(TestModuleComponent1.Greeter greeter); + String GreetAll(); + } +} diff --git a/test/nuget/TestModuleComponent2/TestModuleComponent2.vcxproj b/test/nuget/TestModuleComponent2/TestModuleComponent2.vcxproj new file mode 100644 index 000000000..ff4982965 --- /dev/null +++ b/test/nuget/TestModuleComponent2/TestModuleComponent2.vcxproj @@ -0,0 +1,93 @@ + + + + + true + true + true + true + {126E9412-E861-47C6-8684-C8F9BF32C0BD} + TestModuleComponent2 + TestModuleComponent2 + en-US + 14.0 + + + + + Release + Win32 + + + Release + x64 + + + Release + ARM64 + + + + DynamicLibrary + v145 + Unicode + + + false + true + + + + + + + + + + Use + pch.h + stdcpplatest + Level4 + true + %(AdditionalOptions) /bigobj + true + _WINRT_DLL;NOMINMAX;%(PreprocessorDefinitions) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + + + Console + false + TestModuleComponent2.def + + + + + + TestModuleComponent2.idl + + + + + Create + + + TestModuleComponent2.idl + + + + + + + + + + + + + true + + + + + + diff --git a/test/nuget/TestModuleComponent2/pch.cpp b/test/nuget/TestModuleComponent2/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/nuget/TestModuleComponent2/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/nuget/TestModuleComponent2/pch.h b/test/nuget/TestModuleComponent2/pch.h new file mode 100644 index 000000000..6f70f09be --- /dev/null +++ b/test/nuget/TestModuleComponent2/pch.h @@ -0,0 +1 @@ +#pragma once diff --git a/test/nuget/TestModuleConsumerApp/PropertySheet.props b/test/nuget/TestModuleConsumerApp/PropertySheet.props new file mode 100644 index 000000000..379c2c3a2 --- /dev/null +++ b/test/nuget/TestModuleConsumerApp/PropertySheet.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/test/nuget/TestModuleConsumerApp/TestModuleConsumerApp.vcxproj b/test/nuget/TestModuleConsumerApp/TestModuleConsumerApp.vcxproj new file mode 100644 index 000000000..910586a0c --- /dev/null +++ b/test/nuget/TestModuleConsumerApp/TestModuleConsumerApp.vcxproj @@ -0,0 +1,76 @@ + + + + + true + true + {FB7FEAA7-09DE-465C-BA0E-60374D3EFFD9} + TestModuleConsumerApp + TestModuleConsumerApp + en-US + 14.0 + + + + + Release + Win32 + + + Release + x64 + + + Release + ARM64 + + + + Application + v145 + Unicode + + + false + true + + + + + + + + + + Use + pch.h + stdcpplatest + Level4 + true + %(AdditionalOptions) /bigobj + true + NOMINMAX;%(PreprocessorDefinitions) + + + Console + + + + + + + + Create + + + + + + true + + + + + + + diff --git a/test/nuget/TestModuleConsumerApp/main.cpp b/test/nuget/TestModuleConsumerApp/main.cpp new file mode 100644 index 000000000..da930703b --- /dev/null +++ b/test/nuget/TestModuleConsumerApp/main.cpp @@ -0,0 +1,32 @@ +#include "pch.h" + +import std; +import winrt.Windows.Foundation; +import winrt.TestModuleComponent1; +import winrt.TestModuleComponent2; + +using namespace winrt; +using namespace Windows::Foundation; + +int main() +{ + init_apartment(); + + // Platform types from pre-built modules + Uri uri(L"https://example.com/consumer"); + std::printf("URI: %ls\n", uri.AbsoluteUri().c_str()); + + // Component1 + auto greeter = TestModuleComponent1::Greeter(L"Modules"); + std::printf("Greet: %ls\n", greeter.Greet().c_str()); + std::printf("Homepage: %ls\n", greeter.Homepage().AbsoluteUri().c_str()); + + // Component2 (depends on Component1) + auto group = TestModuleComponent2::GreeterGroup(); + group.Add(TestModuleComponent1::Greeter(L"Alice")); + group.Add(TestModuleComponent1::Greeter(L"Bob")); + std::printf("GreetAll: %ls\n", group.GreetAll().c_str()); + + std::printf("All consumer tests passed.\n"); + return 0; +} diff --git a/test/nuget/TestModuleConsumerApp/pch.cpp b/test/nuget/TestModuleConsumerApp/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/nuget/TestModuleConsumerApp/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/nuget/TestModuleConsumerApp/pch.h b/test/nuget/TestModuleConsumerApp/pch.h new file mode 100644 index 000000000..6f70f09be --- /dev/null +++ b/test/nuget/TestModuleConsumerApp/pch.h @@ -0,0 +1 @@ +#pragma once diff --git a/test/test_cpp20_module/collections.cpp b/test/test_cpp20_module/collections.cpp new file mode 100644 index 000000000..b80e123d2 --- /dev/null +++ b/test/test_cpp20_module/collections.cpp @@ -0,0 +1,57 @@ +#include "pch.h" + +import winrt.Windows.Foundation; + +using namespace winrt; +using namespace Windows::Foundation::Collections; + +TEST_CASE("module_vector") +{ + auto vec = single_threaded_vector(); + vec.Append(10); + vec.Append(20); + vec.Append(30); + REQUIRE(vec.Size() == 3); + REQUIRE(vec.GetAt(0) == 10); + REQUIRE(vec.GetAt(2) == 30); + + vec.RemoveAtEnd(); + REQUIRE(vec.Size() == 2); +} + +TEST_CASE("module_map") +{ + auto map = single_threaded_map(); + map.Insert(L"key1", L"value1"); + map.Insert(L"key2", L"value2"); + REQUIRE(map.Size() == 2); + REQUIRE(map.Lookup(L"key1") == L"value1"); + REQUIRE(map.HasKey(L"key2")); + REQUIRE(!map.HasKey(L"key3")); +} + +TEST_CASE("module_observable_vector") +{ + auto vec = single_threaded_observable_vector(); + int change_count = 0; + auto token = vec.VectorChanged([&](auto&&, auto&&) { ++change_count; }); + vec.Append(1); + vec.Append(2); + REQUIRE(change_count == 2); + vec.VectorChanged(token); +} + +TEST_CASE("module_iterable") +{ + auto vec = single_threaded_vector(); + vec.Append(1); + vec.Append(2); + vec.Append(3); + + int sum = 0; + for (auto v : vec) + { + sum += v; + } + REQUIRE(sum == 6); +} diff --git a/test/test_cpp20_module/com_interop.cpp b/test/test_cpp20_module/com_interop.cpp new file mode 100644 index 000000000..3035d2a05 --- /dev/null +++ b/test/test_cpp20_module/com_interop.cpp @@ -0,0 +1,84 @@ +#include "pch.h" +#include +#include + +import std; +import winrt.Windows.Foundation; + +// +// These tests confirm that COM interop — including legacy (non-WinRT) COM types +// from the Windows SDK — works correctly when consumed via modules. +// +// Note: We avoid 'using namespace Windows::Foundation' here because it brings +// IInspectable/IUnknown into scope and collides with the SDK types of the same name. +// + +using namespace winrt; + +TEST_CASE("module_com_ptr_round_trip") +{ + Windows::Foundation::Uri uri(L"https://example.com"); + + // Detach to raw ABI pointer and re-attach + void* abi = detach_abi(uri); + REQUIRE(abi != nullptr); + + Windows::Foundation::Uri uri2{ nullptr }; + attach_abi(uri2, abi); + REQUIRE(uri2.AbsoluteUri() == L"https://example.com/"); +} + +TEST_CASE("module_sdk_iunknown_interop") +{ + // Interop between winrt projected types and the Windows SDK ::IUnknown + Windows::Foundation::Uri uri(L"https://example.com"); + + // Get the SDK IUnknown pointer from a projected type + ::IUnknown* raw = nullptr; + copy_to_abi(uri, *reinterpret_cast(&raw)); + REQUIRE(raw != nullptr); + + // QI for IInspectable through the raw SDK pointer + ::IInspectable* inspectable = nullptr; + REQUIRE(raw->QueryInterface(IID_IInspectable, reinterpret_cast(&inspectable)) == S_OK); + REQUIRE(inspectable != nullptr); + inspectable->Release(); + + // Round-trip back to a projected type + Windows::Foundation::Uri uri2{ nullptr }; + copy_from_abi(uri2, raw); + REQUIRE(uri2.AbsoluteUri() == L"https://example.com/"); + + raw->Release(); +} + +TEST_CASE("module_com_ptr_sdk_type") +{ + // winrt::com_ptr wrapping a Windows SDK ::IUnknown + Windows::Foundation::Uri uri(L"https://example.com"); + + com_ptr<::IUnknown> unknown; + copy_to_abi(uri, *reinterpret_cast(unknown.put())); + REQUIRE(unknown.get() != nullptr); +} + +TEST_CASE("module_iunknown_identity") +{ + Windows::Foundation::Uri uri(L"https://example.com"); + + auto unknown1 = uri.as(); + auto unknown2 = uri.as(); + REQUIRE(unknown1 == unknown2); +} + +TEST_CASE("module_try_as") +{ + Windows::Foundation::Uri uri(L"https://example.com"); + + auto stringable = uri.try_as(); + REQUIRE(stringable != nullptr); + REQUIRE(!stringable.ToString().empty()); + + auto closable = uri.try_as(); + REQUIRE(closable == nullptr); +} diff --git a/test/test_cpp20_module/coroutines.cpp b/test/test_cpp20_module/coroutines.cpp new file mode 100644 index 000000000..1553b1c6d --- /dev/null +++ b/test/test_cpp20_module/coroutines.cpp @@ -0,0 +1,58 @@ +#include "pch.h" + +import std; +import winrt.Windows.Foundation; + +using namespace winrt; +using namespace Windows::Foundation; + +IAsyncAction do_nothing_async() +{ + co_return; +} + +IAsyncOperation return_42_async() +{ + co_return 42; +} + +IAsyncOperation return_string_async() +{ + co_return L"module coroutine"; +} + +IAsyncAction chain_async() +{ + auto result = co_await return_string_async(); + REQUIRE(!result.empty()); +} + +IAsyncOperation slow_operation() +{ + co_await resume_after(std::chrono::hours(1)); + co_return 0; +} + +TEST_CASE("module_async_action") +{ + auto action = do_nothing_async(); + action.get(); + REQUIRE(action.Status() == AsyncStatus::Completed); +} + +TEST_CASE("module_async_operation") +{ + REQUIRE(return_42_async().get() == 42); +} + +TEST_CASE("module_async_chain") +{ + chain_async().get(); +} + +TEST_CASE("module_async_cancel") +{ + auto op = slow_operation(); + op.Cancel(); + REQUIRE(op.Status() == AsyncStatus::Canceled); +} diff --git a/test/test_cpp20_module/format.cpp b/test/test_cpp20_module/format.cpp new file mode 100644 index 000000000..0c4570300 --- /dev/null +++ b/test/test_cpp20_module/format.cpp @@ -0,0 +1,49 @@ +#include "pch.h" + +#ifdef __cpp_lib_format + +import std; +import winrt.Windows.Foundation; + +// +// These tests confirm that std::format and std::formatter specializations work +// correctly when consumed via modules. Mirrors test/test_cpp20/format.cpp. +// + +using namespace winrt; +using namespace Windows::Foundation; + +TEST_CASE("module_format_hstring") +{ + hstring str = L"World"; + REQUIRE(std::format(L"Hello {}", str) == L"Hello World"); +} + +TEST_CASE("module_format_IStringable") +{ + // Uri implements IStringable — exercises the generated + // std::formatter specialization through modules. + Uri uri(L"https://example.com/path"); + IStringable stringable = uri; + REQUIRE(std::format(L"Visit: {}", stringable) == L"Visit: https://example.com/path"); +} + +TEST_CASE("module_format_projected_class") +{ + // Exercises the generated std::formatter specialization + // (inherits from formatter) through modules. + Uri uri(L"https://example.com"); + REQUIRE(std::format(L"URL: {}", uri) == L"URL: https://example.com/"); +} + +#if __cpp_lib_format >= 202207L +TEST_CASE("module_format_winrt_format") +{ + // winrt::format helper (C++23 formattable concept) + std::wstring str = L"World"; + REQUIRE(winrt::format(L"Hello {}", str) == L"Hello World"); + REQUIRE(winrt::format(L"C++/WinRT #{:d}", 1) == L"C++/WinRT #1"); +} +#endif + +#endif // __cpp_lib_format diff --git a/test/test_cpp20_module/foundation.cpp b/test/test_cpp20_module/foundation.cpp new file mode 100644 index 000000000..d26c55244 --- /dev/null +++ b/test/test_cpp20_module/foundation.cpp @@ -0,0 +1,68 @@ +#include "pch.h" + +import std; +import winrt.Windows.Foundation; + +using namespace winrt; +using namespace Windows::Foundation; + +TEST_CASE("module_uri") +{ + Uri uri(L"https://example.com/path?query=1"); + REQUIRE(!uri.AbsoluteUri().empty()); + REQUIRE(uri.Host() == L"example.com"); + REQUIRE(uri.Path() == L"/path"); +} + +TEST_CASE("module_property_value") +{ + auto pv = PropertyValue::CreateInt32(42); + REQUIRE(pv.as().GetInt32() == 42); + + auto pvs = PropertyValue::CreateString(L"hello"); + REQUIRE(pvs.as().GetString() == L"hello"); +} + +TEST_CASE("module_hstring") +{ + hstring text = L"C++/WinRT modules"; + REQUIRE(!text.empty()); + REQUIRE(text.size() == 17); + + hstring empty; + REQUIRE(empty.empty()); + REQUIRE(empty.size() == 0); +} + +TEST_CASE("module_events") +{ + winrt::event> my_event; + int received = 0; + auto token = my_event.add([&](auto&&, int value) { received = value; }); + my_event(nullptr, 42); + REQUIRE(received == 42); + my_event.remove(token); +} + +TEST_CASE("module_foundation_point") +{ + Point p{ 5.0f, 10.0f }; + REQUIRE(p.X == 5.0f); + REQUIRE(p.Y == 10.0f); +} + +TEST_CASE("module_foundation_size") +{ + Size s{ 800.0f, 600.0f }; + REQUIRE(s.Width == 800.0f); + REQUIRE(s.Height == 600.0f); +} + +TEST_CASE("module_foundation_rect") +{ + Point origin{ 0.0f, 0.0f }; + Size extent{ 100.0f, 200.0f }; + Rect r(origin, extent); + REQUIRE(r.X == 0.0f); + REQUIRE(r.Width == 100.0f); +} diff --git a/test/test_cpp20_module/hash.cpp b/test/test_cpp20_module/hash.cpp new file mode 100644 index 000000000..bb7594104 --- /dev/null +++ b/test/test_cpp20_module/hash.cpp @@ -0,0 +1,73 @@ +#include "pch.h" + +import std; +import winrt.Windows.Foundation; + +// +// These tests confirm that std::hash specializations work correctly +// when consumed via modules, enabling use in unordered containers. +// + +using namespace winrt; +using namespace Windows::Foundation; + +TEST_CASE("module_hash_hstring") +{ + std::unordered_set set; + set.insert(L"hello"); + set.insert(L"world"); + set.insert(L"hello"); // duplicate + REQUIRE(set.size() == 2); + REQUIRE(set.contains(L"hello")); + REQUIRE(set.contains(L"world")); +} + +TEST_CASE("module_hash_IUnknown") +{ + Uri uri(L"https://example.com"); + auto unknown = uri.as(); + + std::unordered_set set; + set.insert(unknown); + set.insert(unknown); // duplicate — same identity + REQUIRE(set.size() == 1); + + // A different object should hash differently (almost certainly) + Uri uri2(L"https://other.com"); + set.insert(uri2.as()); + REQUIRE(set.size() == 2); +} + +TEST_CASE("module_hash_projected_type") +{ + // Projected types like Uri should be hashable via the generated + // std::hash specialization (inherits from hash_base). + std::unordered_set set; + Uri u1(L"https://one.com"); + Uri u2(L"https://two.com"); + set.insert(u1); + set.insert(u2); + set.insert(u1); // duplicate + REQUIRE(set.size() == 2); +} + +TEST_CASE("module_hash_guid") +{ + std::unordered_set set; + guid g1{ 0x01020304, 0x0506, 0x0708, { 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 } }; + guid g2{ 0x11121314, 0x1516, 0x1718, { 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20 } }; + set.insert(g1); + set.insert(g2); + set.insert(g1); // duplicate + REQUIRE(set.size() == 2); +} + +TEST_CASE("module_hash_map_with_hstring_key") +{ + std::unordered_map map; + map[L"one"] = 1; + map[L"two"] = 2; + map[L"three"] = 3; + REQUIRE(map.size() == 3); + REQUIRE(map[L"two"] == 2); +} diff --git a/test/test_cpp20_module/main.cpp b/test/test_cpp20_module/main.cpp new file mode 100644 index 000000000..415e26f0f --- /dev/null +++ b/test/test_cpp20_module/main.cpp @@ -0,0 +1,24 @@ +#include +#define CATCH_CONFIG_RUNNER +#define CATCH_CONFIG_WINDOWS_SEH +#include "catch.hpp" + +import winrt_base; + +using namespace winrt; + +int main(int const argc, char** argv) +{ + init_apartment(); + std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + return Catch::Session().run(argc, argv); +} + +CATCH_TRANSLATE_EXCEPTION(hresult_error const& e) +{ + return to_string(e.message()); +} diff --git a/test/test_cpp20_module/natvis.cpp b/test/test_cpp20_module/natvis.cpp new file mode 100644 index 000000000..470654d07 --- /dev/null +++ b/test/test_cpp20_module/natvis.cpp @@ -0,0 +1,58 @@ +#include "pch.h" +#include + +import std; +import winrt.Windows.Foundation; + +// +// These tests confirm that the natvis infrastructure (winrt::impl::natvis) +// is reachable through modules, ensuring the debugger visualizer can function. +// natvis is only active in _DEBUG builds. +// + +using namespace winrt; +using namespace Windows::Foundation; + +#ifdef _DEBUG + +TEST_CASE("module_natvis_get_val") +{ + // Verify impl::natvis::get_val is callable through the module. + Uri uri(L"http://example.com/"); + IInspectable inspectable = uri; + + // IStringable IID: {96369F54-8EB6-48F0-ABCE-C1B211E627C3} + // Method index 0 = ToString + auto result = impl::natvis::get_val(&inspectable, L"{96369F54-8EB6-48F0-ABCE-C1B211E627C3}", 0); + + // Compare the natvis result with the direct call + hstring expected = uri.ToString(); + uint32_t expected_len = 0; + auto expected_buf = WindowsGetStringRawBuffer(static_cast(get_abi(expected)), &expected_len); + uint32_t actual_len = 0; + auto actual_buf = WindowsGetStringRawBuffer(static_cast(result.s), &actual_len); + REQUIRE(expected_len == actual_len); + REQUIRE(memcmp(expected_buf, actual_buf, expected_len * sizeof(wchar_t)) == 0); +} + +TEST_CASE("module_natvis_uri_properties") +{ + Uri uri(L"http://moderncpp.com/path"); + IInspectable inspectable = uri; + + // IUriRuntimeClass IID: {9E365E57-48B2-4160-956F-C7385120BBFC} + // Method 5 = Host, Method 7 = Path, Method 11 = SchemeName + auto host_val = impl::natvis::get_val(&inspectable, L"{9E365E57-48B2-4160-956F-C7385120BBFC}", 5); + hstring host_expected = uri.Host(); + REQUIRE(host_expected == hstring{ WindowsGetStringRawBuffer(static_cast(host_val.s), nullptr) }); + + auto path_val = impl::natvis::get_val(&inspectable, L"{9E365E57-48B2-4160-956F-C7385120BBFC}", 7); + hstring path_expected = uri.Path(); + REQUIRE(path_expected == hstring{ WindowsGetStringRawBuffer(static_cast(path_val.s), nullptr) }); + + auto scheme_val = impl::natvis::get_val(&inspectable, L"{9E365E57-48B2-4160-956F-C7385120BBFC}", 11); + hstring scheme_expected = uri.SchemeName(); + REQUIRE(scheme_expected == hstring{ WindowsGetStringRawBuffer(static_cast(scheme_val.s), nullptr) }); +} + +#endif // _DEBUG diff --git a/test/test_cpp20_module/numerics.cpp b/test/test_cpp20_module/numerics.cpp new file mode 100644 index 000000000..0f7dcc7fb --- /dev/null +++ b/test/test_cpp20_module/numerics.cpp @@ -0,0 +1,129 @@ +#include "pch.h" + +#if __has_include() + +import std; +import winrt.Windows.Foundation; +import winrt.Windows.Foundation.Numerics; + +// +// These tests exercise the SDK numerics types (float2, float3, etc.) from +// . These are exported by winrt_numerics and +// transitively available from winrt_base (and thus any namespace module). +// The Point/Size ↔ float2 conversions and name_v/category specializations +// are compiled in winrt_base. +// + +using namespace winrt; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Foundation::Numerics; + +// --- SDK math types (from winrt_numerics, re-exported via winrt_base) --- + +TEST_CASE("module_numerics_float2") +{ + float2 a{ 1.0f, 2.0f }; + float2 b{ 3.0f, 4.0f }; + + auto c = a + b; + REQUIRE(c.x == 4.0f); + REQUIRE(c.y == 6.0f); + + REQUIRE(length(a) > 0.0f); +} + +TEST_CASE("module_numerics_float3") +{ + float3 v{ 1.0f, 0.0f, 0.0f }; + float3 up{ 0.0f, 1.0f, 0.0f }; + + REQUIRE(dot(v, up) == 0.0f); + REQUIRE(cross(v, up).z != 0.0f); +} + +TEST_CASE("module_numerics_float4x4") +{ + auto identity = float4x4::identity(); + REQUIRE(identity.m11 == 1.0f); + REQUIRE(identity.m12 == 0.0f); + + auto t = make_float4x4_translation({ 10.0f, 20.0f, 30.0f }); + REQUIRE(t.m41 == 10.0f); +} + +TEST_CASE("module_numerics_quaternion") +{ + auto identity = quaternion::identity(); + REQUIRE(identity.w == 1.0f); + REQUIRE(length(identity) == 1.0f); +} + +// --- Point/Size ↔ float2 conversions (compiled in winrt_base) --- + +TEST_CASE("module_numerics_point_from_float2") +{ + Point p(float2{ 3.0f, 7.0f }); + REQUIRE(p.X == 3.0f); + REQUIRE(p.Y == 7.0f); +} + +TEST_CASE("module_numerics_point_to_float2") +{ + float2 v = Point{ 10.0f, 20.0f }; + REQUIRE(v.x == 10.0f); + REQUIRE(v.y == 20.0f); +} + +TEST_CASE("module_numerics_size_from_float2") +{ + Size s(float2{ 100.0f, 200.0f }); + REQUIRE(s.Width == 100.0f); + REQUIRE(s.Height == 200.0f); +} + +TEST_CASE("module_numerics_size_to_float2") +{ + float2 v = Size{ 640.0f, 480.0f }; + REQUIRE(v.x == 640.0f); + REQUIRE(v.y == 480.0f); +} + +// --- WinRT projection metadata (name_v/category, compiled in winrt_base) --- +// Verify that the projection machinery produces correct IReference GUIDs +// for numerics types. This exercises name_v, category, and the SHA-1 based +// GUID computation across module boundaries, at compile time. + +namespace +{ + constexpr bool equal(guid const& left, guid const& right) noexcept + { + return left.Data1 == right.Data1 && + left.Data2 == right.Data2 && + left.Data3 == right.Data3 && + left.Data4[0] == right.Data4[0] && + left.Data4[1] == right.Data4[1] && + left.Data4[2] == right.Data4[2] && + left.Data4[3] == right.Data4[3] && + left.Data4[4] == right.Data4[4] && + left.Data4[5] == right.Data4[5] && + left.Data4[6] == right.Data4[6] && + left.Data4[7] == right.Data4[7]; + } +} + +#define REQUIRE_EQUAL_GUID(left, ...) STATIC_REQUIRE(equal(guid(left), guid_of<__VA_ARGS__>())); + +TEST_CASE("module_numerics_ireference_guids") +{ + REQUIRE_EQUAL_GUID("48F6A69E-8465-57AE-9400-9764087F65AD", IReference); + REQUIRE_EQUAL_GUID("1EE770FF-C954-59CA-A754-6199A9BE282C", IReference); + REQUIRE_EQUAL_GUID("A5E843C9-ED20-5339-8F8D-9FE404CF3654", IReference); + REQUIRE_EQUAL_GUID("76358CFD-2CBD-525B-A49E-90EE18247B71", IReference); + REQUIRE_EQUAL_GUID("DACBFFDC-68EF-5FD0-B657-782D0AC9807E", IReference); + REQUIRE_EQUAL_GUID("B27004BB-C014-5DCE-9A21-799C5A3C1461", IReference); + REQUIRE_EQUAL_GUID("46D542A1-52F7-58E7-ACFC-9A6D364DA022", IReference); +} + +#undef REQUIRE_EQUAL_GUID + +#endif // __has_include() diff --git a/test/test_cpp20_module/pch.cpp b/test/test_cpp20_module/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/test_cpp20_module/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/test_cpp20_module/pch.h b/test/test_cpp20_module/pch.h new file mode 100644 index 000000000..d0eb301ac --- /dev/null +++ b/test/test_cpp20_module/pch.h @@ -0,0 +1,3 @@ +#pragma once + +#include "catch.hpp" diff --git a/test/test_cpp20_module/range_for.cpp b/test/test_cpp20_module/range_for.cpp new file mode 100644 index 000000000..962c97179 --- /dev/null +++ b/test/test_cpp20_module/range_for.cpp @@ -0,0 +1,135 @@ +#include "pch.h" + +import std; +import winrt.Windows.Foundation.Collections; + +// +// These tests confirm that C++/WinRT collections support range-based for loop iteration +// and structured bindings when consumed via modules. +// + +using namespace winrt; +using namespace Windows::Foundation::Collections; + +TEST_CASE("module_range_for_IIterable") +{ + IIterable c = single_threaded_vector({ 1, 2, 3 }); + std::vector result; + + for (int i : c) + { + result.push_back(i); + } + + REQUIRE(result.size() == 3); + REQUIRE(result[0] == 1); + REQUIRE(result[1] == 2); + REQUIRE(result[2] == 3); +} + +TEST_CASE("module_range_for_IVector") +{ + IVector c = single_threaded_vector({ 1, 2, 3 }); + std::vector result; + + for (int i : c) + { + result.push_back(i); + } + + REQUIRE(result.size() == 3); + REQUIRE(result[0] == 1); + REQUIRE(result[1] == 2); + REQUIRE(result[2] == 3); +} + +TEST_CASE("module_range_for_IVectorView") +{ + IVectorView c = single_threaded_vector({ 1, 2, 3 }).GetView(); + std::vector result; + + for (int i : c) + { + result.push_back(i); + } + + REQUIRE(result.size() == 3); + REQUIRE(result[0] == 1); + REQUIRE(result[1] == 2); + REQUIRE(result[2] == 3); +} + +TEST_CASE("module_structured_bindings_IKeyValuePair") +{ + std::map values + { + { 1, L"one"}, + { 2, L"two"}, + { 3, L"three"}, + }; + + IIterable> c = single_threaded_map(std::map(values)); + std::map result; + + for (IKeyValuePair i : c) + { + result[i.Key()] = i.Value(); + + // Structured binding on IKeyValuePair + auto const [key, value] = i; + REQUIRE(key == i.Key()); + REQUIRE(value == i.Value()); + } + + REQUIRE(result == values); + + // Range-for with structured bindings + result.clear(); + + for (auto&& [key, value] : c) + { + result[key] = value; + } + + REQUIRE(result == values); +} + +TEST_CASE("module_range_for_IMap") +{ + std::map values + { + { 1, L"one" }, + { 2, L"two" }, + { 3, L"three" }, + }; + + IMap c = single_threaded_map(std::map(values)); + std::map result; + + for (auto&& [key, value] : c) + { + result[key] = value; + } + + REQUIRE(result == values); +} + +TEST_CASE("module_range_for_IMapView") +{ + std::map values + { + { 1, L"one" }, + { 2, L"two" }, + { 3, L"three" }, + }; + + IMapView c = single_threaded_map(std::map(values)).GetView(); + std::map result; + + for (auto&& [key, value] : c) + { + result[key] = value; + } + + REQUIRE(result == values); +} diff --git a/test/test_cpp20_module/source_location.cpp b/test/test_cpp20_module/source_location.cpp new file mode 100644 index 000000000..ebf5139c3 --- /dev/null +++ b/test/test_cpp20_module/source_location.cpp @@ -0,0 +1,13 @@ +#include "pch.h" + +import std; +import winrt.Windows.Foundation; + +TEST_CASE("module_source_location") +{ + // Verify that slim_source_location works across the module boundary + auto loc = winrt::impl::slim_source_location::current(); + REQUIRE(loc.line() > 0); + std::string_view file(loc.file_name()); + REQUIRE(file.find("source_location.cpp") != std::string_view::npos); +} diff --git a/test/test_cpp20_module/test_cpp20_module.vcxproj b/test/test_cpp20_module/test_cpp20_module.vcxproj new file mode 100644 index 000000000..1e76c487b --- /dev/null +++ b/test/test_cpp20_module/test_cpp20_module.vcxproj @@ -0,0 +1,112 @@ + + + + + Debug + ARM64 + + + Debug + Win32 + + + Release + ARM64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + 16.0 + {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72} + test_cpp20_module + test_cpp20_module + 10.0 + v145 + + + + Application + v145 + + + true + + + false + true + + + + + + + + + $(IntDir)Generated Files\ + + + + Use + pch.h + stdcpplatest + $(CppWinRTGenDir);..\;%(AdditionalIncludeDirectories) + NOMINMAX;%(PreprocessorDefinitions) + Level4 + true + 5311 + /bigobj + true + true + + + Console + ole32.lib;windowsapp.lib;%(AdditionalDependencies) + + + "$(CppWinRTDir)cppwinrt.exe" -in local -out "$(CppWinRTGenDir)." -modules -base -verbose -module_include "Windows.Foundation" -module_exclude "Windows.Foundation.Diagnostics" + + + + + + + CompileAsCppModule + true + NotUsing + + + + + + + + + Create + + + NotUsing + + + + + + + + + + + + + + \ No newline at end of file From c4cf531f6a8ec29c0e7eb19ed817043405ba9fa7 Mon Sep 17 00:00:00 2001 From: Mathias Berchtold Date: Mon, 1 Jun 2026 05:07:50 +0200 Subject: [PATCH 79/91] base_identity.h: added missing constexpr (#1589) Added missing constexpr to is_guid_of helper. guid_of is already constexpr: constexpr:https://github.com/microsoft/cppwinrt/blob/55f1b452aca069d6ac7eaad3e05cc1058fc39d27/strings/base_identity.h#L8 and find_iid_traits::test is constexpr and calls is_guid_of: https://github.com/microsoft/cppwinrt/blob/55f1b452aca069d6ac7eaad3e05cc1058fc39d27/strings/base_implements.h#L397 --- strings/base_identity.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strings/base_identity.h b/strings/base_identity.h index 7c61c83e2..4a5bedbb1 100644 --- a/strings/base_identity.h +++ b/strings/base_identity.h @@ -11,7 +11,7 @@ WINRT_EXPORT namespace winrt } template - bool is_guid_of(guid const& id) noexcept + constexpr bool is_guid_of(guid const& id) noexcept { return ((id == guid_of()) || ...); } From 478111fc4a4a74937508cf8915436ff2b97b3ca6 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Tue, 23 Jun 2026 16:00:37 -0700 Subject: [PATCH 80/91] Stop exporting winrt::impl::get_marshaler to workaround MSVC modules bug (#1592) * Stop exporting winrt::impl::get_marshaler to workaround MSVC modules bug * Include base.h in marshal.cpp to verify that include-then-import still works --- strings/base_marshaler.h | 2 +- test/test_cpp20_module/marshal.cpp | 25 +++++++++++++++++++ .../test_cpp20_module.vcxproj | 4 ++- 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 test/test_cpp20_module/marshal.cpp diff --git a/strings/base_marshaler.h b/strings/base_marshaler.h index 9be6959c9..526f4d4c3 100644 --- a/strings/base_marshaler.h +++ b/strings/base_marshaler.h @@ -1,5 +1,5 @@ -WINRT_EXPORT namespace winrt::impl +namespace winrt::impl { inline std::int32_t make_marshaler(unknown_abi* outer, void** result) noexcept { diff --git a/test/test_cpp20_module/marshal.cpp b/test/test_cpp20_module/marshal.cpp new file mode 100644 index 000000000..d47f8c3cb --- /dev/null +++ b/test/test_cpp20_module/marshal.cpp @@ -0,0 +1,25 @@ +#include "pch.h" +#include +#include + +import std; +import winrt.Windows.Foundation.Collections; + +using namespace winrt; + +struct S : implements +{ + hstring ToString() + { + return L"S"; + } +}; + +// When winrt::impl::get_marshaler was being exported, an MSVC bug caused the marshaler +// object to have a null vtable, which caused a crash when calling any method on the marshaler. +// This test ensures that the marshaler vtable is properly initialized. +TEST_CASE("IMarshal") +{ + auto s = make(); + auto marshal = s.as(); +} diff --git a/test/test_cpp20_module/test_cpp20_module.vcxproj b/test/test_cpp20_module/test_cpp20_module.vcxproj index 1e76c487b..f5c20a35d 100644 --- a/test/test_cpp20_module/test_cpp20_module.vcxproj +++ b/test/test_cpp20_module/test_cpp20_module.vcxproj @@ -25,7 +25,8 @@ Release x64 - + + 16.0 {B8E3A5CE-4E91-4F27-9B02-E0CAF7E10D72} test_cpp20_module @@ -91,6 +92,7 @@ + Create From b7eb2eacfd857c6334cd688306ab543ac4e96864 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Jun 2026 11:21:55 -0700 Subject: [PATCH 81/91] Migrate GitHub CI off VS 2022, add C++20 module test, dynamic v143/v145 toolset (#1601) * Migrate GitHub CI off VS 2022 (v143) to v145/VS 2026 * Add C++20 module test to CI; dynamic v143/v145 toolset selection --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- .github/instructions/cppwinrt.instructions.md | 2 +- .github/workflows/ci.yml | 26 +++++-------------- Directory.Build.Props | 3 +++ .../nuget/TestProxyStub/TestProxyStub.vcxproj | 1 - 4 files changed, 11 insertions(+), 21 deletions(-) diff --git a/.github/instructions/cppwinrt.instructions.md b/.github/instructions/cppwinrt.instructions.md index ba5d66212..eae2fc3c6 100644 --- a/.github/instructions/cppwinrt.instructions.md +++ b/.github/instructions/cppwinrt.instructions.md @@ -25,7 +25,7 @@ - Use VS Developer Shell for correct toolset environment - `cmake --build build --config Release --target cppwinrt` for cppwinrt.exe (or MSBuild: `msbuild cppwinrt\cppwinrt.vcxproj /p:Configuration=Release /p:Platform=x64`) - NuGet tests: `msbuild test\nuget\NuGetTest.sln /p:Configuration=Release /p:Platform=x64` -- Module test projects require v145 toolset (VS 2026). Directory.Build.Props sets v143 by default — override with `v145` in Configuration PropertyGroup +- Module test projects require v145 toolset (VS 2026). Directory.Build.Props selects v145 when VisualStudioVersion >= 18.0 (VS 2026) and falls back to v143 otherwise; override `` in the Configuration PropertyGroup to force a specific toolset ## Key Patterns diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6c2a04353..37f42ab70 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,8 +15,6 @@ jobs: arch: [x86, x64, arm64] config: [Debug, Release] toolchain: - - image: windows-2025 - platform_toolset: v143 - image: windows-2025-vs2026 platform_toolset: v145 exclude: @@ -99,10 +97,8 @@ jobs: compiler: [MSVC, clang-cl] arch: [x86, x64, arm64] config: [Debug, Release] - test_exe: [test, test_nocoro, test_cpp20, test_cpp20_no_sourcelocation, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] + test_exe: [test, test_nocoro, test_cpp20, test_cpp20_no_sourcelocation, test_cpp20_module, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] toolchain: - - image: windows-2025 - platform_toolset: v143 - image: windows-2025-vs2026 platform_toolset: v145 exclude: @@ -112,6 +108,9 @@ jobs: arch: arm64 - compiler: clang-cl config: Release + # C++20 named modules require the MSVC v145 toolset; clang-cl is not supported. + - compiler: clang-cl + test_exe: test_cpp20_module runs-on: ${{ matrix.toolchain.image }} steps: - uses: actions/checkout@v6 @@ -295,7 +294,7 @@ jobs: arch: [x86, x64, arm64] config: [Release] Deployment: [Component, Standalone] - runs-on: windows-latest + runs-on: windows-2025-vs2026 steps: - uses: actions/checkout@v6 @@ -316,7 +315,7 @@ jobs: $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" $target_version = "999.999.999.999" - Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version" + Add-Content $env:GITHUB_ENV "msbuild_config_props=/p:Configuration=$target_configuration,Platform=$target_platform,CppWinRTBuildVersion=$target_version,PlatformToolset=v145" - name: Restore nuget packages run: | @@ -336,8 +335,6 @@ jobs: arch: [x86, x64] config: [Release] toolchain: - - image: windows-2025 - platform_toolset: v143 - image: windows-2025-vs2026 platform_toolset: v145 runs-on: ${{ matrix.toolchain.image }} @@ -378,15 +375,6 @@ jobs: $target_configuration = "${{ matrix.config }}" $target_platform = "${{ matrix.arch }}" & "_build\$target_platform\$target_configuration\cppwinrt.exe" -in local -out _build\$target_platform\$target_configuration -verbose - - - name: Remove module test projects on v143 - if: matrix.toolchain.platform_toolset == 'v143' - run: | - # Module test projects require v145 toolset - mv test\nuget\NugetTest.sln test\nuget\NugetTest.sln.orig - Get-Content test\nuget\NugetTest.sln.orig | - Where-Object { -not ($_ -match 'TestModule') } | - Set-Content test\nuget\NugetTest.sln - name: Run nuget test run: | @@ -394,7 +382,7 @@ jobs: build-nuget: name: Build nuget package with MSVC - runs-on: windows-latest + runs-on: windows-2025-vs2026 steps: - uses: actions/checkout@v6 diff --git a/Directory.Build.Props b/Directory.Build.Props index c98cd5dd0..5972803c0 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -3,7 +3,10 @@ + v143 + v145 10.0 10.0.18362.0 diff --git a/test/nuget/TestProxyStub/TestProxyStub.vcxproj b/test/nuget/TestProxyStub/TestProxyStub.vcxproj index 69e41cfba..cd646da7f 100644 --- a/test/nuget/TestProxyStub/TestProxyStub.vcxproj +++ b/test/nuget/TestProxyStub/TestProxyStub.vcxproj @@ -40,7 +40,6 @@ DynamicLibrary - v143 Unicode From 5bf26503d49a7454442a8a569ae9e00d043c583e Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 24 Jun 2026 11:34:23 -0700 Subject: [PATCH 82/91] Massive speedup to file_equal and file_to_string (#1584) * Massive speedup to file_equal and file_to_string * Properly cast the result of tellg() and handle filesystem errors more gracefully. --- cppwinrt/text_writer.h | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/cppwinrt/text_writer.h b/cppwinrt/text_writer.h index a274d11ce..c6fc380b3 100644 --- a/cppwinrt/text_writer.h +++ b/cppwinrt/text_writer.h @@ -13,8 +13,26 @@ namespace cppwinrt { inline std::string file_to_string(std::string const& filename) { - std::ifstream file(filename, std::ios::binary); - return static_cast(std::stringstream() << file.rdbuf()).str(); + std::ifstream file(filename, std::ios::binary | std::ios::ate); + if (!file) { return{}; } + + const auto stream_size = file.tellg(); + if (stream_size == std::ifstream::pos_type(-1)) + { + return {}; + } + + file.seekg(0); + + auto size = static_cast(stream_size); + std::string result(size, '\0'); + file.read(result.data(), size); + if (!file) + { + result.resize(static_cast(file.gcount())); + } + + return result; } template @@ -218,18 +236,15 @@ namespace cppwinrt bool file_equal(std::string const& filename) const { - if (!std::filesystem::exists(filename)) + // Non-throwing file_size returns uintmax_t(-1) on errors, which shouldn't ever be the size of m_first or m_second + std::error_code ec; + if (std::filesystem::file_size(filename, ec) != m_first.size() + m_second.size()) { return false; } auto file = file_to_string(filename); - if (file.size() != m_first.size() + m_second.size()) - { - return false; - } - if (!std::equal(m_first.begin(), m_first.end(), file.begin(), file.begin() + m_first.size())) { return false; From 77b1e4e02057e4cfff1ce850e40024e9fbc0f7fb Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 24 Jun 2026 11:45:53 -0700 Subject: [PATCH 83/91] Improve module docs, ship them in the nuget, and add missing properties to Visual Studio proejct properties page (#1586) --- nuget/CppWinrtRules.Project.xml | 21 ++ nuget/Microsoft.Windows.CppWinRT.nuspec | 3 + nuget/modules.md | 415 ++++++++++++++++++++++-- nuget/readme.md | 4 +- nuget/readme.txt | 3 + 5 files changed, 410 insertions(+), 36 deletions(-) diff --git a/nuget/CppWinrtRules.Project.xml b/nuget/CppWinrtRules.Project.xml index 73f32c6d3..43a712d21 100644 --- a/nuget/CppWinrtRules.Project.xml +++ b/nuget/CppWinrtRules.Project.xml @@ -3,6 +3,7 @@ + @@ -86,4 +87,24 @@ Description="Enables the /await:strict compiler option" Category="General" /> + + + + + + + + diff --git a/nuget/Microsoft.Windows.CppWinRT.nuspec b/nuget/Microsoft.Windows.CppWinRT.nuspec index a63e08bf9..52151fc08 100644 --- a/nuget/Microsoft.Windows.CppWinRT.nuspec +++ b/nuget/Microsoft.Windows.CppWinRT.nuspec @@ -12,6 +12,7 @@ native C++ WinRT nativepackage © Microsoft Corporation. All rights reserved. LICENSE + readme.md https://github.com/Microsoft/cppwinrt https://aka.ms/cppwinrt.ico @@ -25,5 +26,7 @@ + + diff --git a/nuget/modules.md b/nuget/modules.md index 479781252..4f0eebb95 100644 --- a/nuget/modules.md +++ b/nuget/modules.md @@ -14,11 +14,41 @@ instead of: #include ``` -Modules provide faster builds through pre-compiled module interfaces (IFCs) and better isolation of macro and declaration scopes. +Benefits include: + +- **Smaller intermediate artifacts.** The IFC representation of a C++/WinRT projection is significantly smaller than the equivalent precompiled header (PCH). +- **Shared compilation across projects.** PCHs eliminate redundant parsing *within* a project, but each project rebuilds its own PCH. Module IFCs can be built once in a shared module builder project and consumed by all dependent projects, eliminating redundant work across the entire solution. +- **Better isolation.** Module imports don't leak macros into the importing translation unit. + +> **Real-world experience:** The guidance in this document was hardened against a prototype conversion of the Windows Terminal codebase (~250 files across 15+ projects) from textual `#include`s to module imports. + +## Prerequisites + +- **MSVC v145 toolset** (Visual Studio 2026) or later with C++20 module support +- **C++/WinRT 3.x** NuGet package with `CppWinRTBuildModule` support +- `/std:c++20` or later (`/std:c++latest` recommended for `import std;`) +- `BuildStlModules=true` for `import std;` support + +## Three Fundamental Constraints + +These three rules drive almost every pattern in this guide. Understanding them up front makes the rest of the document much easier to follow: + +1. **`import` in a PCH breaks the compiler.** MSVC cannot handle module `import` declarations inside a precompiled header — it produces internal compiler errors (ICE). All module imports must live outside the PCH. + +2. **Include-then-import is safe, but has a cost.** MSVC handles the case where you `#include` a header and then `import` the same content. For STL headers this is a reasonable workaround (the compilation cost is modest), but C++/WinRT projection headers can be extremely expensive to parse textually. Include-then-import with winrt headers defeats the build-cost improvements of adopting modules, so it should be avoided where possible. + +3. **Import-then-include is not supported.** When a module has already been imported, `#include`-ing a header that declares the same types causes errors — the compiler sees conflicting declarations. C++/WinRT provides a workaround: defining `WINRT_IMPORT_MODULE` before including a winrt header causes the header to be (mostly) a no-op, defining only its include-guard macro. This makes it safe to include winrt headers *after* importing modules, which is essential for lighting up header-guard-based features in libraries like WIL, and for interoperating with external code that includes winrt headers out of your control (e.g. the XAML compiler). STL headers do not have an equivalent workaround, but can fall back on the "generally safe" include-then-import pattern. + +The patterns throughout this guide are direct consequences of these constraints: + +- The PCH is stripped of all winrt content. +- A separate "module preamble" header centralizes imports. +- Wrapper headers define `WINRT_IMPORT_MODULE` before including winrt headers. +- STL headers are sometimes pre-included in the PCH, but only as a workaround. ## Quick Start — Single Project -For a project that builds and consumes its own modules: +For a small project that builds and consumes its own modules: 1. Set `CppWinRTBuildModule` to `true` in your project: ```xml @@ -34,6 +64,8 @@ For a project that builds and consumes its own modules: ``` + By default, C++/WinRT generates and builds `.ixx` files for **every** namespace reachable from your WinMD inputs — for a typical Windows SDK projection, that's hundreds of namespaces and can add upwards of a minute to your build. If build speed matters, prune the set with `CppWinRTModuleInclude` (or `CppWinRTModuleExclude`) so that only the namespaces you actually `import` are produced. See [Understanding the Include and Exclude Filters](#understanding-the-include-and-exclude-filters) for the full discussion. + 3. Enable `BuildStlModules` for `import std;` support: ```xml @@ -51,25 +83,40 @@ For a project that builds and consumes its own modules: } ``` -## Quick Start — Multi-Project (Recommended) +For a single vcxproj — or a handful of projects that don't share many namespaces — this is all you need. A dedicated module builder is only worth the overhead when multiple projects need the same platform and third-party WinRT modules. + +## Architecture — Module Builder (Recommended for Multi-Project Solutions) + +For solutions with multiple projects, the recommended approach is a dedicated **module builder** project that builds the shared IFC files once, consumed by all other projects. This avoids each project redundantly compiling the same module interfaces. -For larger solutions, compile platform modules once in a dedicated "builder" static library, and share the pre-built IFCs with other projects. +### The Module Builder Project -### Module Builder (static library) +Create a dedicated static library project whose sole purpose is to build the shared platform module IFC files. This project has no source files of its own — the C++/WinRT NuGet targets generate `.ixx` files automatically. ```xml StaticLibrary true - Windows.Foundation + true ``` -### Consumer (exe or dll) +Key configuration: + +- **`CppWinRTBuildModule=true`** generates per-namespace `.ixx` module interface files. +- **`BuildStlModules=true`** is required because the generated `.ixx` files use `import std;`. +- **`WINRT_ENABLE_LEGACY_COM`** — define this preprocessor macro if your project uses classic COM interfaces (`IUnknown`, `IInspectable`). It causes `` and `` to be included within the `winrt_base` module. +- **PCH**: don't bother. The module builder can use a PCH, but there is little benefit — its content is almost entirely C++/WinRT headers, and most non-C++/WinRT headers are only used once in `winrt_base`. + +### Consumer Project Configuration + +Each project that uses modules needs: ```xml true + MyCompany.MyComponent + Microsoft.UI;Microsoft.Web @@ -78,9 +125,25 @@ For larger solutions, compile platform modules once in a dedicated "builder" sta ``` -The `CppWinRTConsumeModule` metadata on the ProjectReference tells the build system to: -- Use the builder's pre-built platform IFCs instead of compiling platform `.ixx` files again -- Skip generating platform `.ixx` files in the consumer's own projection +- **`CppWinRTBuildModule=true`** is required on consumers too. It enables the C++/WinRT targets to generate `.ixx` module interface files for the project's own component namespaces (filtered by `CppWinRTModuleInclude` / `CppWinRTModuleExclude`) and wires up module consumption from referenced projects. +- **`CppWinRTConsumeModule=true`** on the `ProjectReference` tells the build system to use the builder's pre-built platform IFCs instead of compiling platform `.ixx` files again, and skip generating platform `.ixx` files in the consumer's own projection. + +### Adding Third-Party WinMDs to the Module Builder + +If your project uses third-party WinRT components (e.g., WinUI/MUX, WebView2), build their modules in the shared builder by adding their WinMDs as platform inputs: + +```xml + + + + + + +``` + +**Important:** Add these WinMDs as `CppWinRTPlatformWinMDReferences`, **not** as NuGet `` items. In practice, adding third-party WinMDs via NuGet `` items on the module builder has been observed to cause empty path errors in the reference projection step. Adding them directly as `CppWinRTPlatformWinMDReferences` feeds them into the platform projection, which is the correct pipeline for a module builder project. ### Component DLLs @@ -98,8 +161,6 @@ WinRT component projects can also use modules. Set `CppWinRTBuildModule=true` an ``` -### Consuming Components from Other Projects - If project A references a component DLL from project B, project A builds its own reference projection modules from B's `.winmd`: ```cpp @@ -113,19 +174,53 @@ auto obj = winrt::MyComponent::MyClass(); | Property | Default | Description | |-|-|-| -| `CppWinRTBuildModule` | false | Generate `.ixx` module interface units from projections | +| `CppWinRTBuildModule` | `false` | Generate `.ixx` module interface units from projections | | `CppWinRTModuleInclude` | (all) | Semicolon-delimited namespace prefixes to include in module generation | | `CppWinRTModuleExclude` | (none) | Semicolon-delimited namespace prefixes to exclude from module generation | -| ProjectReference Metadata | Default | Description | +| `ProjectReference` Metadata | Default | Description | |-|-|-| -| `CppWinRTConsumeModule` | false | Consume pre-built platform module IFCs from this project reference | +| `CppWinRTConsumeModule` | `false` | Consume pre-built platform module IFCs from this project reference | + +### Understanding the Include and Exclude Filters + +These filters control which C++/WinRT module `.ixx` files are generated from WinMD inputs. They only affect modules produced by the C++/WinRT NuGet targets from `.winmd` files — hand-authored modules or modules unrelated to WinRT are not affected. + +- **`CppWinRTModuleInclude`** — semicolon-separated namespace prefixes. Only matching namespaces will have `.ixx` files generated. Without this, *all* namespaces from the project's WinMD inputs are candidates. +- **`CppWinRTModuleExclude`** — semicolon-separated namespace prefixes to suppress `.ixx` generation for. **Import statements are still generated** in the modules that remain; only the `.ixx` file creation is suppressed. -## Module Filtering and Transitive Dependencies +#### Why Filter at All? + +There are three distinct reasons to set these filters. Most non-trivial projects will hit more than one: + +1. **Build performance.** By default, enabling `CppWinRTBuildModule=true` generates and compiles `.ixx` files for *every* namespace reachable from your WinMD inputs. For a typical Windows SDK projection that's hundreds of namespaces, and the IFC compilation step can easily add upwards of a minute to a clean build. Use `CppWinRTModuleInclude` to narrow generation to namespaces you (or your consumers) actually `import`, or `CppWinRTModuleExclude` to drop large subtrees you don't use (e.g., `Windows.Devices`, `Windows.Media`). For a dedicated module builder project that other projects consume, this is typically the dominant reason to filter. + +2. **Avoiding ambiguous IFC errors (C7684).** An IFC is ambiguous when the same module name resolves to two different `.ifc` files — typically one built locally and one from a referenced project. See [When to Set an Exclude for Ambiguity](#when-to-set-an-exclude-for-ambiguity) below. + +3. **Avoiding modules with unsatisfied dependencies.** Filtering to a subset of namespaces does *not* prune the `import` statements those modules emit for their dependencies — so a generated module whose dependencies fall outside your filter will fail to compile. See [Module Filtering and Transitive Dependencies](#module-filtering-and-transitive-dependencies) below. + +#### When to Set an Exclude for Ambiguity + +Exclude a namespace when its IFC is already provided by a project you reference: + +| Scenario | Action | +|----------|--------| +| You reference a **static library** with `CppWinRTBuildModule=true` | Exclude namespaces that static lib produces (its IFCs propagate via `AdditionalBMIDirectories`) | +| You reference a **DLL** with `CppWinRTBuildModule=true` | **No exclude needed** — DLL IFCs don't propagate by default | +| The **module builder** produces a namespace (e.g., `Microsoft.UI`) | Exclude it — the module builder's IFCs propagate via `CppWinRTConsumeModule` | + +Example — a project that references both the module builder (which provides `Microsoft.UI.*`) and a `TerminalCore` static library (which provides `Microsoft.Terminal.Core`): + +```xml +Microsoft.Terminal +Microsoft.Terminal.Core;Microsoft.UI;Microsoft.Web +``` + +### Module Filtering and Transitive Dependencies `CppWinRTModuleInclude` and `CppWinRTModuleExclude` control which namespace `.ixx` files are **generated**, but they do not suppress `import` statements for dependencies. If namespace A is included in the filter and depends on namespace B, the generated `winrt.A.ixx` will contain `import winrt.B;` even if B is excluded from the filter. This is by design — the module for B must exist *somewhere* (either from the same project or from a referenced project). -This has important implications: +Implications: - **Transitive closure must be satisfied.** If you filter to a subset of namespaces, any dependencies that fall outside the filter must be available from another source (e.g., a module builder project referenced via `CppWinRTConsumeModule`, or MSBuild's automatic `ReferencedModuleBMIs` from a static library reference). Otherwise, compilation will fail with "could not find module" errors. @@ -141,39 +236,289 @@ This has important implications: | `winrt_numerics` | `Windows::Foundation::Numerics` types — re-exported by `winrt_base` | | `winrt.` | Per-namespace projection (e.g., `winrt.Windows.Foundation`) | -## Requirements +## Converting an Existing Project: Step by Step -- MSVC v145 toolset (Visual Studio 2026) or later recommended -- C++20 or later (`/std:c++20` or newer) -- `BuildStlModules=true` for `import std;` support +### 1. Strip winrt from the PCH -## Limitations +Module `import` declarations inside a precompiled header cause compiler ICEs. All C++/WinRT content must be moved out of the PCH and into the module preamble header (see next step). -- Module IFCs are not compatible across toolset versions. All projects must use the same toolset. -- Cyclic namespace dependencies (e.g., `Windows.Foundation` ↔ `Windows.Foundation.Collections`) are handled automatically via SCC consolidation, but the resulting module name is chosen alphabetically. Adding new APIs could change SCC groupings. +Remove the following from your PCH: + +- `#include ` — all winrt projection headers +- `#include ` and `` +- Any header that depends on C++/WinRT types, **including headers that conditionally enable behavior based on C++/WinRT header guards.** For example, `wil/cppwinrt_helpers.h` checks for `WINRT_Windows_UI_Core_H` and uses types from `Windows.UI.Core` when defined — this header must move out of the PCH. + +**Keep** in the PCH: + +- Platform SDK headers (``, ``, etc.) +- Non-winrt third-party headers + +**STL headers and `import std;`** — STL headers are safe to include *before* `import std;` (include-then-import works). Problems arise when STL headers are included *after* `import std;`, which can cause redefinition warnings (C4348, C5028). In most cases it is preferable to use `import std;` instead of putting STL headers in the PCH. However, if you depend on libraries that internally `#include` STL headers *after* modules have been imported, you may need to pre-include the offending STL headers in the PCH to make the later inclusion inert: + +```cpp +// Pre-include STL headers that other libraries include after import std; +#include +#include +``` + +Ideally, the offending library code would also adopt `import std;`, but that's not always immediately practical. + +### 2. Create a Module Preamble Header + +A module preamble header centralizes the module imports and library setup that are shared across a project's source files. It is not strictly required — you could add imports directly to each `.cpp` file — but it speeds up migration significantly and becomes necessary if you need to deal with generated files outside your control (see [XAML Projects](#xaml-projects)). + +Create a preamble header in each project that contains the module imports commonly used across that project: + +```cpp +// ModulePreamble.h (or whatever name you prefer) +#pragma once + +#define WINRT_IMPORT_MODULE + +// Import the C++/WinRT namespaces used across this project +import winrt.Windows.Foundation; +import winrt.Windows.Foundation.Collections; +import winrt.Windows.System; +// ... other namespaces your project needs + +// Component modules +import winrt.MyCompany.MyComponent; +``` + +Importing modules is cheap, so don't hesitate to list every namespace the project uses. You can add library wrapper headers and other setup to this file as needed (see next section). + +Include the preamble in each `.cpp` file after the PCH: + +```cpp +#include "pch.h" +#include "ModulePreamble.h" +// ... rest of the file +``` + +### 3. Wrap Library Headers That Depend on C++/WinRT Types + +Libraries like WIL use `#ifdef WINRT_Windows_Foundation_H` guards to conditionally enable winrt-dependent features. With modules, those header guards are never defined because the winrt headers are never textually included. To light up this behavior, define the appropriate header guards before including the library header — or, equivalently, include the now-inert winrt headers under `WINRT_IMPORT_MODULE`, which defines the guards as a side effect. + +You can do this directly in the module preamble: + +```cpp +// In your module preamble header +import winrt.Windows.Foundation; +#define WINRT_IMPORT_MODULE +#define WINRT_Windows_Foundation_H // Lights up WIL's Foundation support +#include +``` + +If you include the library from many places, you can author a **wrapper header** that bundles the imports, guard definitions, and library include together: + +```cpp +// wil_cppwinrt_module.h +#pragma once + +import winrt_base; +import winrt.Windows.Foundation; +import winrt.Windows.Foundation.Collections; + +#define WINRT_IMPORT_MODULE +// Define header guards to light up WIL's conditional winrt features. +// You can either define the guards directly, or include the now-inert +// winrt headers (which define the guards as a side effect): +#include +#include + +#include +#include +``` + +Include this wrapper in your module preamble as needed. Re-importing modules and re-defining header guards is harmless, so there's no issue with including the wrapper from multiple places. + +This pattern applies to any library that conditionally uses winrt types based on header include guards. + +### 4. Update the vcxproj + +```xml + +true +MyCompany.MyComponent +Microsoft.UI;Microsoft.Web + + + + true + +``` + +### 5. Add Solution Build Dependency + +If using `.slnx` or `.sln`, add a build dependency to ensure the module builder, if using, compiles first: + +```xml + +``` + +## Special Cases + +### XAML Projects + +XAML projects have a two-pass compilation model that complicates module adoption. The XAML compiler generates source files (`XamlTypeInfo.g.cpp`, `XamlTypeInfo.Impl.g.cpp`, `XamlMetaDataProvider.cpp`) that use winrt types but don't know about modules. + +The solution is to inject `ModulePreamble.h` via the `/FI` (forced include) compiler flag on these generated files, using MSBuild targets: + +```xml + + + + + NotUsing + $(MSBuildProjectDirectory)\ModulePreamble.h + + + +``` + +For static library projects, the XAML build system has a second compilation pass (`CompileXamlGeneratedFiles`) that runs after `ClCompile` but before `Lib`. For DLLs and EXEs, the same targets run after the build compile phase. In either case, you need a second target to ensure the `/FI` metadata is applied before `CompileXamlGeneratedFiles`: + +```xml + + + + NotUsing + $(MSBuildProjectDirectory)\ModulePreamble.h + + + +``` + +**Critical MSBuild detail:** Use ``, not just ``. Without `Update`, MSBuild adds new items instead of modifying metadata on existing ones. + +**Why the preamble header needs `#include "pch.h"` for XAML:** When used as `/FI`, the preamble header is processed *before* the generated file's own `#include "pch.h"`. Adding `#include "pch.h"` at the top of the preamble ensures platform headers are available. For regular `.cpp` files that already include pch.h before the preamble, it's a `#pragma once` no-op. If your project doesn't use the `/FI` approach for XAML, you don't need pch.h in the preamble. + +#### Understanding the XAML Build Order + +The XAML build targets schedule `MarkupCompilePass2` and `CompileXamlGeneratedFiles` differently depending on project type: + +- **Static libraries** (`AfterClCompileTargets`): Pass2 runs after `ClCompile`, before `Lib` +- **DLLs/EXEs** (`AfterBuildCompileTargets`): Pass2 runs after the build compile phase, before `Link` + +In both cases, the order is: + +1. **MarkupCompilePass1** (before `ClCompile`): Generates `.xaml.g.h` declarations +2. **ClCompile**: Compiles your source files +3. **MarkupCompilePass2**: Generates `.xaml.g.hpp` implementations +4. **CompileXamlGeneratedFiles**: Compiles `XamlTypeInfo.g.cpp` (which `#include`s the `.xaml.g.hpp` files) + +The XAML-generated items (`XamlTypeInfo.g.cpp`, etc.) are added to `ClCompile` by the `ComputeXamlGeneratedCompileInputs` target, which is why the `/FI` target uses `AfterTargets="ComputeXamlGeneratedCompileInputs"`. + +### Headers with Conditional winrt Conversions + +If you have utility types (like a `color` struct) with conversion operators gated behind winrt header guards: + +```cpp +#ifdef WINRT_Windows_UI_H + operator winrt::Windows::UI::Color() const { ... } +#endif +``` + +These guards must be defined **before** the header is first included (`#pragma once` means it won't be processed again). Create a dedicated wrapper that imports the module, sets the guard, then re-includes the header: + +```cpp +// color_module.h +#pragma once +import winrt.Windows.UI; +#define WINRT_IMPORT_MODULE +#include // Sets WINRT_Windows_UI_H +#include // Now sees the guard, enables converters +``` + +Include this wrapper in your `ModulePreamble.h` **before** any other header that might include the guarded file. + +### Win32 Macro Conflicts + +Some Win32 macros (e.g., `GetObject` from `wingdi.h`) conflict with WinRT method names. With headers, the macro was applied to both the projection types and the call site. With modules, the WinRT types don't have the macro applied (they were compiled in the module without the macro), but your source file still has the macro defined. Use: + +```cpp +#pragma push_macro("GetObject") +#undef GetObject +// ... code using winrt types with GetObject method +#pragma pop_macro("GetObject") +``` ## Caution: Module Reuse Across Projects Pre-built IFCs (via `CppWinRTConsumeModule`) should only be shared when the builder and consumer use the same compilation context. In particular: -- **Component modules are project-private.** A component projection built with `CppWinRTOptimized=true` generates modules that bypass activation factories for in-component type instantiation (`-opt`). If a consuming project accidentally imports these modules instead of building its own reference projection, the consumer will attempt direct instantiation across DLL boundaries, resulting in linker errors or incorrect behavior. Each project should build its own modules from the component's `.winmd` — do not tag component ProjectReferences with `CppWinRTConsumeModule`. +- **Component modules are project-private.** A component projection built with `CppWinRTOptimized=true` generates modules that bypass activation factories for in-component type instantiation (`-opt`). If a consuming project accidentally imports these modules instead of building its own reference projection, the consumer will attempt direct instantiation across DLL boundaries, resulting in linker errors or incorrect behavior. Each project should build its own modules from the component's `.winmd` — do not tag component `ProjectReference`s with `CppWinRTConsumeModule`. -- **`CppWinRTConsumeModule` is intended for platform module builders only.** The builder project is a dedicated static library whose sole purpose is compiling platform SDK modules. Its compilation flags (no `-opt`, no `-comp`) produce modules safe for any consumer. Only tag this builder's ProjectReference with `CppWinRTConsumeModule=true`. +- **`CppWinRTConsumeModule` is intended for platform module builders only.** The builder project is a dedicated static library whose sole purpose is compiling platform SDK modules. Its compilation flags (no `-opt`, no `-comp`) produce modules safe for any consumer. Only tag this builder's `ProjectReference` with `CppWinRTConsumeModule=true`. - **Module filter scope matters.** `CppWinRTModuleInclude` / `CppWinRTModuleExclude` applies to all three projections (platform, reference, component). If you set `CppWinRTModuleInclude=MyComponent`, only `MyComponent` namespaces will get `.ixx` files — platform and reference namespace modules will not be generated. Make sure your filter includes all namespaces you intend to import as modules, or use `CppWinRTConsumeModule` to get platform modules from a builder that was configured with the appropriate filter. - **Compilation settings must be compatible between builder and consumer.** Module IFCs encode assumptions about the compilation environment. While the compiler may not always diagnose mismatches, the following differences between the module builder and consumer may cause subtle or hard-to-diagnose issues: - - **Debug vs Release** — Mixing Debug and Release configurations can produce mismatched code generation, iterator debugging levels, and runtime library selections. - - **Preprocessor definitions** — Definitions that affect type layout, conditional compilation, or feature flags should match between builder and consumer. - - **Struct alignment / packing** — Different `/Zp` settings between projects can change struct layout, causing silent ABI mismatches. - - **Language standard** — While C++20 and later are generally compatible, mixing `/std:c++20` and `/std:c++23` and/or `/std:c++latest` if there are language features that affect type definitions. + - **Debug vs Release** — mixing Debug and Release configurations can produce mismatched code generation, iterator debugging levels, and runtime library selections. + - **Preprocessor definitions** — definitions that affect type layout, conditional compilation, or feature flags should match between builder and consumer. + - **Struct alignment / packing** — different `/Zp` settings between projects can change struct layout, causing silent ABI mismatches. + - **Language standard** — while C++20 and later are generally compatible, mixing `/std:c++20` and `/std:c++23` and/or `/std:c++latest` can affect type definitions if language features differ. + + As a general rule, the module builder project should try to use the same configuration, preprocessor definitions, and compiler options as its consumers. + +## Limitations + +- Module IFCs are not compatible across toolset versions. All projects must use the same toolset. +- Cyclic namespace dependencies (e.g., `Windows.Foundation` ↔ `Windows.Foundation.Collections`) are handled automatically via SCC consolidation, but the resulting module name is chosen alphabetically. Adding new APIs could change SCC groupings. + +## Common Errors and Solutions + +| Error | Cause | Solution | +|-------|-------|----------| +| **C2230**: could not find module `winrt.X` | Missing import or the module IFC wasn't built | Add the import; verify the module builder or consumer produces it; check `CppWinRTModuleInclude` | +| **C7684**: ambiguous resolution to IFC | Same module built by multiple projects visible to the consumer | Add the namespace to `CppWinRTModuleExclude` | +| **C4348**: redefinition of default parameter | STL header included after `import std;` | Pre-include the STL header in the PCH (e.g., `#include `) | +| **C5028**: alignment specified in prior declaration | Same root cause as C4348 | Pre-include the STL header (e.g., `#include `) | +| **C4430 / C2039**: missing type / not a member | Type not visible because module not imported | Add the missing `import winrt.Namespace;` to ModulePreamble | +| **LNK2019**: unresolved external for `InitializeComponent` | XAML-generated code compiled without module imports | Ensure the `/FI` targets are present and use `Update="@(ClCompile)"` | +| **LNK2005**: symbol already defined | XAML-generated file compiled both directly and via a wrapper | Use the `/FI` injection approach instead of wrapper `.cpp` files | +| Redefinition errors when mixing `#include` and `import` | Same namespace included textually after being imported | Define `WINRT_IMPORT_MODULE` before the winrt header, or remove the `#include` | +| **"could not find module 'winrt.X'"** in cross-project consumer | Builder's `IntDir` not visible to consumer | Verify `ProjectReference` to the builder has `CppWinRTConsumeModule=true` | +| Linker errors for component constructors | Importing a component's internal module instead of building your own reference projection | Remove explicit `/reference` flags for component IFCs and ensure your project has `CppWinRTBuildModule=true` so it builds reference projection modules from the component's `.winmd` | + +## Tips + +- **Clean build after configuration changes.** Stale IFC files from previous builds cause confusing ambiguity errors. Clean the intermediate directory when changing module include/exclude filters. +- **Start from leaf projects.** Convert projects with no WinRT component dependencies first (e.g., utility libraries), then work up the dependency graph. +- **One project at a time.** Each conversion may surface new missing imports or exclude requirements. Building incrementally makes errors easier to diagnose. +- **Watch for transitive IFC propagation.** Static library IFCs become visible to all consumers in the reference chain. This is correct behavior but requires `CppWinRTModuleExclude` entries in consumers. +- **`CppWinRTModuleInclude` is usually needed.** Without it, projects with `CppWinRTModuleExclude` may not generate any `.ixx` files at all. Specify the namespace prefix for your component (e.g., `Microsoft.Terminal`). +- **DLL wrapper projects typically need no changes.** If you have a pattern of "static lib + thin DLL wrapper", the DLL wrapper usually just links the lib and doesn't need module conversion. + +## Approaches Tried and Abandoned + +For posterity, these patterns were attempted during the Terminal prototype but proved problematic. Avoid them. + +### Wrapper `.module.cpp` files for XAML-generated code + +The idea was to create wrapper `.cpp` files that would `#include` the XAML-generated files after setting up module imports, then remove the original generated items from `ClCompile` and replace them with the wrappers. + +**Why it failed:** The XAML build system generates files across two compilation passes. `XamlTypeInfo.g.cpp` `#include`s `.xaml.g.hpp` files that don't exist until Pass2, but the wrapper needed to compile during the first `ClCompile` pass. `__has_include` guards to make wrappers compile empty initially and recompile later proved unreliable — `CompileXamlGeneratedFiles` is a separate compilation step, and the wrapper items weren't correctly routed through it. + +**The `/FI` approach works** because it modifies the compiler flags on the *existing* generated items rather than replacing them, working with the XAML build system's two-pass compilation. + +### `AllProjectBMIsArePublic=false` on static libraries - As a general rule, the module builder project try to use the same configuration, preprocessor definitions, and compiler options as its consumers. +The idea was to prevent IFC propagation from static libraries by setting `AllProjectBMIsArePublic=false`, hiding the static lib's IFCs from consumers. -## Troubleshooting +**Why we moved away:** This fights against the intended VC++ build model. If a project consumes a static library, it should also consume that library's IFC files. Using different IFCs for the same types risks ODR violations. The `CppWinRTModuleExclude` approach is better — the consumer avoids building duplicate IFCs while still consuming the producer's IFCs. -**"could not find module 'winrt.X'"** — Ensure the `.ixx` was generated (check `$(GeneratedFilesDir)winrt\`) and that `CppWinRTBuildModule=true` is set. For cross-project references, verify the consuming project's `ProjectReference` to the builder has `CppWinRTConsumeModule=true`, and that the builder's `IntDir` is accessible via `/ifcSearchDir`. +### Moving wrapper items into MSBuild targets -**Linker errors for component constructors** — You may be importing a component's internal module instead of building your own reference projection. Remove explicit `/reference` flags for component IFCs and ensure your project has `CppWinRTBuildModule=true` so it builds reference projection modules from the component's `.winmd`. +The idea was to add wrapper `.cpp` `ClCompile` items inside a `` (dynamically) instead of a static ``, so they'd only enter `ClCompile` after generated files existed. -**Redefinition errors** — Don't mix `#include` and `import` for the same namespace in the same translation unit. Use `import` consistently. +**Why it failed:** Items added inside targets don't get the same metadata processing (module dependency scanning, IFC reference resolution) as items in static `ItemGroup`s. The compiler couldn't find any modules. diff --git a/nuget/readme.md b/nuget/readme.md index c8c0b9537..16eb5d2bb 100644 --- a/nuget/readme.md +++ b/nuget/readme.md @@ -137,7 +137,9 @@ void DerivedPage::InitializeComponent() ## C++20 Modules -C++/WinRT supports C++20 named modules as an alternative to `#include`-based consumption. Instead of `#include `, you can write `import winrt.Windows.Foundation;`. See [modules.md](modules.md) for the full guide. +C++/WinRT supports C++20 named modules as an alternative to `#include`-based consumption. Instead of `#include `, you can write `import winrt.Windows.Foundation;`. + +See the [C++/WinRT C++20 Modules Guide](https://github.com/microsoft/cppwinrt/blob/master/nuget/modules.md) for the full guide (also shipped alongside this file as `modules.md`). | ProjectReference metadata | Description | |-|-| diff --git a/nuget/readme.txt b/nuget/readme.txt index 049ab13b8..8d2681b6b 100644 --- a/nuget/readme.txt +++ b/nuget/readme.txt @@ -19,4 +19,7 @@ In addition, C++/WinRT generates templates and skeleton implementations for each ======================================================================== For more information, visit: https://github.com/Microsoft/cppwinrt/tree/master/nuget + +The full documentation is also included in this package as readme.md, and +the C++20 modules guide as modules.md. ======================================================================== From a31a05cedeee239995bbb09ea6867fbda9bb0fab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 11:56:29 -0700 Subject: [PATCH 84/91] Bump actions/checkout from 6 to 7 (#1600) Bumps [actions/checkout](https://github.com/actions/checkout) from 6 to 7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v6...v7) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Ryan Shepherd --- .github/workflows/check-line-endings.yml | 2 +- .github/workflows/ci.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/check-line-endings.yml b/.github/workflows/check-line-endings.yml index a0705cf58..dea958274 100644 --- a/.github/workflows/check-line-endings.yml +++ b/.github/workflows/check-line-endings.yml @@ -11,7 +11,7 @@ jobs: name: Enforce .gitattributes line endings runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Check for line ending violations run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 37f42ab70..afdeed462 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: config: Release runs-on: ${{ matrix.toolchain.image }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Download nuget run: | @@ -113,7 +113,7 @@ jobs: test_exe: test_cpp20_module runs-on: ${{ matrix.toolchain.image }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' @@ -263,7 +263,7 @@ jobs: CMAKE_COLOR_DIAGNOSTICS: 1 CLICOLOR_FORCE: 1 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Install cross compiler run: | @@ -296,7 +296,7 @@ jobs: Deployment: [Component, Standalone] runs-on: windows-2025-vs2026 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Download nuget run: | @@ -339,7 +339,7 @@ jobs: platform_toolset: v145 runs-on: ${{ matrix.toolchain.image }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Fetch cppwinrt executables uses: actions/download-artifact@v8 @@ -384,7 +384,7 @@ jobs: name: Build nuget package with MSVC runs-on: windows-2025-vs2026 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Package run: | From a535d38f083e6a428b64ac47e3144653c9739bc5 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 8 Jul 2026 12:38:40 -0700 Subject: [PATCH 85/91] Fix C4819 warning: replace non-ASCII em dash in base_macros.h comment (#1606) * Initial plan * Fix C4819 warning: replace non-ASCII em dash with ASCII hyphen in base_macros.h comment --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> --- strings/base_macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strings/base_macros.h b/strings/base_macros.h index 91b0121d9..850d0c627 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -44,7 +44,7 @@ // Template specializations in namespace std (hash, coroutine_traits) need extern "C++" // linkage in module builds for proper merging with the std module, but must NOT be -// exported — exporting namespace std would make all of std transitively visible. +// exported - exporting namespace std would make all of std transitively visible. #ifndef WINRT_IMPL_STD_EXPORT #ifdef WINRT_IMPL_BUILD_MODULE #define WINRT_IMPL_STD_EXPORT extern "C++" From d3d92d70e3e089307ab6d6deb5ed39c7a534fec2 Mon Sep 17 00:00:00 2001 From: Raymond Chen Date: Mon, 27 Jul 2026 09:39:55 -0700 Subject: [PATCH 86/91] Fix race condition in cancellation setup/teardown (#1609) The code failed to handle three cases. 1. A cancellation is in progress when a cancellable awaitable begins. 2. A cancellation is in progress when a cancellable awaitable ends. 3. A cancellation is in progress when a cancel() request is made. The m_canceller member has one of these three values: * nullptr, meaning that there is nothing to cancel. It has this value when the coroutine is not awaiting, or if it is awaiting something that cannot be cancelled. * cancelling_ptr, meaning that another thread (not the coroutine thread) is in the middle of cancellation request. * function pointer, representing the function to call to cancel the await. In case 1, we should not overwrite the canceling_ptr with the function pointer, because only the code doing the cancel() can transition into/out of cancelling_ptr. In case 2, we intended to spin until the m_canceller is no longer cancelling_ptr, but we used m_canceller.exchange(nullptr) in a loop, which means that if m_canceller was cancelling_ptr, we overwrite it with nullptr. As a result, the "while" loop always exits after one iteration. We need to spin on the m_canceller without modifying it if it is cancelling_ptr. In case 3, cancel() function resets m_cancelling back to nullptr, even if the value was cancelling_ptr on entry, prematurely declaring that the existing cancel() has completed. If the original value was cancelling_ptr, we should leave it that way. There are still other cases not handled: * Coroutine already cancelled when a co_await starts. In this case, we never call the canceller, so the coroutine fails to propagate cancellation. This will require a broader fix, so I'm not going to fix it in this PR. This PR is primarily about fixing the crash caused by case 2. Cases 1 and 3 were fixed opportunistically. --- strings/base_coroutine_threadpool.h | 34 +++++++++++++++++++---------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index 057d5b548..c901b94ba 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -146,32 +146,42 @@ WINRT_EXPORT namespace winrt void set_canceller(canceller_t canceller, void* context) { m_context = context; - m_canceller.store(canceller, std::memory_order_release); + canceller_t expected = nullptr; + m_canceller.compare_exchange_strong(expected, canceller, std::memory_order_release, std::memory_order_relaxed); } void revoke_canceller() { - while (m_canceller.exchange(nullptr, std::memory_order_acquire) == cancelling_ptr) + auto existing = m_canceller.load(std::memory_order_relaxed); + do { - std::this_thread::yield(); + while (existing == cancelling_ptr) + { + std::this_thread::yield(); + existing = m_canceller.load(std::memory_order_relaxed); + } } + while (!m_canceller.compare_exchange_weak(existing, nullptr, std::memory_order_acquire, std::memory_order_relaxed)); } void cancel() { auto canceller = m_canceller.exchange(cancelling_ptr, std::memory_order_acquire); - struct unique_cancellation_lock + if (canceller != cancelling_ptr) { - cancellable_promise* promise; - ~unique_cancellation_lock() + struct unique_cancellation_lock + { + cancellable_promise* promise; + ~unique_cancellation_lock() + { + promise->m_canceller.store(nullptr, std::memory_order_release); + } + } lock{ this }; + + if (canceller != nullptr) { - promise->m_canceller.store(nullptr, std::memory_order_release); + canceller(m_context); } - } lock{ this }; - - if ((canceller != nullptr) && (canceller != cancelling_ptr)) - { - canceller(m_context); } } From d6cff316a991152071038668fb586a8b5ab1d51f Mon Sep 17 00:00:00 2001 From: Derek Morris Date: Mon, 27 Jul 2026 18:15:40 -0700 Subject: [PATCH 87/91] Add header to base_includes.h (#1612) base_types.h uses std::ratio_multiply, which is defined in . Under strict include-what-you-use rules not referencing this header can lead to weird build breaks. --- strings/base_includes.h | 1 + 1 file changed, 1 insertion(+) diff --git a/strings/base_includes.h b/strings/base_includes.h index 287a09709..bac7358bd 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include From a7f0233d64620801fd281ae970fe39a2943eca34 Mon Sep 17 00:00:00 2001 From: Yexuan Xiao Date: Thu, 20 Aug 2026 01:49:04 +0800 Subject: [PATCH 88/91] Remove WINRT_EXPORT in Component.g.cpp (#1597) Co-authored-by: Ryan Shepherd --- cppwinrt/code_writers.h | 11 +++++++++++ cppwinrt/component_writers.h | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index ab119ae89..b3855c097 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -226,6 +226,17 @@ namespace cppwinrt return { w, write_close_namespace }; } + [[nodiscard]] static finish_with wrap_type_namespace_without_export(writer& w, std::string_view const& ns) + { + auto format = R"(namespace winrt::@ +{ +)"; + + w.write(format, ns); + + return { w, write_close_namespace }; + } + static void write_enum_field(writer& w, Field const& field) { auto format = R"( % = %, diff --git a/cppwinrt/component_writers.h b/cppwinrt/component_writers.h index af5626d14..94e20e53e 100644 --- a/cppwinrt/component_writers.h +++ b/cppwinrt/component_writers.h @@ -400,7 +400,7 @@ catch (...) { return winrt::to_hresult(); } return; } - auto wrap_type = wrap_type_namespace(w, type_namespace); + auto wrap_type = wrap_type_namespace_without_export(w, type_namespace); for (auto&&[factory_name, factory] : get_factories(w, type)) { From 74a13c5617c04ddc8ae42e087cfb1dd1617bcfaa Mon Sep 17 00:00:00 2001 From: Jon Wiswall Date: Mon, 24 Aug 2026 14:51:11 -0700 Subject: [PATCH 89/91] C++/WinRT ABI interop improvements (#1608) * Add _hs literal for compile-time fast-pass HSTRING Passing a wide string literal to a WinRT API that takes an hstring runs wcslen and fills a seven-field HSTRING_HEADER on the stack on every call (via param::hstring -> create_hstring_on_stack). For a literal, all of that is knowable at compile time and only needs to happen once. Add a `_hs` user-defined literal that builds the fast-pass reference header as a constexpr static, so `L"value"_hs` reduces to a single pointer load at the call site with no per-call wcslen or header fill. The literal-operator-template is keyed on the characters themselves via a C++20 non-type template parameter (hstring_literal_storage), so each distinct literal gets its own static header with static lifetime. It returns a non-owning winrt::hstring_reference (a plain winrt::hstring would assert/free the reference header in its destructor). A matching param::hstring constructor lets the result bind to projected setters in a single user-defined conversion. A bare `param::hstring(wchar_t const(&)[N])` overload is deliberately not added: it would also bind non-literal arrays (e.g. a partially-filled wchar_t buf[260]) and infer length N-1 past the null, silently corrupting; and a runtime constructor cannot produce a content-specific static anyway. `_hs` is the explicit, safe opt-in; bare literal calls keep their unchanged wcslen path. Gated on __cpp_nontype_template_args >= 201911L. Tested under C++20 in test_cpp20/hstring_literal.cpp; the non-gated types build under C++17. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1 * Add make_ready for pre-completed async operations Returning an already-available value through an async-typed API (a cache hit, a fast path, or an API async-typed only for interface uniformity) still pays the full coroutine cost when written as `co_return value`: a heap-allocated coroutine frame plus a promise that is a complete COM object implementing IAsyncOperation and IAsyncInfo, carrying a slim_mutex, an agile completed-handler slot, an atomic status, and cancel machinery, all built and torn down on every call. Add winrt::make_ready(value) and winrt::make_ready() that return a minimal already-completed IAsyncOperation / IAsyncAction: it holds just the value with a fixed Completed status and no coroutine frame, no slim_mutex, no handler slot, and no cancel machinery. Setting a Completed handler on it invokes immediately, and Status()/GetResults() satisfy both the .get() and co_await consumer paths, so it is a drop-in for the synchronous-result case. `co_return` remains correct for genuinely suspending work, where the frame is doing real work and the overhead is amortized to noise. The one-shot Completed assignment is guarded with a lock-free atomic flag rather than a lock. Tested in test/make_ready.cpp. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1 * Buffer range-for iteration over non-GetAt collections Range-for over a collection that lacks GetAt (a plain IIterable, or a map yielding IKeyValuePair) drove the projected IIterator one element per ABI crossing via Current/MoveNext. For a large sequence that is one vtable call per item. Route that path through a buffered_iterator that pulls a block of elements with a single IIterator::GetMany call into a small stack buffer and yields from it, refilling only when the buffer is drained. Existing `for (auto&& x : v)` code gets the speedup with no source change. The block is sized like windows-rs' BufferedIterator -- clamp(2048 / sizeof(T), 1, 128) -- to cap the buffer near 1-2 KB and bound over-fetch for large element types. Only the non-GetAt path changes. Collections with GetAt (IVector, IVectorView) keep the existing random-access fast_iterator, so no iterator-category guarantees are affected. The iterator is single-pass, matching IIterator's own semantics. Tested in test/buffered_iterator.cpp (multi-block, block boundary, empty, and a non-trivial element type). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1 * Perfect-forward make_ready value Use TResult&& + decay_t so make_ready forwards its argument into the operation instead of taking it by value, saving a move and matching the make_unique/make_shared idiom. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1 * Make _hs a constant expression Move the fast-pass header from a function-local static into an inline constexpr variable template and mark hstring_reference and the operator constexpr, so `constexpr auto s = L"x"_hs;` is a genuine compile-time construction rather than per-call work. Add a constexpr construction to the test to prove it. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1 * Box scalars locally instead of via combase PropertyValue box_value on a scalar routed through the cached Windows.Foundation. PropertyValue activation factory into combase, which allocates a general IPropertyValue carrying the discriminated-union machinery for all property types. For the common scalar cases that round-trip is pure overhead. Point the scalar reference_traits (u8..u64, float, double, bool, char16, hstring, guid) at the in-process impl::reference that already backs non-scalar IReference, and make that type a correct IPropertyValue: report the right PropertyType per T (was always OtherType), fix IsNumericScalar (was true for bool), and return the value from the matching typed getter (GetString/GetGuid/GetBoolean/GetChar16/GetSingle/GetDouble previously threw). Mismatched numeric getters keep combase-style conversion (GetInt16 on a boxed int32 converts), so consumers see the same behavior minus the combase hop. This mirrors windows-rs' StockReference. Composite/array/inspectable cases (DateTime, TimeSpan, Point, Size, Rect, IReferenceArray, IInspectable) stay on combase PropertyValue. Two honest deltas vs combase, both matching windows-rs: GetRuntimeClassName is now the IReference`1 name rather than Windows.Foundation. PropertyValue, and cross-process the value marshals as an IReference proxy rather than by value. Tested in test/reference_boxing.cpp. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1 * Marshal boxed scalars by value via combase PropertyValue The in-proc scalar reference introduced in the prior commit is agile via the free-threaded marshaler, so cross-process it marshals by reference (an IReference proxy) rather than by value the way combase PropertyValue does. Mirror windows-rs and combase: for the stock scalar types, mark reference non_agile and supply IMarshal from query_interface_tearoff by lazily building the equivalent combase PropertyValue and delegating marshaling to it, so the destination materializes a real PropertyValue copy. IAgileObject is still advertised (the reference is immutable and thread-safe) to keep the agile fast path. The combase hop is paid only on marshal, never on box_value/unbox_value. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Box DateTime, TimeSpan, and Point in-process too Extend the in-proc reference to cover DateTime, TimeSpan, and Point: report the correct PropertyType, return the value from the matching typed getter, and mark them stock so they still marshal by value through combase PropertyValue. Drop their combase reference_traits specializations so box_value routes to the local reference like the other scalars. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Buffer range-for over GetAt collections (batch IVector via GetMany) fast_iterator (used for random-access, GetAt-capable collections like IVector/ IVectorView) now prefetches a block with a single GetMany call and serves in-window reads from it, so range-for crosses the ABI ~once per block instead of one GetAt per element. Random access is preserved: an out-of-window index re-anchors the block, and an at/after-end index defers to GetAt so E_BOUNDS behavior is unchanged. Elements are copied out (no move-out) so an index may be read repeatedly, as the random-access contract requires. This extends the non-GetAt buffering to vectors, closing the IterateVector gap to windows-rs. * Fix MSVC and clang-cl build breaks from the interop fast paths Three portability breaks surfaced by CI across MSVC and clang-cl: - Iterator batching assumed every collection/iterator has GetMany and every element type is default-constructible. IBindableVectorView has GetAt but no GetMany, IBindableIterator has no GetMany, and types like JsonValue have no default constructor. Gate the GetMany block buffer on both a GetMany detector and default-constructibility (can_batch); otherwise fall back to per-element GetAt / Current+MoveNext. The block buffer is elided entirely when unused. - reference::query_interface_tearoff called .as() on a dependent expression; clang requires .template as(). - hstring_reference::m_handle is only read via layout punning in get_abi, so clang -Werror,-Wunused-private-field rejected it. Mark it [[maybe_unused]]. Verified: msbuild cppwinrt + test/test_old (MSVC) and test/test_nocoro/test_old (clang-cl), x64 Debug, all build clean. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Add optional clang compiler arg to build_test_all.cmd build_test_all.cmd only built the MSVC toolset, so a local pass did not catch clang-cl -Werror breaks that CI's clang-cl leg rejects. Add an optional 5th positional arg (default msvc); pass clang/clang-cl to append Clang=1,PlatformToolset=ClangCl to the cppwinrt.sln compiler and test builds, matching CI. natvis and NugetTest.sln stay on MSVC, as the clang CI leg does not cover them. Also fix a stray trailing quote on the nuget restore line and document the arg in README. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Guard _hs test's literals using-directive for non-conforming NTTP compilers hstring_literal.cpp had an unconditional using-directive for winrt::literals, but that namespace and its operator ""_hs only exist under __cpp_nontype_template_args >= 201911L. clang-cl reports 201411L (no class-type NTTP), so the namespace is absent and the using-directive failed to compile ("expected namespace name"), breaking the clang-cl test_cpp20 leg. Move the using-directive inside the same feature guard the rest of the test already uses. Verified: full CI test-project set builds clean on both MSVC v145 and clang-cl, x64 Debug. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Remove buffered-iterator and ready-async helpers Drop the batched range-for iterator (base_iterator.h) and the already-completed make_ready/ready_async async helpers (base_coroutine_foundation.h), reverting both headers to their base state. These will be reintroduced in wil/cppwinrt.h. Removes the buffered_iterator.cpp and make_ready.cpp tests accordingly. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Simplify reference_base_t and test in-proc agility Collapse reference_base_t to a single implements<> whose trailing marker is conditional (non_agile for stock scalars, an inert marker placeholder otherwise), instead of duplicating the interface list across a conditional_t. implements<> ignores non-interface, non-marker type parameters, so the placeholder is a no-op. Add a test that boxes a scalar in one STA and fetches it from another via the Global Interface Table, asserting the object identity is preserved - proving the IAgileObject in-proc fast path. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Box arrays locally and address review feedback Add an in-process reference_array (IReferenceArray + IPropertyValue), the array counterpart to reference, so box_value/unbox_value of the stock array element types no longer builds a combase PropertyValue. hstring, TimeSpan, DateTime (projected type != ABI) and IInspectable/Size/Rect stay on combase. Collapse every IPropertyValue getter on both types into one internal get_as() that holds the constexpr type check and throw, and share a scalar_property_type()/array_property_type() helper. Also fold in the earlier review fixes: single implements<> with a conditional trailing marker for reference_base_t, GetSize/GetRect fast paths, an _hs null-termination static_assert, and drop the duplicate test_module_lock_none build in build_test_all.cmd. Extend reference_boxing.cpp with array boxing, array marshal-by-value, and cross-STA agile identity coverage. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Share a producer base, drop comments and build-script changes Fold the duplicated IPropertyValue getters and IMarshal tearoff shared by reference and reference_array into a reference_producer CRTP base; the two leaves just supply storage, get_as, and create_property_value. Same codegen and per-instance footprint as the two-template version, ~80 fewer source lines. Per review feedback, strip the newly-added implementation comments from base_reference_produce.h and base_string.h, and revert the build_test_all.cmd compiler-selection helper and its README note so this PR carries only the projection/boxing functionality. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Co-authored-by: Jon Wiswall <18537118+jonwis@users.noreply.github.com> Copilot-Session: 83914e59-f7cd-4284-ad4b-4cb7b79f28c1 --- strings/base_reference_produce.h | 423 ++++++++++++++++------------ strings/base_string.h | 80 ++++++ strings/base_string_input.h | 4 + test/test/reference_boxing.cpp | 268 ++++++++++++++++++ test/test/test.vcxproj | 1 + test/test_cpp20/hstring_literal.cpp | 68 +++++ test/test_cpp20/test_cpp20.vcxproj | 1 + 7 files changed, 660 insertions(+), 185 deletions(-) create mode 100644 test/test/reference_boxing.cpp create mode 100644 test/test_cpp20/hstring_literal.cpp diff --git a/strings/base_reference_produce.h b/strings/base_reference_produce.h index abffb3384..db9639cc3 100644 --- a/strings/base_reference_produce.h +++ b/strings/base_reference_produce.h @@ -2,99 +2,197 @@ WINRT_EXPORT namespace winrt::impl { template - struct reference : implements, Windows::Foundation::IReference, Windows::Foundation::IPropertyValue> + struct reference; + + template + struct reference_array; + + template + inline constexpr bool is_stock_reference_v = + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v; + + template + constexpr Windows::Foundation::PropertyType scalar_property_type() noexcept + { + using pt = Windows::Foundation::PropertyType; + + if constexpr (std::is_same_v) { return pt::UInt8; } + else if constexpr (std::is_same_v) { return pt::Int16; } + else if constexpr (std::is_same_v) { return pt::UInt16; } + else if constexpr (std::is_same_v) { return pt::Int32; } + else if constexpr (std::is_same_v) { return pt::UInt32; } + else if constexpr (std::is_same_v) { return pt::Int64; } + else if constexpr (std::is_same_v) { return pt::UInt64; } + else if constexpr (std::is_same_v) { return pt::Single; } + else if constexpr (std::is_same_v) { return pt::Double; } + else if constexpr (std::is_same_v) { return pt::Char16; } + else if constexpr (std::is_same_v) { return pt::Boolean; } + else if constexpr (std::is_same_v) { return pt::String; } + else if constexpr (std::is_same_v) { return pt::Inspectable; } + else if constexpr (std::is_same_v) { return pt::Guid; } + else if constexpr (std::is_same_v) { return pt::DateTime; } + else if constexpr (std::is_same_v) { return pt::TimeSpan; } + else if constexpr (std::is_same_v) { return pt::Point; } + else if constexpr (std::is_same_v) { return pt::Size; } + else if constexpr (std::is_same_v) { return pt::Rect; } + else { return pt::OtherType; } + } + + template + constexpr Windows::Foundation::PropertyType array_property_type() noexcept { - reference(T const& value) : m_value(value) - { - } + return static_cast( + static_cast(scalar_property_type()) + 1024); + } - T Value() const - { - return m_value; - } + template + inline constexpr bool is_numeric_scalar_v = + (std::is_arithmetic_v && !std::is_same_v && !std::is_same_v) || std::is_enum_v; + template + struct reference_producer : implements, non_agile, marker>> + { Windows::Foundation::PropertyType Type() const noexcept { - return Windows::Foundation::PropertyType::OtherType; + if constexpr (IsArray) { return array_property_type(); } + else { return scalar_property_type(); } } static constexpr bool IsNumericScalar() noexcept { - return std::is_arithmetic_v || std::is_enum_v; + return !IsArray && is_numeric_scalar_v; } - std::uint8_t GetUInt8() const - { - return to_scalar(); - } + std::uint8_t GetUInt8() const { return derived()->template get_as(); } + std::int16_t GetInt16() const { return derived()->template get_as(); } + std::uint16_t GetUInt16() const { return derived()->template get_as(); } + std::int32_t GetInt32() const { return derived()->template get_as(); } + std::uint32_t GetUInt32() const { return derived()->template get_as(); } + std::int64_t GetInt64() const { return derived()->template get_as(); } + std::uint64_t GetUInt64() const { return derived()->template get_as(); } + float GetSingle() const { return derived()->template get_as(); } + double GetDouble() const { return derived()->template get_as(); } + char16_t GetChar16() const { return derived()->template get_as(); } + bool GetBoolean() const { return derived()->template get_as(); } + hstring GetString() const { return derived()->template get_as(); } + guid GetGuid() const { return derived()->template get_as(); } + Windows::Foundation::DateTime GetDateTime() const { return derived()->template get_as(); } + Windows::Foundation::TimeSpan GetTimeSpan() const { return derived()->template get_as(); } + Windows::Foundation::Point GetPoint() const { return derived()->template get_as(); } + Windows::Foundation::Size GetSize() const { return derived()->template get_as(); } + Windows::Foundation::Rect GetRect() const { return derived()->template get_as(); } + void GetUInt8Array(com_array& value) const { derived()->get_as(value); } + void GetInt16Array(com_array& value) const { derived()->get_as(value); } + void GetUInt16Array(com_array& value) const { derived()->get_as(value); } + void GetInt32Array(com_array& value) const { derived()->get_as(value); } + void GetUInt32Array(com_array& value) const { derived()->get_as(value); } + void GetInt64Array(com_array& value) const { derived()->get_as(value); } + void GetUInt64Array(com_array& value) const { derived()->get_as(value); } + void GetSingleArray(com_array& value) const { derived()->get_as(value); } + void GetDoubleArray(com_array& value) const { derived()->get_as(value); } + void GetChar16Array(com_array& value) const { derived()->get_as(value); } + void GetBooleanArray(com_array& value) const { derived()->get_as(value); } + void GetStringArray(com_array& value) const { derived()->get_as(value); } + void GetInspectableArray(com_array& value) const { derived()->get_as(value); } + void GetGuidArray(com_array& value) const { derived()->get_as(value); } + void GetDateTimeArray(com_array& value) const { derived()->get_as(value); } + void GetTimeSpanArray(com_array& value) const { derived()->get_as(value); } + void GetPointArray(com_array& value) const { derived()->get_as(value); } + void GetSizeArray(com_array& value) const { derived()->get_as(value); } + void GetRectArray(com_array& value) const { derived()->get_as(value); } - std::int16_t GetInt16() const - { - return to_scalar(); - } + private: - std::uint16_t GetUInt16() const - { - return to_scalar(); - } + Derived const* derived() const noexcept { return static_cast(this); } - std::int32_t GetInt32() const + std::int32_t query_interface_tearoff(guid const& id, void** object) const noexcept override { - return to_scalar(); - } + if constexpr (is_stock_reference_v) + { + if (is_guid_of(id)) + { + try + { + auto marshal = derived()->create_property_value().template as(); + *object = detach_abi(marshal); + return error_ok; + } + catch (...) + { + *object = nullptr; + return to_hresult(); + } + } - std::uint32_t GetUInt32() const - { - return to_scalar(); + if (is_guid_of(id)) + { + auto unknown = reinterpret_cast(to_abi(derived())); + unknown->AddRef(); + *object = unknown; + return error_ok; + } + } + + *object = nullptr; + return error_no_interface; } + }; - std::int64_t GetInt64() const + template + struct reference : reference_producer, T, Windows::Foundation::IReference, false> + { + reference(T const& value) : m_value(value) { - return to_scalar(); } - std::uint64_t GetUInt64() const + T Value() const { - return to_scalar(); + return m_value; } - float GetSingle() { throw hresult_not_implemented(); } - double GetDouble() { throw hresult_not_implemented(); } - char16_t GetChar16() { throw hresult_not_implemented(); } - bool GetBoolean() { throw hresult_not_implemented(); } - hstring GetString() { throw hresult_not_implemented(); } - guid GetGuid() { throw hresult_not_implemented(); } - Windows::Foundation::DateTime GetDateTime() { throw hresult_not_implemented(); } - Windows::Foundation::TimeSpan GetTimeSpan() { throw hresult_not_implemented(); } - Windows::Foundation::Point GetPoint() { throw hresult_not_implemented(); } - Windows::Foundation::Size GetSize() { throw hresult_not_implemented(); } - Windows::Foundation::Rect GetRect() { throw hresult_not_implemented(); } - void GetUInt8Array(com_array &) { throw hresult_not_implemented(); } - void GetInt16Array(com_array &) { throw hresult_not_implemented(); } - void GetUInt16Array(com_array &) { throw hresult_not_implemented(); } - void GetInt32Array(com_array &) { throw hresult_not_implemented(); } - void GetUInt32Array(com_array &) { throw hresult_not_implemented(); } - void GetInt64Array(com_array &) { throw hresult_not_implemented(); } - void GetUInt64Array(com_array &) { throw hresult_not_implemented(); } - void GetSingleArray(com_array &) { throw hresult_not_implemented(); } - void GetDoubleArray(com_array &) { throw hresult_not_implemented(); } - void GetChar16Array(com_array &) { throw hresult_not_implemented(); } - void GetBooleanArray(com_array &) { throw hresult_not_implemented(); } - void GetStringArray(com_array &) { throw hresult_not_implemented(); } - void GetInspectableArray(com_array &) { throw hresult_not_implemented(); } - void GetGuidArray(com_array &) { throw hresult_not_implemented(); } - void GetDateTimeArray(com_array &) { throw hresult_not_implemented(); } - void GetTimeSpanArray(com_array &) { throw hresult_not_implemented(); } - void GetPointArray(com_array &) { throw hresult_not_implemented(); } - void GetSizeArray(com_array &) { throw hresult_not_implemented(); } - void GetRectArray(com_array &) { throw hresult_not_implemented(); } - private: + template friend struct reference_producer; + + Windows::Foundation::IInspectable create_property_value() const + { + using pv = Windows::Foundation::PropertyValue; + + if constexpr (std::is_same_v) { return pv::CreateUInt8(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateInt16(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateUInt16(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateInt32(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateUInt32(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateInt64(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateUInt64(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateSingle(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateDouble(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateChar16(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateBoolean(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateString(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateGuid(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateDateTime(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateTimeSpan(m_value); } + else if constexpr (std::is_same_v) { return pv::CreatePoint(m_value); } + else { return nullptr; } + } + template - To to_scalar() const + To get_as() const { - if constexpr (IsNumericScalar()) + if constexpr (std::is_same_v) + { + return m_value; + } + else if constexpr (is_numeric_scalar_v && is_numeric_scalar_v) { return static_cast(m_value); } @@ -104,98 +202,81 @@ WINRT_EXPORT namespace winrt::impl } } + template + void get_as(com_array const&) const + { + throw hresult_not_implemented(); + } + T m_value; }; template - struct reference_traits - { - static auto make(T const& value) { return winrt::make>(value); } - using itf = Windows::Foundation::IReference; - }; - - template <> - struct reference_traits - { - static auto make(std::uint8_t value) { return Windows::Foundation::PropertyValue::CreateUInt8(value); } - using itf = Windows::Foundation::IReference; - }; - - template <> - struct reference_traits - { - static auto make(std::uint16_t value) { return Windows::Foundation::PropertyValue::CreateUInt16(value); } - using itf = Windows::Foundation::IReference; - }; - - template <> - struct reference_traits + struct reference_array : reference_producer, T, Windows::Foundation::IReferenceArray, true> { - static auto make(std::int16_t value) { return Windows::Foundation::PropertyValue::CreateInt16(value); } - using itf = Windows::Foundation::IReference; - }; + reference_array(array_view const& value) : m_value(value.begin(), value.end()) + { + } - template <> - struct reference_traits - { - static auto make(std::uint32_t value) { return Windows::Foundation::PropertyValue::CreateUInt32(value); } - using itf = Windows::Foundation::IReference; - }; + com_array Value() const + { + return com_array(m_value.begin(), m_value.end()); + } - template <> - struct reference_traits - { - static auto make(std::int32_t value) { return Windows::Foundation::PropertyValue::CreateInt32(value); } - using itf = Windows::Foundation::IReference; - }; + private: - template <> - struct reference_traits - { - static auto make(std::uint64_t value) { return Windows::Foundation::PropertyValue::CreateUInt64(value); } - using itf = Windows::Foundation::IReference; - }; + template friend struct reference_producer; - template <> - struct reference_traits - { - static auto make(std::int64_t value) { return Windows::Foundation::PropertyValue::CreateInt64(value); } - using itf = Windows::Foundation::IReference; - }; - - template <> - struct reference_traits - { - static auto make(float value) { return Windows::Foundation::PropertyValue::CreateSingle(value); } - using itf = Windows::Foundation::IReference; - }; + Windows::Foundation::IInspectable create_property_value() const + { + using pv = Windows::Foundation::PropertyValue; + + if constexpr (std::is_same_v) { return pv::CreateUInt8Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateInt16Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateUInt16Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateInt32Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateUInt32Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateInt64Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateUInt64Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateSingleArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateDoubleArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateChar16Array(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateBooleanArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateStringArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateGuidArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateDateTimeArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreateTimeSpanArray(m_value); } + else if constexpr (std::is_same_v) { return pv::CreatePointArray(m_value); } + else { return nullptr; } + } - template <> - struct reference_traits - { - static auto make(double value) { return Windows::Foundation::PropertyValue::CreateDouble(value); } - using itf = Windows::Foundation::IReference; - }; + template + To get_as() const + { + throw hresult_not_implemented(); + } - template <> - struct reference_traits - { - static auto make(char16_t value) { return Windows::Foundation::PropertyValue::CreateChar16(value); } - using itf = Windows::Foundation::IReference; - }; + template + void get_as(com_array& value) const + { + if constexpr (std::is_same_v) + { + value = com_array(m_value.begin(), m_value.end()); + } + else + { + throw hresult_not_implemented(); + } + } - template <> - struct reference_traits - { - static auto make(bool value) { return Windows::Foundation::PropertyValue::CreateBoolean(value); } - using itf = Windows::Foundation::IReference; + com_array m_value; }; - template <> - struct reference_traits + template + struct reference_traits { - static auto make(hstring const& value) { return Windows::Foundation::PropertyValue::CreateString(value); } - using itf = Windows::Foundation::IReference; + static auto make(T const& value) { return winrt::make>(value); } + using itf = Windows::Foundation::IReference; }; template <> @@ -205,41 +286,13 @@ WINRT_EXPORT namespace winrt::impl using itf = Windows::Foundation::IInspectable; }; - template <> - struct reference_traits - { - static auto make(guid const& value) { return Windows::Foundation::PropertyValue::CreateGuid(value); } - using itf = Windows::Foundation::IReference; - }; - template <> struct reference_traits { - static auto make(GUID const& value) { return Windows::Foundation::PropertyValue::CreateGuid(reinterpret_cast(value)); } + static auto make(GUID const& value) { return reference_traits::make(reinterpret_cast(value)); } using itf = Windows::Foundation::IReference; }; - template <> - struct reference_traits - { - static auto make(Windows::Foundation::DateTime value) { return Windows::Foundation::PropertyValue::CreateDateTime(value); } - using itf = Windows::Foundation::IReference; - }; - - template <> - struct reference_traits - { - static auto make(Windows::Foundation::TimeSpan value) { return Windows::Foundation::PropertyValue::CreateTimeSpan(value); } - using itf = Windows::Foundation::IReference; - }; - - template <> - struct reference_traits - { - static auto make(Windows::Foundation::Point const& value) { return Windows::Foundation::PropertyValue::CreatePoint(value); } - using itf = Windows::Foundation::IReference; - }; - template <> struct reference_traits { @@ -257,77 +310,77 @@ WINRT_EXPORT namespace winrt::impl template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt8Array(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt16Array(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt16Array(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt32Array(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(com_array const& value) { return Windows::Foundation::PropertyValue::CreateUInt32Array(value); } + static auto make(com_array const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateInt64Array(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateUInt64Array(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateSingleArray(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateDoubleArray(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateChar16Array(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateBooleanArray(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; @@ -348,14 +401,14 @@ WINRT_EXPORT namespace winrt::impl template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateGuidArray(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreateGuidArray(reinterpret_cast const&>(value)); } + static auto make(array_view const& value) { return winrt::make>(reinterpret_cast const&>(value)); } using itf = Windows::Foundation::IReferenceArray; }; @@ -376,7 +429,7 @@ WINRT_EXPORT namespace winrt::impl template <> struct reference_traits> { - static auto make(array_view const& value) { return Windows::Foundation::PropertyValue::CreatePointArray(value); } + static auto make(array_view const& value) { return winrt::make>(value); } using itf = Windows::Foundation::IReferenceArray; }; diff --git a/strings/base_string.h b/strings/base_string.h index 6b1fb37b5..50a248c02 100644 --- a/strings/base_string.h +++ b/strings/base_string.h @@ -155,6 +155,24 @@ WINRT_EXPORT namespace winrt::impl return nullptr; } }; + + template + struct hstring_literal_storage + { + static constexpr std::size_t size = N; + wchar_t value[N]; + + constexpr hstring_literal_storage(wchar_t const (&str)[N]) noexcept + { + for (std::size_t i = 0; i != N; ++i) + { + value[i] = str[i]; + } + } + }; + + template + hstring_literal_storage(wchar_t const (&)[N]) -> hstring_literal_storage; } WINRT_EXPORT namespace winrt @@ -386,6 +404,30 @@ WINRT_EXPORT namespace winrt handle_type m_handle; }; + struct hstring_reference + { + constexpr hstring_reference() noexcept = default; + + constexpr explicit hstring_reference(impl::hstring_header const* header) noexcept : + m_handle(const_cast(header)) + { + } + + operator hstring const&() const noexcept + { + return *reinterpret_cast(this); + } + + private: + + [[maybe_unused]] void* m_handle{}; + }; + + inline void* get_abi(hstring_reference const& object) noexcept + { + return *(void**)(&object); + } + inline void* get_abi(hstring const& object) noexcept { return *(void**)(&object); @@ -437,6 +479,44 @@ WINRT_EXPORT namespace winrt } } +#if defined(__cpp_nontype_template_args) && __cpp_nontype_template_args >= 201911L + +WINRT_EXPORT namespace winrt::impl +{ + template + inline constexpr hstring_header hstring_literal_header + { + hstring_reference_flag, + static_cast(Literal.size - 1), + 0, + 0, + Literal.value + }; +} + +WINRT_EXPORT namespace winrt +{ + inline namespace literals + { + template + constexpr hstring_reference operator ""_hs() noexcept + { + static_assert(Literal.value[Literal.size - 1] == L'\0', "_hs requires a null-terminated wide string literal"); + + if constexpr (Literal.size <= 1) + { + return hstring_reference{}; + } + else + { + return hstring_reference{ &impl::hstring_literal_header }; + } + } + } +} + +#endif + #ifdef __cpp_lib_format template<> struct std::formatter : std::formatter {}; diff --git a/strings/base_string_input.h b/strings/base_string_input.h index 71cd5f3c0..ccf955547 100644 --- a/strings/base_string_input.h +++ b/strings/base_string_input.h @@ -18,6 +18,10 @@ WINRT_EXPORT namespace winrt::param { } + hstring(winrt::hstring_reference const& value) noexcept : m_handle(get_abi(value)) + { + } + hstring(std::wstring_view const& value) noexcept { create_string_reference(value.data(), value.size()); diff --git a/test/test/reference_boxing.cpp b/test/test/reference_boxing.cpp new file mode 100644 index 000000000..c6e300886 --- /dev/null +++ b/test/test/reference_boxing.cpp @@ -0,0 +1,268 @@ +#include "pch.h" +#include +#include +#include + +using namespace winrt; +using namespace Windows::Foundation; + +// Scalar box_value now produces a local IReference/IPropertyValue instead of hopping to +// combase PropertyValue. These confirm it reports the correct PropertyType, keeps combase-style +// numeric conversion on mismatched getters, and round-trips through unbox_value. +TEST_CASE("reference_boxing") +{ + { + auto boxed = box_value(42); + auto pv = boxed.as(); + REQUIRE(pv.Type() == PropertyType::Int32); + REQUIRE(pv.IsNumericScalar()); + REQUIRE(pv.GetInt32() == 42); + REQUIRE(pv.GetInt16() == 42); + REQUIRE(pv.GetDouble() == 42.0); + // A scalar reference holds no array, so every array getter routes through get_as and throws. + { + com_array ints; + REQUIRE_THROWS_AS(pv.GetInt32Array(ints), hresult_not_implemented); + com_array strings; + REQUIRE_THROWS_AS(pv.GetStringArray(strings), hresult_not_implemented); + } + REQUIRE(unbox_value(boxed) == 42); + } + + { + auto pv = box_value(3.5).as(); + REQUIRE(pv.Type() == PropertyType::Double); + REQUIRE(pv.IsNumericScalar()); + REQUIRE(pv.GetDouble() == 3.5); + REQUIRE(pv.GetSingle() == 3.5f); + } + + { + auto pv = box_value(hstring{ L"hello" }).as(); + REQUIRE(pv.Type() == PropertyType::String); + REQUIRE(!pv.IsNumericScalar()); + REQUIRE(pv.GetString() == L"hello"); + REQUIRE_THROWS_AS(pv.GetInt32(), hresult_not_implemented); + } + + { + auto pv = box_value(true).as(); + REQUIRE(pv.Type() == PropertyType::Boolean); + REQUIRE(!pv.IsNumericScalar()); + REQUIRE(pv.GetBoolean()); + REQUIRE_THROWS_AS(pv.GetInt32(), hresult_not_implemented); + } + + { + guid const g{ 0x11223344, 0x5566, 0x7788, { 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00 } }; + auto pv = box_value(g).as(); + REQUIRE(pv.Type() == PropertyType::Guid); + REQUIRE(!pv.IsNumericScalar()); + REQUIRE(pv.GetGuid() == g); + } + + { + auto pv = box_value(static_cast(7)).as(); + REQUIRE(pv.Type() == PropertyType::UInt8); + REQUIRE(pv.IsNumericScalar()); + REQUIRE(pv.GetUInt8() == 7); + REQUIRE(unbox_value(box_value(static_cast(7))) == 7); + } + + // DateTime, TimeSpan, and Point are also boxed in-process now (they still marshal by value). + { + Point const point{ 3.0f, 4.0f }; + auto pv = box_value(point).as(); + REQUIRE(pv.Type() == PropertyType::Point); + REQUIRE(!pv.IsNumericScalar()); + REQUIRE(pv.GetPoint().X == point.X); + REQUIRE(pv.GetPoint().Y == point.Y); + auto const round_tripped = unbox_value(box_value(point)); + REQUIRE(round_tripped.X == point.X); + REQUIRE(round_tripped.Y == point.Y); + REQUIRE_THROWS_AS(pv.GetInt32(), hresult_not_implemented); + } + + { + TimeSpan const span{ std::chrono::seconds{ 90 } }; + auto pv = box_value(span).as(); + REQUIRE(pv.Type() == PropertyType::TimeSpan); + REQUIRE(!pv.IsNumericScalar()); + REQUIRE(pv.GetTimeSpan() == span); + REQUIRE(unbox_value(box_value(span)) == span); + } + + { + DateTime const when{ TimeSpan{ std::chrono::seconds{ 1000 } } }; + auto pv = box_value(when).as(); + REQUIRE(pv.Type() == PropertyType::DateTime); + REQUIRE(!pv.IsNumericScalar()); + REQUIRE(pv.GetDateTime() == when); + REQUIRE(unbox_value(box_value(when)) == when); + } +} + +// Array boxing produces a local IReferenceArray / IPropertyValue (no combase PropertyValue) for the +// stock element types. Confirm the array PropertyType, round-trips, and the get_as throw behavior. +TEST_CASE("reference_boxing arrays") +{ + { + int32_t values[]{ 0, 42, 1729, -1 }; + auto boxed = box_value(com_array{ std::begin(values), std::end(values) }); + auto pv = boxed.as(); + REQUIRE(pv.Type() == PropertyType::Int32Array); + REQUIRE(!pv.IsNumericScalar()); + + com_array out; + pv.GetInt32Array(out); + REQUIRE(out == array_view{ values }); + + // A scalar getter on an array PV throws, and so does a mismatched-element array getter. + REQUIRE_THROWS_AS(pv.GetInt32(), hresult_not_implemented); + com_array wrong; + REQUIRE_THROWS_AS(pv.GetDoubleArray(wrong), hresult_not_implemented); + + REQUIRE(unbox_value>(boxed) == array_view{ values }); + REQUIRE(boxed.as>().Value() == array_view{ values }); + } + + // guid arrays are local too. + { + guid values[]{ + { 0x11223344, 0x5566, 0x7788, { 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00 } }, + { 0x00112233, 0x4455, 0x6677, { 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF } } }; + auto boxed = box_value(com_array{ std::begin(values), std::end(values) }); + REQUIRE(boxed.as().Type() == PropertyType::GuidArray); + REQUIRE(unbox_value>(boxed) == array_view{ values }); + } +} + +// The local array reference must marshal by value across processes just like the scalar one: its +// IMarshal reports the same unmarshal class as a genuine combase array PropertyValue, and not the +// free-threaded (by-reference) class. +TEST_CASE("reference_boxing array marshal by value") +{ + int32_t values[]{ 1, 2, 3 }; + auto boxed = box_value(com_array{ std::begin(values), std::end(values) }); + REQUIRE(boxed.try_as()); + auto ours = boxed.as(); + + auto genuine = PropertyValue::CreateInt32Array(values); + auto reference = genuine.as(); + + guid our_clsid{}; + guid reference_clsid{}; + check_hresult(ours->GetUnmarshalClass(guid_of(), get_unknown(boxed), + MSHCTX_DIFFERENTMACHINE, nullptr, MSHLFLAGS_NORMAL, &our_clsid)); + check_hresult(reference->GetUnmarshalClass(guid_of(), get_unknown(genuine), + MSHCTX_DIFFERENTMACHINE, nullptr, MSHLFLAGS_NORMAL, &reference_clsid)); + + REQUIRE(our_clsid == reference_clsid); + + guid const free_threaded_marshaler{ 0x0000033A, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; + REQUIRE(our_clsid != free_threaded_marshaler); +} + +// The in-proc reference stays agile but must marshal by value across processes, exactly like a real +// combase PropertyValue. Prove it by confirming our IMarshal reports the SAME unmarshal class as a +// genuine PropertyValue - i.e. we forward marshaling to combase - and specifically NOT the +// free-threaded (marshal-by-reference) class the default agile path would have used. +TEST_CASE("reference_boxing marshal by value") +{ + auto boxed = box_value(42); + REQUIRE(boxed.try_as()); + auto ours = boxed.as(); + + auto genuine = PropertyValue::CreateInt32(42); + auto reference = genuine.as(); + + guid our_clsid{}; + guid reference_clsid{}; + check_hresult(ours->GetUnmarshalClass(guid_of(), get_unknown(boxed), + MSHCTX_DIFFERENTMACHINE, nullptr, MSHLFLAGS_NORMAL, &our_clsid)); + check_hresult(reference->GetUnmarshalClass(guid_of(), get_unknown(genuine), + MSHCTX_DIFFERENTMACHINE, nullptr, MSHLFLAGS_NORMAL, &reference_clsid)); + + REQUIRE(our_clsid == reference_clsid); + + // CLSID_InProcFreeMarshaler - the by-reference class the agile FTM would have produced. + guid const free_threaded_marshaler{ 0x0000033A, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; + REQUIRE(our_clsid != free_threaded_marshaler); +} + +// The in-proc reference advertises IAgileObject, so handing it between two single-threaded +// apartments in the same process must resolve to the *same* object pointer - no proxy. The Global +// Interface Table returns an agile object's original pointer directly, but hands back a proxy (a +// different identity) for a non-agile object, so pointer equality here confirms the agile fast path. +TEST_CASE("reference_boxing agile in-proc identity across apartments") +{ + auto identity_of = [](::IUnknown* raw) -> void* + { + com_ptr<::IUnknown> identity; + check_hresult(raw->QueryInterface(IID_PPV_ARGS(identity.put()))); + return identity.get(); + }; + + com_ptr git; + check_hresult(CoCreateInstance(CLSID_StdGlobalInterfaceTable, nullptr, + CLSCTX_INPROC_SERVER, IID_PPV_ARGS(git.put()))); + + Windows::Foundation::IInspectable boxed{ nullptr }; + DWORD cookie{}; + void* original_identity{}; + void* marshaled_identity{}; + HRESULT sta1_hr = S_OK; + HRESULT sta2_hr = S_OK; + + handle registered{ check_pointer(CreateEventW(nullptr, true, false, nullptr)) }; + handle fetched{ check_pointer(CreateEventW(nullptr, true, false, nullptr)) }; + + std::thread sta1([&] + { + sta1_hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + if (SUCCEEDED(sta1_hr)) + { + boxed = box_value(42); + auto unknown = reinterpret_cast<::IUnknown*>(get_abi(boxed)); + original_identity = identity_of(unknown); + sta1_hr = git->RegisterInterfaceInGlobal(unknown, IID_IUnknown, &cookie); + } + SetEvent(registered.get()); + + WaitForSingleObject(fetched.get(), INFINITE); + if (SUCCEEDED(sta1_hr)) + { + CoUninitialize(); + } + }); + + std::thread sta2([&] + { + WaitForSingleObject(registered.get(), INFINITE); + if (SUCCEEDED(sta1_hr)) + { + sta2_hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + if (SUCCEEDED(sta2_hr)) + { + ::IUnknown* raw{}; + sta2_hr = git->GetInterfaceFromGlobal(cookie, IID_IUnknown, reinterpret_cast(&raw)); + if (SUCCEEDED(sta2_hr)) + { + marshaled_identity = identity_of(raw); + raw->Release(); + } + git->RevokeInterfaceFromGlobal(cookie); + CoUninitialize(); + } + } + SetEvent(fetched.get()); + }); + + sta1.join(); + sta2.join(); + + REQUIRE(SUCCEEDED(sta1_hr)); + REQUIRE(SUCCEEDED(sta2_hr)); + REQUIRE(original_identity != nullptr); + REQUIRE(original_identity == marshaled_identity); +} diff --git a/test/test/test.vcxproj b/test/test/test.vcxproj index 43928dab2..f95584d99 100644 --- a/test/test/test.vcxproj +++ b/test/test/test.vcxproj @@ -324,6 +324,7 @@ NotUsing + diff --git a/test/test_cpp20/hstring_literal.cpp b/test/test_cpp20/hstring_literal.cpp new file mode 100644 index 000000000..2ba0f3ad7 --- /dev/null +++ b/test/test_cpp20/hstring_literal.cpp @@ -0,0 +1,68 @@ +#include "pch.h" + +using namespace winrt; +using namespace std::literals; + +#if defined(__cpp_nontype_template_args) && __cpp_nontype_template_args >= 201911L + +using namespace winrt::literals; + +namespace +{ + // Exercises the hstring_reference -> param::hstring conversion that projected + // setters rely on, and duplicates into an owning hstring on the way out. + winrt::hstring copy_via_param(winrt::param::hstring const& value) + { + winrt::hstring const& as_hstring = value; + return as_hstring; + } +} + +TEST_CASE("hstring_literal") +{ + // The literal is a genuine constant expression: the fast-pass header is built at + // compile time, so an hstring_reference can be constructed in a constexpr context. + { + constexpr winrt::hstring_reference lit = L"kittens"_hs; + winrt::hstring const& value = lit; + REQUIRE(value == L"kittens"sv); + REQUIRE(value.size() == 7); + } + + // Content and length match the literal. + { + winrt::hstring_reference const lit = L"kittens"_hs; + winrt::hstring const& value = lit; + REQUIRE(value == L"kittens"sv); + REQUIRE(value.size() == 7); + REQUIRE(wcslen(value.c_str()) == 7); + } + + // Built as a fast-pass reference string (no heap allocation). + { + winrt::hstring_reference const lit = L"puppies"_hs; + auto const header = static_cast(winrt::get_abi(lit)); + REQUIRE(header != nullptr); + REQUIRE((header->flags & winrt::impl::hstring_reference_flag) != 0); + REQUIRE(header->length == 7); + } + + // Empty literal projects as the empty (null) HSTRING. + { + winrt::hstring_reference const lit = L""_hs; + winrt::hstring const& value = lit; + REQUIRE(value.empty()); + REQUIRE(value.size() == 0); + REQUIRE(winrt::get_abi(value) == nullptr); + } + + // Binds to a projected setter parameter in a single conversion, and copying + // into an owning hstring duplicates correctly. + { + winrt::hstring const copied = copy_via_param(L"waffles"_hs); + REQUIRE(copied == L"waffles"sv); + REQUIRE(copied.size() == 7); + } +} + +#endif diff --git a/test/test_cpp20/test_cpp20.vcxproj b/test/test_cpp20/test_cpp20.vcxproj index 4eaee0a18..b13becd23 100644 --- a/test/test_cpp20/test_cpp20.vcxproj +++ b/test/test_cpp20/test_cpp20.vcxproj @@ -239,6 +239,7 @@ + NotUsing From 9cf9564cf31638e41149016f2ca7a07b3f97adb6 Mon Sep 17 00:00:00 2001 From: Chris Guzak Date: Wed, 26 Aug 2026 16:14:48 -0700 Subject: [PATCH 90/91] Add get_unchecked() to async operations (#1565) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add get_only_safe_from_non_presenting_sta() to async operations Add a peer to .get() on IAsyncAction, IAsyncOperation, IAsyncActionWithProgress, and IAsyncOperationWithProgress that skips the _DEBUG-only STA blocking assert. The existing .get() asserts !is_sta_thread() to guard against blocking UI threads. However, not all STAs are UI threads — some never present UI, haven't presented yet, or never will. The assert is also _DEBUG-only, making it invisible to codebases that don't build with _DEBUG (e.g. the Windows OS). The new method get_only_safe_from_non_presenting_sta() is functionally identical to .get() but omits the STA check. The intentionally long name communicates the risk to callers. Changes: - strings/base_coroutine_foundation.h: Add wait_get_bypass_sta_check() impl helper and get_only_safe_from_non_presenting_sta() for all 4 async consume templates - cppwinrt/code_writers.h: Add declaration to generated code for all 4 async types - test/test_nocoro: Add test calling the new method from an STA thread using a real WinRT async operation (PathIO::ReadTextAsync on C:\Windows\win.ini) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Rename STA bypassing async get method Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix STA test cleanup and assertions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Chris Guzak (WINDOWS) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- cppwinrt/code_writers.h | 12 +++++++++ strings/base_coroutine_foundation.h | 33 ++++++++++++++++++++++++ test/test_nocoro/get.cpp | 40 +++++++++++++++++++++++++++++ test/test_nocoro/pch.h | 1 + 4 files changed, 86 insertions(+) diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index b3855c097..a9aa5bc78 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -1475,24 +1475,36 @@ namespace cppwinrt else if (type_name == "Windows.Foundation.IAsyncAction") { w.write(R"( auto get() const; + // Synchronously waits without asserting that the calling thread is not an STA. + // Use only when the STA is not presenting UI and blocking is known to be safe. + auto get_unchecked() const; auto wait_for(Windows::Foundation::TimeSpan const& timeout) const; )"); } else if (type_name == "Windows.Foundation.IAsyncOperation`1") { w.write(R"( auto get() const; + // Synchronously waits without asserting that the calling thread is not an STA. + // Use only when the STA is not presenting UI and blocking is known to be safe. + auto get_unchecked() const; auto wait_for(Windows::Foundation::TimeSpan const& timeout) const; )"); } else if (type_name == "Windows.Foundation.IAsyncActionWithProgress`1") { w.write(R"( auto get() const; + // Synchronously waits without asserting that the calling thread is not an STA. + // Use only when the STA is not presenting UI and blocking is known to be safe. + auto get_unchecked() const; auto wait_for(Windows::Foundation::TimeSpan const& timeout) const; )"); } else if (type_name == "Windows.Foundation.IAsyncOperationWithProgress`2") { w.write(R"( auto get() const; + // Synchronously waits without asserting that the calling thread is not an STA. + // Use only when the STA is not presenting UI and blocking is known to be safe. + auto get_unchecked() const; auto wait_for(Windows::Foundation::TimeSpan const& timeout) const; )"); } diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 5cefad836..82582ee64 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -99,6 +99,19 @@ WINRT_EXPORT namespace winrt::impl return async.GetResults(); } + template + auto wait_get_bypass_sta_check(Async const& async) + { + auto status = async.Status(); + if (status == Windows::Foundation::AsyncStatus::Started) + { + status = wait_for_completed(async, 0xFFFFFFFF); // INFINITE + } + check_status_canceled(status); + + return async.GetResults(); + } + #ifdef WINRT_IMPL_COROUTINES struct ignore_apartment_context {}; @@ -220,6 +233,11 @@ WINRT_EXPORT namespace winrt::impl impl::wait_get(static_cast(static_cast(*this))); } template + auto consume_Windows_Foundation_IAsyncAction::get_unchecked() const + { + impl::wait_get_bypass_sta_check(static_cast(static_cast(*this))); + } + template auto consume_Windows_Foundation_IAsyncAction::wait_for(Windows::Foundation::TimeSpan const& timeout) const { return impl::wait_for(static_cast(static_cast(*this)), timeout); @@ -231,6 +249,11 @@ WINRT_EXPORT namespace winrt::impl return impl::wait_get(static_cast const&>(static_cast(*this))); } template + auto consume_Windows_Foundation_IAsyncOperation::get_unchecked() const + { + return impl::wait_get_bypass_sta_check(static_cast const&>(static_cast(*this))); + } + template auto consume_Windows_Foundation_IAsyncOperation::wait_for(Windows::Foundation::TimeSpan const& timeout) const { return impl::wait_for(static_cast const&>(static_cast(*this)), timeout); @@ -242,6 +265,11 @@ WINRT_EXPORT namespace winrt::impl impl::wait_get(static_cast const&>(static_cast(*this))); } template + auto consume_Windows_Foundation_IAsyncActionWithProgress::get_unchecked() const + { + impl::wait_get_bypass_sta_check(static_cast const&>(static_cast(*this))); + } + template auto consume_Windows_Foundation_IAsyncActionWithProgress::wait_for(Windows::Foundation::TimeSpan const& timeout) const { return impl::wait_for(static_cast const&>(static_cast(*this)), timeout); @@ -253,6 +281,11 @@ WINRT_EXPORT namespace winrt::impl return impl::wait_get(static_cast const&>(static_cast(*this))); } template + auto consume_Windows_Foundation_IAsyncOperationWithProgress::get_unchecked() const + { + return impl::wait_get_bypass_sta_check(static_cast const&>(static_cast(*this))); + } + template auto consume_Windows_Foundation_IAsyncOperationWithProgress::wait_for(Windows::Foundation::TimeSpan const& timeout) const { return impl::wait_for(static_cast const&>(static_cast(*this)), timeout); diff --git a/test/test_nocoro/get.cpp b/test/test_nocoro/get.cpp index 11339e10b..4fd85fe3e 100644 --- a/test/test_nocoro/get.cpp +++ b/test/test_nocoro/get.cpp @@ -2,6 +2,7 @@ using namespace winrt; using namespace Windows::Foundation; +using namespace Windows::Storage; template struct async_completion_source : implements, IAsyncOperation, IAsyncInfo> @@ -72,3 +73,42 @@ TEST_CASE("get") REQUIRE(acs.as>().get() == 0xDEADBEEF); } + +TEST_CASE("get_unchecked") +{ + // Call a real WinRT async operation from an STA thread. + // This is the scenario the new API is designed for: an STA that is not + // presenting UI, where a synchronous blocking wait is safe. + std::exception_ptr failure{}; + bool content_available = false; + std::thread sta_thread([&failure, &content_available] + { + try + { + winrt::init_apartment(winrt::apartment_type::single_threaded); + struct apartment_guard + { + ~apartment_guard() + { + winrt::uninit_apartment(); + } + } guard; + + auto content = PathIO::ReadTextAsync(L"C:\\Windows\\win.ini").get_unchecked(); + content_available = content.size() > 0; + } + catch (...) + { + failure = std::current_exception(); + } + }); + + sta_thread.join(); + + if (failure) + { + std::rethrow_exception(failure); + } + + REQUIRE(content_available); +} diff --git a/test/test_nocoro/pch.h b/test/test_nocoro/pch.h index 7ff48a37c..30a6d3079 100644 --- a/test/test_nocoro/pch.h +++ b/test/test_nocoro/pch.h @@ -2,5 +2,6 @@ #include "catch.hpp" #include "winrt/Windows.Foundation.h" +#include "winrt/Windows.Storage.h" using namespace std::literals; From 856eaff70a48d6b053c2ad3dffec15b81ca34b10 Mon Sep 17 00:00:00 2001 From: Dan Fiedler <151573964+danfiedler-msft@users.noreply.github.com> Date: Wed, 26 Aug 2026 19:33:15 -0400 Subject: [PATCH 91/91] Pin GitHub Actions to full-length commit SHAs (#1618) --- .github/actions/setup-llvm-mingw/action.yml | 4 ++-- .github/actions/setup-llvm-msvc/action.yml | 2 +- .github/dependabot.yml | 2 ++ .github/workflows/check-line-endings.yml | 2 +- .github/workflows/ci.yml | 26 ++++++++++----------- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/.github/actions/setup-llvm-mingw/action.yml b/.github/actions/setup-llvm-mingw/action.yml index 50fe696b7..d36b48a75 100644 --- a/.github/actions/setup-llvm-mingw/action.yml +++ b/.github/actions/setup-llvm-mingw/action.yml @@ -19,7 +19,7 @@ runs: - name: Cache llvm-mingw (Windows) id: cache-llvm if: runner.os == 'Windows' - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: .llvm-mingw key: llvm-mingw-${{ runner.os }}-${{ inputs.llvm-mingw-version }}-${{ inputs.host-arch }} @@ -50,7 +50,7 @@ runs: - name: Cache llvm-mingw (Linux) id: cache-llvm-linux if: runner.os == 'Linux' - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: /opt/llvm-mingw key: llvm-mingw-${{ runner.os }}-${{ inputs.llvm-mingw-version }}-${{ inputs.host-arch }} diff --git a/.github/actions/setup-llvm-msvc/action.yml b/.github/actions/setup-llvm-msvc/action.yml index 036d0fa28..e5a696a9f 100644 --- a/.github/actions/setup-llvm-msvc/action.yml +++ b/.github/actions/setup-llvm-msvc/action.yml @@ -14,7 +14,7 @@ runs: steps: - name: Cache LLVM and tools id: cache-llvm - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: | .LLVM diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 47f88349d..9557baa7a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,3 +8,5 @@ updates: directory: "/" schedule: interval: "daily" + cooldown: + default-days: 7 diff --git a/.github/workflows/check-line-endings.yml b/.github/workflows/check-line-endings.yml index dea958274..3891aec09 100644 --- a/.github/workflows/check-line-endings.yml +++ b/.github/workflows/check-line-endings.yml @@ -11,7 +11,7 @@ jobs: name: Enforce .gitattributes line endings runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Check for line ending violations run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index afdeed462..5e2677fed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: config: Release runs-on: ${{ matrix.toolchain.image }} steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Download nuget run: | @@ -71,7 +71,7 @@ jobs: cmd /c "$env:VSDevCmd" "&" msbuild /m /clp:ForceConsoleColor "$env:msbuild_config_props" cppwinrt.sln /t:cppwinrt - name: Upload built executables - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: | @@ -113,18 +113,18 @@ jobs: test_exe: test_cpp20_module runs-on: ${{ matrix.toolchain.image }} steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Fetch cppwinrt executables if: matrix.arch != 'arm64' - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ - name: Fetch x86 cppwinrt executables (arm64 only) if: matrix.arch == 'arm64' - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: msvc-build-${{ matrix.compiler}}-x86-Release-${{ matrix.toolchain.platform_toolset }}-bin path: _build/x86/Release/ @@ -243,7 +243,7 @@ jobs: - name: Upload arm64 test executables if: matrix.arch == 'arm64' - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: msvc-tests-${{ matrix.test_exe }}-${{ matrix.compiler }}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: | @@ -263,7 +263,7 @@ jobs: CMAKE_COLOR_DIAGNOSTICS: 1 CLICOLOR_FORCE: 1 steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install cross compiler run: | @@ -282,7 +282,7 @@ jobs: cmake --build build/cross_x64/ --target install -j2 - name: Upload cppwinrt.exe - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: cross-build-${{ matrix.arch }}-bin path: install/bin/cppwinrt.exe @@ -296,7 +296,7 @@ jobs: Deployment: [Component, Standalone] runs-on: windows-2025-vs2026 steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Download nuget run: | @@ -339,10 +339,10 @@ jobs: platform_toolset: v145 runs-on: ${{ matrix.toolchain.image }} steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Fetch cppwinrt executables - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: msvc-build-${{ matrix.compiler}}-${{ matrix.arch }}-${{ matrix.config }}-${{ matrix.toolchain.platform_toolset }}-bin path: _build/${{ matrix.arch }}/${{ matrix.config }}/ @@ -384,7 +384,7 @@ jobs: name: Build nuget package with MSVC runs-on: windows-2025-vs2026 steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Package run: | @@ -399,7 +399,7 @@ jobs: } - name: Upload nuget package artifact - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: package path: "*.nupkg"