Home | History | Annotate | Download | only in files
      1 // Copyright 2013 The Chromium 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 "base/files/memory_mapped_file.h"
      6 
      7 #include "base/files/file_path.h"
      8 #include "base/logging.h"
      9 #include "base/metrics/histogram.h"
     10 #include "base/strings/string16.h"
     11 #include "base/threading/thread_restrictions.h"
     12 
     13 namespace base {
     14 
     15 MemoryMappedFile::MemoryMappedFile()
     16     : file_(INVALID_HANDLE_VALUE),
     17       file_mapping_(INVALID_HANDLE_VALUE),
     18       data_(NULL),
     19       length_(INVALID_FILE_SIZE) {
     20 }
     21 
     22 bool MemoryMappedFile::InitializeAsImageSection(const FilePath& file_name) {
     23   if (IsValid())
     24     return false;
     25   file_ = CreatePlatformFile(file_name, PLATFORM_FILE_OPEN | PLATFORM_FILE_READ,
     26                              NULL, NULL);
     27 
     28   if (file_ == kInvalidPlatformFileValue) {
     29     DLOG(ERROR) << "Couldn't open " << file_name.AsUTF8Unsafe();
     30     return false;
     31   }
     32 
     33   if (!MapFileToMemoryInternalEx(SEC_IMAGE)) {
     34     CloseHandles();
     35     return false;
     36   }
     37 
     38   return true;
     39 }
     40 
     41 bool MemoryMappedFile::MapFileToMemoryInternal() {
     42   return MapFileToMemoryInternalEx(0);
     43 }
     44 
     45 bool MemoryMappedFile::MapFileToMemoryInternalEx(int flags) {
     46   ThreadRestrictions::AssertIOAllowed();
     47 
     48   if (file_ == INVALID_HANDLE_VALUE)
     49     return false;
     50 
     51   length_ = ::GetFileSize(file_, NULL);
     52   if (length_ == INVALID_FILE_SIZE)
     53     return false;
     54 
     55   file_mapping_ = ::CreateFileMapping(file_, NULL, PAGE_READONLY | flags,
     56                                       0, 0, NULL);
     57   if (!file_mapping_) {
     58     // According to msdn, system error codes are only reserved up to 15999.
     59     // http://msdn.microsoft.com/en-us/library/ms681381(v=VS.85).aspx.
     60     UMA_HISTOGRAM_ENUMERATION("MemoryMappedFile.CreateFileMapping",
     61                               logging::GetLastSystemErrorCode(), 16000);
     62     return false;
     63   }
     64 
     65   data_ = static_cast<uint8*>(
     66       ::MapViewOfFile(file_mapping_, FILE_MAP_READ, 0, 0, 0));
     67   if (!data_) {
     68     UMA_HISTOGRAM_ENUMERATION("MemoryMappedFile.MapViewOfFile",
     69                               logging::GetLastSystemErrorCode(), 16000);
     70   }
     71   return data_ != NULL;
     72 }
     73 
     74 void MemoryMappedFile::CloseHandles() {
     75   if (data_)
     76     ::UnmapViewOfFile(data_);
     77   if (file_mapping_ != INVALID_HANDLE_VALUE)
     78     ::CloseHandle(file_mapping_);
     79   if (file_ != INVALID_HANDLE_VALUE)
     80     ::CloseHandle(file_);
     81 
     82   data_ = NULL;
     83   file_mapping_ = file_ = INVALID_HANDLE_VALUE;
     84   length_ = INVALID_FILE_SIZE;
     85 }
     86 
     87 }  // namespace base
     88