15db71995Sopenharmony_ci/*
25db71995Sopenharmony_ci * Copyright (c) 2021-2022 The Khronos Group Inc.
35db71995Sopenharmony_ci * Copyright (c) 2021-2022 Valve Corporation
45db71995Sopenharmony_ci * Copyright (c) 2021-2022 LunarG, Inc.
55db71995Sopenharmony_ci *
65db71995Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
75db71995Sopenharmony_ci * of this software and/or associated documentation files (the "Materials"), to
85db71995Sopenharmony_ci * deal in the Materials without restriction, including without limitation the
95db71995Sopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
105db71995Sopenharmony_ci * sell copies of the Materials, and to permit persons to whom the Materials are
115db71995Sopenharmony_ci * furnished to do so, subject to the following conditions:
125db71995Sopenharmony_ci *
135db71995Sopenharmony_ci * The above copyright notice(s) and this permission notice shall be included in
145db71995Sopenharmony_ci * all copies or substantial portions of the Materials.
155db71995Sopenharmony_ci *
165db71995Sopenharmony_ci * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
175db71995Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
185db71995Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
195db71995Sopenharmony_ci *
205db71995Sopenharmony_ci * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
215db71995Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
225db71995Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
235db71995Sopenharmony_ci * USE OR OTHER DEALINGS IN THE MATERIALS.
245db71995Sopenharmony_ci *
255db71995Sopenharmony_ci * Author: Charles Giessen <charles@lunarg.com>
265db71995Sopenharmony_ci */
275db71995Sopenharmony_ci
285db71995Sopenharmony_ci#pragma once
295db71995Sopenharmony_ci
305db71995Sopenharmony_ci#include "test_util.h"
315db71995Sopenharmony_ci
325db71995Sopenharmony_ci#include <unordered_set>
335db71995Sopenharmony_ci#include <stdlib.h>
345db71995Sopenharmony_ci
355db71995Sopenharmony_ci#if defined(WIN32)
365db71995Sopenharmony_ci#include <strsafe.h>
375db71995Sopenharmony_ci#include <cfgmgr32.h>
385db71995Sopenharmony_ci#include <initguid.h>
395db71995Sopenharmony_ci#include <devpkey.h>
405db71995Sopenharmony_ci#include <winternl.h>
415db71995Sopenharmony_ci#include <appmodel.h>
425db71995Sopenharmony_ci
435db71995Sopenharmony_ci#define CINTERFACE
445db71995Sopenharmony_ci#include <dxgi1_6.h>
455db71995Sopenharmony_ci#include <adapters.h>
465db71995Sopenharmony_ci#endif
475db71995Sopenharmony_ci
485db71995Sopenharmony_cienum class ManifestCategory { implicit_layer, explicit_layer, icd, settings };
495db71995Sopenharmony_cienum class GpuType { unspecified, integrated, discrete, external };
505db71995Sopenharmony_ci
515db71995Sopenharmony_ci#if defined(WIN32)
525db71995Sopenharmony_ci#define VK_VARIANT_REG_STR ""
535db71995Sopenharmony_ci#define VK_VARIANT_REG_STR_W L""
545db71995Sopenharmony_ci
555db71995Sopenharmony_ci#define VK_DRIVERS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\Vulkan" VK_VARIANT_REG_STR "\\Drivers"
565db71995Sopenharmony_ci#define VK_ELAYERS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\Vulkan" VK_VARIANT_REG_STR "\\ExplicitLayers"
575db71995Sopenharmony_ci#define VK_ILAYERS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\Vulkan" VK_VARIANT_REG_STR "\\ImplicitLayers"
585db71995Sopenharmony_ci#define VK_SETTINGS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\Vulkan" VK_VARIANT_REG_STR "\\LoaderSettings"
595db71995Sopenharmony_ci
605db71995Sopenharmony_cistruct RegistryEntry {
615db71995Sopenharmony_ci    RegistryEntry() = default;
625db71995Sopenharmony_ci    RegistryEntry(std::string const& name) noexcept : name(name) {}
635db71995Sopenharmony_ci    RegistryEntry(std::string const& name, DWORD value) noexcept : name(name), value(value) {}
645db71995Sopenharmony_ci    std::string name;
655db71995Sopenharmony_ci    DWORD value{};
665db71995Sopenharmony_ci};
675db71995Sopenharmony_ci
685db71995Sopenharmony_cistruct HKeyHandle {
695db71995Sopenharmony_ci    explicit HKeyHandle(const size_t value, const std::string& key_path) noexcept : key(HKEY{}), path(key_path) {
705db71995Sopenharmony_ci        key = reinterpret_cast<HKEY>(value);
715db71995Sopenharmony_ci    }
725db71995Sopenharmony_ci
735db71995Sopenharmony_ci    HKEY get() const noexcept { return key; }
745db71995Sopenharmony_ci
755db71995Sopenharmony_ci    HKEY key{};
765db71995Sopenharmony_ci    std::string path;
775db71995Sopenharmony_ci};
785db71995Sopenharmony_ci
795db71995Sopenharmony_cistatic const char* pnp_registry_path = "SYSTEM\\CurrentControlSet\\Control\\Class\\{4d36e968-e325-11ce-bfc1-08002be10318}";
805db71995Sopenharmony_ci
815db71995Sopenharmony_ci// Needed for DXGI mocking
825db71995Sopenharmony_cistruct KnownDriverData {
835db71995Sopenharmony_ci    const char* filename = nullptr;
845db71995Sopenharmony_ci    int vendor_id = 0;
855db71995Sopenharmony_ci};
865db71995Sopenharmony_cistatic std::array<KnownDriverData, 4> known_driver_list = {
875db71995Sopenharmony_ci#if defined(_WIN64)
885db71995Sopenharmony_ci    KnownDriverData{"igvk64.json", 0x8086}, KnownDriverData{"nv-vk64.json", 0x10de}, KnownDriverData{"amd-vulkan64.json", 0x1002},
895db71995Sopenharmony_ci    KnownDriverData{"amdvlk64.json", 0x1002}
905db71995Sopenharmony_ci#else
915db71995Sopenharmony_ci    KnownDriverData{"igvk32.json", 0x8086}, KnownDriverData{"nv-vk32.json", 0x10de}, KnownDriverData{"amd-vulkan32.json", 0x1002},
925db71995Sopenharmony_ci    KnownDriverData{"amdvlk32.json", 0x1002}
935db71995Sopenharmony_ci#endif
945db71995Sopenharmony_ci};
955db71995Sopenharmony_ci
965db71995Sopenharmony_cistruct DXGIAdapter {
975db71995Sopenharmony_ci    GpuType gpu_preference = GpuType::unspecified;
985db71995Sopenharmony_ci    DXGI_ADAPTER_DESC1 desc1{};
995db71995Sopenharmony_ci    uint32_t adapter_index = 0;
1005db71995Sopenharmony_ci    IDXGIAdapter1 adapter_instance{};
1015db71995Sopenharmony_ci    IDXGIAdapter1Vtbl adapter_vtbl_instance{};
1025db71995Sopenharmony_ci};
1035db71995Sopenharmony_ci
1045db71995Sopenharmony_cistruct D3DKMT_Adapter {
1055db71995Sopenharmony_ci    D3DKMT_Adapter& add_driver_manifest_path(fs::path const& src);
1065db71995Sopenharmony_ci    D3DKMT_Adapter& add_implicit_layer_manifest_path(fs::path const& src);
1075db71995Sopenharmony_ci    D3DKMT_Adapter& add_explicit_layer_manifest_path(fs::path const& src);
1085db71995Sopenharmony_ci
1095db71995Sopenharmony_ci    UINT hAdapter;
1105db71995Sopenharmony_ci    LUID adapter_luid;
1115db71995Sopenharmony_ci    std::vector<std::wstring> driver_paths;
1125db71995Sopenharmony_ci    std::vector<std::wstring> implicit_layer_paths;
1135db71995Sopenharmony_ci    std::vector<std::wstring> explicit_layer_paths;
1145db71995Sopenharmony_ci
1155db71995Sopenharmony_ci   private:
1165db71995Sopenharmony_ci    D3DKMT_Adapter& add_path(fs::path src, std::vector<std::wstring>& dest);
1175db71995Sopenharmony_ci};
1185db71995Sopenharmony_ci
1195db71995Sopenharmony_ci#elif COMMON_UNIX_PLATFORMS
1205db71995Sopenharmony_ci
1215db71995Sopenharmony_cistruct DirEntry {
1225db71995Sopenharmony_ci    DIR* directory = nullptr;
1235db71995Sopenharmony_ci    std::string folder_path;
1245db71995Sopenharmony_ci    std::vector<struct dirent*> contents;
1255db71995Sopenharmony_ci    // the current item being read by an app (incremented by readdir, reset to zero by opendir & closedir)
1265db71995Sopenharmony_ci    size_t current_index = 0;
1275db71995Sopenharmony_ci    bool is_fake_path = false;  // true when this entry is for folder redirection
1285db71995Sopenharmony_ci};
1295db71995Sopenharmony_ci
1305db71995Sopenharmony_ci#endif
1315db71995Sopenharmony_ci
1325db71995Sopenharmony_cistruct FrameworkEnvironment;  // forward declaration
1335db71995Sopenharmony_ci
1345db71995Sopenharmony_ci// Necessary to have inline definitions as shim is a dll and thus functions
1355db71995Sopenharmony_ci// defined in the .cpp wont be found by the rest of the application
1365db71995Sopenharmony_cistruct PlatformShim {
1375db71995Sopenharmony_ci    PlatformShim() = default;
1385db71995Sopenharmony_ci    PlatformShim(std::vector<fs::FolderManager>* folders) : folders(folders) {}
1395db71995Sopenharmony_ci
1405db71995Sopenharmony_ci    // Used to get info about which drivers & layers have been added to folders
1415db71995Sopenharmony_ci    std::vector<fs::FolderManager>* folders;
1425db71995Sopenharmony_ci
1435db71995Sopenharmony_ci    // Test Framework interface
1445db71995Sopenharmony_ci    void reset();
1455db71995Sopenharmony_ci
1465db71995Sopenharmony_ci    void redirect_all_paths(fs::path const& path);
1475db71995Sopenharmony_ci    void redirect_category(fs::path const& new_path, ManifestCategory category);
1485db71995Sopenharmony_ci
1495db71995Sopenharmony_ci    // fake paths are paths that the loader normally looks in but actually point to locations inside the test framework
1505db71995Sopenharmony_ci    void set_fake_path(ManifestCategory category, fs::path const& path);
1515db71995Sopenharmony_ci
1525db71995Sopenharmony_ci    // known paths are real paths but since the test framework guarantee's the order files are found in, files in these paths
1535db71995Sopenharmony_ci    // need to be ordered correctly
1545db71995Sopenharmony_ci    void add_known_path(fs::path const& path);
1555db71995Sopenharmony_ci
1565db71995Sopenharmony_ci    void add_manifest(ManifestCategory category, fs::path const& path);
1575db71995Sopenharmony_ci    void add_unsecured_manifest(ManifestCategory category, fs::path const& path);
1585db71995Sopenharmony_ci
1595db71995Sopenharmony_ci// platform specific shim interface
1605db71995Sopenharmony_ci#if defined(WIN32)
1615db71995Sopenharmony_ci    // Control Platform Elevation Level
1625db71995Sopenharmony_ci    void set_elevated_privilege(bool elev) { elevation_level = (elev) ? SECURITY_MANDATORY_HIGH_RID : SECURITY_MANDATORY_LOW_RID; }
1635db71995Sopenharmony_ci    unsigned long elevation_level = SECURITY_MANDATORY_LOW_RID;
1645db71995Sopenharmony_ci
1655db71995Sopenharmony_ci    void add_dxgi_adapter(GpuType gpu_preference, DXGI_ADAPTER_DESC1 desc1);
1665db71995Sopenharmony_ci    void add_d3dkmt_adapter(D3DKMT_Adapter const& adapter);
1675db71995Sopenharmony_ci    void set_app_package_path(fs::path const& path);
1685db71995Sopenharmony_ci
1695db71995Sopenharmony_ci    std::unordered_map<uint32_t, DXGIAdapter> dxgi_adapters;
1705db71995Sopenharmony_ci
1715db71995Sopenharmony_ci    std::vector<D3DKMT_Adapter> d3dkmt_adapters;
1725db71995Sopenharmony_ci
1735db71995Sopenharmony_ci    // TODO:
1745db71995Sopenharmony_ci    void add_CM_Device_ID(std::wstring const& id, fs::path const& icd_path, fs::path const& layer_path);
1755db71995Sopenharmony_ci    std::wstring CM_device_ID_list = {L'\0'};
1765db71995Sopenharmony_ci    std::vector<RegistryEntry> CM_device_ID_registry_keys;
1775db71995Sopenharmony_ci
1785db71995Sopenharmony_ci    uint32_t random_base_path = 0;
1795db71995Sopenharmony_ci
1805db71995Sopenharmony_ci    std::vector<fs::path> icd_paths;
1815db71995Sopenharmony_ci
1825db71995Sopenharmony_ci    std::vector<RegistryEntry> hkey_current_user_explicit_layers;
1835db71995Sopenharmony_ci    std::vector<RegistryEntry> hkey_current_user_implicit_layers;
1845db71995Sopenharmony_ci    std::vector<RegistryEntry> hkey_local_machine_explicit_layers;
1855db71995Sopenharmony_ci    std::vector<RegistryEntry> hkey_local_machine_implicit_layers;
1865db71995Sopenharmony_ci    std::vector<RegistryEntry> hkey_local_machine_drivers;
1875db71995Sopenharmony_ci    std::vector<RegistryEntry> hkey_local_machine_settings;
1885db71995Sopenharmony_ci    std::vector<RegistryEntry> hkey_current_user_settings;
1895db71995Sopenharmony_ci
1905db71995Sopenharmony_ci    std::wstring app_package_path;
1915db71995Sopenharmony_ci
1925db71995Sopenharmony_ci    // When a key is created, return the index of the
1935db71995Sopenharmony_ci    size_t created_key_count = 0;
1945db71995Sopenharmony_ci    std::vector<HKeyHandle> created_keys;
1955db71995Sopenharmony_ci
1965db71995Sopenharmony_ci#elif COMMON_UNIX_PLATFORMS
1975db71995Sopenharmony_ci    bool is_fake_path(fs::path const& path);
1985db71995Sopenharmony_ci    fs::path const& get_real_path_from_fake_path(fs::path const& path);
1995db71995Sopenharmony_ci
2005db71995Sopenharmony_ci    void redirect_path(fs::path const& path, fs::path const& new_path);
2015db71995Sopenharmony_ci    void remove_redirect(fs::path const& path);
2025db71995Sopenharmony_ci
2035db71995Sopenharmony_ci    bool is_known_path(fs::path const& path);
2045db71995Sopenharmony_ci    void remove_known_path(fs::path const& path);
2055db71995Sopenharmony_ci
2065db71995Sopenharmony_ci    void redirect_dlopen_name(fs::path const& filename, fs::path const& actual_path);
2075db71995Sopenharmony_ci    bool is_dlopen_redirect_name(fs::path const& filename);
2085db71995Sopenharmony_ci
2095db71995Sopenharmony_ci    fs::path query_default_redirect_path(ManifestCategory category);
2105db71995Sopenharmony_ci
2115db71995Sopenharmony_ci    std::unordered_map<std::string, fs::path> redirection_map;
2125db71995Sopenharmony_ci    std::unordered_map<std::string, fs::path> dlopen_redirection_map;
2135db71995Sopenharmony_ci    std::unordered_set<std::string> known_path_set;
2145db71995Sopenharmony_ci
2155db71995Sopenharmony_ci    void set_elevated_privilege(bool elev) { use_fake_elevation = elev; }
2165db71995Sopenharmony_ci    bool use_fake_elevation = false;
2175db71995Sopenharmony_ci
2185db71995Sopenharmony_ci    std::vector<DirEntry> dir_entries;
2195db71995Sopenharmony_ci
2205db71995Sopenharmony_ci#if defined(__APPLE__)
2215db71995Sopenharmony_ci    std::string bundle_contents;
2225db71995Sopenharmony_ci#endif
2235db71995Sopenharmony_ci#endif
2245db71995Sopenharmony_ci    bool is_during_destruction = false;
2255db71995Sopenharmony_ci};
2265db71995Sopenharmony_ci
2275db71995Sopenharmony_cistd::vector<std::string> parse_env_var_list(std::string const& var);
2285db71995Sopenharmony_cistd::string category_path_name(ManifestCategory category);
2295db71995Sopenharmony_ci
2305db71995Sopenharmony_cistd::vector<std::string> get_folder_contents(std::vector<fs::FolderManager>* folders, std::string folder_name) noexcept;
2315db71995Sopenharmony_ci
2325db71995Sopenharmony_ciextern "C" {
2335db71995Sopenharmony_ci// dynamically link on windows and macos
2345db71995Sopenharmony_ci#if defined(WIN32) || defined(__APPLE__)
2355db71995Sopenharmony_ciusing PFN_get_platform_shim = PlatformShim* (*)(std::vector<fs::FolderManager>* folders);
2365db71995Sopenharmony_ci#define GET_PLATFORM_SHIM_STR "get_platform_shim"
2375db71995Sopenharmony_ci
2385db71995Sopenharmony_ci#elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__GNU__)
2395db71995Sopenharmony_ci// statically link on linux
2405db71995Sopenharmony_ciPlatformShim* get_platform_shim(std::vector<fs::FolderManager>* folders);
2415db71995Sopenharmony_ci#endif
2425db71995Sopenharmony_ci}
243