#pragma once
#include "xr_dependencies.h"
#include <string>
#include <stdint.h>
#include <stdlib.h>
#define OPENXR_RELATIVE_PATH …
#define OPENXR_IMPLICIT_API_LAYER_RELATIVE_PATH …
#define OPENXR_EXPLICIT_API_LAYER_RELATIVE_PATH …
#ifdef XR_OS_WINDOWS
#define OPENXR_REGISTRY_LOCATION …
#define OPENXR_IMPLICIT_API_LAYER_REGISTRY_LOCATION …
#define OPENXR_EXPLICIT_API_LAYER_REGISTRY_LOCATION …
#endif
#define OPENXR_RUNTIME_JSON_ENV_VAR …
#define OPENXR_API_LAYER_PATH_ENV_VAR …
#ifdef OPENXR_HAVE_COMMON_CONFIG
#include "common_config.h"
#endif
#if defined(__x86_64__) && defined(__ILP32__)
#define XR_ARCH_ABI …
#elif defined(_M_X64) || defined(__x86_64__)
#define XR_ARCH_ABI …
#elif defined(_M_IX86) || defined(__i386__) || defined(_X86_)
#define XR_ARCH_ABI …
#elif (defined(__aarch64__) && defined(__LP64__)) || defined(_M_ARM64)
#define XR_ARCH_ABI …
#elif (defined(__ARM_ARCH) && __ARM_ARCH >= 7 && (defined(__ARM_PCS_VFP) || defined(__ANDROID__))) || defined(_M_ARM)
#define XR_ARCH_ABI …
#elif defined(__ARM_ARCH_5TE__) || (defined(__ARM_ARCH) && __ARM_ARCH > 5)
#define XR_ARCH_ABI …
#elif defined(__mips64)
#define XR_ARCH_ABI …
#elif defined(__mips)
#define XR_ARCH_ABI …
#elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define XR_ARCH_ABI …
#elif defined(__powerpc__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define XR_ARCH_ABI …
#elif defined(__s390x__) || defined(__zarch__)
#define XR_ARCH_ABI …
#elif defined(__hppa__)
#define XR_ARCH_ABI …
#elif defined(__alpha__)
#define XR_ARCH_ABI …
#elif defined(__ia64__) || defined(_M_IA64)
#define XR_ARCH_ABI …
#elif defined(__m68k__)
#define XR_ARCH_ABI …
#elif defined(__riscv_xlen) && (__riscv_xlen == 64)
#define XR_ARCH_ABI …
#elif defined(__sparc__) && defined(__arch64__)
#define XR_ARCH_ABI …
#else
#error "No architecture string known!"
#endif
void LogPlatformUtilsError(const std::string& message);
#if defined(XR_OS_LINUX) || defined(XR_OS_APPLE)
#include <unistd.h>
#include <fcntl.h>
#include <iostream>
#include <sys/stat.h>
namespace detail {
static inline char* ImplGetEnv(const char* name) { … }
static inline char* ImplGetSecureEnv(const char* name) { … }
}
#endif
#if defined(XR_OS_ANDROID) || defined(XR_OS_APPLE)
#include <sys/stat.h>
namespace detail {
static inline bool ImplTryRuntimeFilename(const char* rt_dir_prefix, uint16_t major_version, std::string& file_name) {
auto decorated_path = rt_dir_prefix + std::to_string(major_version) + "/active_runtime." XR_ARCH_ABI ".json";
auto undecorated_path = rt_dir_prefix + std::to_string(major_version) + "/active_runtime.json";
struct stat buf {};
if (0 == stat(decorated_path.c_str(), &buf)) {
file_name = decorated_path;
return true;
}
if (0 == stat(undecorated_path.c_str(), &buf)) {
file_name = undecorated_path;
return true;
}
return false;
}
}
#endif
#if defined(XR_OS_LINUX)
static inline std::string PlatformUtilsGetEnv(const char* name) { … }
static inline std::string PlatformUtilsGetSecureEnv(const char* name) { … }
static inline bool PlatformUtilsGetEnvSet(const char* name) { … }
#elif defined(XR_OS_APPLE)
static inline std::string PlatformUtilsGetEnv(const char* name) {
auto str = detail::ImplGetEnv(name);
if (str == nullptr) {
return {};
}
return str;
}
static inline std::string PlatformUtilsGetSecureEnv(const char* name) {
auto str = detail::ImplGetSecureEnv(name);
if (str == nullptr) {
return {};
}
return str;
}
static inline bool PlatformUtilsGetEnvSet(const char* name) { return detail::ImplGetEnv(name) != nullptr; }
static inline bool PlatformGetGlobalRuntimeFileName(uint16_t major_version, std::string& file_name) {
return detail::ImplTryRuntimeFilename("/usr/local/share/openxr/", major_version, file_name);
}
#elif defined(XR_OS_WINDOWS)
inline std::wstring utf8_to_wide(const std::string& utf8Text) {
if (utf8Text.empty()) {
return {};
}
std::wstring wideText;
const int wideLength = ::MultiByteToWideChar(CP_UTF8, 0, utf8Text.data(), (int)utf8Text.size(), nullptr, 0);
if (wideLength == 0) {
LogPlatformUtilsError("utf8_to_wide get size error: " + std::to_string(::GetLastError()));
return {};
}
wideText.resize(wideLength, 0);
wchar_t* wideString = const_cast<wchar_t*>(wideText.data());
const int length = ::MultiByteToWideChar(CP_UTF8, 0, utf8Text.data(), (int)utf8Text.size(), wideString, wideLength);
if (length != wideLength) {
LogPlatformUtilsError("utf8_to_wide convert string error: " + std::to_string(::GetLastError()));
return {};
}
return wideText;
}
inline std::string wide_to_utf8(const std::wstring& wideText) {
if (wideText.empty()) {
return {};
}
std::string narrowText;
int narrowLength = ::WideCharToMultiByte(CP_UTF8, 0, wideText.data(), (int)wideText.size(), nullptr, 0, nullptr, nullptr);
if (narrowLength == 0) {
LogPlatformUtilsError("wide_to_utf8 get size error: " + std::to_string(::GetLastError()));
return {};
}
narrowText.resize(narrowLength, 0);
char* narrowString = const_cast<char*>(narrowText.data());
const int length =
::WideCharToMultiByte(CP_UTF8, 0, wideText.data(), (int)wideText.size(), narrowString, narrowLength, nullptr, nullptr);
if (length != narrowLength) {
LogPlatformUtilsError("wide_to_utf8 convert string error: " + std::to_string(::GetLastError()));
return {};
}
return narrowText;
}
static inline bool IsHighIntegrityLevel() {
static bool isHighIntegrityLevel = ([] {
HANDLE processToken;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_QUERY_SOURCE, &processToken)) {
uint8_t mandatoryLabelBuffer[SECURITY_MAX_SID_SIZE + sizeof(DWORD)]{};
DWORD bufferSize;
if (GetTokenInformation(processToken, TokenIntegrityLevel, mandatoryLabelBuffer, sizeof(mandatoryLabelBuffer),
&bufferSize) != 0) {
const auto mandatoryLabel = reinterpret_cast<const TOKEN_MANDATORY_LABEL*>(mandatoryLabelBuffer);
if (mandatoryLabel->Label.Sid != 0) {
const DWORD subAuthorityCount = *GetSidSubAuthorityCount(mandatoryLabel->Label.Sid);
const DWORD integrityLevel = *GetSidSubAuthority(mandatoryLabel->Label.Sid, subAuthorityCount - 1);
CloseHandle(processToken);
return integrityLevel > SECURITY_MANDATORY_MEDIUM_RID;
}
}
CloseHandle(processToken);
}
return false;
})();
return isHighIntegrityLevel;
}
static inline bool PlatformUtilsGetEnvSet(const char* name) {
const std::wstring wname = utf8_to_wide(name);
const DWORD valSize = ::GetEnvironmentVariableW(wname.c_str(), nullptr, 0);
return 0 != valSize;
}
static inline std::string PlatformUtilsGetEnv(const char* name) {
const std::wstring wname = utf8_to_wide(name);
const DWORD valSize = ::GetEnvironmentVariableW(wname.c_str(), nullptr, 0);
if (valSize == 0 || valSize == 1) {
return {};
}
std::wstring wValue(valSize, 0);
wchar_t* wValueData = &wValue[0];
const DWORD length = ::GetEnvironmentVariableW(wname.c_str(), wValueData, (DWORD)wValue.size());
if ((length == 0) || (length >= wValue.size())) {
LogPlatformUtilsError("GetEnvironmentVariable get value error: " + std::to_string(::GetLastError()));
return {};
}
wValue.resize(length);
return wide_to_utf8(wValue);
}
static inline std::string PlatformUtilsGetSecureEnv(const char* name) {
const std::string envValue = PlatformUtilsGetEnv(name);
if (IsHighIntegrityLevel()) {
if (!envValue.empty()) {
LogPlatformUtilsError(std::string("!!! WARNING !!! Environment variable ") + name +
" is being ignored due to running from an elevated context. The value '" + envValue +
"' will NOT be used.");
}
return {};
}
return envValue;
}
#elif defined(XR_OS_ANDROID)
#include <sys/system_properties.h>
static inline bool PlatformUtilsGetEnvSet(const char* ) {
return false;
}
static inline std::string PlatformUtilsGetEnv(const char* ) {
return {};
}
static inline std::string PlatformUtilsGetSecureEnv(const char* ) {
return {};
}
static inline bool PlatformGetGlobalRuntimeFileName(uint16_t major_version, std::string& file_name) {
static const char* rt_dir_prefixes[] = {"/product", "/odm", "/oem", "/vendor", "/system"};
static const std::string subdir = "/etc/openxr/";
for (const auto prefix : rt_dir_prefixes) {
const std::string rt_dir_prefix = prefix + subdir;
if (detail::ImplTryRuntimeFilename(rt_dir_prefix.c_str(), major_version, file_name)) {
return true;
}
}
return false;
}
static inline std::string PlatformUtilsGetAndroidSystemProperty(const char* name) {
std::string result;
const prop_info* pi = __system_property_find(name);
if (pi == nullptr) {
return {};
}
#if __ANDROID_API__ >= 26
__system_property_read_callback(
pi,
[](void* cookie, const char*, const char* value, uint32_t) {
auto property_value = reinterpret_cast<std::string*>(cookie);
*property_value = value;
},
reinterpret_cast<void*>(&result));
#endif
if (result.empty()) {
char value[PROP_VALUE_MAX] = {};
if (__system_property_get(name, value) != 0) {
result = value;
}
}
return result;
}
#else
static inline bool PlatformUtilsGetEnvSet(const char* ) {
return false;
}
static inline std::string PlatformUtilsGetEnv(const char* ) {
return {};
}
static inline std::string PlatformUtilsGetSecureEnv(const char* ) {
return {};
}
static inline bool PlatformGetGlobalRuntimeFileName(uint16_t , std::string const& ) {
return false;
}
#endif