| 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 |