Runtime.cpp (7427B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #include "pch.h" 4 #include <binver/version.h> 5 #include "Public/winget/Runtime.h" 6 #include "Public/AppInstallerLogging.h" 7 #include "Public/AppInstallerStrings.h" 8 9 10 namespace AppInstaller::Runtime 11 { 12 using namespace Utility; 13 14 namespace 15 { 16 using namespace std::string_view_literals; 17 constexpr std::string_view s_PreviewBuildSuffix = "-preview"sv; 18 19 // Gets a boolean indicating whether the current process has identity. 20 bool DoesCurrentProcessHaveIdentity() 21 { 22 UINT32 length = 0; 23 LONG result = ::GetPackageFamilyName(GetCurrentProcess(), &length, nullptr); 24 return (result != APPMODEL_ERROR_NO_PACKAGE); 25 } 26 27 std::unique_ptr<byte[]> GetPACKAGE_ID() 28 { 29 UINT32 bufferLength = 0; 30 LONG gcpiResult = GetCurrentPackageId(&bufferLength, nullptr); 31 THROW_HR_IF(E_UNEXPECTED, gcpiResult != ERROR_INSUFFICIENT_BUFFER); 32 33 std::unique_ptr<byte[]> buffer = std::make_unique<byte[]>(bufferLength); 34 35 gcpiResult = GetCurrentPackageId(&bufferLength, buffer.get()); 36 if (FAILED_WIN32_LOG(gcpiResult)) 37 { 38 return {}; 39 } 40 41 return buffer; 42 } 43 44 // Gets the package name; only succeeds if running in a packaged context. 45 std::string GetPackageName() 46 { 47 std::unique_ptr<byte[]> buffer = GetPACKAGE_ID(); 48 if (!buffer) 49 { 50 return {}; 51 } 52 53 PACKAGE_ID* packageId = reinterpret_cast<PACKAGE_ID*>(buffer.get()); 54 return Utility::ConvertToUTF8(packageId->name); 55 } 56 57 // Gets the package version; only succeeds if running in a packaged context. 58 std::optional<PACKAGE_VERSION> GetPACKAGE_VERSION() 59 { 60 std::unique_ptr<byte[]> buffer = GetPACKAGE_ID(); 61 if (!buffer) 62 { 63 return {}; 64 } 65 66 PACKAGE_ID* packageId = reinterpret_cast<PACKAGE_ID*>(buffer.get()); 67 return packageId->version; 68 } 69 } 70 71 bool IsRunningInPackagedContext() 72 { 73 static bool result = DoesCurrentProcessHaveIdentity(); 74 return result; 75 } 76 77 LocIndString GetClientVersion() 78 { 79 std::ostringstream strstr; 80 strstr << VERSION_MAJOR << '.' << VERSION_MINOR << '.' << VERSION_BUILD; 81 82 if (!IsReleaseBuild()) 83 { 84 strstr << s_PreviewBuildSuffix; 85 } 86 87 return LocIndString{ strstr.str() }; 88 } 89 90 std::wstring GetPackageFamilyName() 91 { 92 UINT32 length = 0; 93 LONG returnValue = ::GetPackageFamilyName(GetCurrentProcess(), &length, nullptr); 94 95 if (returnValue == APPMODEL_ERROR_NO_PACKAGE) 96 { 97 return {}; 98 } 99 100 if (returnValue != ERROR_INSUFFICIENT_BUFFER) 101 { 102 THROW_IF_WIN32_ERROR(returnValue); 103 } 104 105 std::wstring result(length, '\0'); 106 returnValue = ::GetPackageFamilyName(GetCurrentProcess(), &length, &result[0]); 107 THROW_IF_WIN32_ERROR(returnValue); 108 THROW_HR_IF(E_UNEXPECTED, length == 0); 109 110 result.resize(length - 1); 111 return result; 112 } 113 114 LocIndString GetPackageVersion() 115 { 116 using namespace std::string_literals; 117 118 if (IsRunningInPackagedContext()) 119 { 120 auto version = GetPACKAGE_VERSION(); 121 122 if (!version) 123 { 124 // In the extremely unlikely event of a failure, this is merely a sentinel value 125 // to indicated such. The only other option is to completely prevent execution, 126 // which seems unnecessary. 127 return LocIndString{ "error"sv }; 128 } 129 130 std::ostringstream strstr; 131 strstr << GetPackageName() << " v" << version->Major << '.' << version->Minor << '.' << version->Build << '.' << version->Revision; 132 133 return LocIndString{ strstr.str() }; 134 } 135 else 136 { 137 // Calling code should avoid calling in when this is the case. 138 return LocIndString{ "none"sv }; 139 } 140 } 141 142 LocIndString GetOSVersion() 143 { 144 winrt::Windows::System::Profile::AnalyticsInfo analyticsInfo{}; 145 auto versionInfo = analyticsInfo.VersionInfo(); 146 147 uint64_t version = std::stoull(Utility::ConvertToUTF8(versionInfo.DeviceFamilyVersion())); 148 uint16_t parts[4]; 149 150 for (size_t i = 0; i < ARRAYSIZE(parts); ++i) 151 { 152 parts[i] = version & 0xFFFF; 153 version = version >> 16; 154 } 155 156 std::ostringstream strstr; 157 strstr << Utility::ConvertToUTF8(versionInfo.DeviceFamily()) << " v" << parts[3] << '.' << parts[2] << '.' << parts[1] << '.' << parts[0]; 158 159 return LocIndString{ strstr.str() }; 160 } 161 162 std::string GetOSRegion() 163 { 164 winrt::Windows::Globalization::GeographicRegion region; 165 return Utility::ConvertToUTF8(region.CodeTwoLetter()); 166 } 167 168 bool IsCurrentOSVersionGreaterThanOrEqual(const Utility::Version& version) 169 { 170 DWORD versionParts[3] = {}; 171 172 for (size_t i = 0; i < ARRAYSIZE(versionParts) && i < version.GetParts().size(); ++i) 173 { 174 versionParts[i] = static_cast<DWORD>(std::min(static_cast<decltype(version.GetParts()[i].Integer)>(std::numeric_limits<DWORD>::max()), version.GetParts()[i].Integer)); 175 } 176 177 OSVERSIONINFOEXW osVersionInfo{}; 178 osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo); 179 osVersionInfo.dwMajorVersion = versionParts[0]; 180 osVersionInfo.dwMinorVersion = versionParts[1]; 181 osVersionInfo.dwBuildNumber = versionParts[2]; 182 osVersionInfo.wServicePackMajor = 0; 183 osVersionInfo.wServicePackMinor = 0; 184 185 DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR; 186 187 DWORDLONG conditions = 0; 188 VER_SET_CONDITION(conditions, VER_MAJORVERSION, VER_GREATER_EQUAL); 189 VER_SET_CONDITION(conditions, VER_MINORVERSION, VER_GREATER_EQUAL); 190 VER_SET_CONDITION(conditions, VER_BUILDNUMBER, VER_GREATER_EQUAL); 191 VER_SET_CONDITION(conditions, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); 192 VER_SET_CONDITION(conditions, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL); 193 194 BOOL result = VerifyVersionInfoW(&osVersionInfo, mask, conditions); 195 if (!result) 196 { 197 THROW_LAST_ERROR_IF(GetLastError() != ERROR_OLD_WIN_VERSION); 198 } 199 return !!result; 200 } 201 202 bool IsRunningAsAdmin() 203 { 204 return wil::test_token_membership(nullptr, SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS); 205 } 206 207 bool IsRunningAsSystem() 208 { 209 return wil::test_token_membership(nullptr, SECURITY_NT_AUTHORITY, SECURITY_LOCAL_SYSTEM_RID); 210 } 211 212 bool IsRunningAsAdminOrSystem() 213 { 214 return IsRunningAsAdmin() || IsRunningAsSystem(); 215 } 216 217 bool IsRunningWithLimitedToken() 218 { 219 return wil::get_token_information<TOKEN_ELEVATION_TYPE>() == TokenElevationTypeLimited; 220 } 221 }