1 // Copyright 2016 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // This API is a usability layer for direct registry access via NTDLL. 6 // It allows for "advapi32-free" registry access, which is especially 7 // useful for accessing registy from DllMain (holding loader lock), 8 // or if a dependency on/linkage of ADVAPI32.dll is not desired. 9 10 // The implementation of this API should only use ntdll and kernel32 system 11 // DLLs. 12 13 // Note that this API is currently lazy initialized. Any function that is 14 // NOT merely a wrapper function (i.e. any function that directly interacts with 15 // NTDLL) will immediately check: 16 // 17 // if (!g_initialized && !InitNativeRegApi()) 18 // return false; 19 // 20 // There is currently no multi-threading lock around the lazy initialization, 21 // as the main client for this API (chrome_elf) does not introduce 22 // a multi-threading concern. This can easily be changed if needed. 23 24 #ifndef CHROME_CHROME_ELF_NT_REGISTRY_NT_REGISTRY_H_ 25 #define CHROME_CHROME_ELF_NT_REGISTRY_NT_REGISTRY_H_ 26 27 #include <string> 28 #include <vector> 29 30 #include "sandbox/win/src/nt_internals.h" // NTSTATUS 31 32 namespace nt { 33 34 // Windows registry maximum lengths (in chars). Not including null char. 35 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724872(v=vs.85).aspx 36 constexpr size_t g_kRegMaxPathLen = 255; 37 constexpr size_t g_kRegMaxValueName = 16383; 38 39 // AUTO will choose depending on system install or not. 40 // Use HKLM or HKCU to override. 41 typedef enum _ROOT_KEY { AUTO = 0, HKLM, HKCU } ROOT_KEY; 42 43 // Used with wrapper functions to request registry redirection override. 44 // Maps to KEY_WOW64_32KEY and KEY_WOW64_64KEY access flags. 45 enum WOW64_OVERRIDE { 46 NONE = 0L, 47 WOW6432 = KEY_WOW64_32KEY, 48 WOW6464 = KEY_WOW64_64KEY 49 }; 50 51 //------------------------------------------------------------------------------ 52 // Create, open, delete, close functions 53 //------------------------------------------------------------------------------ 54 55 // Create and/or open a registry key. 56 // - This function will recursively create multiple sub-keys if required for 57 // |key_path|. 58 // - If the key doesn't need to be left open, pass in nullptr for |out_handle|. 59 // - This function will happily succeed if the key already exists. 60 // - Optional |out_handle|. If nullptr, function will close handle when done. 61 // Otherwise, will hold the open handle to the deepest subkey. 62 // - Caller must call CloseRegKey on returned handle (on success). 63 bool CreateRegKey(ROOT_KEY root, 64 const wchar_t* key_path, 65 ACCESS_MASK access, 66 HANDLE* out_handle OPTIONAL); 67 68 // Open existing registry key. 69 // - Caller must call CloseRegKey on returned handle (on success). 70 // - Optional error code can be returned on failure for extra detail. 71 bool OpenRegKey(ROOT_KEY root, 72 const wchar_t* key_path, 73 ACCESS_MASK access, 74 HANDLE* out_handle, 75 NTSTATUS* error_code OPTIONAL); 76 77 // Delete a registry key. 78 // - Caller must still call CloseRegKey after the delete. 79 // - Non-recursive. Must have no subkeys. 80 bool DeleteRegKey(HANDLE key); 81 82 // Delete a registry key. 83 // - WRAPPER: Function opens and closes the target key for caller. 84 // - Use |wow64_override| to force redirection behaviour, or pass nt::NONE. 85 // - Non-recursive. Must have no subkeys. 86 bool DeleteRegKey(ROOT_KEY root, 87 WOW64_OVERRIDE wow64_override, 88 const wchar_t* key_path); 89 90 // Close a registry key handle that was opened with CreateRegKey or OpenRegKey. 91 void CloseRegKey(HANDLE key); 92 93 //------------------------------------------------------------------------------ 94 // Getter functions 95 //------------------------------------------------------------------------------ 96 97 // Main function to query a registry value. 98 // - Key handle should have been opened with CreateRegKey or OpenRegKey. 99 // - Types defined in winnt.h. E.g.: REG_DWORD, REG_SZ. 100 bool QueryRegKeyValue(HANDLE key, 101 const wchar_t* value_name, 102 ULONG* out_type, 103 std::vector<BYTE>* out_buffer); 104 105 // Query DWORD value. 106 // - WRAPPER: Function works with DWORD data type. 107 // - Key handle should have been opened with CreateRegKey or OpenRegKey. 108 // - Handle will be left open. Caller must still call CloseRegKey when done. 109 bool QueryRegValueDWORD(HANDLE key, 110 const wchar_t* value_name, 111 DWORD* out_dword); 112 113 // Query DWORD value. 114 // - WRAPPER: Function opens and closes the target key for caller, and works 115 // with DWORD data type. 116 // - Use |wow64_override| to force redirection behaviour, or pass nt::NONE. 117 bool QueryRegValueDWORD(ROOT_KEY root, 118 WOW64_OVERRIDE wow64_override, 119 const wchar_t* key_path, 120 const wchar_t* value_name, 121 DWORD* out_dword); 122 123 // Query SZ (string) value. 124 // - WRAPPER: Function works with SZ or EXPAND_SZ data type. 125 // - Key handle should have been opened with CreateRegKey or OpenRegKey. 126 // - Handle will be left open. Caller must still call CloseRegKey when done. 127 // - Note: this function only returns the string up to the first end-of-string. 128 // Any string packed with embedded nulls can be accessed via the raw 129 // QueryRegKeyValue function. 130 bool QueryRegValueSZ(HANDLE key, 131 const wchar_t* value_name, 132 std::wstring* out_sz); 133 134 // Query SZ (string) value. 135 // - WRAPPER: Function opens and closes the target key for caller, and works 136 // with SZ or EXPAND_SZ data type. 137 // - Use |wow64_override| to force redirection behaviour, or pass nt::NONE. 138 // - Note: this function only returns the string up to the first end-of-string. 139 // Any string packed with embedded nulls can be accessed via the raw 140 // QueryRegKeyValue function. 141 bool QueryRegValueSZ(ROOT_KEY root, 142 WOW64_OVERRIDE wow64_override, 143 const wchar_t* key_path, 144 const wchar_t* value_name, 145 std::wstring* out_sz); 146 147 // Query MULTI_SZ (multiple strings) value. 148 // - WRAPPER: Function works with MULTI_SZ data type. 149 // - Key handle should have been opened with CreateRegKey or OpenRegKey. 150 // - Handle will be left open. Caller must still call CloseRegKey when done. 151 bool QueryRegValueMULTISZ(HANDLE key, 152 const wchar_t* value_name, 153 std::vector<std::wstring>* out_multi_sz); 154 155 // Query MULTI_SZ (multiple strings) value. 156 // - WRAPPER: Function opens and closes the target key for caller, and works 157 // with MULTI_SZ data type. 158 // - Use |wow64_override| to force redirection behaviour, or pass nt::NONE. 159 bool QueryRegValueMULTISZ(ROOT_KEY root, 160 WOW64_OVERRIDE wow64_override, 161 const wchar_t* key_path, 162 const wchar_t* value_name, 163 std::vector<std::wstring>* out_multi_sz); 164 165 //------------------------------------------------------------------------------ 166 // Setter functions 167 //------------------------------------------------------------------------------ 168 169 // Main function to set a registry value. 170 // - Key handle should have been opened with CreateRegKey or OpenRegKey. 171 // - Types defined in winnt.h. E.g.: REG_DWORD, REG_SZ. 172 bool SetRegKeyValue(HANDLE key, 173 const wchar_t* value_name, 174 ULONG type, 175 const BYTE* data, 176 DWORD data_size); 177 178 // Set DWORD value. 179 // - WRAPPER: Function works with DWORD data type. 180 // - Key handle should have been opened with CreateRegKey or OpenRegKey. 181 // - Handle will be left open. Caller must still call CloseRegKey when done. 182 bool SetRegValueDWORD(HANDLE key, const wchar_t* value_name, DWORD value); 183 184 // Set DWORD value. 185 // - WRAPPER: Function opens and closes the target key for caller, and works 186 // with DWORD data type. 187 // - Use |wow64_override| to force redirection behaviour, or pass nt::NONE. 188 bool SetRegValueDWORD(ROOT_KEY root, 189 WOW64_OVERRIDE wow64_override, 190 const wchar_t* key_path, 191 const wchar_t* value_name, 192 DWORD value); 193 194 // Set SZ (string) value. 195 // - WRAPPER: Function works with SZ data type. 196 // - Key handle should have been opened with CreateRegKey or OpenRegKey. 197 // - Handle will be left open. Caller must still call CloseRegKey when done. 198 bool SetRegValueSZ(HANDLE key, 199 const wchar_t* value_name, 200 const std::wstring& value); 201 202 // Set SZ (string) value. 203 // - WRAPPER: Function opens and closes the target key for caller, and works 204 // with SZ data type. 205 // - Use |wow64_override| to force redirection behaviour, or pass nt::NONE. 206 bool SetRegValueSZ(ROOT_KEY root, 207 WOW64_OVERRIDE wow64_override, 208 const wchar_t* key_path, 209 const wchar_t* value_name, 210 const std::wstring& value); 211 212 // Set MULTI_SZ (multiple strings) value. 213 // - WRAPPER: Function works with MULTI_SZ data type. 214 // - Key handle should have been opened with CreateRegKey or OpenRegKey. 215 // - Handle will be left open. Caller must still call CloseRegKey when done. 216 bool SetRegValueMULTISZ(HANDLE key, 217 const wchar_t* value_name, 218 const std::vector<std::wstring>& values); 219 220 // Set MULTI_SZ (multiple strings) value. 221 // - WRAPPER: Function opens and closes the target key for caller, and works 222 // with MULTI_SZ data type. 223 // - Use |wow64_override| to force redirection behaviour, or pass nt::NONE. 224 bool SetRegValueMULTISZ(ROOT_KEY root, 225 WOW64_OVERRIDE wow64_override, 226 const wchar_t* key_path, 227 const wchar_t* value_name, 228 const std::vector<std::wstring>& values); 229 230 //------------------------------------------------------------------------------ 231 // Enumeration Support 232 //------------------------------------------------------------------------------ 233 234 // Query key information for subkey enumeration. 235 // - Key handle should have been opened with OpenRegKey (with at least 236 // KEY_ENUMERATE_SUB_KEYS access rights). 237 // - Currently only returns the number of subkeys. Use |subkey_count| 238 // in a loop for calling QueryRegSubkey. 239 bool QueryRegEnumerationInfo(HANDLE key, ULONG* out_subkey_count); 240 241 // Enumerate subkeys by index. 242 // - Key handle should have been opened with OpenRegKey (with at least 243 // KEY_ENUMERATE_SUB_KEYS access rights). 244 // - Get subkey count by calling QueryRegEnumerationInfo. 245 bool QueryRegSubkey(HANDLE key, 246 ULONG subkey_index, 247 std::wstring* out_subkey_name); 248 249 //------------------------------------------------------------------------------ 250 // Utils 251 //------------------------------------------------------------------------------ 252 253 // Returns the current user SID in string form. 254 const wchar_t* GetCurrentUserSidString(); 255 256 // Returns true if this process is WOW64. 257 bool IsCurrentProcWow64(); 258 259 // Setter function for test suites that use reg redirection. 260 bool SetTestingOverride(ROOT_KEY root, const std::wstring& new_path); 261 262 // Getter function for test suites that use reg redirection. 263 std::wstring GetTestingOverride(ROOT_KEY root); 264 265 } // namespace nt 266 267 #endif // CHROME_CHROME_ELF_NT_REGISTRY_NT_REGISTRY_H_ 268