winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 709416538bd6d2a26346b9e98c5210a2652a412b
parent 71036bdab7a231cc75c2e551be20106b564c7b19
Author: JohnMcPMS <johnmcp@microsoft.com>
Date:   Mon, 30 Mar 2020 14:57:43 -0700

Add a function to check OS version, and leverage it to block installs if MinOSVersion is set and higher than the systems. (#75)


Diffstat:
Msrc/AppInstallerCLI/AppInstallerCLI.vcxproj | 24++++++++++++++++++++++++
Msrc/AppInstallerCLICore/Workflows/InstallFlow.cpp | 22+++++++++++++++++++---
Msrc/AppInstallerCLICore/Workflows/InstallFlow.h | 3+++
Msrc/AppInstallerCLITests/AppInstallerCLITests.vcxproj | 12++++++++++++
Msrc/AppInstallerCLITests/Versions.cpp | 11+++++++++++
Msrc/AppInstallerCommonCore/Public/AppInstallerRuntime.h | 6++++++
Msrc/AppInstallerCommonCore/Runtime.cpp | 34++++++++++++++++++++++++++++++++++
Msrc/AppInstallerSQLiteIndexUtil/AppInstallerSQLiteIndexUtil.vcxproj | 24++++++++++++++++++++++++
Asrc/manifest/shared.manifest | 26++++++++++++++++++++++++++
9 files changed, 159 insertions(+), 3 deletions(-)

diff --git a/src/AppInstallerCLI/AppInstallerCLI.vcxproj b/src/AppInstallerCLI/AppInstallerCLI.vcxproj @@ -136,6 +136,15 @@ <GenerateWindowsMetadata>false</GenerateWindowsMetadata> <AdditionalDependencies Condition="'$(Configuration)'=='Debug'">wininet.lib;shell32.lib;winsqlite3.lib;shlwapi.lib;icuuc.lib;icuin.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies> </Link> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles> + </Manifest> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles> + </Manifest> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles> + </Manifest> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'"> <ClCompile> @@ -143,6 +152,9 @@ <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir);..\AppInstallerCLICore\Public\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <TreatWarningAsError Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</TreatWarningAsError> </ClCompile> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles> + </Manifest> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'"> <ClCompile> @@ -166,6 +178,18 @@ <GenerateWindowsMetadata>false</GenerateWindowsMetadata> <AdditionalDependencies Condition="'$(Configuration)'=='Release'">wininet.lib;shell32.lib;winsqlite3.lib;shlwapi.lib;icuuc.lib;icuin.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies> </Link> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles> + </Manifest> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles> + </Manifest> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles> + </Manifest> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles> + </Manifest> </ItemDefinitionGroup> <ItemGroup> <ClCompile Include="main.cpp" /> diff --git a/src/AppInstallerCLICore/Workflows/InstallFlow.cpp b/src/AppInstallerCLICore/Workflows/InstallFlow.cpp @@ -1,6 +1,5 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - #include "pch.h" #include "InstallFlow.h" #include "ShellExecuteInstallerHandler.h" @@ -28,8 +27,11 @@ namespace AppInstaller::Workflow m_reporterRef.ShowMsg("Found app: " + m_searchResult.Matches[0].Application->GetName()); } - SelectInstaller(); - InstallInternal(); + if (VerifyOSVersion()) + { + SelectInstaller(); + InstallInternal(); + } } void InstallFlow::InstallInternal() @@ -40,6 +42,20 @@ namespace AppInstaller::Workflow installerHandler->Install(); } + bool InstallFlow::VerifyOSVersion() + { + if (!m_manifest.MinOSVersion.empty() && + !Runtime::IsCurrentOSVersionGreaterThanOrEqual(Version(m_manifest.MinOSVersion))) + { + m_reporterRef.Error() << "Cannot install application, as it requires a higher OS version: " << m_manifest.MinOSVersion << std::endl; + return false; + } + else + { + return true; + } + } + std::unique_ptr<InstallerHandlerBase> InstallFlow::GetInstallerHandler() { switch (m_selectedInstaller.InstallerType) diff --git a/src/AppInstallerCLICore/Workflows/InstallFlow.h b/src/AppInstallerCLICore/Workflows/InstallFlow.h @@ -21,6 +21,9 @@ namespace AppInstaller::Workflow protected: void InstallInternal(); + // Verifies the OS version is capable of supporting the application. + bool VerifyOSVersion(); + // Creates corresponding InstallerHandler according to InstallerType virtual std::unique_ptr<InstallerHandlerBase> GetInstallerHandler(); }; diff --git a/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj b/src/AppInstallerCLITests/AppInstallerCLITests.vcxproj @@ -116,6 +116,9 @@ <GenerateWindowsMetadata>false</GenerateWindowsMetadata> <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">wininet.lib;shell32.lib;winsqlite3.lib;shlwapi.lib;icuuc.lib;icuin.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies> </Link> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir)..\manifest\shared.manifest</AdditionalManifestFiles> + </Manifest> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'"> <ClCompile> @@ -126,6 +129,9 @@ <Link> <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">wininet.lib;shell32.lib;winsqlite3.lib;shlwapi.lib;icuuc.lib;icuin.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies> </Link> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\manifest\shared.manifest</AdditionalManifestFiles> + </Manifest> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'"> <ClCompile> @@ -146,6 +152,12 @@ <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">wininet.lib;shell32.lib;winsqlite3.lib;shlwapi.lib;icuuc.lib;icuin.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|x64'">wininet.lib;shell32.lib;winsqlite3.lib;shlwapi.lib;icuuc.lib;icuin.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies> </Link> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir)..\manifest\shared.manifest</AdditionalManifestFiles> + </Manifest> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\manifest\shared.manifest</AdditionalManifestFiles> + </Manifest> </ItemDefinitionGroup> <ItemGroup> <ClInclude Include="pch.h" /> diff --git a/src/AppInstallerCLITests/Versions.cpp b/src/AppInstallerCLITests/Versions.cpp @@ -2,8 +2,10 @@ // Licensed under the MIT License. #include "pch.h" #include "TestCommon.h" +#include <AppInstallerRuntime.h> #include <AppInstallerVersions.h> +using namespace AppInstaller; using namespace AppInstaller::Utility; @@ -136,3 +138,12 @@ TEST_CASE("VersionAndChannelSort", "[versions]") REQUIRE(sortedVAC.GetChannel().ToString() == jumbledVAC.GetChannel().ToString()); } } + +TEST_CASE("MinOsVersion_Check", "[versions]") +{ + // Just verify that we are greater than Win 7 and less than far future Win 10. + // Unfortunately, an unmanifested process will also pass these validations, + // but an unmanifested process also can't use Windows APIs to determine the actual version. + REQUIRE(Runtime::IsCurrentOSVersionGreaterThanOrEqual(Version("6.1"))); + REQUIRE(!Runtime::IsCurrentOSVersionGreaterThanOrEqual(Version("10.0.65535"))); +} diff --git a/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h b/src/AppInstallerCommonCore/Public/AppInstallerRuntime.h @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. #pragma once +#include <AppInstallerVersions.h> + #include <filesystem> #include <memory> #include <string> @@ -29,4 +31,8 @@ namespace AppInstaller::Runtime // Deletes the given setting. void RemoveSetting(std::filesystem::path name); + + // Determines whether the current OS version is >= the given one. + // We treat the given Version struct as a standard 4 part Windows OS version. + bool IsCurrentOSVersionGreaterThanOrEqual(const Utility::Version& version); } diff --git a/src/AppInstallerCommonCore/Runtime.cpp b/src/AppInstallerCommonCore/Runtime.cpp @@ -273,6 +273,40 @@ namespace AppInstaller::Runtime } } + bool IsCurrentOSVersionGreaterThanOrEqual(const Utility::Version& version) + { + DWORD versionParts[3] = {}; + + for (size_t i = 0; i < ARRAYSIZE(versionParts) && i < version.GetParts().size(); ++i) + { + versionParts[i] = static_cast<DWORD>(std::min(static_cast<decltype(version.GetParts()[i].Integer)>(std::numeric_limits<DWORD>::max()), version.GetParts()[i].Integer)); + } + + OSVERSIONINFOEXW osVersionInfo{}; + osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo); + osVersionInfo.dwMajorVersion = versionParts[0]; + osVersionInfo.dwMinorVersion = versionParts[1]; + osVersionInfo.dwBuildNumber = versionParts[2]; + osVersionInfo.wServicePackMajor = 0; + osVersionInfo.wServicePackMinor = 0; + + DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR; + + DWORDLONG conditions = 0; + VER_SET_CONDITION(conditions, VER_MAJORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(conditions, VER_MINORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(conditions, VER_BUILDNUMBER, VER_GREATER_EQUAL); + VER_SET_CONDITION(conditions, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); + VER_SET_CONDITION(conditions, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL); + + BOOL result = VerifyVersionInfoW(&osVersionInfo, mask, conditions); + if (!result) + { + THROW_LAST_ERROR_IF(GetLastError() != ERROR_OLD_WIN_VERSION); + } + return !!result; + } + #ifndef AICLI_DISABLE_TEST_HOOKS void TestHook_ForceContainerPrepend(const std::filesystem::path& prepend) { diff --git a/src/AppInstallerSQLiteIndexUtil/AppInstallerSQLiteIndexUtil.vcxproj b/src/AppInstallerSQLiteIndexUtil/AppInstallerSQLiteIndexUtil.vcxproj @@ -143,6 +143,15 @@ <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">wininet.lib;shell32.lib;winsqlite3.lib;shlwapi.lib;icuuc.lib;icuin.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">wininet.lib;shell32.lib;winsqlite3.lib;shlwapi.lib;icuuc.lib;icuin.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies> </Link> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles> + </Manifest> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles> + </Manifest> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles> + </Manifest> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'"> <ClCompile> @@ -155,6 +164,9 @@ <ModuleDefinitionFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Source.def</ModuleDefinitionFile> <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">wininet.lib;shell32.lib;winsqlite3.lib;shlwapi.lib;icuuc.lib;icuin.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies> </Link> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles> + </Manifest> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'"> <ClCompile> @@ -188,6 +200,18 @@ <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">wininet.lib;shell32.lib;winsqlite3.lib;shlwapi.lib;icuuc.lib;icuin.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|x64'">wininet.lib;shell32.lib;winsqlite3.lib;shlwapi.lib;icuuc.lib;icuin.lib;urlmon.lib;%(AdditionalDependencies)</AdditionalDependencies> </Link> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles> + </Manifest> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles> + </Manifest> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles> + </Manifest> + <Manifest> + <AdditionalManifestFiles Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir)..\manifest\shared.manifest %(AdditionalManifestFiles)</AdditionalManifestFiles> + </Manifest> </ItemDefinitionGroup> <ItemGroup> <ClInclude Include="AppInstallerSQLiteIndexUtil.h" /> diff --git a/src/manifest/shared.manifest b/src/manifest/shared.manifest @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"> + <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> + <application> + <!-- Windows 10 --> + <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> + <!-- Windows 8.1 --> + <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> + <!-- Windows 8 --> + <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> + <!-- Windows 7 --> + <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> + </application> + </compatibility> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> + <security> + <requestedPrivileges> + <requestedExecutionLevel + level="asInvoker" + uiAccess="false" + /> + </requestedPrivileges> + </security> + </trustInfo> +</assembly>+ \ No newline at end of file