shared_memory_win.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1// Copyright (c) 2006-2008 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/shared_memory.h" 6 7#include "base/logging.h" 8#include "base/win_util.h" 9 10namespace base { 11 12SharedMemory::SharedMemory() 13 : mapped_file_(NULL), 14 memory_(NULL), 15 read_only_(false), 16 max_size_(0), 17 lock_(NULL) { 18} 19 20SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only) 21 : mapped_file_(handle), 22 memory_(NULL), 23 read_only_(read_only), 24 max_size_(0), 25 lock_(NULL) { 26} 27 28SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only, 29 ProcessHandle process) 30 : mapped_file_(NULL), 31 memory_(NULL), 32 read_only_(read_only), 33 max_size_(0), 34 lock_(NULL) { 35 ::DuplicateHandle(process, handle, 36 GetCurrentProcess(), &mapped_file_, 37 STANDARD_RIGHTS_REQUIRED | 38 (read_only_ ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS), 39 FALSE, 0); 40} 41 42SharedMemory::~SharedMemory() { 43 Close(); 44 if (lock_ != NULL) 45 CloseHandle(lock_); 46} 47 48// static 49bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) { 50 return handle != NULL; 51} 52 53// static 54SharedMemoryHandle SharedMemory::NULLHandle() { 55 return NULL; 56} 57 58// static 59void SharedMemory::CloseHandle(const SharedMemoryHandle& handle) { 60 DCHECK(handle != NULL); 61 ::CloseHandle(handle); 62} 63 64bool SharedMemory::Create(const std::wstring &name, bool read_only, 65 bool open_existing, uint32 size) { 66 DCHECK(mapped_file_ == NULL); 67 68 // NaCl's memory allocator requires 0mod64K alignment and size for 69 // shared memory objects. To allow passing shared memory to NaCl, 70 // therefore we round the size actually created to the nearest 64K unit. 71 // To avoid client impact, we continue to retain the size as the 72 // actual requested size. 73 uint32 rounded_size = (size + 0xffff) & ~0xffff; 74 name_ = name; 75 read_only_ = read_only; 76 mapped_file_ = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, 77 read_only_ ? PAGE_READONLY : PAGE_READWRITE, 0, 78 static_cast<DWORD>(rounded_size), 79 name.empty() ? NULL : name.c_str()); 80 if (!mapped_file_) 81 return false; 82 83 // Check if the shared memory pre-exists. 84 if (GetLastError() == ERROR_ALREADY_EXISTS && !open_existing) { 85 Close(); 86 return false; 87 } 88 max_size_ = size; 89 return true; 90} 91 92bool SharedMemory::Delete(const std::wstring& name) { 93 // intentionally empty -- there is nothing for us to do on Windows. 94 return true; 95} 96 97bool SharedMemory::Open(const std::wstring &name, bool read_only) { 98 DCHECK(mapped_file_ == NULL); 99 100 name_ = name; 101 read_only_ = read_only; 102 mapped_file_ = OpenFileMapping( 103 read_only_ ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS, false, 104 name.empty() ? NULL : name.c_str()); 105 if (mapped_file_ != NULL) { 106 // Note: size_ is not set in this case. 107 return true; 108 } 109 return false; 110} 111 112bool SharedMemory::Map(uint32 bytes) { 113 if (mapped_file_ == NULL) 114 return false; 115 116 memory_ = MapViewOfFile(mapped_file_, 117 read_only_ ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS, 0, 0, bytes); 118 if (memory_ != NULL) { 119 return true; 120 } 121 return false; 122} 123 124bool SharedMemory::Unmap() { 125 if (memory_ == NULL) 126 return false; 127 128 UnmapViewOfFile(memory_); 129 memory_ = NULL; 130 return true; 131} 132 133bool SharedMemory::ShareToProcessCommon(ProcessHandle process, 134 SharedMemoryHandle *new_handle, 135 bool close_self) { 136 *new_handle = 0; 137 DWORD access = STANDARD_RIGHTS_REQUIRED | FILE_MAP_READ; 138 DWORD options = 0; 139 HANDLE mapped_file = mapped_file_; 140 HANDLE result; 141 if (!read_only_) 142 access |= FILE_MAP_WRITE; 143 if (close_self) { 144 // DUPLICATE_CLOSE_SOURCE causes DuplicateHandle to close mapped_file. 145 options = DUPLICATE_CLOSE_SOURCE; 146 mapped_file_ = NULL; 147 Unmap(); 148 } 149 150 if (process == GetCurrentProcess() && close_self) { 151 *new_handle = mapped_file; 152 return true; 153 } 154 155 if (!DuplicateHandle(GetCurrentProcess(), mapped_file, process, 156 &result, access, FALSE, options)) 157 return false; 158 *new_handle = result; 159 return true; 160} 161 162 163void SharedMemory::Close() { 164 if (memory_ != NULL) { 165 UnmapViewOfFile(memory_); 166 memory_ = NULL; 167 } 168 169 if (mapped_file_ != NULL) { 170 CloseHandle(mapped_file_); 171 mapped_file_ = NULL; 172 } 173} 174 175void SharedMemory::Lock() { 176 if (lock_ == NULL) { 177 std::wstring name = name_; 178 name.append(L"lock"); 179 lock_ = CreateMutex(NULL, FALSE, name.c_str()); 180 DCHECK(lock_ != NULL); 181 if (lock_ == NULL) { 182 DLOG(ERROR) << "Could not create mutex" << GetLastError(); 183 return; // there is nothing good we can do here. 184 } 185 } 186 WaitForSingleObject(lock_, INFINITE); 187} 188 189void SharedMemory::Unlock() { 190 DCHECK(lock_ != NULL); 191 ReleaseMutex(lock_); 192} 193 194SharedMemoryHandle SharedMemory::handle() const { 195 return mapped_file_; 196} 197 198} // namespace base 199