WindowsAppSDK/dev/Common/WindowsAppRuntime.VersionIn...

146 строки
5.5 KiB
C++

// Copyright (c) Microsoft Corporation and Contributors.
// Licensed under the MIT License.
#include "pch.h"
#include <Microsoft.Utf8.h>
#include "WindowsAppRuntime.VersionInfo.h"
// Function prototype of the function exported by the resource DLL
// (defined later in the build pipeline so we can't #include a header from there)
STDAPI_(const void*) WindowsAppRuntime_GetVersionInfo();
static std::wstring g_test_frameworkPackageFamilyName;
static std::wstring g_test_mainPackageFamilyName;
static std::atomic<const ::Microsoft::WindowsAppSDK::VersionInfo*> g_versionInfo{};
static const ::Microsoft::WindowsAppSDK::VersionInfo c_noVersionInfo{};
namespace Microsoft::WindowsAppRuntime::VersionInfo
{
class RuntimeInformation
{
public:
static const std::wstring& GetFrameworkPackageFamilyName()
{
if (!g_test_frameworkPackageFamilyName.empty())
{
return g_test_frameworkPackageFamilyName;
}
const uint32_t c_frameworkPackageFamilyNameResourceId{ 10002 };
static std::wstring frameworkPackageFamilyName{ LoadStringWFromResource(c_frameworkPackageFamilyNameResourceId) };
return frameworkPackageFamilyName;
}
static const std::wstring& GetMainPackageFamilyName()
{
if (!g_test_mainPackageFamilyName.empty())
{
return g_test_mainPackageFamilyName;
}
const uint32_t c_mainPackageFamilyNameResourceId{ 10002 };
static std::wstring mainPackageFamilyName{ LoadStringWFromResource(c_mainPackageFamilyNameResourceId) };
return mainPackageFamilyName;
}
public:
static const ::Microsoft::WindowsAppSDK::VersionInfo* GetVersionInfo()
{
if (!g_versionInfo)
{
static wil::unique_hmodule module{ LoadResourceModule() };
auto getVersionInfo{ GetProcAddressByFunctionDeclaration(module.get(), WindowsAppRuntime_GetVersionInfo) };
THROW_LAST_ERROR_IF_NULL(getVersionInfo);
g_versionInfo = static_cast<const ::Microsoft::WindowsAppSDK::VersionInfo*>(getVersionInfo());
}
return g_versionInfo;
}
private:
static std::wstring LoadStringWFromResource(uint32_t id)
{
const auto string{ LoadStringAFromResource(id) };
return ::Microsoft::Utf8::ToUtf16<std::wstring>(string.c_str());
}
static std::string LoadStringAFromResource(uint32_t id)
{
static wil::unique_hmodule module{ LoadResourceModule() };
const uint32_t c_ResourceMaxLength{ 1024 };
char resourceValue[c_ResourceMaxLength]{};
const auto resourceValueLength{ ::LoadStringA(module.get(), id, resourceValue, ARRAYSIZE(resourceValue)) };
THROW_LAST_ERROR_IF_MSG(resourceValueLength == 0, "Failed to load resource string. id: %u", id);
return resourceValue;
}
static wil::unique_hmodule LoadResourceModule()
{
const PCWSTR c_resourceDllName{ L"Microsoft.WindowsAppRuntime.Insights.Resource.dll" };
wil::unique_hmodule resourceDllHandle(::LoadLibraryW(c_resourceDllName));
THROW_LAST_ERROR_IF_NULL_MSG(resourceDllHandle, "Unable to load resource dll. %ls", c_resourceDllName);
return resourceDllHandle;
}
};
}
STDAPI WindowsAppRuntime_VersionInfo_MSIX_Framework_PackageFamilyName_Get(
PCWSTR* packageFamilyName) noexcept try
{
*packageFamilyName = nullptr;
const auto& frameworkPackageFamilyName{ ::Microsoft::WindowsAppRuntime::VersionInfo::RuntimeInformation::GetFrameworkPackageFamilyName() };
*packageFamilyName = frameworkPackageFamilyName.c_str();
RETURN_HR_IF_MSG(E_UNEXPECTED, frameworkPackageFamilyName.empty(), "WindowsAppSDK framework PackageFamilyName resource not valid (\"\")");
return S_OK;
}
CATCH_RETURN();
STDAPI WindowsAppRuntime_VersionInfo_MSIX_Main_PackageFamilyName_Get(
PCWSTR* packageFamilyName) noexcept try
{
*packageFamilyName = nullptr;
const auto& mainPackageFamilyName{ ::Microsoft::WindowsAppRuntime::VersionInfo::RuntimeInformation::GetMainPackageFamilyName() };
*packageFamilyName = mainPackageFamilyName.c_str();
RETURN_HR_IF_MSG(E_UNEXPECTED, mainPackageFamilyName.empty(), "WindowsAppSDK main PackageFamilyName resource not valid (\"\")");
return S_OK;
}
CATCH_RETURN();
STDAPI WindowsAppRuntime_VersionInfo_TestInitialize(
PCWSTR frameworkPackageFamilyName,
PCWSTR mainPackageFamilyName) noexcept try
{
// Both or neither must be valued
const bool frameworkPackageFamilyNameIsEmpty{ !frameworkPackageFamilyName || (*frameworkPackageFamilyName == L'0') };
const bool mainPackageFamilyNameIsEmpty{ !mainPackageFamilyName || (*mainPackageFamilyName == L'0') };
FAIL_FAST_HR_IF(E_UNEXPECTED, frameworkPackageFamilyNameIsEmpty && !mainPackageFamilyNameIsEmpty);
FAIL_FAST_HR_IF(E_UNEXPECTED, !frameworkPackageFamilyNameIsEmpty && mainPackageFamilyNameIsEmpty);
// Update our state
if (frameworkPackageFamilyNameIsEmpty)
{
// Shutdown test support
g_test_frameworkPackageFamilyName.clear();
g_test_mainPackageFamilyName.clear();
}
else
{
// Initialize test support
g_test_frameworkPackageFamilyName = frameworkPackageFamilyName;
g_test_mainPackageFamilyName = mainPackageFamilyName;
}
return S_OK;
}
CATCH_RETURN();
const ::Microsoft::WindowsAppSDK::VersionInfo* Microsoft::WindowsAppSDK::GetVersionInfo()
{
const auto versionInfo{ ::Microsoft::WindowsAppRuntime::VersionInfo::RuntimeInformation::GetVersionInfo() };
return !versionInfo ? &c_noVersionInfo : versionInfo;
}