| // Copyright 2013 The Flutter Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "flutter/fml/mapping.h" | |
| #include <fcntl.h> | |
| #include <io.h> | |
| #include <windows.h> | |
| #include <type_traits> | |
| #include "flutter/fml/file.h" | |
| #include "flutter/fml/platform/win/errors_win.h" | |
| #include "flutter/fml/platform/win/wstring_conversion.h" | |
| namespace fml { | |
| Mapping::Mapping() = default; | |
| Mapping::~Mapping() = default; | |
| static bool IsWritable( | |
| std::initializer_list<FileMapping::Protection> protection_flags) { | |
| for (auto protection : protection_flags) { | |
| if (protection == FileMapping::Protection::kWrite) { | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| static bool IsExecutable( | |
| std::initializer_list<FileMapping::Protection> protection_flags) { | |
| for (auto protection : protection_flags) { | |
| if (protection == FileMapping::Protection::kExecute) { | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| FileMapping::FileMapping(const fml::UniqueFD& fd, | |
| std::initializer_list<Protection> protections) | |
| : size_(0), mapping_(nullptr) { | |
| if (!fd.is_valid()) { | |
| return; | |
| } | |
| const auto mapping_size = ::GetFileSize(fd.get(), nullptr); | |
| if (mapping_size == INVALID_FILE_SIZE) { | |
| FML_DLOG(ERROR) << "Invalid file size. " << GetLastErrorMessage(); | |
| return; | |
| } | |
| if (mapping_size == 0) { | |
| valid_ = true; | |
| return; | |
| } | |
| DWORD protect_flags = 0; | |
| bool read_only = !IsWritable(protections); | |
| if (IsExecutable(protections)) { | |
| protect_flags = PAGE_EXECUTE_READ; | |
| } else if (read_only) { | |
| protect_flags = PAGE_READONLY; | |
| } else { | |
| protect_flags = PAGE_READWRITE; | |
| } | |
| mapping_handle_.reset(::CreateFileMapping(fd.get(), // hFile | |
| nullptr, // lpAttributes | |
| protect_flags, // flProtect | |
| 0, // dwMaximumSizeHigh | |
| 0, // dwMaximumSizeLow | |
| nullptr // lpName | |
| )); | |
| if (!mapping_handle_.is_valid()) { | |
| return; | |
| } | |
| const DWORD desired_access = read_only ? FILE_MAP_READ : FILE_MAP_WRITE; | |
| auto mapping = reinterpret_cast<uint8_t*>( | |
| MapViewOfFile(mapping_handle_.get(), desired_access, 0, 0, mapping_size)); | |
| if (mapping == nullptr) { | |
| FML_DLOG(ERROR) << "Could not set up file mapping. " | |
| << GetLastErrorMessage(); | |
| return; | |
| } | |
| mapping_ = mapping; | |
| size_ = mapping_size; | |
| valid_ = true; | |
| if (IsWritable(protections)) { | |
| mutable_mapping_ = mapping_; | |
| } | |
| } | |
| FileMapping::~FileMapping() { | |
| if (mapping_ != nullptr) { | |
| UnmapViewOfFile(mapping_); | |
| } | |
| } | |
| size_t FileMapping::GetSize() const { | |
| return size_; | |
| } | |
| const uint8_t* FileMapping::GetMapping() const { | |
| return mapping_; | |
| } | |
| bool FileMapping::IsDontNeedSafe() const { | |
| return mutable_mapping_ == nullptr; | |
| } | |
| bool FileMapping::IsValid() const { | |
| return valid_; | |
| } | |
| } // namespace fml |