• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "flutter/fml/mapping.h"
6 
7 #include <fcntl.h>
8 #include <io.h>
9 #include <windows.h>
10 
11 #include <type_traits>
12 
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 namespace fml {
18 
19 Mapping::Mapping() = default;
20 
21 Mapping::~Mapping() = default;
22 
IsWritable(std::initializer_list<FileMapping::Protection> protection_flags)23 static bool IsWritable(
24     std::initializer_list<FileMapping::Protection> protection_flags) {
25   for (auto protection : protection_flags) {
26     if (protection == FileMapping::Protection::kWrite) {
27       return true;
28     }
29   }
30   return false;
31 }
32 
IsExecutable(std::initializer_list<FileMapping::Protection> protection_flags)33 static bool IsExecutable(
34     std::initializer_list<FileMapping::Protection> protection_flags) {
35   for (auto protection : protection_flags) {
36     if (protection == FileMapping::Protection::kExecute) {
37       return true;
38     }
39   }
40   return false;
41 }
42 
FileMapping(const fml::UniqueFD & fd,std::initializer_list<Protection> protections)43 FileMapping::FileMapping(const fml::UniqueFD& fd,
44                          std::initializer_list<Protection> protections)
45     : size_(0), mapping_(nullptr) {
46   if (!fd.is_valid()) {
47     return;
48   }
49 
50   const auto mapping_size = ::GetFileSize(fd.get(), nullptr);
51 
52   if (mapping_size == INVALID_FILE_SIZE) {
53     FML_DLOG(ERROR) << "Invalid file size. " << GetLastErrorMessage();
54     return;
55   }
56 
57   if (mapping_size == 0) {
58     valid_ = true;
59     return;
60   }
61 
62   DWORD protect_flags = 0;
63   bool read_only = !IsWritable(protections);
64 
65   if (IsExecutable(protections)) {
66     protect_flags = PAGE_EXECUTE_READ;
67   } else if (read_only) {
68     protect_flags = PAGE_READONLY;
69   } else {
70     protect_flags = PAGE_READWRITE;
71   }
72 
73   mapping_handle_.reset(::CreateFileMapping(fd.get(),       // hFile
74                                             nullptr,        // lpAttributes
75                                             protect_flags,  // flProtect
76                                             0,              // dwMaximumSizeHigh
77                                             0,              // dwMaximumSizeLow
78                                             nullptr         // lpName
79                                             ));
80 
81   if (!mapping_handle_.is_valid()) {
82     return;
83   }
84 
85   const DWORD desired_access = read_only ? FILE_MAP_READ : FILE_MAP_WRITE;
86 
87   auto mapping = reinterpret_cast<uint8_t*>(
88       MapViewOfFile(mapping_handle_.get(), desired_access, 0, 0, mapping_size));
89 
90   if (mapping == nullptr) {
91     FML_DLOG(ERROR) << "Could not setup file mapping. "
92                     << GetLastErrorMessage();
93     return;
94   }
95 
96   mapping_ = mapping;
97   size_ = mapping_size;
98   valid_ = true;
99   if (IsWritable(protections)) {
100     mutable_mapping_ = mapping_;
101   }
102 }
103 
~FileMapping()104 FileMapping::~FileMapping() {
105   if (mapping_ != nullptr) {
106     UnmapViewOfFile(mapping_);
107   }
108 }
109 
GetSize() const110 size_t FileMapping::GetSize() const {
111   return size_;
112 }
113 
GetMapping() const114 const uint8_t* FileMapping::GetMapping() const {
115   return mapping_;
116 }
117 
IsValid() const118 bool FileMapping::IsValid() const {
119   return valid_;
120 }
121 
122 }  // namespace fml
123