From 0a35e0177dff1d8ef7a1806bf7d0e9c33b7cb901 Mon Sep 17 00:00:00 2001
From: angelazhangmsft <angzhang@microsoft.com>
Date: Thu, 10 Jun 2021 19:20:02 -0700
Subject: [PATCH]  Project COM interop APIs  (#830)

* add COM interop API projections and tests

* revising tests

* Added cswinrt support for interop interfaces

* remove UAC check on IPrinting3DManagerInterop

* clarified wording

* updated to latest cppwinrt to disable mdmerge validation

* Removed Printing3DManager, as not in universal contract

* minor tweaks

* typo

* fix incorrect merge conflict

* add comment on unit tests

* restored cswinrt nuget package reference to resolve NETSDK1130 errors

* add COM interop wrappers

* fully automate COM interop support for Windows SDK projection

* PR feedback

Co-authored-by: Scott Jones <sjones@microsoft.com>
---
 docs/interop.md                               |   2 +-
 nuget/Microsoft.Windows.CsWinRT.nuspec        |   1 +
 nuget/Microsoft.Windows.CsWinRT.targets       |   8 +-
 src/Directory.Build.props                     |   1 +
 src/Projections/Test/Test.csproj              |   2 +-
 src/Projections/Windows/Windows.csproj        |  74 +--
 .../WinUIDesktopSample.csproj                 |   2 +
 .../TestComponentCSharp/Directory.Build.props |  15 +-
 .../Directory.Build.targets                   |  46 --
 .../TestComponentCSharp.idl                   |   7 -
 .../TestComponentCSharp.vcxproj               |   9 +-
 .../TestComponentCSharp.vcxproj.filters       |   1 -
 src/Tests/TestComponentCSharp/packages.config |   8 +-
 src/Tests/UnitTest/ComInteropTests.cs         | 117 +++++
 .../UnitTest/TestComponentCSharp_Tests.cs     | 482 +++++++++---------
 src/WinRT.Runtime/WinRT.Runtime.csproj        |   2 +-
 src/cswinrt.sln                               | 130 +++++
 src/cswinrt/Directory.Build.props             |  11 +
 src/cswinrt/Directory.Build.targets           |  14 +-
 src/cswinrt/WinRT.Interop.idl                 | 182 +++++++
 src/cswinrt/code_writers.h                    |  12 +-
 src/cswinrt/cswinrt.vcxproj                   |  12 +-
 src/cswinrt/cswinrt.vcxproj.filters           |   7 +
 src/cswinrt/helpers.h                         |  11 +
 src/cswinrt/main.cpp                          |   4 +
 src/cswinrt/packages.config                   |   9 +-
 src/cswinrt/strings/ComInteropHelpers.cs      | 343 +++++++++++++
 27 files changed, 1150 insertions(+), 362 deletions(-)
 delete mode 100644 src/Tests/TestComponentCSharp/Directory.Build.targets
 create mode 100644 src/Tests/UnitTest/ComInteropTests.cs
 create mode 100644 src/cswinrt/Directory.Build.props
 create mode 100644 src/cswinrt/WinRT.Interop.idl
 create mode 100644 src/cswinrt/strings/ComInteropHelpers.cs

diff --git a/docs/interop.md b/docs/interop.md
index 29848a6ef..ad28cad82 100644
--- a/docs/interop.md
+++ b/docs/interop.md
@@ -95,7 +95,7 @@ SetString(MarshalString.GetAbi(marshalStr));
 ```
 
 #### Interop Interfaces
-**Note:** The CLR still supports marshaling COM (IUnknown), but not WinRT (IInspectable), interop interfaces. There are two approaches to marshaling IInspectable interfaces in C#/WinRT. 
+The CLR still supports marshaling COM (IUnknown), but not WinRT (IInspectable), interop interfaces.  The Windows SDK projection provides definitions for several COM interop interfaces, including ***Windows.Storage.Streams.IBufferByteAccess***, ***WinRT.Interop.IWindowNative***, and ***WinRT.Interop.IInitializeWithWindow***. The Windows SDK projection also provides wrappers for all WinRT interop interfaces included in the Universal API Contract, such as ***Windows.Security.Credentials.UI.UserConsentVerifierInterop***. For custom or extension SDK interop interfaces, C#/WinRT supports two marshaling techniques.
 
 ##### Projected
 If possible, the interop interface should be defined in IDL and a C#/WinRT projection produced for it. This automatically generates all marshaling logic so that calling code can pass and receive projected types. This definition of `IUserConsentVerifierInterop` from one of our test components is an example of this: 
diff --git a/nuget/Microsoft.Windows.CsWinRT.nuspec b/nuget/Microsoft.Windows.CsWinRT.nuspec
index 6c7ac3a44..cd6ee30d8 100644
--- a/nuget/Microsoft.Windows.CsWinRT.nuspec
+++ b/nuget/Microsoft.Windows.CsWinRT.nuspec
@@ -26,6 +26,7 @@
     <file src="Microsoft.Windows.CsWinRT.Prerelease*.targets" target="build"/>
     <file src="Microsoft.Windows.CsWinRT.Authoring.Transitive.targets" target="build"/>
     <file src="Microsoft.Windows.CsWinRT.Authoring.Transitive.targets" target="buildTransitive"/>
+    <file src="$cswinrt_exe$\..\..\obj\merged\WinRT.Interop.winmd" target="metadata"/>
     <file src="readme.txt"/>
     <file src="$net5_runtime$" target="lib\net5.0\"/>
     <file src="$source_generator$" target="analyzers\dotnet\cs\"/>
diff --git a/nuget/Microsoft.Windows.CsWinRT.targets b/nuget/Microsoft.Windows.CsWinRT.targets
index 8c6645369..cc10d2595 100644
--- a/nuget/Microsoft.Windows.CsWinRT.targets
+++ b/nuget/Microsoft.Windows.CsWinRT.targets
@@ -90,7 +90,12 @@ Copyright (C) Microsoft Corporation. All rights reserved.
       <CsWinRTFilters Condition="'$(CsWinRTFilters)' == ''">
 @(CsWinRTExcludeItems->'-exclude %(Identity)', '&#x0d;&#x0a;')
 @(CsWinRTIncludeItems->'-include %(Identity)', '&#x0d;&#x0a;')
-      </CsWinRTFilters> 
+      </CsWinRTFilters>
+      <CsWinRTInteropMetadata Condition="'$(CsWinRTInteropMetadata)' == ''">$([MSBuild]::NormalizeDirectory('$(MSBuildThisFileDirectory)', '..\metadata\WinRT.Interop.winmd'))</CsWinRTInteropMetadata>
+      <CsWinRTIncludeWinRTInterop Condition="$(CsWinRTFilters.Contains('-include Windows&#x0d;&#x0a;'))">
+-input $(CsWinRTInteropMetadata)
+-include WinRT.Interop
+      </CsWinRTIncludeWinRTInterop>
       <CsWinRTParams Condition="'$(CsWinRTParams)' == ''">
 $(CsWinRTCommandVerbosity)
 -target $(TargetFramework)
@@ -98,6 +103,7 @@ $(CsWinRTWindowsMetadataInput)
 -input @(CsWinRTInputs->'"%(FullPath)"', ' ')
 -output "$(CsWinRTGeneratedFilesDir.TrimEnd('\'))"
 $(CsWinRTFilters)
+$(CsWinRTIncludeWinRTInterop)
       </CsWinRTParams>
     </PropertyGroup>
     <MakeDir Directories="$(CsWinRTGeneratedFilesDir)" />
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index eee4c5c30..8a93f61d9 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -34,6 +34,7 @@
     <BuildOutDir Condition="'$(BuildOutDir)'==''">$([MSBuild]::NormalizeDirectory('$(SolutionDir)_build', '$(BuildPlatform)', '$(Configuration)'))</BuildOutDir>
     <CsWinRTPath>$([MSBuild]::NormalizeDirectory('$(BuildOutDir)', 'cswinrt', 'bin'))</CsWinRTPath>
     <CsWinRTPath Condition="'$(Platform)'=='ARM' or '$(Platform)'=='ARM64'">$([MSBuild]::NormalizeDirectory('$(SolutionDir)_build', 'x86', '$(Configuration)', 'cswinrt', 'bin'))</CsWinRTPath>
+    <CsWinRTInteropMetadata Condition="'$(CsWinRTInteropMetadata)' == ''">$(CsWinRTPath)..\obj\merged\WinRT.Interop.winmd</CsWinRTInteropMetadata>
   </PropertyGroup>
 
   <PropertyGroup Condition="'$(MSBuildProjectExtension)' == '.vcxproj' or '$(MSBuildProjectExtension)' == '.wapproj'">
diff --git a/src/Projections/Test/Test.csproj b/src/Projections/Test/Test.csproj
index ad43fb7d5..867f91ae4 100644
--- a/src/Projections/Test/Test.csproj
+++ b/src/Projections/Test/Test.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
     <TargetFrameworks>netstandard2.0;net5.0</TargetFrameworks>
diff --git a/src/Projections/Windows/Windows.csproj b/src/Projections/Windows/Windows.csproj
index f0e9d5265..982dfdcc6 100644
--- a/src/Projections/Windows/Windows.csproj
+++ b/src/Projections/Windows/Windows.csproj
@@ -1,35 +1,39 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFrameworks>netstandard2.0;net5.0</TargetFrameworks>
-    <Platforms>x64;x86</Platforms>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
-    <ProjectReference Include="..\..\WinRT.Runtime\WinRT.Runtime.csproj" />
-    <ProjectReference Include="..\..\cswinrt\cswinrt.vcxproj" />
-  </ItemGroup>
-
-  <PropertyGroup>
-    <CsWinRTFilters>
--include Windows
-# Exclude Windows.UI, Windows.UI.Text, Windows.UI.Xaml per Microsoft.Windows.SDK.WinUI.Contracts NuGet
--include Windows.UI.Popups
--exclude Windows.UI.Colors
--exclude Windows.UI.IColors
--exclude Windows.UI.ColorHelper
--exclude Windows.UI.IColorHelper
-#-exclude Windows.UI.Text (must include Windows.UI.Text to work around WinUI nuget issues)
--exclude Windows.UI.Xaml
--exclude Windows.ApplicationModel.Store.Preview
-# Allow Windows.UI.Text, Windows.UI.Xaml types used in other namespaces
--include Windows.UI.Text.FontStretch
--include Windows.UI.Text.FontStyle
--include Windows.UI.Text.FontWeight
--include Windows.UI.Text.UnderlineType
--include Windows.UI.Xaml.Media.Animation.ConditionallyIndependentlyAnimatableAttribute      
-    </CsWinRTFilters>
-  </PropertyGroup>
- 
-</Project>
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFrameworks>netstandard2.0;net5.0</TargetFrameworks>
+    <Platforms>x64;x86</Platforms>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
+    <ProjectReference Include="..\..\WinRT.Runtime\WinRT.Runtime.csproj" />
+    <ProjectReference Include="..\..\cswinrt\cswinrt.vcxproj" />
+  </ItemGroup>
+
+  <PropertyGroup>
+    <CsWinRTFilters>
+-include Windows
+# Exclude Windows.UI, Windows.UI.Text, Windows.UI.Xaml per Microsoft.Windows.SDK.WinUI.Contracts NuGet
+-include Windows.UI.Popups
+-exclude Windows.UI.Colors
+-exclude Windows.UI.IColors
+-exclude Windows.UI.ColorHelper
+-exclude Windows.UI.IColorHelper
+#-exclude Windows.UI.Text (must include Windows.UI.Text to work around WinUI nuget issues)
+-exclude Windows.UI.Xaml
+-exclude Windows.ApplicationModel.Store.Preview
+# Allow Windows.UI.Text, Windows.UI.Xaml types used in other namespaces
+-include Windows.UI.Text.FontStretch
+-include Windows.UI.Text.FontStyle
+-include Windows.UI.Text.FontWeight
+-include Windows.UI.Text.UnderlineType
+-include Windows.UI.Xaml.Media.Animation.ConditionallyIndependentlyAnimatableAttribute     
+    </CsWinRTFilters>
+  </PropertyGroup>
+
+  <PropertyGroup>
+    <DefineConstants>TRACE;MANUAL_IUNKNOWN,UAC_VERSION_13</DefineConstants>
+  </PropertyGroup>
+ 
+</Project>
diff --git a/src/Samples/WinUIDesktopSample/WinUIDesktopSample.csproj b/src/Samples/WinUIDesktopSample/WinUIDesktopSample.csproj
index fc78a792c..7c54070c2 100644
--- a/src/Samples/WinUIDesktopSample/WinUIDesktopSample.csproj
+++ b/src/Samples/WinUIDesktopSample/WinUIDesktopSample.csproj
@@ -11,6 +11,8 @@
     -->
     <XamlCodeGenerationControlFlags>DoNotGenerateOtherProviders</XamlCodeGenerationControlFlags>
     <Platforms>x86;x64</Platforms>
+    <SimulateCsWinRTNugetReference>true</SimulateCsWinRTNugetReference>
+    <CsWinRTEnabled>false</CsWinRTEnabled>
   </PropertyGroup>
 
   <ItemGroup>
diff --git a/src/Tests/TestComponentCSharp/Directory.Build.props b/src/Tests/TestComponentCSharp/Directory.Build.props
index dfb7b481e..8ee64c421 100644
--- a/src/Tests/TestComponentCSharp/Directory.Build.props
+++ b/src/Tests/TestComponentCSharp/Directory.Build.props
@@ -1,10 +1,15 @@
 <Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
 
-  <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
+    <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
 
-  <!--Only need the WinUI winmd files for compiling idl, so stub out Xaml targets-->
-  <Target Name="MarkupCompilePass1" />
-  <Target Name="MarkupCompilePass2" />
-  <Target Name="Prep_ComputeProcessXamlFiles" />
+    <PropertyGroup>
+        <!--Avoid UniversalApiContract type not found error-->
+        <CppWinRTMergeNoValidate>true</CppWinRTMergeNoValidate>
+    </PropertyGroup>
+
+    <!--Only need the WinUI winmd files for compiling idl, so stub out Xaml targets-->
+    <Target Name="MarkupCompilePass1" />
+    <Target Name="MarkupCompilePass2" />
+    <Target Name="Prep_ComputeProcessXamlFiles" />
 
 </Project>
diff --git a/src/Tests/TestComponentCSharp/Directory.Build.targets b/src/Tests/TestComponentCSharp/Directory.Build.targets
deleted file mode 100644
index e2ea5ceeb..000000000
--- a/src/Tests/TestComponentCSharp/Directory.Build.targets
+++ /dev/null
@@ -1,46 +0,0 @@
-<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
-
-    <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)../'))" />
-
-    <PropertyGroup>
-        <CppWinRTMergeProjectWinMDInputsDependsOn>
-            CppWinRTMergeProjectWinMDInputsOverride;$(CppWinRTMergeProjectWinMDInputsDependsOn)
-        </CppWinRTMergeProjectWinMDInputsDependsOn>
-    </PropertyGroup>
-
-    <!-- Override C++/WinRT mdmerge target to disable validation and prevent contract typedef not found errors -->
-    <!-- Consider making mdmerge validation an option for C++/WinRT -->
-    <Target Name="CppWinRTMergeProjectWinMDInputsOverride"
-            DependsOnTargets="Midl;GetCppWinRTMdMergeInputs"
-            Inputs="$(MSBuildAllProjects);@(CppWinRTMdMergeInputs)"
-            Outputs="@(_MdMergedOutput);$(IntDir)mdmerge.rsp">
-        <PropertyGroup>
-            <!--Note: CppWinRTNamespaceMergeDepth supersedes CppWinRTMergeDepth-->
-            <_MdMergeDepth Condition="'$(CppWinRTNamespaceMergeDepth)' != ''">-n:$(CppWinRTNamespaceMergeDepth)</_MdMergeDepth>
-            <_MdMergeDepth Condition="'$(_MdMergeDepth)' == ''">$(CppWinRTMergeDepth)</_MdMergeDepth>
-            <_MdMergeDepth Condition="'$(_MdMergeDepth)' == '' And '$(CppWinRTRootNamespaceAutoMerge)' == 'true'">-n:$(RootNamespace.Split('.').length)</_MdMergeDepth>
-            <_MdMergeDepth Condition="'$(_MdMergeDepth)' == '' And ('@(Page)' != '' Or '@(ApplicationDefinition)' != '')">-n:1</_MdMergeDepth>
-            <_MdMergeCommand>$(MdMergePath)mdmerge %40"$(IntDir)mdmerge.rsp"</_MdMergeCommand>
-        </PropertyGroup>
-        <PropertyGroup>
-            <!-- mdmerge.exe wants the folders to not have a trailing \ -->
-            <_MdMergeParameters>@(CppWinRTMdMergeMetadataDirectories->'-metadata_dir &quot;%(RelativeDir).&quot;', '&#x0d;&#x0a;')</_MdMergeParameters>
-            <_MdMergeParameters>$(_MdMergeParameters) @(CppWinRTMdMergeInputs->'-i &quot;%(Identity)&quot;', '&#x0d;&#x0a;')</_MdMergeParameters>
-            <_MdMergeParameters>$(_MdMergeParameters) -o &quot;$(CppWinRTMergedDir.TrimEnd('\'))&quot; -partial $(_MdMergeDepth)</_MdMergeParameters>
-        </PropertyGroup>
-        <!-- Always write the mdmerge.rsp file when the target runs, because the file is used as the output of this target. -->
-        <WriteLinesToFile
-            File="$(IntDir)mdmerge.rsp" Lines="$(_MdMergeParameters)"
-            ContinueOnError="true" Overwrite="true" />
-        <MakeDir Directories="$(CppWinRTUnmergedDir);$(CppWinRTMergedDir)" />
-        <Message Text="$(_MdMergeCommand)" Importance="$(CppWinRTVerbosity)" Condition="'@(CppWinRTMdMergeInputs)' != ''" />
-        <!-- Only run mdmerge.exe when we actually have inputs -->
-        <Exec Command="$(_MdMergeCommand)" Condition="'@(CppWinRTMdMergeInputs)' != ''" />
-        <ItemGroup>
-            <_MdMergedOutput Remove="@(_MdMergedOutput)"/>
-            <_MdMergedOutput Include="$(CppWinRTMergedDir)*.winmd"/>
-        </ItemGroup>
-        <Message Text="CppWinRTMdMerge output: @(MdMergeOutput)" Importance="$(CppWinRTVerbosity)"/>
-    </Target>
-
-</Project>
diff --git a/src/Tests/TestComponentCSharp/TestComponentCSharp.idl b/src/Tests/TestComponentCSharp/TestComponentCSharp.idl
index 4ed99328c..0bdc432dc 100644
--- a/src/Tests/TestComponentCSharp/TestComponentCSharp.idl
+++ b/src/Tests/TestComponentCSharp/TestComponentCSharp.idl
@@ -423,13 +423,6 @@ namespace TestComponentCSharp
         CustomDisposableTest();
     }
     
-    // IInspectable-based interop interface
-    [uuid(39E050C3-4E74-441A-8DC0-B81104DF949C)]
-    interface IUserConsentVerifierInterop
-    {
-        Object RequestVerificationForWindowAsync(UInt64 appWindow, String message, GUID riid);
-    }
-
     [default_interface]
     runtimeclass CustomBindableVectorTest : Microsoft.UI.Xaml.Interop.IBindableVector
     {
diff --git a/src/Tests/TestComponentCSharp/TestComponentCSharp.vcxproj b/src/Tests/TestComponentCSharp/TestComponentCSharp.vcxproj
index 23a88346b..312f7793b 100644
--- a/src/Tests/TestComponentCSharp/TestComponentCSharp.vcxproj
+++ b/src/Tests/TestComponentCSharp/TestComponentCSharp.vcxproj
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\..\packages\Microsoft.Windows.CppWinRT.2.0.210504.3\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.210504.3\build\native\Microsoft.Windows.CppWinRT.props')" />
   <Import Project="..\..\packages\Microsoft.WinUI.3.0.0-preview1.200515.3\build\native\Microsoft.WinUI.props" Condition="Exists('..\..\packages\Microsoft.WinUI.3.0.0-preview1.200515.3\build\native\Microsoft.WinUI.props')" />
-  <Import Project="..\..\packages\Microsoft.Windows.CppWinRT.2.0.200615.7\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.200615.7\build\native\Microsoft.Windows.CppWinRT.props')" />
   <PropertyGroup Label="Globals">
     <CppWinRTVerbosity>high</CppWinRTVerbosity>
     <CppWinRTOptimized>true</CppWinRTOptimized>
@@ -94,22 +94,21 @@
   </ItemGroup>
   <ItemGroup>
     <None Include="Directory.Build.props" />
-    <None Include="Directory.Build.targets" />
     <None Include="packages.config" />
     <None Include="TestComponentCSharp.def" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
-    <Import Project="..\..\packages\Microsoft.Windows.CppWinRT.2.0.200615.7\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.200615.7\build\native\Microsoft.Windows.CppWinRT.targets')" />
     <Import Project="..\..\packages\Microsoft.WinUI.3.0.0-preview1.200515.3\build\native\Microsoft.WinUI.targets" Condition="Exists('..\..\packages\Microsoft.WinUI.3.0.0-preview1.200515.3\build\native\Microsoft.WinUI.targets')" />
+    <Import Project="..\..\packages\Microsoft.Windows.CppWinRT.2.0.210504.3\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.210504.3\build\native\Microsoft.Windows.CppWinRT.targets')" />
   </ImportGroup>
   <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
     <PropertyGroup>
       <ErrorText>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}.</ErrorText>
     </PropertyGroup>
-    <Error Condition="!Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.200615.7\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.200615.7\build\native\Microsoft.Windows.CppWinRT.props'))" />
-    <Error Condition="!Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.200615.7\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.200615.7\build\native\Microsoft.Windows.CppWinRT.targets'))" />
     <Error Condition="!Exists('..\..\packages\Microsoft.WinUI.3.0.0-preview1.200515.3\build\native\Microsoft.WinUI.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WinUI.3.0.0-preview1.200515.3\build\native\Microsoft.WinUI.props'))" />
     <Error Condition="!Exists('..\..\packages\Microsoft.WinUI.3.0.0-preview1.200515.3\build\native\Microsoft.WinUI.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.WinUI.3.0.0-preview1.200515.3\build\native\Microsoft.WinUI.targets'))" />
+    <Error Condition="!Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.210504.3\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.210504.3\build\native\Microsoft.Windows.CppWinRT.props'))" />
+    <Error Condition="!Exists('..\..\packages\Microsoft.Windows.CppWinRT.2.0.210504.3\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Windows.CppWinRT.2.0.210504.3\build\native\Microsoft.Windows.CppWinRT.targets'))" />
   </Target>
 </Project>
\ No newline at end of file
diff --git a/src/Tests/TestComponentCSharp/TestComponentCSharp.vcxproj.filters b/src/Tests/TestComponentCSharp/TestComponentCSharp.vcxproj.filters
index a268c04e7..8619e0939 100644
--- a/src/Tests/TestComponentCSharp/TestComponentCSharp.vcxproj.filters
+++ b/src/Tests/TestComponentCSharp/TestComponentCSharp.vcxproj.filters
@@ -33,6 +33,5 @@
     <None Include="TestComponentCSharp.def" />
     <None Include="packages.config" />
     <None Include="Directory.Build.props" />
-    <None Include="Directory.Build.targets" />
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/src/Tests/TestComponentCSharp/packages.config b/src/Tests/TestComponentCSharp/packages.config
index 3e4579339..56121e4ac 100644
--- a/src/Tests/TestComponentCSharp/packages.config
+++ b/src/Tests/TestComponentCSharp/packages.config
@@ -1,5 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
-  <package id="Microsoft.Windows.CppWinRT" version="2.0.200615.7" targetFramework="native" />
-  <package id="Microsoft.WinUI" version="3.0.0-preview1.200515.3" targetFramework="native" />
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Microsoft.Windows.CppWinRT" version="2.0.210504.3" targetFramework="native" />
+  <package id="Microsoft.WinUI" version="3.0.0-preview1.200515.3" targetFramework="native" />
 </packages>
\ No newline at end of file
diff --git a/src/Tests/UnitTest/ComInteropTests.cs b/src/Tests/UnitTest/ComInteropTests.cs
new file mode 100644
index 000000000..1617db06b
--- /dev/null
+++ b/src/Tests/UnitTest/ComInteropTests.cs
@@ -0,0 +1,117 @@
+using System;
+using System.Runtime.InteropServices;
+using Windows.ApplicationModel.DataTransfer.DragDrop.Core;
+using Windows.Graphics.Printing;
+using Windows.Media;
+using Windows.Media.PlayTo;
+using Windows.Security.Authentication.Web.Core;
+using Windows.Security.Credentials;
+using Windows.Security.Credentials.UI;
+using Windows.UI.ApplicationSettings;
+using Windows.UI.Input;
+using Windows.UI.Input.Core;
+using Windows.UI.Input.Spatial;
+using Windows.UI.ViewManagement;
+using Xunit;
+
+namespace UnitTest
+{
+    // Note: Many of the COM interop APIs cannot be easily tested without significant test setup.
+    // These cases either expect a runtime exception, or are compile-time only (skipped to validate types).
+    public class ComInteropTests
+    {
+        [Fact]
+        public void TestAccountsSettingsPane()
+        {
+            Assert.Throws<COMException>(() => AccountsSettingsPaneInterop.GetForWindow(new IntPtr(0)));
+            Assert.Throws<COMException>(() => AccountsSettingsPaneInterop.ShowAddAccountForWindowAsync(new IntPtr(0)));
+            Assert.Throws<COMException>(() => AccountsSettingsPaneInterop.ShowManageAccountsForWindowAsync(new IntPtr(0)));
+        }
+
+        [Fact]
+        public void TestDragDropManager()
+        {
+            Assert.Throws<COMException>(() => DragDropManagerInterop.GetForWindow(new IntPtr(0)));
+        }
+
+        [Fact]
+        public void TestInputPane()
+        {
+           Assert.Throws<TypeInitializationException>(() => InputPaneInterop.GetForWindow(new IntPtr(0)));
+        }
+
+        [Fact]
+        public void TestPlayToManager()
+        {
+            Assert.Throws<COMException>(() => PlayToManagerInterop.GetForWindow(new IntPtr(0)));
+            PlayToManagerInterop.ShowPlayToUIForWindow(new IntPtr(0));
+        }
+
+        [Fact]
+        public void TestPrintManager()
+        {
+            Assert.Throws<COMException>(() => PrintManagerInterop.GetForWindow(new IntPtr(0)));
+            Assert.Throws<COMException>(() => PrintManagerInterop.ShowPrintUIForWindowAsync(new IntPtr(0)));
+        }
+
+        [Fact]
+        public void TestRadialControllerConfiguration()
+        {
+            Assert.Throws<COMException>(() => RadialControllerConfigurationInterop.GetForWindow(new IntPtr(0)));
+        }
+
+        // Skipping this test as it causes a hang 
+        [Fact(Skip = "Compile-time only interop test")]
+        public void TestRadialControllerIndependentInputSource()
+        {
+            var radialControllerIndependentInputSource = RadialControllerIndependentInputSourceInterop.CreateForWindow(new IntPtr(0));
+            Assert.IsType<Windows.UI.Input.Core.RadialControllerIndependentInputSource>(radialControllerIndependentInputSource);
+        }
+
+        // Skipping this test as it causes a hang 
+        [Fact(Skip = "Compile-time only interop test")]
+        public void TestRadialControllerInterop()
+        {
+            var radialController = RadialControllerInterop.CreateForWindow(new IntPtr(0));
+            Assert.IsType<Windows.UI.Input.RadialController>(radialController);
+
+        }
+
+        // Skipping this test as it raises non-catchable 'System.AccessViolationException' occurred in Windows.dll 
+        [Fact(Skip = "Compile-time only interop test")]
+        public void TestSpatialInteractionManager()
+        {
+           Assert.Throws<COMException>(() => SpatialInteractionManagerInterop.GetForWindow(new IntPtr(0)));
+        }
+
+        // Skipping this test as it raises non-catchable 'System.AccessViolationException' occurred in Windows.dll 
+        [Fact(Skip = "Compile-time only interop test")]
+        public void TestSystemMediaTransportControls()
+        {
+           Assert.Throws<COMException>(() => SystemMediaTransportControlsInterop.GetForWindow(new IntPtr(0)));
+        }
+
+        [Fact]
+        public void TestUIViewSettings()
+        {
+           Assert.Throws<COMException>(() => UIViewSettingsInterop.GetForWindow(new IntPtr(0)));
+        }
+
+        [Fact]
+        public void TestUserConsentVerifier()
+        {
+            var operation = UserConsentVerifierInterop.RequestVerificationForWindowAsync(new IntPtr(0), "message");
+            Assert.NotNull(operation);
+        }
+
+        [Fact]
+        public void TestWebAuthenticationCoreManager()
+        {
+            WebAccountProvider provider = new WebAccountProvider("id", "name", null);
+            WebTokenRequest webTokenRequest = new WebTokenRequest(provider);
+            Assert.Throws<ArgumentException>(() => WebAuthenticationCoreManagerInterop.RequestTokenForWindowAsync(new IntPtr(0), webTokenRequest));
+            var webAccount = new WebAccount(provider, "user name", 0);
+            Assert.Throws<ArgumentException>(() => WebAuthenticationCoreManagerInterop.RequestTokenWithWebAccountForWindowAsync(new IntPtr(0), webTokenRequest, webAccount));
+        }
+    }
+}
diff --git a/src/Tests/UnitTest/TestComponentCSharp_Tests.cs b/src/Tests/UnitTest/TestComponentCSharp_Tests.cs
index c9e601cf9..7b9bda1bc 100644
--- a/src/Tests/UnitTest/TestComponentCSharp_Tests.cs
+++ b/src/Tests/UnitTest/TestComponentCSharp_Tests.cs
@@ -53,8 +53,8 @@ public TestCSharp()
 
         [Fact]
         public void TestEnums()
-        {
-            // Enums
+        {
+            // Enums
             var expectedEnum = EnumValue.Two;
             TestObject.EnumProperty = expectedEnum;
             Assert.Equal(expectedEnum, TestObject.EnumProperty);
@@ -63,7 +63,7 @@ public void TestEnums()
             TestObject.EnumPropertyChanged +=
                 (object sender, EnumValue value) => Assert.Equal(expectedEnum, value);
             TestObject.RaiseEnumChanged();
-
+
             var expectedEnumStruct = new EnumStruct() { value = EnumValue.Two };
             TestObject.EnumStructProperty = expectedEnumStruct;
             Assert.Equal(expectedEnumStruct, TestObject.EnumStructProperty);
@@ -71,16 +71,16 @@ public void TestEnums()
             TestObject.CallForEnumStruct(() => expectedEnumStruct);
             TestObject.EnumStructPropertyChanged +=
                 (object sender, EnumStruct value) => Assert.Equal(expectedEnumStruct, value);
-            TestObject.RaiseEnumStructChanged();
-
+            TestObject.RaiseEnumStructChanged();
+
             var expectedEnums = new EnumValue[] { EnumValue.One, EnumValue.Two };
-            TestObject.EnumsProperty = expectedEnums;
+            TestObject.EnumsProperty = expectedEnums;
             Assert.Equal(expectedEnums, TestObject.EnumsProperty);
             TestObject.CallForEnums(() => expectedEnums);
             Assert.Equal(expectedEnums, TestObject.EnumsProperty);
 
             var expectedEnumStructs = new EnumStruct[] { new EnumStruct(EnumValue.One), new EnumStruct(EnumValue.Two) };
-            TestObject.EnumStructsProperty = expectedEnumStructs;
+            TestObject.EnumStructsProperty = expectedEnumStructs;
             Assert.Equal(expectedEnumStructs, TestObject.EnumStructsProperty);
             TestObject.CallForEnumStructs(() => expectedEnumStructs);
             Assert.Equal(expectedEnumStructs, TestObject.EnumStructsProperty);
@@ -94,7 +94,7 @@ public void TestEnums()
             TestObject.FlagPropertyChanged +=
                 (object sender, FlagValue value) => Assert.Equal(expectedFlag, value);
             TestObject.RaiseFlagChanged();
-
+
             var expectedFlagStruct = new FlagStruct() { value = FlagValue.All };
             TestObject.FlagStructProperty = expectedFlagStruct;
             Assert.Equal(expectedFlagStruct, TestObject.FlagStructProperty);
@@ -102,16 +102,16 @@ public void TestEnums()
             TestObject.CallForFlagStruct(() => expectedFlagStruct);
             TestObject.FlagStructPropertyChanged +=
                 (object sender, FlagStruct value) => Assert.Equal(expectedFlagStruct, value);
-            TestObject.RaiseFlagStructChanged();
-
+            TestObject.RaiseFlagStructChanged();
+
             var expectedFlags = new FlagValue[] { FlagValue.One, FlagValue.All };
-            TestObject.FlagsProperty = expectedFlags;
+            TestObject.FlagsProperty = expectedFlags;
             Assert.Equal(expectedFlags, TestObject.FlagsProperty);
             TestObject.CallForFlags(() => expectedFlags);
             Assert.Equal(expectedFlags, TestObject.FlagsProperty);
 
             var expectedFlagStructs = new FlagStruct[] { new FlagStruct(FlagValue.One), new FlagStruct(FlagValue.All) };
-            TestObject.FlagStructsProperty = expectedFlagStructs;
+            TestObject.FlagStructsProperty = expectedFlagStructs;
             Assert.Equal(expectedFlagStructs, TestObject.FlagStructsProperty);
             TestObject.CallForFlagStructs(() => expectedFlagStructs);
             Assert.Equal(expectedFlagStructs, TestObject.FlagStructsProperty);
@@ -424,11 +424,11 @@ public void TestStreamWriteAsync()
             Assert.True(InvokeStreamWriteAsync().Wait(1000));
         }
 
-        [Fact]
-        public void TestAsStream()
-        {
-            using InMemoryRandomAccessStream winrtStream = new InMemoryRandomAccessStream();
-            using Stream normalStream = winrtStream.AsStream();
+        [Fact]
+        public void TestAsStream()
+        {
+            using InMemoryRandomAccessStream winrtStream = new InMemoryRandomAccessStream();
+            using Stream normalStream = winrtStream.AsStream();
             using var memoryStream = new MemoryStream();
             normalStream.CopyTo(memoryStream);
         }
@@ -759,26 +759,26 @@ public void TestObjectCasting()
 
             var objects = new List<ManagedType>() { new ManagedType(), new ManagedType() };
             var query = from item in objects select item;
-            TestObject.ObjectIterableProperty = query;
-
-            TestObject.ObjectProperty = "test";
-            Assert.Equal("test", TestObject.ObjectProperty);
-
-            var objectArray = new ManagedType[] { new ManagedType(), new ManagedType() };
-            TestObject.ObjectIterableProperty = objectArray;
-            Assert.True(TestObject.ObjectIterableProperty.SequenceEqual(objectArray));
-
-            var strArray = new string[] { "str1", "str2", "str3" };
-            TestObject.ObjectIterableProperty = strArray;
-            Assert.True(TestObject.ObjectIterableProperty.SequenceEqual(strArray));
-
-            var uriArray = new Uri[] { new Uri("http://aka.ms/cswinrt"), new Uri("http://github.com") };
-            TestObject.ObjectIterableProperty = uriArray;
-            Assert.True(TestObject.ObjectIterableProperty.SequenceEqual(uriArray));
-
-            var objectUriArray = new object[] { new Uri("http://github.com") };
-            TestObject.ObjectIterableProperty = objectUriArray;
-            Assert.True(TestObject.ObjectIterableProperty.SequenceEqual(objectUriArray));
+            TestObject.ObjectIterableProperty = query;
+
+            TestObject.ObjectProperty = "test";
+            Assert.Equal("test", TestObject.ObjectProperty);
+
+            var objectArray = new ManagedType[] { new ManagedType(), new ManagedType() };
+            TestObject.ObjectIterableProperty = objectArray;
+            Assert.True(TestObject.ObjectIterableProperty.SequenceEqual(objectArray));
+
+            var strArray = new string[] { "str1", "str2", "str3" };
+            TestObject.ObjectIterableProperty = strArray;
+            Assert.True(TestObject.ObjectIterableProperty.SequenceEqual(strArray));
+
+            var uriArray = new Uri[] { new Uri("http://aka.ms/cswinrt"), new Uri("http://github.com") };
+            TestObject.ObjectIterableProperty = uriArray;
+            Assert.True(TestObject.ObjectIterableProperty.SequenceEqual(uriArray));
+
+            var objectUriArray = new object[] { new Uri("http://github.com") };
+            TestObject.ObjectIterableProperty = objectUriArray;
+            Assert.True(TestObject.ObjectIterableProperty.SequenceEqual(objectUriArray));
         }
 
         [Fact]
@@ -1158,12 +1158,6 @@ public unsafe void TestFactoryCast()
             var staticFactory = ComImports.As<IStringableInterop>();
             staticFactory.ToString(out hstr);
             Assert.Equal("ComImports", MarshalString.FromAbi(hstr));
-
-            // IInspectable-based (projected) interop interface
-            var interop = Windows.Security.Credentials.UI.UserConsentVerifier.As<IUserConsentVerifierInterop>();
-            var guid = GuidGenerator.CreateIID(typeof(IAsyncOperation<UserConsentVerificationResult>));
-            var operation = (IAsyncOperation<UserConsentVerificationResult>)interop.RequestVerificationForWindowAsync(0, "message", guid);
-            Assert.NotNull(operation);
         }
 
         [Fact]
@@ -1379,59 +1373,59 @@ public void TestSimpleCCWs()
             var managedProperties = new ManagedProperties(42);
             TestObject.CopyProperties(managedProperties);
             Assert.Equal(managedProperties.ReadWriteProperty, TestObject.ReadWriteProperty);
-        }
-
+        }
+
         [Fact]
         public void TestCCWMarshaler()
         {
             Guid IID_IMarshal = new Guid("00000003-0000-0000-c000-000000000046");
-            var managedProperties = new ManagedProperties(42);
+            var managedProperties = new ManagedProperties(42);
             IObjectReference ccw = MarshalInterface<IProperties1>.CreateMarshaler(managedProperties);
             ccw.TryAs<IUnknownVftbl>(IID_IMarshal, out var marshalCCW);
-            Assert.NotNull(marshalCCW);
-
-            var array = new byte[] { 0x01 };
-            var buff = array.AsBuffer();
+            Assert.NotNull(marshalCCW);
+
+            var array = new byte[] { 0x01 };
+            var buff = array.AsBuffer();
             IObjectReference ccw2 = MarshalInterface<IBuffer>.CreateMarshaler(buff);
             ccw2.TryAs<IUnknownVftbl>(IID_IMarshal, out var marshalCCW2);
-            Assert.NotNull(marshalCCW2);
-        }
-
-#if !NETCOREAPP2_0
-        [Fact]
-        public void TestDelegateCCWMarshaler()
-        {
-            CreateAndValidateStreamedFile().Wait();
-        }
-
-        private async Task CreateAndValidateStreamedFile()
-        {
-            var storageFile = await StorageFile.CreateStreamedFileAsync("CreateAndValidateStreamedFile.txt", StreamedFileWriter, null);
-            using var inputStream = await storageFile.OpenSequentialReadAsync();
-            using var stream = inputStream.AsStreamForRead();
-            byte[] buff = new byte[50];
-            var numRead = stream.Read(buff, 0, 50);
-            Assert.True(numRead > 0);
-            var result = System.Text.Encoding.Default.GetString(buff, 0, numRead).TrimEnd(null);
-            Assert.Equal("Success!", result);
-        }
-
-        private static async void StreamedFileWriter(StreamedFileDataRequest request)
-        {
-            try
-            {
-                using (var stream = request.AsStreamForWrite())
-                using (var streamWriter = new StreamWriter(stream))
-                {
-                    await streamWriter.WriteLineAsync("Success!");
-                }
-                request.Dispose();
-            }
-            catch (Exception)
-            {
-                request.FailAndClose(StreamedFileFailureMode.Incomplete);
-            }
-        }
+            Assert.NotNull(marshalCCW2);
+        }
+
+#if !NETCOREAPP2_0
+        [Fact]
+        public void TestDelegateCCWMarshaler()
+        {
+            CreateAndValidateStreamedFile().Wait();
+        }
+
+        private async Task CreateAndValidateStreamedFile()
+        {
+            var storageFile = await StorageFile.CreateStreamedFileAsync("CreateAndValidateStreamedFile.txt", StreamedFileWriter, null);
+            using var inputStream = await storageFile.OpenSequentialReadAsync();
+            using var stream = inputStream.AsStreamForRead();
+            byte[] buff = new byte[50];
+            var numRead = stream.Read(buff, 0, 50);
+            Assert.True(numRead > 0);
+            var result = System.Text.Encoding.Default.GetString(buff, 0, numRead).TrimEnd(null);
+            Assert.Equal("Success!", result);
+        }
+
+        private static async void StreamedFileWriter(StreamedFileDataRequest request)
+        {
+            try
+            {
+                using (var stream = request.AsStreamForWrite())
+                using (var streamWriter = new StreamWriter(stream))
+                {
+                    await streamWriter.WriteLineAsync("Success!");
+                }
+                request.Dispose();
+            }
+            catch (Exception)
+            {
+                request.FailAndClose(StreamedFileFailureMode.Incomplete);
+            }
+        }
 #endif
 
         [Fact]
@@ -1735,11 +1729,11 @@ public void TestPointTypeMapping()
             Assert.True(TestObject.PointProperty == pt);
             Assert.Equal(pt, TestObject.GetPointReference().Value);
 
-            var vector2 = TestObject.PointProperty.ToVector2();
+            var vector2 = TestObject.PointProperty.ToVector2();
             Assert.Equal(pt.X, vector2.X);
             Assert.Equal(pt.Y, vector2.Y);
 
-            TestObject.PointProperty = vector2.ToPoint();
+            TestObject.PointProperty = vector2.ToPoint();
             Assert.Equal(pt.X, TestObject.PointProperty.X);
             Assert.Equal(pt.Y, TestObject.PointProperty.Y);
         }
@@ -1763,13 +1757,13 @@ public void TestSizeTypeMapping()
             TestObject.SizeProperty = size;
             Assert.Equal(size.Height, TestObject.SizeProperty.Height);
             Assert.Equal(size.Width, TestObject.SizeProperty.Width);
-            Assert.True(TestObject.SizeProperty == size);
-
-            var vector2 = TestObject.SizeProperty.ToVector2();
+            Assert.True(TestObject.SizeProperty == size);
+
+            var vector2 = TestObject.SizeProperty.ToVector2();
             Assert.Equal(size.Width, vector2.X);
             Assert.Equal(size.Height, vector2.Y);
 
-            TestObject.SizeProperty = vector2.ToSize();
+            TestObject.SizeProperty = vector2.ToSize();
             Assert.Equal(size.Width, TestObject.SizeProperty.Width);
             Assert.Equal(size.Height, TestObject.SizeProperty.Height);
         }
@@ -2035,12 +2029,12 @@ public void TestDateTimeMapping()
         }
 
         [Fact]
-        public void TestDateTimeMappingNegative()
-        {
-            var time = new DateTimeOffset(1501, 1, 1, 0, 0, 0, TimeSpan.Zero);
-            TestObject.DateTimeProperty = time;
-            Assert.Equal(time, TestObject.DateTimeProperty);
-            Assert.Equal(time, TestObject.GetDateTimeProperty().Value);
+        public void TestDateTimeMappingNegative()
+        {
+            var time = new DateTimeOffset(1501, 1, 1, 0, 0, 0, TimeSpan.Zero);
+            TestObject.DateTimeProperty = time;
+            Assert.Equal(time, TestObject.DateTimeProperty);
+            Assert.Equal(time, TestObject.GetDateTimeProperty().Value);
         }
 
         [Fact]
@@ -2247,15 +2241,15 @@ public void AcquireObject()
                 nonAgileObject.Commands.Add(new Windows.UI.Popups.UICommand("test"));
                 nonAgileObject.Commands.Add(new Windows.UI.Popups.UICommand("test2"));
                 Assert.ThrowsAny<System.Exception>(() => nonAgileObject.As<IAgileObject>());
-
+
                 agileReference = nonAgileObject.AsAgile();
                 objectAcquired.Set();
-                valueAcquired.WaitOne();
-
-                // Object gets proxied to the apartment.
-                Assert.Equal(2, proxyObject.Commands.Count);
-                agileReference.Dispose();
-
+                valueAcquired.WaitOne();
+
+                // Object gets proxied to the apartment.
+                Assert.Equal(2, proxyObject.Commands.Count);
+                agileReference.Dispose();
+
                 proxyObject2 = agileReference2.Get();
             }
 
@@ -2263,19 +2257,19 @@ public void CheckValue()
             {
                 objectAcquired.WaitOne();
                 Assert.Equal(ApartmentState.MTA, Thread.CurrentThread.GetApartmentState());
-                proxyObject = agileReference.Get();
-                Assert.Equal(2, proxyObject.Commands.Count);
-                
+                proxyObject = agileReference.Get();
+                Assert.Equal(2, proxyObject.Commands.Count);
+                
                 nonAgileObject2 = new Windows.UI.Popups.PopupMenu();
                 agileReference2 = nonAgileObject2.AsAgile();
-
+
                 valueAcquired.Set();
             }
 
-            public void CallProxyObject()
-            {
-                // Call to the proxy object after the apartment is gone should throw.
-                Assert.ThrowsAny<System.Exception>(() => proxyObject2.Commands);
+            public void CallProxyObject()
+            {
+                // Call to the proxy object after the apartment is gone should throw.
+                Assert.ThrowsAny<System.Exception>(() => proxyObject2.Commands);
             }
 
             private Windows.UI.Popups.PopupMenu nonAgileObject, nonAgileObject2;
@@ -2298,11 +2292,11 @@ public void TestNonAgileObjectCall()
             mtaThread.SetApartmentState(ApartmentState.MTA);
             mtaThread.Start();
             mtaThread.Join();
-            staThread.Join();
-
-            // Spin another STA thread after the other 2 threads are done and try to
-            // access one of the proxied objects.  They should fail as there is no context
-            // to switch to in order to marshal it to the current apartment.
+            staThread.Join();
+
+            // Spin another STA thread after the other 2 threads are done and try to
+            // access one of the proxied objects.  They should fail as there is no context
+            // to switch to in order to marshal it to the current apartment.
             Thread anotherStaThread = new Thread(new ThreadStart(caller.CallProxyObject));
             anotherStaThread.SetApartmentState(ApartmentState.STA);
             anotherStaThread.Start();
@@ -2378,7 +2372,7 @@ static void TestImports()
             GC.Collect();
             GC.WaitForPendingFinalizers();
             Assert.Equal(0, ComImports.NumObjects);
-        }
+        }
 
         [Fact]
         public void TestInterfaceObjectMarshalling()
@@ -2402,133 +2396,133 @@ public void TestNonProjectedRuntimeClass()
         }
 
         [Fact(Skip="Operation not supported")]
-        public void TestIBindableIterator()
-        {
-            CustomBindableIteratorTest bindableIterator = new CustomBindableIteratorTest();
-            Assert.True(bindableIterator.MoveNext());
-            Assert.True(bindableIterator.HasCurrent);
-            Assert.Equal(27861, bindableIterator.Current);
-        }
-
-        [Fact]
-        public void TestIDisposable()
-        {
-            CustomDisposableTest disposable = new CustomDisposableTest();
-            disposable.Dispose();
-        }
-
-        [Fact]
-        public void TestIBindableVector()
-        {
-            CustomBindableVectorTest vector = new CustomBindableVectorTest();
-            Assert.NotNull(vector);
-        }
-
-        [Fact]
-        public void TestCovariance()
-        {
-            var listOfListOfPoints = new List<List<Point>>() {
-                new List<Point>{ new Point(1, 1), new Point(1, 2), new Point(1, 3) },
-                new List<Point>{ new Point(2, 1), new Point(2, 2), new Point(2, 3) },
-                new List<Point>{ new Point(3, 1), new Point(3, 2), new Point(3, 3) }
-            };
-            TestObject.IterableOfPointIterablesProperty = listOfListOfPoints;
-            Assert.True(TestObject.IterableOfPointIterablesProperty.SequenceEqual(listOfListOfPoints));
-
-            var listOfListOfUris = new List<List<Uri>>() {
-                new List<Uri>{ new Uri("http://aka.ms/cswinrt"), new Uri("http://github.com") },
-                new List<Uri>{ new Uri("http://aka.ms/cswinrt") },
-                new List<Uri>{ new Uri("http://aka.ms/cswinrt"), new Uri("http://microsoft.com") }
-            };
-            TestObject.IterableOfObjectIterablesProperty = listOfListOfUris;
-            Assert.True(TestObject.IterableOfObjectIterablesProperty.SequenceEqual(listOfListOfUris));
-        }
-
-        // Ensure that event subscription state is properly cached to enable later unsubscribes
-        [Fact]
-        public void TestEventSourceCaching()
-        {
-            bool eventCalled = false;
-            void Class_StaticIntPropertyChanged(object sender, int e) => eventCalled = (e == 3);
-
-            // Test static codegen-based EventSource caching
-            Class.StaticIntPropertyChanged += Class_StaticIntPropertyChanged;
-            GC.Collect(2, GCCollectionMode.Forced, true);
-            GC.WaitForPendingFinalizers();
-            Class.StaticIntPropertyChanged -= Class_StaticIntPropertyChanged;
-            Class.StaticIntProperty = 3;
-            Assert.False(eventCalled);
-            Class.StaticIntPropertyChanged += Class_StaticIntPropertyChanged;
-            GC.Collect(2, GCCollectionMode.Forced, true);
-            GC.WaitForPendingFinalizers();
-            Class.StaticIntProperty = 3;
-            Assert.True(eventCalled);
-
-            // Test dynamic WeakRef-based EventSource caching
-            eventCalled = false;
+        public void TestIBindableIterator()
+        {
+            CustomBindableIteratorTest bindableIterator = new CustomBindableIteratorTest();
+            Assert.True(bindableIterator.MoveNext());
+            Assert.True(bindableIterator.HasCurrent);
+            Assert.Equal(27861, bindableIterator.Current);
+        }
+
+        [Fact]
+        public void TestIDisposable()
+        {
+            CustomDisposableTest disposable = new CustomDisposableTest();
+            disposable.Dispose();
+        }
+
+        [Fact]
+        public void TestIBindableVector()
+        {
+            CustomBindableVectorTest vector = new CustomBindableVectorTest();
+            Assert.NotNull(vector);
+        }
+
+        [Fact]
+        public void TestCovariance()
+        {
+            var listOfListOfPoints = new List<List<Point>>() {
+                new List<Point>{ new Point(1, 1), new Point(1, 2), new Point(1, 3) },
+                new List<Point>{ new Point(2, 1), new Point(2, 2), new Point(2, 3) },
+                new List<Point>{ new Point(3, 1), new Point(3, 2), new Point(3, 3) }
+            };
+            TestObject.IterableOfPointIterablesProperty = listOfListOfPoints;
+            Assert.True(TestObject.IterableOfPointIterablesProperty.SequenceEqual(listOfListOfPoints));
+
+            var listOfListOfUris = new List<List<Uri>>() {
+                new List<Uri>{ new Uri("http://aka.ms/cswinrt"), new Uri("http://github.com") },
+                new List<Uri>{ new Uri("http://aka.ms/cswinrt") },
+                new List<Uri>{ new Uri("http://aka.ms/cswinrt"), new Uri("http://microsoft.com") }
+            };
+            TestObject.IterableOfObjectIterablesProperty = listOfListOfUris;
+            Assert.True(TestObject.IterableOfObjectIterablesProperty.SequenceEqual(listOfListOfUris));
+        }
+
+        // Ensure that event subscription state is properly cached to enable later unsubscribes
+        [Fact]
+        public void TestEventSourceCaching()
+        {
+            bool eventCalled = false;
+            void Class_StaticIntPropertyChanged(object sender, int e) => eventCalled = (e == 3);
+
+            // Test static codegen-based EventSource caching
+            Class.StaticIntPropertyChanged += Class_StaticIntPropertyChanged;
+            GC.Collect(2, GCCollectionMode.Forced, true);
+            GC.WaitForPendingFinalizers();
+            Class.StaticIntPropertyChanged -= Class_StaticIntPropertyChanged;
+            Class.StaticIntProperty = 3;
+            Assert.False(eventCalled);
+            Class.StaticIntPropertyChanged += Class_StaticIntPropertyChanged;
+            GC.Collect(2, GCCollectionMode.Forced, true);
+            GC.WaitForPendingFinalizers();
+            Class.StaticIntProperty = 3;
+            Assert.True(eventCalled);
+
+            // Test dynamic WeakRef-based EventSource caching
+            eventCalled = false;
             static void Subscribe(EventHandler<int> handler) => Singleton.Instance.IntPropertyChanged += handler;
             static void Unsubscribe(EventHandler<int> handler) => Singleton.Instance.IntPropertyChanged -= handler;
             static void Assign(int value) => Singleton.Instance.IntProperty = value;
-            Subscribe(Class_StaticIntPropertyChanged);
-            GC.Collect(2, GCCollectionMode.Forced, true);
-            GC.WaitForPendingFinalizers();
-            Unsubscribe(Class_StaticIntPropertyChanged);
-            Assign(3);
-            Assert.False(eventCalled);
-            Subscribe(Class_StaticIntPropertyChanged);
-            GC.Collect(2, GCCollectionMode.Forced, true);
-            GC.WaitForPendingFinalizers();
-            Assign(3);
-            Assert.True(eventCalled);
-        }
-
+            Subscribe(Class_StaticIntPropertyChanged);
+            GC.Collect(2, GCCollectionMode.Forced, true);
+            GC.WaitForPendingFinalizers();
+            Unsubscribe(Class_StaticIntPropertyChanged);
+            Assign(3);
+            Assert.False(eventCalled);
+            Subscribe(Class_StaticIntPropertyChanged);
+            GC.Collect(2, GCCollectionMode.Forced, true);
+            GC.WaitForPendingFinalizers();
+            Assign(3);
+            Assert.True(eventCalled);
+        }
+
 #if NET5_0
-        [TestComponentCSharp.Warning]  // NO warning CA1416
-        class WarningManaged { };
-
-        class WarningSubclass : WarningClass
-        {
-            void InvokeOverridableWarnings()
-            {
-                WarningOverridableMethod(); // warning CA1416
-                WarningOverridableProperty = 0; // warning CA1416
-                // see https://github.com/microsoft/cppwinrt/issues/782
-                //WarningOverridableEvent += (object s, Int32 v) => { }; // warning CA1416
-            }
-        }
-
-        // Manual for now - verify that all APIs targeting 19041 generate a warning
-        private void TestSupportedOSPlatformWarnings()
-        {
-            // Types
-            var a = new WarningAttribute();    // warning CA1416
-            Assert.NotNull(a);
-            var w = new WarningStruct{ i32 = 0 }; // warning CA1416
-            Assert.Equal(0, w.i32);     // warning CA1416
-            var v = WarningEnum.Value;
-            Assert.NotEqual(WarningEnum.WarningValue, v);   // warning CA1416
-
-            // Members
-            var o = new WarningClass();    // warning CA1416
-            o = new WarningClass(WarningEnum.Value);    // warning CA1416
-            o.WarningMethod();     // warning CA1416
-            var p = o.WarningProperty; // warning CA1416
-            o.WarningProperty = 0; // warning CA1416
-            p = o.WarningPropertySetter;
-            o.WarningPropertySetter = 0;   // warning CA1416
-            o.WarningEvent += (object s, Int32 v) => { }; // warning CA1416
-            o.WarningInterfaceMethod();     // warning CA1416
-            p = o.WarningInterfaceProperty; // warning CA1416
-            o.WarningInterfaceProperty = 0; // warning CA1416
-            p = o.WarningInterfacePropertySetter;
-            o.WarningInterfacePropertySetter = 0;   // warning CA1416
-            o.WarningInterfaceEvent += (object s, Int32 v) => { }; // warning CA1416
-
-            // Attributed statics
-            WarningStatic.WarningMethod(); // warning CA1416
-            WarningStatic.WarningProperty = 0; // warning CA1416
-            WarningStatic.WarningEvent += (object s, Int32 v) => { }; // warning CA1416
+        [TestComponentCSharp.Warning]  // NO warning CA1416
+        class WarningManaged { };
+
+        class WarningSubclass : WarningClass
+        {
+            void InvokeOverridableWarnings()
+            {
+                WarningOverridableMethod(); // warning CA1416
+                WarningOverridableProperty = 0; // warning CA1416
+                // see https://github.com/microsoft/cppwinrt/issues/782
+                //WarningOverridableEvent += (object s, Int32 v) => { }; // warning CA1416
+            }
+        }
+
+        // Manual for now - verify that all APIs targeting 19041 generate a warning
+        private void TestSupportedOSPlatformWarnings()
+        {
+            // Types
+            var a = new WarningAttribute();    // warning CA1416
+            Assert.NotNull(a);
+            var w = new WarningStruct{ i32 = 0 }; // warning CA1416
+            Assert.Equal(0, w.i32);     // warning CA1416
+            var v = WarningEnum.Value;
+            Assert.NotEqual(WarningEnum.WarningValue, v);   // warning CA1416
+
+            // Members
+            var o = new WarningClass();    // warning CA1416
+            o = new WarningClass(WarningEnum.Value);    // warning CA1416
+            o.WarningMethod();     // warning CA1416
+            var p = o.WarningProperty; // warning CA1416
+            o.WarningProperty = 0; // warning CA1416
+            p = o.WarningPropertySetter;
+            o.WarningPropertySetter = 0;   // warning CA1416
+            o.WarningEvent += (object s, Int32 v) => { }; // warning CA1416
+            o.WarningInterfaceMethod();     // warning CA1416
+            p = o.WarningInterfaceProperty; // warning CA1416
+            o.WarningInterfaceProperty = 0; // warning CA1416
+            p = o.WarningInterfacePropertySetter;
+            o.WarningInterfacePropertySetter = 0;   // warning CA1416
+            o.WarningInterfaceEvent += (object s, Int32 v) => { }; // warning CA1416
+
+            // Attributed statics
+            WarningStatic.WarningMethod(); // warning CA1416
+            WarningStatic.WarningProperty = 0; // warning CA1416
+            WarningStatic.WarningEvent += (object s, Int32 v) => { }; // warning CA1416
         }
 #endif
     }
-}
+}
diff --git a/src/WinRT.Runtime/WinRT.Runtime.csproj b/src/WinRT.Runtime/WinRT.Runtime.csproj
index 897d91af8..4a61f108a 100644
--- a/src/WinRT.Runtime/WinRT.Runtime.csproj
+++ b/src/WinRT.Runtime/WinRT.Runtime.csproj
@@ -24,7 +24,7 @@
   </PropertyGroup>
     
   <ItemGroup>
-    <Compile Include="../cswinrt/strings/*.cs" Link="cswinrt/%(FileName)%(Extension)" />
+    <Compile Include="../cswinrt/strings/WinRT*.cs" Link="cswinrt/%(FileName)%(Extension)" />
   </ItemGroup>
 
   <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
diff --git a/src/cswinrt.sln b/src/cswinrt.sln
index 9197abf9a..dcdc88368 100644
--- a/src/cswinrt.sln
+++ b/src/cswinrt.sln
@@ -101,202 +101,332 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AuthoringWinUITest", "Tests
 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
+		{7E3A9AB3-8CBB-4B9C-BA76-0FE7108DCAEB}.Debug|ARM.ActiveCfg = Debug|Win32
+		{7E3A9AB3-8CBB-4B9C-BA76-0FE7108DCAEB}.Debug|ARM64.ActiveCfg = Debug|Win32
 		{7E3A9AB3-8CBB-4B9C-BA76-0FE7108DCAEB}.Debug|x64.ActiveCfg = Debug|x64
 		{7E3A9AB3-8CBB-4B9C-BA76-0FE7108DCAEB}.Debug|x64.Build.0 = Debug|x64
 		{7E3A9AB3-8CBB-4B9C-BA76-0FE7108DCAEB}.Debug|x86.ActiveCfg = Debug|Win32
 		{7E3A9AB3-8CBB-4B9C-BA76-0FE7108DCAEB}.Debug|x86.Build.0 = Debug|Win32
+		{7E3A9AB3-8CBB-4B9C-BA76-0FE7108DCAEB}.Release|ARM.ActiveCfg = Release|Win32
+		{7E3A9AB3-8CBB-4B9C-BA76-0FE7108DCAEB}.Release|ARM64.ActiveCfg = Release|Win32
 		{7E3A9AB3-8CBB-4B9C-BA76-0FE7108DCAEB}.Release|x64.ActiveCfg = Release|x64
 		{7E3A9AB3-8CBB-4B9C-BA76-0FE7108DCAEB}.Release|x64.Build.0 = Release|x64
 		{7E3A9AB3-8CBB-4B9C-BA76-0FE7108DCAEB}.Release|x86.ActiveCfg = Release|Win32
 		{7E3A9AB3-8CBB-4B9C-BA76-0FE7108DCAEB}.Release|x86.Build.0 = Release|Win32
+		{9A9F52CA-F624-43A4-B5EF-C50861F584C2}.Debug|ARM.ActiveCfg = Debug|x86
+		{9A9F52CA-F624-43A4-B5EF-C50861F584C2}.Debug|ARM64.ActiveCfg = Debug|x86
 		{9A9F52CA-F624-43A4-B5EF-C50861F584C2}.Debug|x64.ActiveCfg = Debug|x64
 		{9A9F52CA-F624-43A4-B5EF-C50861F584C2}.Debug|x64.Build.0 = Debug|x64
 		{9A9F52CA-F624-43A4-B5EF-C50861F584C2}.Debug|x86.ActiveCfg = Debug|x86
 		{9A9F52CA-F624-43A4-B5EF-C50861F584C2}.Debug|x86.Build.0 = Debug|x86
+		{9A9F52CA-F624-43A4-B5EF-C50861F584C2}.Release|ARM.ActiveCfg = Release|x86
+		{9A9F52CA-F624-43A4-B5EF-C50861F584C2}.Release|ARM64.ActiveCfg = Release|x86
 		{9A9F52CA-F624-43A4-B5EF-C50861F584C2}.Release|x64.ActiveCfg = Release|x64
 		{9A9F52CA-F624-43A4-B5EF-C50861F584C2}.Release|x64.Build.0 = Release|x64
 		{9A9F52CA-F624-43A4-B5EF-C50861F584C2}.Release|x86.ActiveCfg = Release|x86
 		{9A9F52CA-F624-43A4-B5EF-C50861F584C2}.Release|x86.Build.0 = Release|x86
+		{6ACFD2B2-E8AA-4CD4-AAD8-213CE8BB2637}.Debug|ARM.ActiveCfg = Debug|Win32
+		{6ACFD2B2-E8AA-4CD4-AAD8-213CE8BB2637}.Debug|ARM64.ActiveCfg = Debug|Win32
 		{6ACFD2B2-E8AA-4CD4-AAD8-213CE8BB2637}.Debug|x64.ActiveCfg = Debug|x64
 		{6ACFD2B2-E8AA-4CD4-AAD8-213CE8BB2637}.Debug|x64.Build.0 = Debug|x64
 		{6ACFD2B2-E8AA-4CD4-AAD8-213CE8BB2637}.Debug|x86.ActiveCfg = Debug|Win32
 		{6ACFD2B2-E8AA-4CD4-AAD8-213CE8BB2637}.Debug|x86.Build.0 = Debug|Win32
+		{6ACFD2B2-E8AA-4CD4-AAD8-213CE8BB2637}.Release|ARM.ActiveCfg = Release|Win32
+		{6ACFD2B2-E8AA-4CD4-AAD8-213CE8BB2637}.Release|ARM64.ActiveCfg = Release|Win32
 		{6ACFD2B2-E8AA-4CD4-AAD8-213CE8BB2637}.Release|x64.ActiveCfg = Release|x64
 		{6ACFD2B2-E8AA-4CD4-AAD8-213CE8BB2637}.Release|x64.Build.0 = Release|x64
 		{6ACFD2B2-E8AA-4CD4-AAD8-213CE8BB2637}.Release|x86.ActiveCfg = Release|Win32
 		{6ACFD2B2-E8AA-4CD4-AAD8-213CE8BB2637}.Release|x86.Build.0 = Release|Win32
+		{2954F343-85A7-46F5-A3F3-F106FDD13900}.Debug|ARM.ActiveCfg = Debug|ARM
+		{2954F343-85A7-46F5-A3F3-F106FDD13900}.Debug|ARM.Build.0 = Debug|ARM
+		{2954F343-85A7-46F5-A3F3-F106FDD13900}.Debug|ARM64.ActiveCfg = Debug|Win32
 		{2954F343-85A7-46F5-A3F3-F106FDD13900}.Debug|x64.ActiveCfg = Debug|x64
 		{2954F343-85A7-46F5-A3F3-F106FDD13900}.Debug|x64.Build.0 = Debug|x64
 		{2954F343-85A7-46F5-A3F3-F106FDD13900}.Debug|x86.ActiveCfg = Debug|Win32
 		{2954F343-85A7-46F5-A3F3-F106FDD13900}.Debug|x86.Build.0 = Debug|Win32
+		{2954F343-85A7-46F5-A3F3-F106FDD13900}.Release|ARM.ActiveCfg = Release|ARM
+		{2954F343-85A7-46F5-A3F3-F106FDD13900}.Release|ARM.Build.0 = Release|ARM
+		{2954F343-85A7-46F5-A3F3-F106FDD13900}.Release|ARM64.ActiveCfg = Release|Win32
 		{2954F343-85A7-46F5-A3F3-F106FDD13900}.Release|x64.ActiveCfg = Release|x64
 		{2954F343-85A7-46F5-A3F3-F106FDD13900}.Release|x64.Build.0 = Release|x64
 		{2954F343-85A7-46F5-A3F3-F106FDD13900}.Release|x86.ActiveCfg = Release|Win32
 		{2954F343-85A7-46F5-A3F3-F106FDD13900}.Release|x86.Build.0 = Release|Win32
+		{25244CED-966E-45F2-9711-1F51E951FF89}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{25244CED-966E-45F2-9711-1F51E951FF89}.Debug|ARM.Build.0 = Debug|Any CPU
+		{25244CED-966E-45F2-9711-1F51E951FF89}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+		{25244CED-966E-45F2-9711-1F51E951FF89}.Debug|ARM64.Build.0 = Debug|Any CPU
 		{25244CED-966E-45F2-9711-1F51E951FF89}.Debug|x64.ActiveCfg = Debug|Any CPU
 		{25244CED-966E-45F2-9711-1F51E951FF89}.Debug|x64.Build.0 = Debug|Any CPU
 		{25244CED-966E-45F2-9711-1F51E951FF89}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{25244CED-966E-45F2-9711-1F51E951FF89}.Debug|x86.Build.0 = Debug|Any CPU
+		{25244CED-966E-45F2-9711-1F51E951FF89}.Release|ARM.ActiveCfg = Release|Any CPU
+		{25244CED-966E-45F2-9711-1F51E951FF89}.Release|ARM.Build.0 = Release|Any CPU
+		{25244CED-966E-45F2-9711-1F51E951FF89}.Release|ARM64.ActiveCfg = Release|Any CPU
+		{25244CED-966E-45F2-9711-1F51E951FF89}.Release|ARM64.Build.0 = Release|Any CPU
 		{25244CED-966E-45F2-9711-1F51E951FF89}.Release|x64.ActiveCfg = Release|Any CPU
 		{25244CED-966E-45F2-9711-1F51E951FF89}.Release|x64.Build.0 = Release|Any CPU
 		{25244CED-966E-45F2-9711-1F51E951FF89}.Release|x86.ActiveCfg = Release|Any CPU
 		{25244CED-966E-45F2-9711-1F51E951FF89}.Release|x86.Build.0 = Release|Any CPU
+		{8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Debug|ARM.ActiveCfg = Debug|x86
+		{8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Debug|ARM64.ActiveCfg = Debug|x86
 		{8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Debug|x64.ActiveCfg = Debug|x64
 		{8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Debug|x64.Build.0 = Debug|x64
 		{8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Debug|x86.ActiveCfg = Debug|x86
 		{8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Debug|x86.Build.0 = Debug|x86
+		{8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Release|ARM.ActiveCfg = Release|x86
+		{8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Release|ARM64.ActiveCfg = Release|x86
 		{8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Release|x64.ActiveCfg = Release|x64
 		{8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Release|x64.Build.0 = Release|x64
 		{8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Release|x86.ActiveCfg = Release|x86
 		{8E6FBCB2-B0C1-4E92-8AEB-2A11564E6E0D}.Release|x86.Build.0 = Release|x86
+		{C6D580C5-7037-4733-B933-916FF400AFE2}.Debug|ARM.ActiveCfg = Debug|x86
+		{C6D580C5-7037-4733-B933-916FF400AFE2}.Debug|ARM64.ActiveCfg = Debug|x86
 		{C6D580C5-7037-4733-B933-916FF400AFE2}.Debug|x64.ActiveCfg = Debug|x64
 		{C6D580C5-7037-4733-B933-916FF400AFE2}.Debug|x64.Build.0 = Debug|x64
 		{C6D580C5-7037-4733-B933-916FF400AFE2}.Debug|x86.ActiveCfg = Debug|x86
 		{C6D580C5-7037-4733-B933-916FF400AFE2}.Debug|x86.Build.0 = Debug|x86
+		{C6D580C5-7037-4733-B933-916FF400AFE2}.Release|ARM.ActiveCfg = Release|x86
+		{C6D580C5-7037-4733-B933-916FF400AFE2}.Release|ARM64.ActiveCfg = Release|x86
 		{C6D580C5-7037-4733-B933-916FF400AFE2}.Release|x64.ActiveCfg = Release|x64
 		{C6D580C5-7037-4733-B933-916FF400AFE2}.Release|x64.Build.0 = Release|x64
 		{C6D580C5-7037-4733-B933-916FF400AFE2}.Release|x86.ActiveCfg = Release|x86
 		{C6D580C5-7037-4733-B933-916FF400AFE2}.Release|x86.Build.0 = Release|x86
+		{FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Debug|ARM.ActiveCfg = Debug|x86
+		{FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Debug|ARM64.ActiveCfg = Debug|x86
 		{FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Debug|x64.ActiveCfg = Debug|x64
 		{FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Debug|x64.Build.0 = Debug|x64
 		{FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Debug|x86.ActiveCfg = Debug|x86
 		{FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Debug|x86.Build.0 = Debug|x86
+		{FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Release|ARM.ActiveCfg = Release|x86
+		{FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Release|ARM64.ActiveCfg = Release|x86
 		{FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Release|x64.ActiveCfg = Release|x64
 		{FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Release|x64.Build.0 = Release|x64
 		{FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Release|x86.ActiveCfg = Release|x86
 		{FFA9A78B-F53F-43EE-AF87-24A80F4C330A}.Release|x86.Build.0 = Release|x86
+		{0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Debug|ARM.ActiveCfg = Debug|x86
+		{0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Debug|ARM64.ActiveCfg = Debug|x86
 		{0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Debug|x64.ActiveCfg = Debug|x64
 		{0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Debug|x64.Build.0 = Debug|x64
 		{0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Debug|x86.ActiveCfg = Debug|x86
 		{0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Debug|x86.Build.0 = Debug|x86
+		{0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Release|ARM.ActiveCfg = Release|x86
+		{0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Release|ARM64.ActiveCfg = Release|x86
 		{0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Release|x64.ActiveCfg = Release|x64
 		{0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Release|x64.Build.0 = Release|x64
 		{0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Release|x86.ActiveCfg = Release|x86
 		{0A991D5F-BFEE-4D2F-9AAD-6AD06470A5DF}.Release|x86.Build.0 = Release|x86
+		{B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Debug|ARM.ActiveCfg = Debug|x86
+		{B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Debug|ARM64.ActiveCfg = Debug|x86
 		{B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Debug|x64.ActiveCfg = Debug|x64
 		{B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Debug|x64.Build.0 = Debug|x64
 		{B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Debug|x86.ActiveCfg = Debug|x86
+		{B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Release|ARM.ActiveCfg = Release|x86
+		{B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Release|ARM64.ActiveCfg = Release|x86
 		{B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Release|x64.ActiveCfg = Release|x64
 		{B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Release|x64.Build.0 = Release|x64
 		{B34C96F4-3660-4B2D-8ABD-A4B428166DC7}.Release|x86.ActiveCfg = Release|x86
+		{78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Debug|ARM.ActiveCfg = Debug|ARM
+		{78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Debug|ARM.Build.0 = Debug|ARM
+		{78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Debug|ARM64.ActiveCfg = Debug|Win32
 		{78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Debug|x64.ActiveCfg = Debug|x64
 		{78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Debug|x64.Build.0 = Debug|x64
 		{78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Debug|x86.ActiveCfg = Debug|Win32
 		{78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Debug|x86.Build.0 = Debug|Win32
+		{78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Release|ARM.ActiveCfg = Release|ARM
+		{78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Release|ARM.Build.0 = Release|ARM
+		{78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Release|ARM64.ActiveCfg = Release|Win32
 		{78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Release|x64.ActiveCfg = Release|x64
 		{78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Release|x64.Build.0 = Release|x64
 		{78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Release|x86.ActiveCfg = Release|Win32
 		{78D85F23-7CB1-44A1-9238-6DF2C76754E4}.Release|x86.Build.0 = Release|Win32
+		{03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Debug|ARM.ActiveCfg = Debug|x86
+		{03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Debug|ARM64.ActiveCfg = Debug|x86
 		{03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Debug|x64.ActiveCfg = Debug|x64
 		{03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Debug|x64.Build.0 = Debug|x64
 		{03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Debug|x86.ActiveCfg = Debug|x86
 		{03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Debug|x86.Build.0 = Debug|x86
+		{03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Release|ARM.ActiveCfg = Release|x86
+		{03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Release|ARM64.ActiveCfg = Release|x86
 		{03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Release|x64.ActiveCfg = Release|x64
 		{03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Release|x64.Build.0 = Release|x64
 		{03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Release|x86.ActiveCfg = Release|x86
 		{03EEF460-2F10-4FBE-AFFA-53477D3FC8D5}.Release|x86.Build.0 = Release|x86
+		{7E33BCB7-19C5-4061-981D-BA695322708A}.Debug|ARM.ActiveCfg = Debug|Win32
+		{7E33BCB7-19C5-4061-981D-BA695322708A}.Debug|ARM64.ActiveCfg = Debug|Win32
 		{7E33BCB7-19C5-4061-981D-BA695322708A}.Debug|x64.ActiveCfg = Debug|x64
 		{7E33BCB7-19C5-4061-981D-BA695322708A}.Debug|x64.Build.0 = Debug|x64
 		{7E33BCB7-19C5-4061-981D-BA695322708A}.Debug|x86.ActiveCfg = Debug|Win32
 		{7E33BCB7-19C5-4061-981D-BA695322708A}.Debug|x86.Build.0 = Debug|Win32
+		{7E33BCB7-19C5-4061-981D-BA695322708A}.Release|ARM.ActiveCfg = Release|Win32
+		{7E33BCB7-19C5-4061-981D-BA695322708A}.Release|ARM64.ActiveCfg = Release|Win32
 		{7E33BCB7-19C5-4061-981D-BA695322708A}.Release|x64.ActiveCfg = Release|x64
 		{7E33BCB7-19C5-4061-981D-BA695322708A}.Release|x64.Build.0 = Release|x64
 		{7E33BCB7-19C5-4061-981D-BA695322708A}.Release|x86.ActiveCfg = Release|Win32
 		{7E33BCB7-19C5-4061-981D-BA695322708A}.Release|x86.Build.0 = Release|Win32
+		{B511B7C9-C8E2-47ED-A0D1-538C00747D30}.Debug|ARM.ActiveCfg = Debug|Win32
+		{B511B7C9-C8E2-47ED-A0D1-538C00747D30}.Debug|ARM64.ActiveCfg = Debug|Win32
 		{B511B7C9-C8E2-47ED-A0D1-538C00747D30}.Debug|x64.ActiveCfg = Debug|x64
 		{B511B7C9-C8E2-47ED-A0D1-538C00747D30}.Debug|x64.Build.0 = Debug|x64
 		{B511B7C9-C8E2-47ED-A0D1-538C00747D30}.Debug|x86.ActiveCfg = Debug|Win32
 		{B511B7C9-C8E2-47ED-A0D1-538C00747D30}.Debug|x86.Build.0 = Debug|Win32
+		{B511B7C9-C8E2-47ED-A0D1-538C00747D30}.Release|ARM.ActiveCfg = Release|Win32
+		{B511B7C9-C8E2-47ED-A0D1-538C00747D30}.Release|ARM64.ActiveCfg = Release|Win32
 		{B511B7C9-C8E2-47ED-A0D1-538C00747D30}.Release|x64.ActiveCfg = Release|x64
 		{B511B7C9-C8E2-47ED-A0D1-538C00747D30}.Release|x64.Build.0 = Release|x64
 		{B511B7C9-C8E2-47ED-A0D1-538C00747D30}.Release|x86.ActiveCfg = Release|Win32
 		{B511B7C9-C8E2-47ED-A0D1-538C00747D30}.Release|x86.Build.0 = Release|Win32
+		{0BB8F82D-874E-45AA-BCA3-20CE0562164A}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{0BB8F82D-874E-45AA-BCA3-20CE0562164A}.Debug|ARM.Build.0 = Debug|Any CPU
+		{0BB8F82D-874E-45AA-BCA3-20CE0562164A}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+		{0BB8F82D-874E-45AA-BCA3-20CE0562164A}.Debug|ARM64.Build.0 = Debug|Any CPU
 		{0BB8F82D-874E-45AA-BCA3-20CE0562164A}.Debug|x64.ActiveCfg = Debug|Any CPU
 		{0BB8F82D-874E-45AA-BCA3-20CE0562164A}.Debug|x64.Build.0 = Debug|Any CPU
 		{0BB8F82D-874E-45AA-BCA3-20CE0562164A}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{0BB8F82D-874E-45AA-BCA3-20CE0562164A}.Debug|x86.Build.0 = Debug|Any CPU
+		{0BB8F82D-874E-45AA-BCA3-20CE0562164A}.Release|ARM.ActiveCfg = Release|Any CPU
+		{0BB8F82D-874E-45AA-BCA3-20CE0562164A}.Release|ARM.Build.0 = Release|Any CPU
+		{0BB8F82D-874E-45AA-BCA3-20CE0562164A}.Release|ARM64.ActiveCfg = Release|Any CPU
+		{0BB8F82D-874E-45AA-BCA3-20CE0562164A}.Release|ARM64.Build.0 = Release|Any CPU
 		{0BB8F82D-874E-45AA-BCA3-20CE0562164A}.Release|x64.ActiveCfg = Release|Any CPU
 		{0BB8F82D-874E-45AA-BCA3-20CE0562164A}.Release|x64.Build.0 = Release|Any CPU
 		{0BB8F82D-874E-45AA-BCA3-20CE0562164A}.Release|x86.ActiveCfg = Release|Any CPU
 		{0BB8F82D-874E-45AA-BCA3-20CE0562164A}.Release|x86.Build.0 = Release|Any CPU
+		{EF3326B5-716F-41D2-AB30-4EFAB30955E2}.Debug|ARM.ActiveCfg = Debug|x86
+		{EF3326B5-716F-41D2-AB30-4EFAB30955E2}.Debug|ARM64.ActiveCfg = Debug|x86
 		{EF3326B5-716F-41D2-AB30-4EFAB30955E2}.Debug|x64.ActiveCfg = Debug|x64
 		{EF3326B5-716F-41D2-AB30-4EFAB30955E2}.Debug|x64.Build.0 = Debug|x64
 		{EF3326B5-716F-41D2-AB30-4EFAB30955E2}.Debug|x86.ActiveCfg = Debug|x86
 		{EF3326B5-716F-41D2-AB30-4EFAB30955E2}.Debug|x86.Build.0 = Debug|x86
+		{EF3326B5-716F-41D2-AB30-4EFAB30955E2}.Release|ARM.ActiveCfg = Release|x86
+		{EF3326B5-716F-41D2-AB30-4EFAB30955E2}.Release|ARM64.ActiveCfg = Release|x86
 		{EF3326B5-716F-41D2-AB30-4EFAB30955E2}.Release|x64.ActiveCfg = Release|x64
 		{EF3326B5-716F-41D2-AB30-4EFAB30955E2}.Release|x64.Build.0 = Release|x64
 		{EF3326B5-716F-41D2-AB30-4EFAB30955E2}.Release|x86.ActiveCfg = Release|x86
 		{EF3326B5-716F-41D2-AB30-4EFAB30955E2}.Release|x86.Build.0 = Release|x86
+		{E0C26D3A-504A-4826-BAE2-DE775F865B2A}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{E0C26D3A-504A-4826-BAE2-DE775F865B2A}.Debug|ARM.Build.0 = Debug|Any CPU
+		{E0C26D3A-504A-4826-BAE2-DE775F865B2A}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+		{E0C26D3A-504A-4826-BAE2-DE775F865B2A}.Debug|ARM64.Build.0 = Debug|Any CPU
 		{E0C26D3A-504A-4826-BAE2-DE775F865B2A}.Debug|x64.ActiveCfg = Debug|Any CPU
 		{E0C26D3A-504A-4826-BAE2-DE775F865B2A}.Debug|x64.Build.0 = Debug|Any CPU
 		{E0C26D3A-504A-4826-BAE2-DE775F865B2A}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{E0C26D3A-504A-4826-BAE2-DE775F865B2A}.Debug|x86.Build.0 = Debug|Any CPU
+		{E0C26D3A-504A-4826-BAE2-DE775F865B2A}.Release|ARM.ActiveCfg = Release|Any CPU
+		{E0C26D3A-504A-4826-BAE2-DE775F865B2A}.Release|ARM.Build.0 = Release|Any CPU
+		{E0C26D3A-504A-4826-BAE2-DE775F865B2A}.Release|ARM64.ActiveCfg = Release|Any CPU
+		{E0C26D3A-504A-4826-BAE2-DE775F865B2A}.Release|ARM64.Build.0 = Release|Any CPU
 		{E0C26D3A-504A-4826-BAE2-DE775F865B2A}.Release|x64.ActiveCfg = Release|Any CPU
 		{E0C26D3A-504A-4826-BAE2-DE775F865B2A}.Release|x64.Build.0 = Release|Any CPU
 		{E0C26D3A-504A-4826-BAE2-DE775F865B2A}.Release|x86.ActiveCfg = Release|Any CPU
 		{E0C26D3A-504A-4826-BAE2-DE775F865B2A}.Release|x86.Build.0 = Release|Any CPU
+		{41E2A272-150F-42F5-AD40-047AAD9088A0}.Debug|ARM.ActiveCfg = Debug|x86
+		{41E2A272-150F-42F5-AD40-047AAD9088A0}.Debug|ARM64.ActiveCfg = Debug|x86
 		{41E2A272-150F-42F5-AD40-047AAD9088A0}.Debug|x64.ActiveCfg = Debug|x64
 		{41E2A272-150F-42F5-AD40-047AAD9088A0}.Debug|x64.Build.0 = Debug|x64
 		{41E2A272-150F-42F5-AD40-047AAD9088A0}.Debug|x86.ActiveCfg = Debug|x86
 		{41E2A272-150F-42F5-AD40-047AAD9088A0}.Debug|x86.Build.0 = Debug|x86
+		{41E2A272-150F-42F5-AD40-047AAD9088A0}.Release|ARM.ActiveCfg = Release|x86
+		{41E2A272-150F-42F5-AD40-047AAD9088A0}.Release|ARM64.ActiveCfg = Release|x86
 		{41E2A272-150F-42F5-AD40-047AAD9088A0}.Release|x64.ActiveCfg = Release|x64
 		{41E2A272-150F-42F5-AD40-047AAD9088A0}.Release|x64.Build.0 = Release|x64
 		{41E2A272-150F-42F5-AD40-047AAD9088A0}.Release|x86.ActiveCfg = Release|x86
 		{41E2A272-150F-42F5-AD40-047AAD9088A0}.Release|x86.Build.0 = Release|x86
+		{0212A7C5-8D3F-443C-9EBC-1F28091FDF88}.Debug|ARM.ActiveCfg = Debug|Win32
+		{0212A7C5-8D3F-443C-9EBC-1F28091FDF88}.Debug|ARM64.ActiveCfg = Debug|Win32
 		{0212A7C5-8D3F-443C-9EBC-1F28091FDF88}.Debug|x64.ActiveCfg = Debug|x64
 		{0212A7C5-8D3F-443C-9EBC-1F28091FDF88}.Debug|x64.Build.0 = Debug|x64
 		{0212A7C5-8D3F-443C-9EBC-1F28091FDF88}.Debug|x86.ActiveCfg = Debug|Win32
 		{0212A7C5-8D3F-443C-9EBC-1F28091FDF88}.Debug|x86.Build.0 = Debug|Win32
+		{0212A7C5-8D3F-443C-9EBC-1F28091FDF88}.Release|ARM.ActiveCfg = Release|Win32
+		{0212A7C5-8D3F-443C-9EBC-1F28091FDF88}.Release|ARM64.ActiveCfg = Release|Win32
 		{0212A7C5-8D3F-443C-9EBC-1F28091FDF88}.Release|x64.ActiveCfg = Release|x64
 		{0212A7C5-8D3F-443C-9EBC-1F28091FDF88}.Release|x64.Build.0 = Release|x64
 		{0212A7C5-8D3F-443C-9EBC-1F28091FDF88}.Release|x86.ActiveCfg = Release|Win32
 		{0212A7C5-8D3F-443C-9EBC-1F28091FDF88}.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|Win32
 		{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|Win32
 		{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|Win32
 		{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|Win32
 		{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
+		{FC05C557-C974-4CB3-9DA7-BB5476710E91}.Debug|ARM.ActiveCfg = Debug|Any CPU
+		{FC05C557-C974-4CB3-9DA7-BB5476710E91}.Debug|ARM.Build.0 = Debug|Any CPU
+		{FC05C557-C974-4CB3-9DA7-BB5476710E91}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+		{FC05C557-C974-4CB3-9DA7-BB5476710E91}.Debug|ARM64.Build.0 = Debug|Any CPU
 		{FC05C557-C974-4CB3-9DA7-BB5476710E91}.Debug|x64.ActiveCfg = Debug|Any CPU
 		{FC05C557-C974-4CB3-9DA7-BB5476710E91}.Debug|x64.Build.0 = Debug|Any CPU
 		{FC05C557-C974-4CB3-9DA7-BB5476710E91}.Debug|x86.ActiveCfg = Debug|Any CPU
 		{FC05C557-C974-4CB3-9DA7-BB5476710E91}.Debug|x86.Build.0 = Debug|Any CPU
+		{FC05C557-C974-4CB3-9DA7-BB5476710E91}.Release|ARM.ActiveCfg = Release|Any CPU
+		{FC05C557-C974-4CB3-9DA7-BB5476710E91}.Release|ARM.Build.0 = Release|Any CPU
+		{FC05C557-C974-4CB3-9DA7-BB5476710E91}.Release|ARM64.ActiveCfg = Release|Any CPU
+		{FC05C557-C974-4CB3-9DA7-BB5476710E91}.Release|ARM64.Build.0 = Release|Any CPU
 		{FC05C557-C974-4CB3-9DA7-BB5476710E91}.Release|x64.ActiveCfg = Release|Any CPU
 		{FC05C557-C974-4CB3-9DA7-BB5476710E91}.Release|x64.Build.0 = Release|Any CPU
 		{FC05C557-C974-4CB3-9DA7-BB5476710E91}.Release|x86.ActiveCfg = Release|Any CPU
 		{FC05C557-C974-4CB3-9DA7-BB5476710E91}.Release|x86.Build.0 = Release|Any CPU
+		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Debug|ARM.ActiveCfg = Debug|x86
+		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Debug|ARM64.ActiveCfg = Debug|arm64
+		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Debug|ARM64.Build.0 = Debug|arm64
+		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Debug|ARM64.Deploy.0 = Debug|arm64
 		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Debug|x64.ActiveCfg = Debug|x64
 		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Debug|x64.Build.0 = Debug|x64
 		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Debug|x64.Deploy.0 = Debug|x64
 		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Debug|x86.ActiveCfg = Debug|x86
 		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Debug|x86.Build.0 = Debug|x86
 		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Debug|x86.Deploy.0 = Debug|x86
+		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Release|ARM.ActiveCfg = Release|x86
+		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Release|ARM64.ActiveCfg = Release|arm64
+		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Release|ARM64.Build.0 = Release|arm64
+		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Release|ARM64.Deploy.0 = Release|arm64
 		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Release|x64.ActiveCfg = Release|x64
 		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Release|x64.Build.0 = Release|x64
 		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Release|x64.Deploy.0 = Release|x64
 		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Release|x86.ActiveCfg = Release|x86
 		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Release|x86.Build.0 = Release|x86
 		{75B1621F-EC51-4D77-BD7E-BEE576B3ADC9}.Release|x86.Deploy.0 = Release|x86
+		{493C7729-2F21-4198-AB09-BDF56BF501D3}.Debug|ARM.ActiveCfg = Debug|Win32
+		{493C7729-2F21-4198-AB09-BDF56BF501D3}.Debug|ARM64.ActiveCfg = Debug|arm64
+		{493C7729-2F21-4198-AB09-BDF56BF501D3}.Debug|ARM64.Build.0 = Debug|arm64
 		{493C7729-2F21-4198-AB09-BDF56BF501D3}.Debug|x64.ActiveCfg = Debug|x64
 		{493C7729-2F21-4198-AB09-BDF56BF501D3}.Debug|x64.Build.0 = Debug|x64
 		{493C7729-2F21-4198-AB09-BDF56BF501D3}.Debug|x86.ActiveCfg = Debug|Win32
 		{493C7729-2F21-4198-AB09-BDF56BF501D3}.Debug|x86.Build.0 = Debug|Win32
+		{493C7729-2F21-4198-AB09-BDF56BF501D3}.Release|ARM.ActiveCfg = Release|Win32
+		{493C7729-2F21-4198-AB09-BDF56BF501D3}.Release|ARM64.ActiveCfg = Release|arm64
+		{493C7729-2F21-4198-AB09-BDF56BF501D3}.Release|ARM64.Build.0 = Release|arm64
 		{493C7729-2F21-4198-AB09-BDF56BF501D3}.Release|x64.ActiveCfg = Release|x64
 		{493C7729-2F21-4198-AB09-BDF56BF501D3}.Release|x64.Build.0 = Release|x64
 		{493C7729-2F21-4198-AB09-BDF56BF501D3}.Release|x86.ActiveCfg = Release|Win32
diff --git a/src/cswinrt/Directory.Build.props b/src/cswinrt/Directory.Build.props
new file mode 100644
index 000000000..a07333970
--- /dev/null
+++ b/src/cswinrt/Directory.Build.props
@@ -0,0 +1,11 @@
+<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" >
+
+    <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
+
+    <ItemDefinitionGroup>
+        <Midl>
+            <AdditionalOptions>%(AdditionalOptions) /D UAC_VERSION=99</AdditionalOptions>
+        </Midl>
+    </ItemDefinitionGroup>
+
+</Project>
diff --git a/src/cswinrt/Directory.Build.targets b/src/cswinrt/Directory.Build.targets
index bdfcec900..1296467d1 100644
--- a/src/cswinrt/Directory.Build.targets
+++ b/src/cswinrt/Directory.Build.targets
@@ -1,5 +1,17 @@
 <Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 
-  <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)../'))" />
+    <PropertyGroup>
+        <MidlRTCopyWinMDToOutputDirectoryDependsOn>$(MidlRTCopyWinMDToOutputDirectoryDependsOn);CopyWinRTInteropWinMD</MidlRTCopyWinMDToOutputDirectoryDependsOn>
+    </PropertyGroup>
+
+    <!--Workaround for MidlRT nupkg expecting project to publish $(RootNamespace).winmd-->
+    <Target Name="CopyWinRTInteropWinMD" Inputs="$(CsWinRTInteropMetadata)" Outputs="$(MidlRTProjectWinMD)">
+        <Copy UseHardlinksIfPossible="$(MidlRTUseHardlinksIfPossible)"
+            SkipUnchangedFiles="$(MidlRTSkipUnchangedFiles)"
+            SourceFiles="$(CsWinRTInteropMetadata)"
+            DestinationFiles="$(MidlRTProjectWinMD)" />
+    </Target>
+
+    <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)../'))" />
 
 </Project>
diff --git a/src/cswinrt/WinRT.Interop.idl b/src/cswinrt/WinRT.Interop.idl
new file mode 100644
index 000000000..3a016cff0
--- /dev/null
+++ b/src/cswinrt/WinRT.Interop.idl
@@ -0,0 +1,182 @@
+// Modern IDL 3.0: https://docs.microsoft.com/en-us/uwp/midl-3/intro
+
+// Note: the projection generated for this metadata should be internal, and only
+// accessed indirectly with the user-friendly wrappers in ComInteropHelpers.cs.
+namespace WinRT.Interop
+{
+    // C#/WinRT provides support for generating internal interface projections
+    [attributeusage(target_interface)]
+    [attributename("ProjectionInternal")]
+    attribute ProjectionInternalAttribute
+    {
+    }
+
+    // C#/WinRT provides a custom mapping of WinRT.Interop.HWND to System.IntPtr
+    struct HWND
+    {
+        Int32 unused;
+    };
+
+    // accountssettingspaneinterop.idl
+#if UAC_VERSION > 2
+    [uuid(D3EE12AD-3865-4362-9746-B75A682DF0E6), ProjectionInternal]
+    interface IAccountsSettingsPaneInterop
+    {
+        Object GetForWindow(
+            HWND appWindow,
+            GUID riid);
+        Object ShowManageAccountsForWindowAsync(
+            HWND appWindow,
+            GUID riid);
+        Object ShowAddAccountForWindowAsync(
+            HWND appWindow,
+            GUID riid);
+    }
+#endif
+
+    // dragdropinterop.idl
+#if UAC_VERSION > 0
+    [uuid(5AD8CBA7-4C01-4DAC-9074-827894292D63), ProjectionInternal]
+    interface IDragDropManagerInterop
+    {
+        Object GetForWindow(
+            HWND hwnd,
+            GUID riid);
+    }
+#endif
+
+    // inputpaneinterop.idl
+#if UAC_VERSION > 2
+    [uuid(75CF2C57-9195-4931-8332-F0B409E916AF), ProjectionInternal]
+    interface IInputPaneInterop
+    {
+        Object GetForWindow(
+            HWND appWindow,
+            GUID riid);
+    }
+#endif
+
+    // PlayToManagerInterop.idl
+#if UAC_VERSION > 0
+    [uuid(24394699-1F2C-4EB3-8CD7-0EC1DA42A540), ProjectionInternal]
+    interface IPlayToManagerInterop
+    {
+        Object GetForWindow(
+            HWND appWindow,
+            GUID riid);
+
+        void ShowPlayToUIForWindow(
+            HWND appWindow);
+    }
+#endif
+
+    // PrintManagerInterop.idl
+#if UAC_VERSION > 0
+    [uuid(c5435a42-8d43-4e7b-a68a-ef311e392087), ProjectionInternal]
+    interface IPrintManagerInterop
+    {
+        Object GetForWindow(
+            HWND appWindow,
+            GUID riid);
+
+        Object ShowPrintUIForWindowAsync(
+            HWND appWindow,
+            GUID riid);
+    }
+#endif
+
+    // RadialControllerInterop.idl
+#if UAC_VERSION > 2
+    [uuid(1B0535C9-57AD-45C1-9D79-AD5C34360513), ProjectionInternal]
+    interface IRadialControllerInterop
+    {
+        Object CreateForWindow(
+            HWND hwnd,
+            GUID riid);
+    }
+#endif
+
+#if UAC_VERSION > 2
+    [uuid(787cdaac-3186-476d-87e4-b9374a7b9970), ProjectionInternal]
+    interface IRadialControllerConfigurationInterop
+    {
+        Object GetForWindow(
+            HWND hwnd,
+            GUID riid);
+    }
+#endif
+
+#if UAC_VERSION > 3
+    [uuid(3D577EFF-4CEE-11E6-B535-001BDC06AB3B), ProjectionInternal]
+    interface IRadialControllerIndependentInputSourceInterop
+    {
+        Object CreateForWindow(
+            HWND hwnd,
+            GUID riid);
+    }
+#endif
+
+    // SpatialInteractionManagerInterop.idl
+    // This interop interface is duplicated by IHolographicSpaceInterop, which has the same IID
+#if UAC_VERSION > 3
+    [uuid(5C4EE536-6A98-4B86-A170-587013D6FD4B), ProjectionInternal]
+    interface ISpatialInteractionManagerInterop
+    {
+        Object GetForWindow(
+            HWND window,
+            GUID riid);
+    }
+#endif
+
+    // SystemMediaTransportControlsInterop.idl
+#if UAC_VERSION > 0
+    [uuid(ddb0472d-c911-4a1f-86d9-dc3d71a95f5a), ProjectionInternal]
+    interface ISystemMediaTransportControlsInterop
+    {
+        Object GetForWindow(
+            HWND appWindow,
+            GUID riid);
+    }
+#endif
+
+    // UIViewSettingsInterop.idl
+#if UAC_VERSION > 0
+    [uuid(3694dbf9-8f68-44be-8ff5-195c98ede8a6), ProjectionInternal]
+    interface IUIViewSettingsInterop
+    {
+        Object GetForWindow(
+            HWND hwnd,
+            GUID riid);
+    }
+#endif
+
+    // UserConsentVerifierInterop.idl
+#if UAC_VERSION > 4
+    [uuid(39E050C3-4E74-441A-8DC0-B81104DF949C), ProjectionInternal]
+    interface IUserConsentVerifierInterop
+    {
+        Object RequestVerificationForWindowAsync(
+            HWND appWindow,
+            String message,
+            GUID riid);
+    }
+#endif
+
+    // WebAuthenticationCoreManagerInterop.idl
+#if UAC_VERSION > 0
+    [uuid(F4B8E804-811E-4436-B69C-44CB67B72084), ProjectionInternal]
+    interface IWebAuthenticationCoreManagerInterop
+    {
+        Object RequestTokenForWindowAsync(
+            HWND appWindow,
+            Windows.Security.Authentication.Web.Core.WebTokenRequest request, 
+            GUID riid); // __uuidof(IAsyncOperation<WebTokenRequestResult*>)    
+
+        Object RequestTokenWithWebAccountForWindowAsync(
+            HWND appWindow,
+            Windows.Security.Authentication.Web.Core.WebTokenRequest request,
+            Windows.Security.Credentials.WebAccount webAccount,
+            GUID riid); // __uuidof(IAsyncOperation<WebTokenRequestResult*>)
+    }
+#endif
+}
\ No newline at end of file
diff --git a/src/cswinrt/code_writers.h b/src/cswinrt/code_writers.h
index c0b190a86..193e7c0d0 100644
--- a/src/cswinrt/code_writers.h
+++ b/src/cswinrt/code_writers.h
@@ -1468,8 +1468,9 @@ remove => %.% -= value;
         {
             auto [attribute_namespace, attribute_name] = attribute.TypeNamespaceAndName();
             attribute_name = attribute_name.substr(0, attribute_name.length() - "Attribute"sv.length());
-            // GCPressure, Guid, Flags are handled separately
-            if (attribute_name == "GCPressure" || attribute_name == "Guid" || attribute_name == "Flags") continue;
+            // GCPressure, Guid, Flags, ProjectionInternal are handled separately
+            if (attribute_name == "GCPressure" || attribute_name == "Guid" || 
+                attribute_name == "Flags" || attribute_name == "ProjectionInternal") continue;
             auto attribute_full = (attribute_name == "AttributeUsage") ? "AttributeUsage" :
                 w.write_temp("%.%", attribute_namespace, attribute_name);
             auto signature = attribute.Value();
@@ -2514,10 +2515,11 @@ db_path.stem().string());
 
     void write_static_class(writer& w, TypeDef const& type)
     {
-        w.write(R"(%public static class %
+        w.write(R"(%%public static class %
 {
 %})",
             bind<write_winrt_attribute>(type),
+            bind<write_type_custom_attributes>(type, true),
             bind<write_type_name>(type, typedef_name_type::Projected, false),
             bind<write_attributed_types>(type)
         );
@@ -4909,7 +4911,7 @@ IInspectableVftbl = global::WinRT.IInspectable.Vftbl.AbiToProjectionVftable,
             bind<write_winrt_attribute>(type),
             bind<write_guid_attribute>(type),
             bind<write_type_custom_attributes>(type, false),
-            is_exclusive_to(type) ? "internal" : "public",
+            is_exclusive_to(type) || is_projection_internal(type) ? "internal" : "public",
             type_name,
             bind<write_type_inheritance>(type, object_type{}, false, false),
             bind<write_interface_member_signatures>(type)
@@ -6452,7 +6454,7 @@ bind<write_type_name>(type, typedef_name_type::CCW, true)
             {
                 std::vector<std::string> genericArgs;
                 auto arg_count = std::get<generic_type_instance>(eventTypeSemantics).generic_args.size();
-                for (int i = 0; i < arg_count; i++)
+                for (int i = 0; i < arg_count; ++i )
                 {
                     auto semantics = w.get_generic_arg_scope(i).first;
                     if (std::holds_alternative<generic_type_param>(semantics))
diff --git a/src/cswinrt/cswinrt.vcxproj b/src/cswinrt/cswinrt.vcxproj
index 8303e61f6..674c12582 100644
--- a/src/cswinrt/cswinrt.vcxproj
+++ b/src/cswinrt/cswinrt.vcxproj
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\packages\Microsoft.Windows.MidlRT.2.0.200924.1\build\native\Microsoft.Windows.MidlRT.props" Condition="Exists('..\packages\Microsoft.Windows.MidlRT.2.0.200924.1\build\native\Microsoft.Windows.MidlRT.props')" />
   <Import Project="..\packages\Microsoft.Windows.WinMD.1.0.191022.1\build\native\Microsoft.Windows.WinMD.props" Condition="Exists('..\packages\Microsoft.Windows.WinMD.1.0.191022.1\build\native\Microsoft.Windows.WinMD.props')" />
   <PropertyGroup Label="Globals">
     <VCProjectVersion>15.0</VCProjectVersion>
@@ -69,6 +70,7 @@
     <ResourceCompile Include="version.rc" />
   </ItemGroup>
   <ItemGroup>
+    <None Include="Directory.Build.props" />
     <None Include="Directory.Build.targets" />
     <None Include="packages.config" />
     <None Include="PreviousPlatforms.linq" />
@@ -108,15 +110,23 @@
     <None Include="strings\additions\Microsoft.UI.Xaml\Microsoft.UI.Xaml.cs" />
     <None Include="strings\additions\Microsoft.UI.Xaml\Microsoft.UI.Xaml.SR.cs" />
     <None Include="strings\additions\Windows.UI\Windows.UI.cs" />
+    <None Include="strings\ComInteropHelpers.cs" />
     <None Include="strings\WinRT.cs" />
     <None Include="strings\WinRT_Interop.cs" />
   </ItemGroup>
+  <ItemGroup>
+    <Midl Include="WinRT.Interop.idl" />
+  </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets" />
+  <ImportGroup Label="ExtensionTargets">
+    <Import Project="..\packages\Microsoft.Windows.MidlRT.2.0.200924.1\build\native\Microsoft.Windows.MidlRT.targets" Condition="Exists('..\packages\Microsoft.Windows.MidlRT.2.0.200924.1\build\native\Microsoft.Windows.MidlRT.targets')" />
+  </ImportGroup>
   <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
     <PropertyGroup>
       <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}.</ErrorText>
     </PropertyGroup>
     <Error Condition="!Exists('..\packages\Microsoft.Windows.WinMD.1.0.191022.1\build\native\Microsoft.Windows.WinMD.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.WinMD.1.0.191022.1\build\native\Microsoft.Windows.WinMD.props'))" />
+    <Error Condition="!Exists('..\packages\Microsoft.Windows.MidlRT.2.0.200924.1\build\native\Microsoft.Windows.MidlRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.MidlRT.2.0.200924.1\build\native\Microsoft.Windows.MidlRT.props'))" />
+    <Error Condition="!Exists('..\packages\Microsoft.Windows.MidlRT.2.0.200924.1\build\native\Microsoft.Windows.MidlRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Windows.MidlRT.2.0.200924.1\build\native\Microsoft.Windows.MidlRT.targets'))" />
   </Target>
 </Project>
\ No newline at end of file
diff --git a/src/cswinrt/cswinrt.vcxproj.filters b/src/cswinrt/cswinrt.vcxproj.filters
index 54b0f08fc..57e31721d 100644
--- a/src/cswinrt/cswinrt.vcxproj.filters
+++ b/src/cswinrt/cswinrt.vcxproj.filters
@@ -170,5 +170,12 @@
     </None>
     <None Include="Directory.Build.targets" />
     <None Include="PreviousPlatforms.linq" />
+    <None Include="Directory.Build.props" />
+    <None Include="strings\ComInteropHelpers.cs">
+      <Filter>strings</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <Midl Include="WinRT.Interop.idl" />
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/src/cswinrt/helpers.h b/src/cswinrt/helpers.h
index 04c2a262b..e95e2cdd6 100644
--- a/src/cswinrt/helpers.h
+++ b/src/cswinrt/helpers.h
@@ -38,6 +38,11 @@ namespace cswinrt
         return get_category(type) == category::interface_type && has_attribute(type, "Windows.Foundation.Metadata"sv, "ExclusiveToAttribute"sv);
     }
 
+    bool is_projection_internal(TypeDef const& type)
+    {
+        return has_attribute(type, "WinRT.Interop"sv, "ProjectionInternalAttribute"sv);
+    }
+
     bool is_flags_enum(TypeDef const& type)
     {
         return get_category(type) == category::enum_type && has_attribute(type, "System"sv, "FlagsAttribute"sv);
@@ -557,6 +562,12 @@ namespace cswinrt
                     { "Matrix3DHelper" },
                 }
             },
+            { "WinRT.Interop",
+                {
+                    { "HWND", "System", "IntPtr" },
+                    { "ProjectionInternalAttribute" },
+                }
+            },
             { "Windows.Foundation",
                 {
                     { "DateTime", "System", "DateTimeOffset", true },
diff --git a/src/cswinrt/main.cpp b/src/cswinrt/main.cpp
index 1a4254304..e700b4a2a 100644
--- a/src/cswinrt/main.cpp
+++ b/src/cswinrt/main.cpp
@@ -342,6 +342,10 @@ Where <spec> is one or more of:
             {
                 for (auto&& string : strings::base)
                 {
+                    if (std::string(string.name) == "ComInteropHelpers" && !settings.filter.includes("Windows"))
+                    {
+                        continue;
+                    }
                     writer ws;
                     ws.write("// This file was generated by cswinrt.exe version %", VERSION_STRING);
                     ws.write(string.value);
diff --git a/src/cswinrt/packages.config b/src/cswinrt/packages.config
index fd4cca025..293ccb4f7 100644
--- a/src/cswinrt/packages.config
+++ b/src/cswinrt/packages.config
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
-  <package id="Microsoft.Windows.WinMD" version="1.0.191022.1" targetFramework="native" />
-</packages>
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="Microsoft.Windows.MidlRT" version="2.0.200924.1" targetFramework="native" />
+  <package id="Microsoft.Windows.WinMD" version="1.0.191022.1" targetFramework="native" />
+</packages>
\ No newline at end of file
diff --git a/src/cswinrt/strings/ComInteropHelpers.cs b/src/cswinrt/strings/ComInteropHelpers.cs
new file mode 100644
index 000000000..cf417b398
--- /dev/null
+++ b/src/cswinrt/strings/ComInteropHelpers.cs
@@ -0,0 +1,343 @@
+#if UAC_VERSION_13
+#define UAC_VERSION_12
+#endif
+#if UAC_VERSION_12
+#define UAC_VERSION_11
+#endif
+#if UAC_VERSION_11
+#define UAC_VERSION_10
+#endif
+#if UAC_VERSION_10
+#define UAC_VERSION_9
+#endif
+#if UAC_VERSION_9
+#define UAC_VERSION_8
+#endif
+#if UAC_VERSION_8
+#define UAC_VERSION_7
+#endif
+#if UAC_VERSION_7
+#define UAC_VERSION_6
+#endif
+#if UAC_VERSION_6
+#define UAC_VERSION_5
+#endif
+#if UAC_VERSION_5
+#define UAC_VERSION_4
+#endif
+#if UAC_VERSION_4
+#define UAC_VERSION_3
+#endif
+#if UAC_VERSION_3
+#define UAC_VERSION_2
+#endif
+#if UAC_VERSION_2
+#define UAC_VERSION_1
+#endif
+#if !UAC_VERSION_1
+#error Unsupported Universal API Contract version
+#endif
+
+using System;
+using System.Runtime.InteropServices;
+using Windows.Foundation;
+using Windows.Security.Credentials;
+using WinRT;
+using WinRT.Interop;
+
+namespace WinRT.Interop
+{
+    [ComImport]
+    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+    [Guid("EECDBF0E-BAE9-4CB6-A68E-9598E1CB57BB")]
+    internal interface IWindowNative
+    {
+        IntPtr WindowHandle { get; }
+    }
+
+    public static class WindowNative
+    {
+        public static IntPtr GetWindowHandle(object target) => target.As<IWindowNative>().WindowHandle;
+    }
+
+    [ComImport]
+    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+    [Guid("3E68D4BD-7135-4D10-8018-9FB6D9F33FA1")]
+    internal interface IInitializeWithWindow
+    {
+        void Initialize(IntPtr hwnd);
+    }
+
+    public static class InitializeWithWindow
+    {
+        public static void Initialize(object target, IntPtr hwnd) => target.As<IInitializeWithWindow>().Initialize(hwnd);
+    }
+}
+
+namespace Windows.ApplicationModel.DataTransfer.DragDrop.Core
+{
+#if UAC_VERSION_1
+#if !NETSTANDARD2_0
+    [global::System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.10240.0")]
+#endif
+    public static class DragDropManagerInterop
+    {
+        private static IDragDropManagerInterop dragDropManagerInterop = CoreDragDropManager.As<IDragDropManagerInterop>();
+        
+        public static CoreDragDropManager GetForWindow(IntPtr appWindow)
+        {
+            Guid iid = GuidGenerator.CreateIID(typeof(ICoreDragDropManager));
+            return (CoreDragDropManager)dragDropManagerInterop.GetForWindow(appWindow, iid);
+        }
+    }
+#endif
+}
+
+namespace Windows.Graphics.Printing
+{
+#if UAC_VERSION_1
+#if !NETSTANDARD2_0
+    [global::System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.10240.0")]
+#endif
+    public static class PrintManagerInterop
+    {
+        private static IPrintManagerInterop printManagerInterop = PrintManager.As<IPrintManagerInterop>();
+
+        public static PrintManager GetForWindow(IntPtr appWindow)
+        {
+            Guid iid = GuidGenerator.CreateIID(typeof(IPrintManager));
+            return (PrintManager)printManagerInterop.GetForWindow(appWindow, iid);
+        }
+
+        public static IAsyncOperation<bool> ShowPrintUIForWindowAsync(IntPtr appWindow)
+        {
+            Guid iid = GuidGenerator.CreateIID(typeof(IAsyncOperation<bool>));
+            return (IAsyncOperation<bool>)printManagerInterop.ShowPrintUIForWindowAsync(appWindow, iid);
+        }
+    }
+#endif
+}
+
+namespace Windows.Media
+{
+#if UAC_VERSION_1
+#if !NETSTANDARD2_0
+    [global::System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.10240.0")]
+#endif
+    public static class SystemMediaTransportControlsInterop
+    {
+        private static ISystemMediaTransportControlsInterop systemMediaTransportControlsInterop = SystemMediaTransportControls.As<ISystemMediaTransportControlsInterop>();
+
+        public static SystemMediaTransportControls GetForWindow(IntPtr appWindow)
+        {
+            Guid iid = GuidGenerator.CreateIID(typeof(ISystemMediaTransportControls));
+            return (SystemMediaTransportControls)systemMediaTransportControlsInterop.GetForWindow(appWindow, iid);
+        }
+    }
+#endif
+}
+
+namespace Windows.Media.PlayTo
+{
+#if UAC_VERSION_1
+#if !NETSTANDARD2_0
+    [global::System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.10240.0")]
+#endif
+    public static class PlayToManagerInterop
+    {
+        private static IPlayToManagerInterop playToManagerInterop = PlayToManager.As<IPlayToManagerInterop>();
+        
+        public static PlayToManager GetForWindow(IntPtr appWindow)
+        {
+            Guid iid = GuidGenerator.CreateIID(typeof(IPlayToManager));
+            return (PlayToManager)playToManagerInterop.GetForWindow(appWindow, iid);
+        }
+
+        public static void ShowPlayToUIForWindow(IntPtr appWindow)
+        {
+            playToManagerInterop.ShowPlayToUIForWindow(appWindow);
+        }
+    }
+#endif
+}
+
+namespace Windows.Security.Credentials.UI
+{
+#if UAC_VERSION_1
+#if !NETSTANDARD2_0
+    [global::System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.10240.0")]
+#endif
+    public static class UserConsentVerifierInterop
+    {
+        private static IUserConsentVerifierInterop userConsentVerifierInterop = UserConsentVerifier.As<IUserConsentVerifierInterop>();
+
+        public static IAsyncOperation<UserConsentVerificationResult> RequestVerificationForWindowAsync(IntPtr appWindow, string message)
+        {
+            var iid = GuidGenerator.CreateIID(typeof(IAsyncOperation<UserConsentVerificationResult>));
+            return (IAsyncOperation<UserConsentVerificationResult>)userConsentVerifierInterop.RequestVerificationForWindowAsync(appWindow, message, iid);
+        }
+    }
+#endif
+}
+
+namespace Windows.Security.Authentication.Web.Core
+{
+#if UAC_VERSION_1
+#if !NETSTANDARD2_0
+    [global::System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.10240.0")]
+#endif
+    public static class WebAuthenticationCoreManagerInterop
+    {
+        private static IWebAuthenticationCoreManagerInterop webAuthenticationCoreManagerInterop = WebAuthenticationCoreManager.As<IWebAuthenticationCoreManagerInterop>();
+
+        public static IAsyncInfo RequestTokenForWindowAsync(IntPtr appWindow, WebTokenRequest request)
+        {
+            var iid = GuidGenerator.CreateIID(typeof(IAsyncOperation<WebTokenRequestResult>));
+            return (IAsyncInfo)webAuthenticationCoreManagerInterop.RequestTokenForWindowAsync(appWindow, request, iid);
+        }
+
+        public static IAsyncInfo RequestTokenWithWebAccountForWindowAsync(IntPtr appWindow, WebTokenRequest request, WebAccount webAccount)
+        {
+            var iid = GuidGenerator.CreateIID(typeof(IAsyncOperation<WebTokenRequestResult>));
+            return (IAsyncInfo)webAuthenticationCoreManagerInterop.RequestTokenWithWebAccountForWindowAsync(appWindow, request, webAccount, iid);
+        }
+    }
+#endif
+}
+
+namespace Windows.UI.ApplicationSettings
+{
+#if UAC_VERSION_1
+#if !NETSTANDARD2_0
+    [global::System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.10240.0")]
+#endif
+    public static class AccountsSettingsPaneInterop
+    {
+        private static IAccountsSettingsPaneInterop accountsSettingsPaneInterop = AccountsSettingsPane.As<IAccountsSettingsPaneInterop>();
+
+        public static AccountsSettingsPane GetForWindow(IntPtr appWindow)
+        {
+            Guid iid = GuidGenerator.CreateIID(typeof(IAccountsSettingsPane));
+            return (AccountsSettingsPane)accountsSettingsPaneInterop.GetForWindow(appWindow, iid);
+        }
+
+        public static IAsyncAction ShowManageAccountsForWindowAsync(IntPtr appWindow)
+        {
+            Guid iid = GuidGenerator.CreateIID(typeof(IAsyncAction));
+            return (IAsyncAction)accountsSettingsPaneInterop.ShowManageAccountsForWindowAsync(appWindow, iid);
+        }
+
+        public static IAsyncAction ShowAddAccountForWindowAsync(IntPtr appWindow)
+        {
+            Guid iid = GuidGenerator.CreateIID(typeof(IAsyncAction));
+            return (IAsyncAction)accountsSettingsPaneInterop.ShowAddAccountForWindowAsync(appWindow, iid);
+        }
+    }
+#endif
+}
+
+namespace Windows.UI.Input
+{
+#if UAC_VERSION_3
+#if !NETSTANDARD2_0
+    [global::System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.14393.0")]
+#endif
+    public static class RadialControllerConfigurationInterop
+    {
+        private static IRadialControllerConfigurationInterop radialControllerConfigurationInterop 
+            = RadialControllerConfiguration.As<IRadialControllerConfigurationInterop>();
+        
+        public static RadialControllerConfiguration GetForWindow(IntPtr hwnd)
+        {
+            Guid iid = GuidGenerator.CreateIID(typeof(IRadialControllerConfiguration));
+            return (RadialControllerConfiguration)radialControllerConfigurationInterop.GetForWindow(hwnd, iid);
+        }
+    }
+
+#if !NETSTANDARD2_0
+    [global::System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.14393.0")]
+#endif
+    public static class RadialControllerInterop
+    {
+        private static IRadialControllerInterop radialControllerInterop = RadialController.As<IRadialControllerInterop>();
+
+        public static RadialController CreateForWindow(IntPtr hwnd)
+        {
+            Guid iid = GuidGenerator.CreateIID(typeof(IRadialController));
+            return (RadialController)radialControllerInterop.CreateForWindow(hwnd, iid);
+        }
+    }
+#endif
+}
+
+namespace Windows.UI.Input.Core
+{
+#if UAC_VERSION_4
+#if !NETSTANDARD2_0
+    [global::System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.15063.0")]
+#endif
+    public static class RadialControllerIndependentInputSourceInterop
+    {
+        private static IRadialControllerIndependentInputSourceInterop radialControllerIndependentInputSourceInterop 
+            = RadialControllerIndependentInputSource.As<IRadialControllerIndependentInputSourceInterop>();
+
+        public static RadialControllerIndependentInputSource CreateForWindow(IntPtr hwnd)
+        {
+            Guid iid = GuidGenerator.CreateIID(typeof(IRadialControllerIndependentInputSource));
+            return (RadialControllerIndependentInputSource)radialControllerIndependentInputSourceInterop.CreateForWindow(hwnd, iid);
+        }
+    }
+#endif
+}
+
+namespace Windows.UI.Input.Spatial
+{
+#if UAC_VERSION_2
+#if !NETSTANDARD2_0
+    [global::System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.10586.0")]
+#endif
+    public static class SpatialInteractionManagerInterop
+    {
+        private static ISpatialInteractionManagerInterop spatialInteractionManagerInterop = SpatialInteractionManager.As<ISpatialInteractionManagerInterop>();
+        
+        public static SpatialInteractionManager GetForWindow(IntPtr window)
+        {
+            Guid iid = GuidGenerator.CreateIID(typeof(ISpatialInteractionManager));
+            return (SpatialInteractionManager)spatialInteractionManagerInterop.GetForWindow(window, iid);
+        }
+    }
+#endif
+}
+
+namespace Windows.UI.ViewManagement
+{
+#if UAC_VERSION_1
+#if !NETSTANDARD2_0
+    [global::System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.10240.0")]
+#endif
+    public static class InputPaneInterop
+    {
+        private static IInputPaneInterop inputPaneInterop = InputPane.As<IInputPaneInterop>();
+
+        public static InputPane GetForWindow(IntPtr appWindow)
+        {
+            Guid iid = GuidGenerator.CreateIID(typeof(IInputPane));
+            return (InputPane)inputPaneInterop.GetForWindow(appWindow, iid);
+        }
+    }
+
+#if !NETSTANDARD2_0
+    [global::System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.10240.0")]
+#endif
+    public static class UIViewSettingsInterop
+    {
+        private static IUIViewSettingsInterop uIViewSettingsInterop = UIViewSettings.As<IUIViewSettingsInterop>();
+
+        public static UIViewSettings GetForWindow(IntPtr hwnd)
+        {
+            var iid = GuidGenerator.CreateIID(typeof(IUIViewSettings));
+            return (UIViewSettings)uIViewSettingsInterop.GetForWindow(hwnd, iid);
+        }
+    }
+#endif
+}