• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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