ProjectReunion/dev/Common/AppModel.Identity.h

434 строки
15 KiB
C++

// Copyright (c) Microsoft Corporation and Contributors.
// Licensed under the MIT License.
#ifndef __APPMODEL_IDENTITY_H
#define __APPMODEL_IDENTITY_H
#include <appmodel.h>
#include <memory>
#include <stdint.h>
namespace AppModel::Identity
{
inline bool IsPackagedProcess()
{
UINT32 n{};
const auto rc{ ::GetCurrentPackageFullName(&n, nullptr) };
THROW_HR_IF_MSG(HRESULT_FROM_WIN32(rc), (rc != APPMODEL_ERROR_NO_PACKAGE) && (rc != ERROR_INSUFFICIENT_BUFFER), "GetCurrentPackageFullName rc=%d", rc);
return rc == ERROR_INSUFFICIENT_BUFFER;
}
template <typename Tstring>
inline Tstring GetCurrentPackageFullName()
{
WCHAR packageFullName[PACKAGE_FULL_NAME_MAX_LENGTH + 1]{};
UINT32 n{ ARRAYSIZE(packageFullName) };
THROW_IF_WIN32_ERROR(::GetCurrentPackageFullName(&n, packageFullName));
return Tstring{ packageFullName };
}
template <typename Tstring>
inline Tstring GetCurrentPackageFamilyName()
{
WCHAR packageFamilyName[PACKAGE_FAMILY_NAME_MAX_LENGTH + 1]{};
UINT32 n{ ARRAYSIZE(packageFamilyName) };
THROW_IF_WIN32_ERROR(::GetCurrentPackageFamilyName(&n, packageFamilyName));
return Tstring{ packageFamilyName };
}
template <typename Tstring>
inline Tstring GetCurrentApplicationUserModelId()
{
WCHAR applicationUserModelId[APPLICATION_USER_MODEL_ID_MAX_LENGTH]{};
UINT32 n{ ARRAYSIZE(applicationUserModelId) };
THROW_IF_WIN32_ERROR(::GetCurrentApplicationUserModelId(&n, applicationUserModelId));
return Tstring{ applicationUserModelId };
}
constexpr winrt::Windows::System::ProcessorArchitecture GetCurrentArchitecture()
{
#if defined(_M_X64)
return winrt::Windows::System::ProcessorArchitecture::X64;
#elif defined(_M_IX86)
return winrt::Windows::System::ProcessorArchitecture::X86;
#elif defined(_M_ARM64)
return winrt::Windows::System::ProcessorArchitecture::Arm64;
#elif defined(_M_ARM)
return winrt::Windows::System::ProcessorArchitecture::Arm;
#else
# error "Unknown processor architecture"
#endif
}
constexpr PCWSTR GetCurrentArchitectureAsString()
{
#if defined(_M_X64)
return L"x64";
#elif defined(_M_IX86)
return L"x86";
#elif defined(_M_ARM64)
return L"arm64";
#elif defined(_M_ARM)
return L"arm";
#else
# error "Unknown processor architecture"
#endif
}
constexpr PCWSTR GetArchitectureAsString(const std::uint32_t architecture)
{
switch (architecture)
{
case PROCESSOR_ARCHITECTURE_AMD64: return L"x64";
case PROCESSOR_ARCHITECTURE_ARM: return L"arm";
case PROCESSOR_ARCHITECTURE_ARM64: return L"arm64";
case PROCESSOR_ARCHITECTURE_IA32_ON_ARM64: return L"x86onArm64";
case PROCESSOR_ARCHITECTURE_INTEL: return L"x86";
case PROCESSOR_ARCHITECTURE_NEUTRAL: return L"neutral";
case PROCESSOR_ARCHITECTURE_UNKNOWN: return L"unknown";
default: THROW_HR_MSG(E_UNEXPECTED, "Unknown architecture 0x%X", architecture);
}
}
constexpr PCWSTR GetArchitectureAsString(const winrt::Windows::System::ProcessorArchitecture architecture)
{
static_assert(static_cast<int>(winrt::Windows::System::ProcessorArchitecture::Arm) == static_cast<int>(PROCESSOR_ARCHITECTURE_ARM), "winrt::Windows::System::ProcessorArchitecture::Arm != PROCESSOR_ARCHITECTURE_ARM");
static_assert(static_cast<int>(winrt::Windows::System::ProcessorArchitecture::Arm64) == static_cast<int>(PROCESSOR_ARCHITECTURE_ARM64), "winrt::Windows::System::ProcessorArchitecture::Arm64 != PROCESSOR_ARCHITECTURE_ARM64");
static_assert(static_cast<int>(winrt::Windows::System::ProcessorArchitecture::Neutral) == static_cast<int>(PROCESSOR_ARCHITECTURE_NEUTRAL), "winrt::Windows::System::ProcessorArchitecture::Neutral != PROCESSOR_ARCHITECTURE_NEUTRAL");
static_assert(static_cast<int>(winrt::Windows::System::ProcessorArchitecture::Unknown) == static_cast<int>(PROCESSOR_ARCHITECTURE_UNKNOWN), "winrt::Windows::System::ProcessorArchitecture::Unknown != PROCESSOR_ARCHITECTURE_UNKNOWN");
static_assert(static_cast<int>(winrt::Windows::System::ProcessorArchitecture::X64) == static_cast<int>(PROCESSOR_ARCHITECTURE_AMD64), "winrt::Windows::System::ProcessorArchitecture::X64 != PROCESSOR_ARCHITECTURE_AMD64");
static_assert(static_cast<int>(winrt::Windows::System::ProcessorArchitecture::X86) == static_cast<int>(PROCESSOR_ARCHITECTURE_INTEL), "winrt::Windows::System::ProcessorArchitecture::X86 != PROCESSOR_ARCHITECTURE_INTEL");
static_assert(static_cast<int>(winrt::Windows::System::ProcessorArchitecture::X86OnArm64) == static_cast<int>(PROCESSOR_ARCHITECTURE_IA32_ON_ARM64), "winrt::Windows::System::ProcessorArchitecture::X86OnArm64 != PROCESSOR_ARCHITECTURE_IA32_ON_ARM64");
return GetArchitectureAsString(static_cast<std::uint32_t>(architecture));
}
inline winrt::Windows::System::ProcessorArchitecture ParseArchitecture(_In_ PCWSTR architecture)
{
if (CompareStringOrdinal(architecture, -1, L"x64", -1, TRUE) == CSTR_EQUAL)
{
return winrt::Windows::System::ProcessorArchitecture::X64;
}
else if (CompareStringOrdinal(architecture, -1, L"x86", -1, TRUE) == CSTR_EQUAL)
{
return winrt::Windows::System::ProcessorArchitecture::X86;
}
else if (CompareStringOrdinal(architecture, -1, L"arm64", -1, TRUE) == CSTR_EQUAL)
{
return winrt::Windows::System::ProcessorArchitecture::Arm64;
}
else if (CompareStringOrdinal(architecture, -1, L"arm", -1, TRUE) == CSTR_EQUAL)
{
return winrt::Windows::System::ProcessorArchitecture::Arm;
}
else
{
return winrt::Windows::System::ProcessorArchitecture::Unknown;
}
}
constexpr PCWSTR GetCurrentArchitectureAsShortString()
{
#if defined(_M_X64)
return L"x6";
#elif defined(_M_IX86)
return L"x8";
#elif defined(_M_ARM64)
return L"a6";
#elif defined(_M_ARM)
return L"ar";
#else
# error "Unknown processor architecture"
#endif
}
inline winrt::Windows::System::ProcessorArchitecture ParseShortArchitecture(_In_ PCWSTR architecture)
{
if (CompareStringOrdinal(architecture, -1, L"x6", -1, TRUE) == CSTR_EQUAL)
{
return winrt::Windows::System::ProcessorArchitecture::X64;
}
else if (CompareStringOrdinal(architecture, -1, L"x8", -1, TRUE) == CSTR_EQUAL)
{
return winrt::Windows::System::ProcessorArchitecture::X86;
}
else if (CompareStringOrdinal(architecture, -1, L"a6", -1, TRUE) == CSTR_EQUAL)
{
return winrt::Windows::System::ProcessorArchitecture::Arm64;
}
else if (CompareStringOrdinal(architecture, -1, L"ar", -1, TRUE) == CSTR_EQUAL)
{
return winrt::Windows::System::ProcessorArchitecture::Arm;
}
else
{
return winrt::Windows::System::ProcessorArchitecture::Unknown;
}
}
class PackageVersion : public PACKAGE_VERSION
{
public:
PackageVersion(const PackageVersion&) = default;
// Create an instance with the value `major.minor.build.revision`.
PackageVersion(std::uint16_t major, std::uint16_t minor = 0, std::uint16_t build = 0, std::uint16_t revision = 0) :
PACKAGE_VERSION()
{
Major = major;
Minor = minor;
Build = build;
Revision = revision;
}
// Create an instance from a version as a uint64.
PackageVersion(std::uint64_t version = 0)
{
Version = version;
}
template<typename TVersion>
PackageVersion(TVersion const& t) :
PackageVersion(t.Major, t.Minor, t.Build, t.Revision)
{
}
#if defined(WINRT_Windows_ApplicationModel_2_H)
PackageVersion(winrt::Windows::ApplicationModel::PackageVersion packageVersion) :
PACKAGE_VERSION()
{
Major = packageVersion.Major;
Minor = packageVersion.Minor;
Build = packageVersion.Build;
Revision = packageVersion.Revision;
}
#endif // defined(WINRT_Windows_ApplicationModel_2_H)
PackageVersion& operator=(const PackageVersion&) = default;
// Return the version as a uint64.
std::uint64_t ToVersion() const
{
return Version;
}
#if defined(____x_ABI_CWindows_CApplicationModel_CIPackageId_INTERFACE_DEFINED__)
ABI::Windows::ApplicationModel::PackageVersion ToPackageVersion() const
{
return ABI::Windows::ApplicationModel::PackageVersion{ Major, Minor, Build, Revision };
}
#endif // defined(____x_ABI_CWindows_CApplicationModel_CIPackageId_INTERFACE_DEFINED__)
#if defined(WINRT_Windows_ApplicationModel_2_H)
winrt::Windows::ApplicationModel::PackageVersion ToWinrtPackageVersion() const
{
return winrt::Windows::ApplicationModel::PackageVersion{ Major, Minor, Build, Revision };
}
#endif // defined(WINRT_Windows_ApplicationModel_2_H)
#if defined(_XSTRING_)
// Return the string as a formatted value "major.minor.build.revision".
std::wstring ToString() const
{
return ToString(Major, Minor, Build, Revision);
}
static std::wstring ToString(std::uint16_t major, std::uint16_t minor, std::uint16_t build, std::uint16_t revision)
{
#if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 202002L))
return std::format(L"{}.{}.{}.{}", major, minor, build, revision);
#else
return std::to_wstring(major) + L"." + std::to_wstring(minor) + L"." + std::to_wstring(build) + L"." + std::to_wstring(revision);
#endif
}
#endif defined(_XSTRING_)
};
inline bool operator==(const PackageVersion& packageVersion1, const PackageVersion& packageVersion2)
{
return packageVersion1.Version == packageVersion2.Version;
}
inline bool operator!=(const PackageVersion& packageVersion1, const PackageVersion& packageVersion2)
{
return packageVersion1.Version != packageVersion2.Version;
}
inline bool operator<(const PackageVersion& packageVersion1, const PackageVersion& packageVersion2)
{
return packageVersion1.Version < packageVersion2.Version;
}
inline bool operator<=(const PackageVersion& packageVersion1, const PackageVersion& packageVersion2)
{
return packageVersion1.Version <= packageVersion2.Version;
}
inline bool operator>(const PackageVersion& packageVersion1, const PackageVersion& packageVersion2)
{
return packageVersion1.Version > packageVersion2.Version;
}
inline bool operator>=(const PackageVersion& packageVersion1, const PackageVersion& packageVersion2)
{
return packageVersion1.Version >= packageVersion2.Version;
}
inline bool IsValidVersionShortTag(
const std::wstring& versionShortTag)
{
// VersionShortTag must be "" or 1 ASCII letter optionally followed by 1 ASCII digit
if (versionShortTag.empty())
{
return true;
}
const size_t c_maxVersionShortTagLength{ 2 };
const auto versionShortTagLength{ versionShortTag.length() };
if (versionShortTagLength > c_maxVersionShortTagLength)
{
return false;
}
const auto tagPrefix{ versionShortTag[0] };
const auto isTagPrefixALetter{ (('a' <= tagPrefix) && (tagPrefix <= 'z')) ||
(('A' <= tagPrefix) && (tagPrefix <= 'Z')) };
if (!isTagPrefixALetter)
{
return false;
}
if (versionShortTagLength > 1)
{
const auto tagSuffix{ versionShortTag[1] };
const auto isTagSuffixADigit{ ('0' <= tagSuffix) && (tagSuffix <= '9') };
if (!isTagSuffixADigit)
{
return false;
}
}
return true;
}
/// VersionShortTag = VersionTag[0] [+ VersionTag[last] if 0-9]
inline std::wstring GetVersionShortTagFromVersionTag(
PCWSTR versionTag)
{
std::wstring versionShortTag;
if (versionTag && (versionTag[0] != L'\0'))
{
versionShortTag = versionTag[0];
const auto versionTagLength{ wcslen(versionTag) };
if (versionTagLength > 1)
{
auto lastCharInVersionTag{ versionTag[versionTagLength - 1] };
if ((L'0' <= lastCharInVersionTag) && (lastCharInVersionTag <= '9'))
{
versionShortTag += lastCharInVersionTag;
}
}
THROW_HR_IF_MSG(E_INVALIDARG, !IsValidVersionShortTag(versionShortTag.c_str()), "VersionTag=%ls", versionTag);
}
return versionShortTag;
}
/// Package Identity
class PackageIdentity
{
public:
static PackageIdentity FromPackageFullName(PCWSTR packageFullName)
{
PackageIdentity packageIdentity;
UINT32 bufferLength{ sizeof(packageIdentity.m_buffer) };
THROW_IF_WIN32_ERROR(PackageIdFromFullName(packageFullName, PACKAGE_INFORMATION_BASIC, &bufferLength, packageIdentity.m_buffer));
packageIdentity.m_packageId = reinterpret_cast<PACKAGE_ID*>(packageIdentity.m_buffer);
packageIdentity.m_packageFullName = packageFullName;
return packageIdentity;
}
public:
PackageIdentity() = default;
PackageIdentity(PackageIdentity&& other) :
m_packageFullName(std::move(other.m_packageFullName))
{
memcpy(m_buffer, other.m_buffer, sizeof(m_buffer));
m_packageId = reinterpret_cast<PACKAGE_ID*>(m_buffer);
other.m_packageId = nullptr;
memset(other.m_buffer, 0, sizeof(other.m_buffer));
}
~PackageIdentity() = default;
PackageIdentity& operator=(PackageIdentity&& other) noexcept
{
if (this != &other)
{
m_packageFullName = std::move(other.m_packageFullName);
memcpy(m_buffer, other.m_buffer, sizeof(m_buffer));
m_packageId = reinterpret_cast<PACKAGE_ID*>(m_buffer);
other.m_packageId = nullptr;
memset(other.m_buffer, 0, sizeof(other.m_buffer));
}
return *this;
}
const std::wstring& PackageFullName() const
{
return m_packageFullName;
}
PCWSTR Name() const
{
return m_packageId->name;
}
PACKAGE_VERSION Version() const
{
return m_packageId->version;
}
winrt::Windows::System::ProcessorArchitecture Architecture() const
{
return static_cast<winrt::Windows::System::ProcessorArchitecture>(m_packageId->processorArchitecture);
}
PCWSTR ResourceId() const
{
return m_packageId->resourceId;
}
PCWSTR PublisherId() const
{
return m_packageId->publisherId;
}
std::wstring PackageFamilyName() const
{
WCHAR packageFamilyName[PACKAGE_FAMILY_NAME_MAX_LENGTH + 1]{};
UINT32 packageFamilyNameLength{ ARRAYSIZE(packageFamilyName) };
THROW_IF_WIN32_ERROR_MSG(::PackageFamilyNameFromId(m_packageId, &packageFamilyNameLength, packageFamilyName), "%ls", m_packageFullName.c_str());
return packageFamilyName;
}
explicit operator bool() const
{
return m_packageId != nullptr;
}
private:
std::wstring m_packageFullName;
const PACKAGE_ID * m_packageId{};
BYTE m_buffer[sizeof(PACKAGE_ID) + (PACKAGE_NAME_MAX_LENGTH + 1 +
PACKAGE_RESOURCEID_MAX_LENGTH + 1 +
PACKAGE_PUBLISHERID_MAX_LENGTH + 1) * sizeof(WCHAR)]{};
};
template<typename T>
T ToPackageFamilyName(PCWSTR packageFullName)
{
WCHAR packageFamilyName[PACKAGE_FAMILY_NAME_MAX_LENGTH + 1]{};
UINT32 packageFamilyNameLength{ ARRAYSIZE(packageFamilyName) };
THROW_IF_WIN32_ERROR_MSG(::PackageFamilyNameFromFullName(packageFullName, &packageFamilyNameLength, packageFamilyName), "%ls", packageFullName);
return T{ packageFamilyName };
}
}
#endif // __APPMODEL_IDENTITY_H