mapping_win.cc 3.0 KB
Newer Older
M
Michael Goderbauer 已提交
1
// Copyright 2013 The Flutter Authors. All rights reserved.
2 3 4 5 6 7
// 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>
8 9
#include <io.h>
#include <windows.h>
10 11 12

#include <type_traits>

13
#include "flutter/fml/file.h"
14
#include "flutter/fml/platform/win/errors_win.h"
15
#include "flutter/fml/platform/win/wstring_conversion.h"
16 17 18 19 20 21 22

namespace fml {

Mapping::Mapping() = default;

Mapping::~Mapping() = default;

23 24 25 26 27 28 29 30 31
static bool IsWritable(
    std::initializer_list<FileMapping::Protection> protection_flags) {
  for (auto protection : protection_flags) {
    if (protection == FileMapping::Protection::kWrite) {
      return true;
    }
  }
  return false;
}
32

33 34 35 36 37 38 39 40 41 42 43 44
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)
45 46
    : size_(0), mapping_(nullptr) {
  if (!fd.is_valid()) {
47 48 49
    return;
  }

50 51 52 53 54
  const auto mapping_size = ::GetFileSize(fd.get(), nullptr);

  if (mapping_size == INVALID_FILE_SIZE) {
    FML_DLOG(ERROR) << "Invalid file size. " << GetLastErrorMessage();
    return;
55 56
  }

57 58 59 60 61
  if (mapping_size == 0) {
    valid_ = true;
    return;
  }

62 63 64 65 66 67 68 69 70 71
  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;
  }
72

73 74 75 76 77 78
  mapping_handle_.reset(::CreateFileMapping(fd.get(),       // hFile
                                            nullptr,        // lpAttributes
                                            protect_flags,  // flProtect
                                            0,              // dwMaximumSizeHigh
                                            0,              // dwMaximumSizeLow
                                            nullptr         // lpName
79
                                            ));
80

81
  if (!mapping_handle_.is_valid()) {
82 83 84
    return;
  }

85 86 87 88
  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));
89

90
  if (mapping == nullptr) {
91
    FML_DLOG(ERROR) << "Could not set up file mapping. "
92 93 94 95 96 97
                    << GetLastErrorMessage();
    return;
  }

  mapping_ = mapping;
  size_ = mapping_size;
98
  valid_ = true;
99 100 101
  if (IsWritable(protections)) {
    mutable_mapping_ = mapping_;
  }
102 103 104 105
}

FileMapping::~FileMapping() {
  if (mapping_ != nullptr) {
106
    UnmapViewOfFile(mapping_);
107 108 109 110 111 112 113 114 115 116 117
  }
}

size_t FileMapping::GetSize() const {
  return size_;
}

const uint8_t* FileMapping::GetMapping() const {
  return mapping_;
}

118 119 120 121
bool FileMapping::IsValid() const {
  return valid_;
}

122
}  // namespace fml