OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "sandbox/win/src/win_utils.h" | 5 #include "sandbox/win/src/win_utils.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 | 8 |
9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "sandbox/win/src/internal_types.h" | 10 #include "sandbox/win/src/internal_types.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 { L"HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE}, | 26 { L"HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE}, |
27 { L"HKEY_USERS", HKEY_USERS}, | 27 { L"HKEY_USERS", HKEY_USERS}, |
28 { L"HKEY_PERFORMANCE_DATA", HKEY_PERFORMANCE_DATA}, | 28 { L"HKEY_PERFORMANCE_DATA", HKEY_PERFORMANCE_DATA}, |
29 { L"HKEY_PERFORMANCE_TEXT", HKEY_PERFORMANCE_TEXT}, | 29 { L"HKEY_PERFORMANCE_TEXT", HKEY_PERFORMANCE_TEXT}, |
30 { L"HKEY_PERFORMANCE_NLSTEXT", HKEY_PERFORMANCE_NLSTEXT}, | 30 { L"HKEY_PERFORMANCE_NLSTEXT", HKEY_PERFORMANCE_NLSTEXT}, |
31 { L"HKEY_CURRENT_CONFIG", HKEY_CURRENT_CONFIG}, | 31 { L"HKEY_CURRENT_CONFIG", HKEY_CURRENT_CONFIG}, |
32 { L"HKEY_DYN_DATA", HKEY_DYN_DATA} | 32 { L"HKEY_DYN_DATA", HKEY_DYN_DATA} |
33 }; | 33 }; |
34 | 34 |
35 // Returns true if the provided path points to a pipe. | 35 // Returns true if the provided path points to a pipe. |
36 bool IsPipe(const std::wstring& path) { | 36 bool IsPipe(const base::string16& path) { |
37 size_t start = 0; | 37 size_t start = 0; |
38 if (0 == path.compare(0, sandbox::kNTPrefixLen, sandbox::kNTPrefix)) | 38 if (0 == path.compare(0, sandbox::kNTPrefixLen, sandbox::kNTPrefix)) |
39 start = sandbox::kNTPrefixLen; | 39 start = sandbox::kNTPrefixLen; |
40 | 40 |
41 const wchar_t kPipe[] = L"pipe\\"; | 41 const wchar_t kPipe[] = L"pipe\\"; |
42 return (0 == path.compare(start, arraysize(kPipe) - 1, kPipe)); | 42 return (0 == path.compare(start, arraysize(kPipe) - 1, kPipe)); |
43 } | 43 } |
44 | 44 |
45 } // namespace | 45 } // namespace |
46 | 46 |
47 namespace sandbox { | 47 namespace sandbox { |
48 | 48 |
49 HKEY GetReservedKeyFromName(const std::wstring& name) { | 49 HKEY GetReservedKeyFromName(const base::string16& name) { |
50 for (size_t i = 0; i < arraysize(kKnownKey); ++i) { | 50 for (size_t i = 0; i < arraysize(kKnownKey); ++i) { |
51 if (name == kKnownKey[i].name) | 51 if (name == kKnownKey[i].name) |
52 return kKnownKey[i].key; | 52 return kKnownKey[i].key; |
53 } | 53 } |
54 | 54 |
55 return NULL; | 55 return NULL; |
56 } | 56 } |
57 | 57 |
58 bool ResolveRegistryName(std::wstring name, std::wstring* resolved_name) { | 58 bool ResolveRegistryName(base::string16 name, base::string16* resolved_name) { |
59 for (size_t i = 0; i < arraysize(kKnownKey); ++i) { | 59 for (size_t i = 0; i < arraysize(kKnownKey); ++i) { |
60 if (name.find(kKnownKey[i].name) == 0) { | 60 if (name.find(kKnownKey[i].name) == 0) { |
61 HKEY key; | 61 HKEY key; |
62 DWORD disposition; | 62 DWORD disposition; |
63 if (ERROR_SUCCESS != ::RegCreateKeyEx(kKnownKey[i].key, L"", 0, NULL, 0, | 63 if (ERROR_SUCCESS != ::RegCreateKeyEx(kKnownKey[i].key, L"", 0, NULL, 0, |
64 MAXIMUM_ALLOWED, NULL, &key, | 64 MAXIMUM_ALLOWED, NULL, &key, |
65 &disposition)) | 65 &disposition)) |
66 return false; | 66 return false; |
67 | 67 |
68 bool result = GetPathFromHandle(key, resolved_name); | 68 bool result = GetPathFromHandle(key, resolved_name); |
69 ::RegCloseKey(key); | 69 ::RegCloseKey(key); |
70 | 70 |
71 if (!result) | 71 if (!result) |
72 return false; | 72 return false; |
73 | 73 |
74 *resolved_name += name.substr(wcslen(kKnownKey[i].name)); | 74 *resolved_name += name.substr(wcslen(kKnownKey[i].name)); |
75 return true; | 75 return true; |
76 } | 76 } |
77 } | 77 } |
78 | 78 |
79 return false; | 79 return false; |
80 } | 80 } |
81 | 81 |
82 DWORD IsReparsePoint(const std::wstring& full_path, bool* result) { | 82 DWORD IsReparsePoint(const base::string16& full_path, bool* result) { |
83 std::wstring path = full_path; | 83 base::string16 path = full_path; |
84 | 84 |
85 // Remove the nt prefix. | 85 // Remove the nt prefix. |
86 if (0 == path.compare(0, kNTPrefixLen, kNTPrefix)) | 86 if (0 == path.compare(0, kNTPrefixLen, kNTPrefix)) |
87 path = path.substr(kNTPrefixLen); | 87 path = path.substr(kNTPrefixLen); |
88 | 88 |
89 // Check if it's a pipe. We can't query the attributes of a pipe. | 89 // Check if it's a pipe. We can't query the attributes of a pipe. |
90 if (IsPipe(path)) { | 90 if (IsPipe(path)) { |
91 *result = FALSE; | 91 *result = FALSE; |
92 return ERROR_SUCCESS; | 92 return ERROR_SUCCESS; |
93 } | 93 } |
94 | 94 |
95 std::wstring::size_type last_pos = std::wstring::npos; | 95 base::string16::size_type last_pos = base::string16::npos; |
96 | 96 |
97 do { | 97 do { |
98 path = path.substr(0, last_pos); | 98 path = path.substr(0, last_pos); |
99 | 99 |
100 DWORD attributes = ::GetFileAttributes(path.c_str()); | 100 DWORD attributes = ::GetFileAttributes(path.c_str()); |
101 if (INVALID_FILE_ATTRIBUTES == attributes) { | 101 if (INVALID_FILE_ATTRIBUTES == attributes) { |
102 DWORD error = ::GetLastError(); | 102 DWORD error = ::GetLastError(); |
103 if (error != ERROR_FILE_NOT_FOUND && | 103 if (error != ERROR_FILE_NOT_FOUND && |
104 error != ERROR_PATH_NOT_FOUND && | 104 error != ERROR_PATH_NOT_FOUND && |
105 error != ERROR_INVALID_NAME) { | 105 error != ERROR_INVALID_NAME) { |
106 // Unexpected error. | 106 // Unexpected error. |
107 NOTREACHED_NT(); | 107 NOTREACHED_NT(); |
108 return error; | 108 return error; |
109 } | 109 } |
110 } else if (FILE_ATTRIBUTE_REPARSE_POINT & attributes) { | 110 } else if (FILE_ATTRIBUTE_REPARSE_POINT & attributes) { |
111 // This is a reparse point. | 111 // This is a reparse point. |
112 *result = true; | 112 *result = true; |
113 return ERROR_SUCCESS; | 113 return ERROR_SUCCESS; |
114 } | 114 } |
115 | 115 |
116 last_pos = path.rfind(L'\\'); | 116 last_pos = path.rfind(L'\\'); |
117 } while (last_pos != std::wstring::npos); | 117 } while (last_pos != base::string16::npos); |
118 | 118 |
119 *result = false; | 119 *result = false; |
120 return ERROR_SUCCESS; | 120 return ERROR_SUCCESS; |
121 } | 121 } |
122 | 122 |
123 // We get a |full_path| of the form \??\c:\some\foo\bar, and the name that | 123 // We get a |full_path| of the form \??\c:\some\foo\bar, and the name that |
124 // we'll get from |handle| will be \device\harddiskvolume1\some\foo\bar. | 124 // we'll get from |handle| will be \device\harddiskvolume1\some\foo\bar. |
125 bool SameObject(HANDLE handle, const wchar_t* full_path) { | 125 bool SameObject(HANDLE handle, const wchar_t* full_path) { |
126 std::wstring path(full_path); | 126 base::string16 path(full_path); |
127 DCHECK_NT(!path.empty()); | 127 DCHECK_NT(!path.empty()); |
128 | 128 |
129 // Check if it's a pipe. | 129 // Check if it's a pipe. |
130 if (IsPipe(path)) | 130 if (IsPipe(path)) |
131 return true; | 131 return true; |
132 | 132 |
133 std::wstring actual_path; | 133 base::string16 actual_path; |
134 if (!GetPathFromHandle(handle, &actual_path)) | 134 if (!GetPathFromHandle(handle, &actual_path)) |
135 return false; | 135 return false; |
136 | 136 |
137 // This may end with a backslash. | 137 // This may end with a backslash. |
138 const wchar_t kBackslash = '\\'; | 138 const wchar_t kBackslash = '\\'; |
139 if (path[path.length() - 1] == kBackslash) | 139 if (path[path.length() - 1] == kBackslash) |
140 path = path.substr(0, path.length() - 1); | 140 path = path.substr(0, path.length() - 1); |
141 | 141 |
142 // Perfect match (case-insesitive check). | 142 // Perfect match (case-insesitive check). |
143 if (0 == _wcsicmp(actual_path.c_str(), path.c_str())) | 143 if (0 == _wcsicmp(actual_path.c_str(), path.c_str())) |
144 return true; | 144 return true; |
145 | 145 |
146 // Look for the drive letter. | 146 // Look for the drive letter. |
147 size_t colon_pos = path.find(L':'); | 147 size_t colon_pos = path.find(L':'); |
148 if (colon_pos == 0 || colon_pos == std::wstring::npos) | 148 if (colon_pos == 0 || colon_pos == base::string16::npos) |
149 return false; | 149 return false; |
150 | 150 |
151 // Only one character for the drive. | 151 // Only one character for the drive. |
152 if (colon_pos > 1 && path[colon_pos - 2] != kBackslash) | 152 if (colon_pos > 1 && path[colon_pos - 2] != kBackslash) |
153 return false; | 153 return false; |
154 | 154 |
155 // We only need 3 chars, but let's alloc a buffer for four. | 155 // We only need 3 chars, but let's alloc a buffer for four. |
156 wchar_t drive[4] = {0}; | 156 wchar_t drive[4] = {0}; |
157 wchar_t vol_name[MAX_PATH]; | 157 wchar_t vol_name[MAX_PATH]; |
158 memcpy(drive, &path[colon_pos - 1], 2 * sizeof(*drive)); | 158 memcpy(drive, &path[colon_pos - 1], 2 * sizeof(*drive)); |
(...skipping 14 matching lines...) Expand all Loading... |
173 if (0 != _wcsnicmp(actual_path.c_str(), vol_name, vol_length)) | 173 if (0 != _wcsnicmp(actual_path.c_str(), vol_name, vol_length)) |
174 return false; | 174 return false; |
175 | 175 |
176 // Check the path after the drive letter. | 176 // Check the path after the drive letter. |
177 if (0 != _wcsicmp(&actual_path[vol_length], &path[colon_pos + 1])) | 177 if (0 != _wcsicmp(&actual_path[vol_length], &path[colon_pos + 1])) |
178 return false; | 178 return false; |
179 | 179 |
180 return true; | 180 return true; |
181 } | 181 } |
182 | 182 |
183 bool ConvertToLongPath(const std::wstring& short_path, | 183 bool ConvertToLongPath(const base::string16& short_path, |
184 std::wstring* long_path) { | 184 base::string16* long_path) { |
185 // Check if the path is a NT path. | 185 // Check if the path is a NT path. |
186 bool is_nt_path = false; | 186 bool is_nt_path = false; |
187 std::wstring path = short_path; | 187 base::string16 path = short_path; |
188 if (0 == path.compare(0, kNTPrefixLen, kNTPrefix)) { | 188 if (0 == path.compare(0, kNTPrefixLen, kNTPrefix)) { |
189 path = path.substr(kNTPrefixLen); | 189 path = path.substr(kNTPrefixLen); |
190 is_nt_path = true; | 190 is_nt_path = true; |
191 } | 191 } |
192 | 192 |
193 DWORD size = MAX_PATH; | 193 DWORD size = MAX_PATH; |
194 scoped_ptr<wchar_t[]> long_path_buf(new wchar_t[size]); | 194 scoped_ptr<wchar_t[]> long_path_buf(new wchar_t[size]); |
195 | 195 |
196 DWORD return_value = ::GetLongPathName(path.c_str(), long_path_buf.get(), | 196 DWORD return_value = ::GetLongPathName(path.c_str(), long_path_buf.get(), |
197 size); | 197 size); |
198 while (return_value >= size) { | 198 while (return_value >= size) { |
199 size *= 2; | 199 size *= 2; |
200 long_path_buf.reset(new wchar_t[size]); | 200 long_path_buf.reset(new wchar_t[size]); |
201 return_value = ::GetLongPathName(path.c_str(), long_path_buf.get(), size); | 201 return_value = ::GetLongPathName(path.c_str(), long_path_buf.get(), size); |
202 } | 202 } |
203 | 203 |
204 DWORD last_error = ::GetLastError(); | 204 DWORD last_error = ::GetLastError(); |
205 if (0 == return_value && (ERROR_FILE_NOT_FOUND == last_error || | 205 if (0 == return_value && (ERROR_FILE_NOT_FOUND == last_error || |
206 ERROR_PATH_NOT_FOUND == last_error || | 206 ERROR_PATH_NOT_FOUND == last_error || |
207 ERROR_INVALID_NAME == last_error)) { | 207 ERROR_INVALID_NAME == last_error)) { |
208 // The file does not exist, but maybe a sub path needs to be expanded. | 208 // The file does not exist, but maybe a sub path needs to be expanded. |
209 std::wstring::size_type last_slash = path.rfind(L'\\'); | 209 base::string16::size_type last_slash = path.rfind(L'\\'); |
210 if (std::wstring::npos == last_slash) | 210 if (base::string16::npos == last_slash) |
211 return false; | 211 return false; |
212 | 212 |
213 std::wstring begin = path.substr(0, last_slash); | 213 base::string16 begin = path.substr(0, last_slash); |
214 std::wstring end = path.substr(last_slash); | 214 base::string16 end = path.substr(last_slash); |
215 if (!ConvertToLongPath(begin, &begin)) | 215 if (!ConvertToLongPath(begin, &begin)) |
216 return false; | 216 return false; |
217 | 217 |
218 // Ok, it worked. Let's reset the return value. | 218 // Ok, it worked. Let's reset the return value. |
219 path = begin + end; | 219 path = begin + end; |
220 return_value = 1; | 220 return_value = 1; |
221 } else if (0 != return_value) { | 221 } else if (0 != return_value) { |
222 path = long_path_buf.get(); | 222 path = long_path_buf.get(); |
223 } | 223 } |
224 | 224 |
225 if (return_value != 0) { | 225 if (return_value != 0) { |
226 if (is_nt_path) { | 226 if (is_nt_path) { |
227 *long_path = kNTPrefix; | 227 *long_path = kNTPrefix; |
228 *long_path += path; | 228 *long_path += path; |
229 } else { | 229 } else { |
230 *long_path = path; | 230 *long_path = path; |
231 } | 231 } |
232 | 232 |
233 return true; | 233 return true; |
234 } | 234 } |
235 | 235 |
236 return false; | 236 return false; |
237 } | 237 } |
238 | 238 |
239 bool GetPathFromHandle(HANDLE handle, std::wstring* path) { | 239 bool GetPathFromHandle(HANDLE handle, base::string16* path) { |
240 NtQueryObjectFunction NtQueryObject = NULL; | 240 NtQueryObjectFunction NtQueryObject = NULL; |
241 ResolveNTFunctionPtr("NtQueryObject", &NtQueryObject); | 241 ResolveNTFunctionPtr("NtQueryObject", &NtQueryObject); |
242 | 242 |
243 OBJECT_NAME_INFORMATION initial_buffer; | 243 OBJECT_NAME_INFORMATION initial_buffer; |
244 OBJECT_NAME_INFORMATION* name = &initial_buffer; | 244 OBJECT_NAME_INFORMATION* name = &initial_buffer; |
245 ULONG size = sizeof(initial_buffer); | 245 ULONG size = sizeof(initial_buffer); |
246 // Query the name information a first time to get the size of the name. | 246 // Query the name information a first time to get the size of the name. |
247 NTSTATUS status = NtQueryObject(handle, ObjectNameInformation, name, size, | 247 NTSTATUS status = NtQueryObject(handle, ObjectNameInformation, name, size, |
248 &size); | 248 &size); |
249 | 249 |
250 scoped_ptr<OBJECT_NAME_INFORMATION> name_ptr; | 250 scoped_ptr<OBJECT_NAME_INFORMATION> name_ptr; |
251 if (size) { | 251 if (size) { |
252 name = reinterpret_cast<OBJECT_NAME_INFORMATION*>(new BYTE[size]); | 252 name = reinterpret_cast<OBJECT_NAME_INFORMATION*>(new BYTE[size]); |
253 name_ptr.reset(name); | 253 name_ptr.reset(name); |
254 | 254 |
255 // Query the name information a second time to get the name of the | 255 // Query the name information a second time to get the name of the |
256 // object referenced by the handle. | 256 // object referenced by the handle. |
257 status = NtQueryObject(handle, ObjectNameInformation, name, size, &size); | 257 status = NtQueryObject(handle, ObjectNameInformation, name, size, &size); |
258 } | 258 } |
259 | 259 |
260 if (STATUS_SUCCESS != status) | 260 if (STATUS_SUCCESS != status) |
261 return false; | 261 return false; |
262 | 262 |
263 path->assign(name->ObjectName.Buffer, name->ObjectName.Length / | 263 path->assign(name->ObjectName.Buffer, name->ObjectName.Length / |
264 sizeof(name->ObjectName.Buffer[0])); | 264 sizeof(name->ObjectName.Buffer[0])); |
265 return true; | 265 return true; |
266 } | 266 } |
267 | 267 |
268 bool GetNtPathFromWin32Path(const std::wstring& path, std::wstring* nt_path) { | 268 bool GetNtPathFromWin32Path(const base::string16& path, |
| 269 base::string16* nt_path) { |
269 HANDLE file = ::CreateFileW(path.c_str(), 0, | 270 HANDLE file = ::CreateFileW(path.c_str(), 0, |
270 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, | 271 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, |
271 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); | 272 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); |
272 if (file == INVALID_HANDLE_VALUE) | 273 if (file == INVALID_HANDLE_VALUE) |
273 return false; | 274 return false; |
274 bool rv = GetPathFromHandle(file, nt_path); | 275 bool rv = GetPathFromHandle(file, nt_path); |
275 ::CloseHandle(file); | 276 ::CloseHandle(file); |
276 return rv; | 277 return rv; |
277 } | 278 } |
278 | 279 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 | 315 |
315 for (int tries = 1; !(*function_ptr) && tries < max_tries; ++tries) { | 316 for (int tries = 1; !(*function_ptr) && tries < max_tries; ++tries) { |
316 if (tries >= sleep_threshold) | 317 if (tries >= sleep_threshold) |
317 ::Sleep(1); | 318 ::Sleep(1); |
318 ntdll = ::GetModuleHandle(sandbox::kNtdllName); | 319 ntdll = ::GetModuleHandle(sandbox::kNtdllName); |
319 *function_ptr = ::GetProcAddress(ntdll, name); | 320 *function_ptr = ::GetProcAddress(ntdll, name); |
320 } | 321 } |
321 | 322 |
322 CHECK_NT(*function_ptr); | 323 CHECK_NT(*function_ptr); |
323 } | 324 } |
OLD | NEW |