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