1 /* 2 * Copyright (c) 2021-2022 The Khronos Group Inc. 3 * Copyright (c) 2021-2022 Valve Corporation 4 * Copyright (c) 2021-2022 LunarG, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and/or associated documentation files (the "Materials"), to 8 * deal in the Materials without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Materials, and to permit persons to whom the Materials are 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice(s) and this permission notice shall be included in 14 * all copies or substantial portions of the Materials. 15 * 16 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 * 20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE 23 * USE OR OTHER DEALINGS IN THE MATERIALS. 24 * 25 * Author: Charles Giessen <charles@lunarg.com> 26 */ 27 28 #pragma once 29 30 #include "test_util.h" 31 32 #include <stdlib.h> 33 34 #if defined(WIN32) 35 #include <strsafe.h> 36 #include <cfgmgr32.h> 37 #include <initguid.h> 38 #include <devpkey.h> 39 #include <winternl.h> 40 #include <appmodel.h> 41 42 #define CINTERFACE 43 #include <dxgi1_6.h> 44 #include <adapters.h> 45 #endif 46 47 enum class ManifestCategory { implicit_layer, explicit_layer, icd }; 48 enum class GpuType { unspecified, integrated, discrete, external }; 49 50 #if defined(WIN32) 51 struct RegistryEntry { 52 RegistryEntry() = default; RegistryEntryRegistryEntry53 RegistryEntry(std::string const& name) noexcept : name(name) {} RegistryEntryRegistryEntry54 RegistryEntry(std::string const& name, DWORD value) noexcept : name(name), value(value) {} 55 std::string name; 56 DWORD value{}; 57 }; 58 59 struct HKeyHandle { HKeyHandleHKeyHandle60 explicit HKeyHandle(const size_t value, const std::string& key_path) noexcept : key(HKEY{}), path(key_path) { 61 key = reinterpret_cast<HKEY>(value); 62 } 63 getHKeyHandle64 HKEY get() const noexcept { return key; } 65 66 HKEY key{}; 67 std::string path; 68 }; 69 70 static const char* pnp_registry_path = "SYSTEM\\CurrentControlSet\\Control\\Class\\{4d36e968-e325-11ce-bfc1-08002be10318}"; 71 72 // Needed for DXGI mocking 73 struct KnownDriverData { 74 const char* filename; 75 int vendor_id; 76 }; 77 static std::array<KnownDriverData, 4> known_driver_list = { 78 #if defined(_WIN64) 79 KnownDriverData{"igvk64.json", 0x8086}, KnownDriverData{"nv-vk64.json", 0x10de}, KnownDriverData{"amd-vulkan64.json", 0x1002}, 80 KnownDriverData{"amdvlk64.json", 0x1002} 81 #else 82 KnownDriverData{"igvk32.json", 0x8086}, KnownDriverData{"nv-vk32.json", 0x10de}, KnownDriverData{"amd-vulkan32.json", 0x1002}, 83 KnownDriverData{"amdvlk32.json", 0x1002} 84 #endif 85 }; 86 87 struct DXGIAdapter { DXGIAdapterDXGIAdapter88 DXGIAdapter(GpuType gpu_preference, DXGI_ADAPTER_DESC1 desc1, uint32_t adapter_index) 89 : gpu_preference(gpu_preference), desc1(desc1), adapter_index(adapter_index) {} 90 GpuType gpu_preference = GpuType::unspecified; 91 DXGI_ADAPTER_DESC1 desc1{}; 92 uint32_t adapter_index = 0; 93 }; 94 95 struct D3DKMT_Adapter { 96 D3DKMT_Adapter() = default; D3DKMT_AdapterD3DKMT_Adapter97 D3DKMT_Adapter(UINT hAdapter, LUID adapter_luid) noexcept : hAdapter(hAdapter), adapter_luid(adapter_luid) {} 98 99 D3DKMT_Adapter& add_driver_manifest_path(fs::path const& src); 100 D3DKMT_Adapter& add_implicit_layer_manifest_path(fs::path const& src); 101 D3DKMT_Adapter& add_explicit_layer_manifest_path(fs::path const& src); 102 103 UINT hAdapter; 104 LUID adapter_luid; 105 std::vector<std::wstring> driver_paths; 106 std::vector<std::wstring> implicit_layer_paths; 107 std::vector<std::wstring> explicit_layer_paths; 108 109 private: 110 D3DKMT_Adapter& add_path(fs::path src, std::vector<std::wstring>& dest); 111 }; 112 113 #elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) 114 115 struct DirEntry { 116 DIR* directory; 117 std::string folder_path; 118 std::vector<struct dirent*> contents; 119 size_t current_index; 120 }; 121 122 #endif 123 124 struct FrameworkEnvironment; // forward declaration 125 126 // Necessary to have inline definitions as shim is a dll and thus functions 127 // defined in the .cpp wont be found by the rest of the application 128 struct PlatformShim { 129 PlatformShim() = default; PlatformShimPlatformShim130 PlatformShim(std::vector<fs::FolderManager>* folders) : folders(folders) {} 131 132 // Used to get info about which drivers & layers have been added to folders 133 std::vector<fs::FolderManager>* folders; 134 135 // Test Framework interface 136 void reset(); 137 138 void redirect_all_paths(fs::path const& path); 139 void redirect_category(fs::path const& new_path, ManifestCategory category); 140 141 void set_path(ManifestCategory category, fs::path const& path); 142 143 void add_manifest(ManifestCategory category, fs::path const& path); 144 145 // platform specific shim interface 146 #if defined(WIN32) 147 // Control Platform Elevation Level set_elevated_privilegePlatformShim148 void set_elevated_privilege(bool elev) { 149 (elev) ? elevation_level = SECURITY_MANDATORY_HIGH_RID : elevation_level = SECURITY_MANDATORY_LOW_RID; 150 } 151 unsigned long elevation_level = SECURITY_MANDATORY_LOW_RID; 152 153 void add_dxgi_adapter(GpuType gpu_preference, DXGI_ADAPTER_DESC1 desc1); 154 void add_d3dkmt_adapter(D3DKMT_Adapter const& adapter); 155 void set_app_package_path(fs::path const& path); 156 157 uint32_t next_adapter_handle = 1; // increment everytime add_dxgi_adapter is called 158 std::vector<DXGIAdapter> dxgi_adapters; 159 std::unordered_map<IDXGIAdapter1*, uint32_t> dxgi_adapter_map; 160 // next two are a pair 161 std::vector<D3DKMT_Adapter> d3dkmt_adapters; 162 163 // TODO: 164 void add_CM_Device_ID(std::wstring const& id, fs::path const& icd_path, fs::path const& layer_path); 165 std::wstring CM_device_ID_list = {L'\0'}; 166 std::vector<RegistryEntry> CM_device_ID_registry_keys; 167 168 uint32_t random_base_path = 0; 169 170 std::vector<fs::path> icd_paths; 171 172 std::vector<RegistryEntry> hkey_current_user_explicit_layers; 173 std::vector<RegistryEntry> hkey_current_user_implicit_layers; 174 std::vector<RegistryEntry> hkey_local_machine_explicit_layers; 175 std::vector<RegistryEntry> hkey_local_machine_implicit_layers; 176 std::vector<RegistryEntry> hkey_local_machine_drivers; 177 178 std::wstring app_package_path; 179 180 // When a key is created, return the index of the 181 size_t created_key_count = 0; 182 std::vector<HKeyHandle> created_keys; 183 184 #elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) 185 bool is_fake_path(fs::path const& path); 186 fs::path const& get_fake_path(fs::path const& path); 187 188 void redirect_path(fs::path const& path, fs::path const& new_path); 189 void remove_redirect(fs::path const& path); 190 191 std::unordered_map<std::string, fs::path> redirection_map; 192 set_elevated_privilegePlatformShim193 void set_elevated_privilege(bool elev) { use_fake_elevation = elev; } 194 bool use_fake_elevation = false; 195 196 std::vector<DirEntry> dir_entries; 197 #endif 198 }; 199 200 std::vector<std::string> parse_env_var_list(std::string const& var); 201 std::string category_path_name(ManifestCategory category); 202 203 std::vector<std::string> get_folder_contents(std::vector<fs::FolderManager>* folders, std::string folder_name) noexcept; 204 205 extern "C" { 206 // dynamically link on windows and macos 207 #if defined(WIN32) || defined(__APPLE__) 208 using PFN_get_platform_shim = PlatformShim* (*)(std::vector<fs::FolderManager>* folders); 209 #define GET_PLATFORM_SHIM_STR "get_platform_shim" 210 211 #elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) 212 // statically link on linux 213 PlatformShim* get_platform_shim(std::vector<fs::FolderManager>* folders); 214 #endif 215 } 216