| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 FileStream *Win32Filesystem::OpenFile(const Pathname &filename, | 65 FileStream *Win32Filesystem::OpenFile(const Pathname &filename, |
| 66 const std::string &mode) { | 66 const std::string &mode) { |
| 67 FileStream *fs = new FileStream(); | 67 FileStream *fs = new FileStream(); |
| 68 if (fs && !fs->Open(filename.pathname().c_str(), mode.c_str(), NULL)) { | 68 if (fs && !fs->Open(filename.pathname().c_str(), mode.c_str(), NULL)) { |
| 69 delete fs; | 69 delete fs; |
| 70 fs = NULL; | 70 fs = NULL; |
| 71 } | 71 } |
| 72 return fs; | 72 return fs; |
| 73 } | 73 } |
| 74 | 74 |
| 75 bool Win32Filesystem::CreatePrivateFile(const Pathname &filename) { | |
| 76 // To make the file private to the current user, we first must construct a | |
| 77 // SECURITY_DESCRIPTOR specifying an ACL. This code is mostly based upon | |
| 78 // http://msdn.microsoft.com/en-us/library/ms707085%28VS.85%29.aspx | |
| 79 | |
| 80 // Get the current process token. | |
| 81 HANDLE process_token = INVALID_HANDLE_VALUE; | |
| 82 if (!::OpenProcessToken(::GetCurrentProcess(), | |
| 83 TOKEN_QUERY, | |
| 84 &process_token)) { | |
| 85 LOG_ERR(LS_ERROR) << "OpenProcessToken() failed"; | |
| 86 return false; | |
| 87 } | |
| 88 | |
| 89 // Get the size of its TOKEN_USER structure. Return value is not checked | |
| 90 // because we expect it to fail. | |
| 91 DWORD token_user_size = 0; | |
| 92 (void)::GetTokenInformation(process_token, | |
| 93 TokenUser, | |
| 94 NULL, | |
| 95 0, | |
| 96 &token_user_size); | |
| 97 | |
| 98 // Get the TOKEN_USER structure. | |
| 99 std::unique_ptr<char[]> token_user_bytes(new char[token_user_size]); | |
| 100 PTOKEN_USER token_user = reinterpret_cast<PTOKEN_USER>( | |
| 101 token_user_bytes.get()); | |
| 102 memset(token_user, 0, token_user_size); | |
| 103 BOOL success = ::GetTokenInformation(process_token, | |
| 104 TokenUser, | |
| 105 token_user, | |
| 106 token_user_size, | |
| 107 &token_user_size); | |
| 108 // We're now done with this. | |
| 109 ::CloseHandle(process_token); | |
| 110 if (!success) { | |
| 111 LOG_ERR(LS_ERROR) << "GetTokenInformation() failed"; | |
| 112 return false; | |
| 113 } | |
| 114 | |
| 115 if (!IsValidSid(token_user->User.Sid)) { | |
| 116 LOG_ERR(LS_ERROR) << "Current process has invalid user SID"; | |
| 117 return false; | |
| 118 } | |
| 119 | |
| 120 // Compute size needed for an ACL that allows access to just this user. | |
| 121 int acl_size = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + | |
| 122 GetLengthSid(token_user->User.Sid); | |
| 123 | |
| 124 // Allocate it. | |
| 125 std::unique_ptr<char[]> acl_bytes(new char[acl_size]); | |
| 126 PACL acl = reinterpret_cast<PACL>(acl_bytes.get()); | |
| 127 memset(acl, 0, acl_size); | |
| 128 if (!::InitializeAcl(acl, acl_size, ACL_REVISION)) { | |
| 129 LOG_ERR(LS_ERROR) << "InitializeAcl() failed"; | |
| 130 return false; | |
| 131 } | |
| 132 | |
| 133 // Allow access to only the current user. | |
| 134 if (!::AddAccessAllowedAce(acl, | |
| 135 ACL_REVISION, | |
| 136 GENERIC_READ | GENERIC_WRITE | STANDARD_RIGHTS_ALL, | |
| 137 token_user->User.Sid)) { | |
| 138 LOG_ERR(LS_ERROR) << "AddAccessAllowedAce() failed"; | |
| 139 return false; | |
| 140 } | |
| 141 | |
| 142 // Now make the security descriptor. | |
| 143 SECURITY_DESCRIPTOR security_descriptor; | |
| 144 if (!::InitializeSecurityDescriptor(&security_descriptor, | |
| 145 SECURITY_DESCRIPTOR_REVISION)) { | |
| 146 LOG_ERR(LS_ERROR) << "InitializeSecurityDescriptor() failed"; | |
| 147 return false; | |
| 148 } | |
| 149 | |
| 150 // Put the ACL in it. | |
| 151 if (!::SetSecurityDescriptorDacl(&security_descriptor, | |
| 152 TRUE, | |
| 153 acl, | |
| 154 FALSE)) { | |
| 155 LOG_ERR(LS_ERROR) << "SetSecurityDescriptorDacl() failed"; | |
| 156 return false; | |
| 157 } | |
| 158 | |
| 159 // Finally create the file. | |
| 160 SECURITY_ATTRIBUTES security_attributes; | |
| 161 security_attributes.nLength = sizeof(security_attributes); | |
| 162 security_attributes.lpSecurityDescriptor = &security_descriptor; | |
| 163 security_attributes.bInheritHandle = FALSE; | |
| 164 HANDLE handle = ::CreateFile( | |
| 165 ToUtf16(filename.pathname()).c_str(), | |
| 166 GENERIC_READ | GENERIC_WRITE, | |
| 167 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, | |
| 168 &security_attributes, | |
| 169 CREATE_NEW, | |
| 170 0, | |
| 171 NULL); | |
| 172 if (INVALID_HANDLE_VALUE == handle) { | |
| 173 LOG_ERR(LS_ERROR) << "CreateFile() failed"; | |
| 174 return false; | |
| 175 } | |
| 176 if (!::CloseHandle(handle)) { | |
| 177 LOG_ERR(LS_ERROR) << "CloseFile() failed"; | |
| 178 // Continue. | |
| 179 } | |
| 180 return true; | |
| 181 } | |
| 182 | |
| 183 bool Win32Filesystem::DeleteFile(const Pathname &filename) { | 75 bool Win32Filesystem::DeleteFile(const Pathname &filename) { |
| 184 LOG(LS_INFO) << "Deleting file " << filename.pathname(); | 76 LOG(LS_INFO) << "Deleting file " << filename.pathname(); |
| 185 if (!IsFile(filename)) { | 77 if (!IsFile(filename)) { |
| 186 ASSERT(IsFile(filename)); | 78 ASSERT(IsFile(filename)); |
| 187 return false; | 79 return false; |
| 188 } | 80 } |
| 189 return ::DeleteFile(ToUtf16(filename.pathname()).c_str()) != 0; | 81 return ::DeleteFile(ToUtf16(filename.pathname()).c_str()) != 0; |
| 190 } | 82 } |
| 191 | 83 |
| 192 bool Win32Filesystem::DeleteEmptyFolder(const Pathname &folder) { | 84 bool Win32Filesystem::DeleteEmptyFolder(const Pathname &folder) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 if (!IsFile(old_path)) { | 126 if (!IsFile(old_path)) { |
| 235 ASSERT(IsFile(old_path)); | 127 ASSERT(IsFile(old_path)); |
| 236 return false; | 128 return false; |
| 237 } | 129 } |
| 238 LOG(LS_INFO) << "Moving " << old_path.pathname() | 130 LOG(LS_INFO) << "Moving " << old_path.pathname() |
| 239 << " to " << new_path.pathname(); | 131 << " to " << new_path.pathname(); |
| 240 return ::MoveFile(ToUtf16(old_path.pathname()).c_str(), | 132 return ::MoveFile(ToUtf16(old_path.pathname()).c_str(), |
| 241 ToUtf16(new_path.pathname()).c_str()) != 0; | 133 ToUtf16(new_path.pathname()).c_str()) != 0; |
| 242 } | 134 } |
| 243 | 135 |
| 244 bool Win32Filesystem::MoveFolder(const Pathname &old_path, | |
| 245 const Pathname &new_path) { | |
| 246 if (!IsFolder(old_path)) { | |
| 247 ASSERT(IsFolder(old_path)); | |
| 248 return false; | |
| 249 } | |
| 250 LOG(LS_INFO) << "Moving " << old_path.pathname() | |
| 251 << " to " << new_path.pathname(); | |
| 252 if (::MoveFile(ToUtf16(old_path.pathname()).c_str(), | |
| 253 ToUtf16(new_path.pathname()).c_str()) == 0) { | |
| 254 if (::GetLastError() != ERROR_NOT_SAME_DEVICE) { | |
| 255 LOG_GLE(LS_ERROR) << "Failed to move file"; | |
| 256 return false; | |
| 257 } | |
| 258 if (!CopyFolder(old_path, new_path)) | |
| 259 return false; | |
| 260 if (!DeleteFolderAndContents(old_path)) | |
| 261 return false; | |
| 262 } | |
| 263 return true; | |
| 264 } | |
| 265 | |
| 266 bool Win32Filesystem::IsFolder(const Pathname &path) { | 136 bool Win32Filesystem::IsFolder(const Pathname &path) { |
| 267 WIN32_FILE_ATTRIBUTE_DATA data = {0}; | 137 WIN32_FILE_ATTRIBUTE_DATA data = {0}; |
| 268 if (0 == ::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(), | 138 if (0 == ::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(), |
| 269 GetFileExInfoStandard, &data)) | 139 GetFileExInfoStandard, &data)) |
| 270 return false; | 140 return false; |
| 271 return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == | 141 return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == |
| 272 FILE_ATTRIBUTE_DIRECTORY; | 142 FILE_ATTRIBUTE_DIRECTORY; |
| 273 } | 143 } |
| 274 | 144 |
| 275 bool Win32Filesystem::IsFile(const Pathname &path) { | 145 bool Win32Filesystem::IsFile(const Pathname &path) { |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 (PULARGE_INTEGER)free_bytes, | 286 (PULARGE_INTEGER)free_bytes, |
| 417 (PULARGE_INTEGER)&total_number_of_bytes, | 287 (PULARGE_INTEGER)&total_number_of_bytes, |
| 418 (PULARGE_INTEGER)&total_number_of_free_bytes)) { | 288 (PULARGE_INTEGER)&total_number_of_free_bytes)) { |
| 419 return true; | 289 return true; |
| 420 } else { | 290 } else { |
| 421 LOG(LS_VERBOSE) << "GetDiskFreeSpaceEx returns error."; | 291 LOG(LS_VERBOSE) << "GetDiskFreeSpaceEx returns error."; |
| 422 return false; | 292 return false; |
| 423 } | 293 } |
| 424 } | 294 } |
| 425 | 295 |
| 426 Pathname Win32Filesystem::GetCurrentDirectory() { | |
| 427 Pathname cwd; | |
| 428 int path_len = 0; | |
| 429 std::unique_ptr<wchar_t[]> path; | |
| 430 do { | |
| 431 int needed = ::GetCurrentDirectory(path_len, path.get()); | |
| 432 if (needed == 0) { | |
| 433 // Error. | |
| 434 LOG_GLE(LS_ERROR) << "::GetCurrentDirectory() failed"; | |
| 435 return cwd; // returns empty pathname | |
| 436 } | |
| 437 if (needed <= path_len) { | |
| 438 // It wrote successfully. | |
| 439 break; | |
| 440 } | |
| 441 // Else need to re-alloc for "needed". | |
| 442 path.reset(new wchar_t[needed]); | |
| 443 path_len = needed; | |
| 444 } while (true); | |
| 445 cwd.SetFolder(ToUtf8(path.get())); | |
| 446 return cwd; | |
| 447 } | |
| 448 | |
| 449 // TODO: Consider overriding DeleteFolderAndContents for speed and potentially | |
| 450 // better OS integration (recycle bin?) | |
| 451 /* | |
| 452 std::wstring temp_path16 = ToUtf16(temp_path.pathname()); | |
| 453 temp_path16.append(1, '*'); | |
| 454 temp_path16.append(1, '\0'); | |
| 455 | |
| 456 SHFILEOPSTRUCT file_op = { 0 }; | |
| 457 file_op.wFunc = FO_DELETE; | |
| 458 file_op.pFrom = temp_path16.c_str(); | |
| 459 file_op.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT; | |
| 460 return (0 == SHFileOperation(&file_op)); | |
| 461 */ | |
| 462 | |
| 463 } // namespace rtc | 296 } // namespace rtc |
| OLD | NEW |