henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2004 The WebRTC Project Authors. All rights reserved. |
| 3 | * |
| 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 |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
Henrik Kjellander | 0072511 | 2017-06-30 15:14:45 +0200 | [diff] [blame] | 11 | #include "webrtc/base/win32filesystem.h" |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 12 | |
Henrik Kjellander | 0072511 | 2017-06-30 15:14:45 +0200 | [diff] [blame] | 13 | #include "webrtc/base/win32.h" |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 14 | #include <shellapi.h> |
| 15 | #include <shlobj.h> |
| 16 | #include <tchar.h> |
| 17 | |
jbauch | 555604a | 2016-04-26 03:13:22 -0700 | [diff] [blame] | 18 | #include <memory> |
| 19 | |
Henrik Kjellander | 0072511 | 2017-06-30 15:14:45 +0200 | [diff] [blame] | 20 | #include "webrtc/base/arraysize.h" |
| 21 | #include "webrtc/base/checks.h" |
| 22 | #include "webrtc/base/fileutils.h" |
| 23 | #include "webrtc/base/pathutils.h" |
| 24 | #include "webrtc/base/stream.h" |
| 25 | #include "webrtc/base/stringutils.h" |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 26 | |
| 27 | // In several places in this file, we test the integrity level of the process |
| 28 | // before calling GetLongPathName. We do this because calling GetLongPathName |
| 29 | // when running under protected mode IE (a low integrity process) can result in |
| 30 | // a virtualized path being returned, which is wrong if you only plan to read. |
| 31 | // TODO: Waiting to hear back from IE team on whether this is the |
| 32 | // best approach; IEIsProtectedModeProcess is another possible solution. |
| 33 | |
| 34 | namespace rtc { |
| 35 | |
| 36 | bool Win32Filesystem::CreateFolder(const Pathname &pathname) { |
| 37 | if (pathname.pathname().empty() || !pathname.filename().empty()) |
| 38 | return false; |
| 39 | |
| 40 | std::wstring path16; |
| 41 | if (!Utf8ToWindowsFilename(pathname.pathname(), &path16)) |
| 42 | return false; |
| 43 | |
| 44 | DWORD res = ::GetFileAttributes(path16.c_str()); |
| 45 | if (res != INVALID_FILE_ATTRIBUTES) { |
| 46 | // Something exists at this location, check if it is a directory |
| 47 | return ((res & FILE_ATTRIBUTE_DIRECTORY) != 0); |
| 48 | } else if ((GetLastError() != ERROR_FILE_NOT_FOUND) |
| 49 | && (GetLastError() != ERROR_PATH_NOT_FOUND)) { |
| 50 | // Unexpected error |
| 51 | return false; |
| 52 | } |
| 53 | |
| 54 | // Directory doesn't exist, look up one directory level |
| 55 | if (!pathname.parent_folder().empty()) { |
| 56 | Pathname parent(pathname); |
| 57 | parent.SetFolder(pathname.parent_folder()); |
| 58 | if (!CreateFolder(parent)) { |
| 59 | return false; |
| 60 | } |
| 61 | } |
| 62 | |
deadbeef | 37f5ecf | 2017-02-27 14:06:41 -0800 | [diff] [blame] | 63 | return (::CreateDirectory(path16.c_str(), nullptr) != 0); |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 64 | } |
| 65 | |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 66 | bool Win32Filesystem::DeleteFile(const Pathname &filename) { |
| 67 | LOG(LS_INFO) << "Deleting file " << filename.pathname(); |
| 68 | if (!IsFile(filename)) { |
nisse | ede5da4 | 2017-01-12 05:15:36 -0800 | [diff] [blame] | 69 | RTC_DCHECK(IsFile(filename)); |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 70 | return false; |
| 71 | } |
| 72 | return ::DeleteFile(ToUtf16(filename.pathname()).c_str()) != 0; |
| 73 | } |
| 74 | |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 75 | bool Win32Filesystem::GetTemporaryFolder(Pathname &pathname, bool create, |
| 76 | const std::string *append) { |
| 77 | wchar_t buffer[MAX_PATH + 1]; |
tfarina | 5237aaf | 2015-11-10 23:44:30 -0800 | [diff] [blame] | 78 | if (!::GetTempPath(arraysize(buffer), buffer)) |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 79 | return false; |
| 80 | if (!IsCurrentProcessLowIntegrity() && |
tfarina | 5237aaf | 2015-11-10 23:44:30 -0800 | [diff] [blame] | 81 | !::GetLongPathName(buffer, buffer, arraysize(buffer))) |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 82 | return false; |
| 83 | size_t len = strlen(buffer); |
| 84 | if ((len > 0) && (buffer[len-1] != '\\')) { |
tfarina | 5237aaf | 2015-11-10 23:44:30 -0800 | [diff] [blame] | 85 | len += strcpyn(buffer + len, arraysize(buffer) - len, L"\\"); |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 86 | } |
tfarina | 5237aaf | 2015-11-10 23:44:30 -0800 | [diff] [blame] | 87 | if (len >= arraysize(buffer) - 1) |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 88 | return false; |
| 89 | pathname.clear(); |
| 90 | pathname.SetFolder(ToUtf8(buffer)); |
deadbeef | 37f5ecf | 2017-02-27 14:06:41 -0800 | [diff] [blame] | 91 | if (append != nullptr) { |
nisse | ede5da4 | 2017-01-12 05:15:36 -0800 | [diff] [blame] | 92 | RTC_DCHECK(!append->empty()); |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 93 | pathname.AppendFolder(*append); |
| 94 | } |
| 95 | return !create || CreateFolder(pathname); |
| 96 | } |
| 97 | |
| 98 | std::string Win32Filesystem::TempFilename(const Pathname &dir, |
| 99 | const std::string &prefix) { |
| 100 | wchar_t filename[MAX_PATH]; |
| 101 | if (::GetTempFileName(ToUtf16(dir.pathname()).c_str(), |
| 102 | ToUtf16(prefix).c_str(), 0, filename) != 0) |
| 103 | return ToUtf8(filename); |
nisse | c80e741 | 2017-01-11 05:56:46 -0800 | [diff] [blame] | 104 | RTC_NOTREACHED(); |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 105 | return ""; |
| 106 | } |
| 107 | |
| 108 | bool Win32Filesystem::MoveFile(const Pathname &old_path, |
| 109 | const Pathname &new_path) { |
| 110 | if (!IsFile(old_path)) { |
nisse | ede5da4 | 2017-01-12 05:15:36 -0800 | [diff] [blame] | 111 | RTC_DCHECK(IsFile(old_path)); |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 112 | return false; |
| 113 | } |
| 114 | LOG(LS_INFO) << "Moving " << old_path.pathname() |
| 115 | << " to " << new_path.pathname(); |
| 116 | return ::MoveFile(ToUtf16(old_path.pathname()).c_str(), |
| 117 | ToUtf16(new_path.pathname()).c_str()) != 0; |
| 118 | } |
| 119 | |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 120 | bool Win32Filesystem::IsFolder(const Pathname &path) { |
| 121 | WIN32_FILE_ATTRIBUTE_DATA data = {0}; |
| 122 | if (0 == ::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(), |
| 123 | GetFileExInfoStandard, &data)) |
| 124 | return false; |
| 125 | return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == |
| 126 | FILE_ATTRIBUTE_DIRECTORY; |
| 127 | } |
| 128 | |
| 129 | bool Win32Filesystem::IsFile(const Pathname &path) { |
| 130 | WIN32_FILE_ATTRIBUTE_DATA data = {0}; |
| 131 | if (0 == ::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(), |
| 132 | GetFileExInfoStandard, &data)) |
| 133 | return false; |
| 134 | return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0; |
| 135 | } |
| 136 | |
| 137 | bool Win32Filesystem::IsAbsent(const Pathname& path) { |
| 138 | WIN32_FILE_ATTRIBUTE_DATA data = {0}; |
| 139 | if (0 != ::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(), |
| 140 | GetFileExInfoStandard, &data)) |
| 141 | return false; |
| 142 | DWORD err = ::GetLastError(); |
| 143 | return (ERROR_FILE_NOT_FOUND == err || ERROR_PATH_NOT_FOUND == err); |
| 144 | } |
| 145 | |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 146 | bool Win32Filesystem::GetFileSize(const Pathname &pathname, size_t *size) { |
| 147 | WIN32_FILE_ATTRIBUTE_DATA data = {0}; |
| 148 | if (::GetFileAttributesEx(ToUtf16(pathname.pathname()).c_str(), |
| 149 | GetFileExInfoStandard, &data) == 0) |
| 150 | return false; |
| 151 | *size = data.nFileSizeLow; |
| 152 | return true; |
| 153 | } |
| 154 | |
henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 155 | } // namespace rtc |