From 89c027f55b3e249c950a3fff21324ea47f4e6a90 Mon Sep 17 00:00:00 2001 From: Vitek Karas Date: Wed, 31 Oct 2018 01:24:01 -0700 Subject: [PATCH] Add os supported versions to host (dotnet/core-setup#4700) Add a manifest to dotnet.exe with supported versions of Windows. Also remove any manifest from apphost.exe as it will get the one from the app when it's used. Commit migrated from https://github.com/dotnet/core-setup/commit/16fc8e9125638f24527091a573d9dbe546a1f609 --- src/installer/corehost/cli/apphost/CMakeLists.txt | 7 + src/installer/corehost/cli/dotnet/CMakeLists.txt | 6 + src/installer/corehost/cli/dotnet/dotnet.manifest | 19 +++ .../TestProjects/TestWindowsOsShimsApp/Program.cs | 149 +++++++++++++++++++++ .../TestWindowsOsShimsApp.csproj | 12 ++ .../GivenThatICareAboutWindowsOsShims.cs | 59 ++++++++ 6 files changed, 252 insertions(+) create mode 100644 src/installer/corehost/cli/dotnet/dotnet.manifest create mode 100644 src/installer/test/Assets/TestProjects/TestWindowsOsShimsApp/Program.cs create mode 100644 src/installer/test/Assets/TestProjects/TestWindowsOsShimsApp/TestWindowsOsShimsApp.csproj create mode 100644 src/installer/test/HostActivationTests/GivenThatICareAboutWindowsOsShims.cs diff --git a/src/installer/corehost/cli/apphost/CMakeLists.txt b/src/installer/corehost/cli/apphost/CMakeLists.txt index cc610cd..4dac1f3 100644 --- a/src/installer/corehost/cli/apphost/CMakeLists.txt +++ b/src/installer/corehost/cli/apphost/CMakeLists.txt @@ -26,3 +26,10 @@ include(../exe.cmake) add_definitions(-DFEATURE_APPHOST=1) install_library_and_symbols (apphost) + +# Disable manifest generation into the file .exe on Windows +if(WIN32) + set_property(TARGET ${PROJECT_NAME} PROPERTY + LINK_FLAGS "/MANIFEST:NO" + ) +endif() \ No newline at end of file diff --git a/src/installer/corehost/cli/dotnet/CMakeLists.txt b/src/installer/corehost/cli/dotnet/CMakeLists.txt index 5b3b392..fa666cf 100644 --- a/src/installer/corehost/cli/dotnet/CMakeLists.txt +++ b/src/installer/corehost/cli/dotnet/CMakeLists.txt @@ -6,6 +6,12 @@ project(dotnet) set(DOTNET_HOST_EXE_NAME "dotnet") set(SOURCES ../fxr/fx_ver.cpp) + +if(WIN32) + list(APPEND SOURCES + dotnet.manifest) +endif() + include(../exe.cmake) install_library_and_symbols (dotnet) diff --git a/src/installer/corehost/cli/dotnet/dotnet.manifest b/src/installer/corehost/cli/dotnet/dotnet.manifest new file mode 100644 index 0000000..caf8501 --- /dev/null +++ b/src/installer/corehost/cli/dotnet/dotnet.manifest @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/installer/test/Assets/TestProjects/TestWindowsOsShimsApp/Program.cs b/src/installer/test/Assets/TestProjects/TestWindowsOsShimsApp/Program.cs new file mode 100644 index 0000000..79238ad --- /dev/null +++ b/src/installer/test/Assets/TestProjects/TestWindowsOsShimsApp/Program.cs @@ -0,0 +1,149 @@ +using System; +using System.Runtime.InteropServices; + +namespace TestWindowsOsShimsApp +{ + public static class Program + { + public static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + Console.WriteLine(string.Join(Environment.NewLine, args)); + Console.WriteLine($"Framework Version:{GetFrameworkVersionFromAppDomain()}"); + + #if WINDOWS + Version osVersion = RtlGetVersion(); + if (osVersion == null) + { + Console.WriteLine("Failed to get OS version through RtlGetVersion."); + } + else + { + Console.WriteLine($"Detected true OS version: {osVersion.Major}.{osVersion.Minor}"); + if (OsVersionIsNewerThan(osVersion)) + { + Console.WriteLine($"Reported OS version is newer or equal to the true OS version - no shims."); + } + else + { + Console.WriteLine($"Reported OS version is lower than the true OS version - shims in use."); + } + } + #endif + } + + private static string GetFrameworkVersionFromAppDomain() + { + return System.AppDomain.CurrentDomain.GetData("FX_PRODUCT_VERSION") as string; + } + +#if WINDOWS + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + internal struct OSVERSIONINFOEX + { + + internal uint dwOSVersionInfoSize; + internal uint dwMajorVersion; + internal uint dwMinorVersion; + internal uint dwBuildNumber; + internal uint dwPlatformId; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] // + internal string szCSDVersion; + internal ushort wServicePackMajor; + internal ushort wServicePackMinor; + internal ushort wSuiteMask; + internal byte wProductType; + internal byte wReserved; + } + + [Flags] + enum ConditionMask : byte + { + VER_EQUAL = 1, + VER_GREATER = 2, + VER_GREATER_EQUAL = 3, + VER_LESS = 4, + VER_LESS_EQUAL = 5, + VER_AND = 6, + VER_OR = 7 + } + + [Flags] + enum TypeMask : uint + { + VER_MINORVERSION = 0x0000001, + VER_MAJORVERSION = 0x0000002, + VER_BUILDNUMBER = 0x0000004, + VER_PLATFORMID = 0x0000008, + VER_SERVICEPACKMINOR = 0x0000010, + VER_SERVICEPACKMAJOR = 0x0000020, + VER_SUITENAME = 0x0000040, + VER_PRODUCT_TYPE = 0x0000080 + } + + [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] + internal unsafe struct RTL_OSVERSIONINFOEX + { + internal uint dwOSVersionInfoSize; + internal uint dwMajorVersion; + internal uint dwMinorVersion; + internal uint dwBuildNumber; + internal uint dwPlatformId; + internal fixed char szCSDVersion[128]; + } + + [DllImport("ntdll.dll", ExactSpelling=true)] + private static extern int RtlGetVersion(ref RTL_OSVERSIONINFOEX lpVersionInformation); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool VerifyVersionInfo(ref OSVERSIONINFOEX lpVersionInfo, TypeMask dwTypeMask, ulong dwlConditionMask); + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] + private static extern ulong VerSetConditionMask(ulong dwlConditionMask, TypeMask dwTypeBitMask, ConditionMask dwConditionMask); + + internal unsafe static int RtlGetVersionEx(out RTL_OSVERSIONINFOEX osvi) + { + osvi = new RTL_OSVERSIONINFOEX(); + osvi.dwOSVersionInfoSize = (uint)sizeof(RTL_OSVERSIONINFOEX); + return RtlGetVersion(ref osvi); + } + + internal static Version RtlGetVersion() + { + if (RtlGetVersionEx(out RTL_OSVERSIONINFOEX osvi) == 0) + { + return new Version((int)osvi.dwMajorVersion, (int)osvi.dwMinorVersion); + } + else + { + return null; + } + } + + internal static bool OsVersionIsNewerThan(Version osVersion) + { + // check if newer than + OSVERSIONINFOEX osv = new OSVERSIONINFOEX() + { + dwOSVersionInfoSize = (uint)Marshal.SizeOf(), + dwMajorVersion = (uint)osVersion.Major, + dwMinorVersion = (uint)osVersion.Minor + }; + + var conditionMask = 0uL; + conditionMask = VerSetConditionMask(conditionMask, TypeMask.VER_MAJORVERSION, ConditionMask.VER_GREATER_EQUAL); + conditionMask = VerSetConditionMask(conditionMask, TypeMask.VER_MINORVERSION, ConditionMask.VER_GREATER_EQUAL); + + if (VerifyVersionInfo(ref osv, TypeMask.VER_MAJORVERSION | TypeMask.VER_MINORVERSION, conditionMask)) + { + return true; + } + else + { + return false; + } + } +#endif + } +} diff --git a/src/installer/test/Assets/TestProjects/TestWindowsOsShimsApp/TestWindowsOsShimsApp.csproj b/src/installer/test/Assets/TestProjects/TestWindowsOsShimsApp/TestWindowsOsShimsApp.csproj new file mode 100644 index 0000000..70d4c67 --- /dev/null +++ b/src/installer/test/Assets/TestProjects/TestWindowsOsShimsApp/TestWindowsOsShimsApp.csproj @@ -0,0 +1,12 @@ + + + + $(NETCoreAppFramework) + $(TestTargetRid) + Exe + $(MNAVersion) + WINDOWS;$(DefineConstants) + true + + + diff --git a/src/installer/test/HostActivationTests/GivenThatICareAboutWindowsOsShims.cs b/src/installer/test/HostActivationTests/GivenThatICareAboutWindowsOsShims.cs new file mode 100644 index 0000000..559d987 --- /dev/null +++ b/src/installer/test/HostActivationTests/GivenThatICareAboutWindowsOsShims.cs @@ -0,0 +1,59 @@ +using System; +using System.Runtime.InteropServices; +using Xunit; + +namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.WindowsOsShims +{ + public class GivenThatICareAboutWindowsOsShims : IClassFixture + { + private SharedTestState sharedTestState; + + public GivenThatICareAboutWindowsOsShims(SharedTestState fixture) + { + sharedTestState = fixture; + } + + [Fact] + public void MuxerRunsPortableAppWithoutWindowsOsShims() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // Manifests are only supported on Windows OSes. + return; + } + + TestProjectFixture portableAppFixture = sharedTestState.PortableTestWindowsOsShimsAppFixture.Copy(); + + portableAppFixture.BuiltDotnet.Exec(portableAppFixture.TestProject.AppDll) + .CaptureStdErr() + .CaptureStdOut() + .Execute() + .Should().Pass() + .And.HaveStdOutContaining("Reported OS version is newer or equal to the true OS version - no shims."); + } + + // Testing the standalone version (apphost) would require to make a copy of the entire SDK + // and overwrite the apphost.exe in it. Currently this is just too expensive for one test (160MB of data). + + public class SharedTestState : IDisposable + { + private static RepoDirectoriesProvider RepoDirectories { get; set; } + + public TestProjectFixture PortableTestWindowsOsShimsAppFixture { get; set; } + + public SharedTestState() + { + RepoDirectories = new RepoDirectoriesProvider(); + + PortableTestWindowsOsShimsAppFixture = new TestProjectFixture("TestWindowsOsShimsApp", RepoDirectories) + .EnsureRestored(RepoDirectories.CorehostPackages) + .PublishProject(); + } + + public void Dispose() + { + PortableTestWindowsOsShimsAppFixture.Dispose(); + } + } + } +} -- 2.7.4