| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/memory/shared_memory.h" | 5 #include "base/memory/shared_memory.h" |
| 6 | 6 |
| 7 #include <aclapi.h> | 7 #include <aclapi.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 | 10 |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 SharedMemory::SharedMemory(const std::wstring& name) | 145 SharedMemory::SharedMemory(const std::wstring& name) |
| 146 : external_section_(false), | 146 : external_section_(false), |
| 147 name_(name), | 147 name_(name), |
| 148 mapped_size_(0), | 148 mapped_size_(0), |
| 149 memory_(NULL), | 149 memory_(NULL), |
| 150 read_only_(false), | 150 read_only_(false), |
| 151 requested_size_(0) {} | 151 requested_size_(0) {} |
| 152 | 152 |
| 153 SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) | 153 SharedMemory::SharedMemory(const SharedMemoryHandle& handle, bool read_only) |
| 154 : external_section_(true), | 154 : external_section_(true), |
| 155 shm_(handle), |
| 155 mapped_size_(0), | 156 mapped_size_(0), |
| 156 memory_(NULL), | 157 memory_(NULL), |
| 157 read_only_(read_only), | 158 read_only_(read_only), |
| 158 requested_size_(0) { | 159 requested_size_(0) {} |
| 159 mapped_file_.Set(handle.GetHandle()); | |
| 160 } | |
| 161 | 160 |
| 162 SharedMemory::~SharedMemory() { | 161 SharedMemory::~SharedMemory() { |
| 163 Unmap(); | 162 Unmap(); |
| 164 Close(); | 163 Close(); |
| 165 } | 164 } |
| 166 | 165 |
| 167 // static | 166 // static |
| 168 bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) { | 167 bool SharedMemory::IsHandleValid(const SharedMemoryHandle& handle) { |
| 169 return handle.IsValid(); | 168 return handle.IsValid(); |
| 170 } | 169 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 189 | 188 |
| 190 bool SharedMemory::CreateAndMapAnonymous(size_t size) { | 189 bool SharedMemory::CreateAndMapAnonymous(size_t size) { |
| 191 return CreateAnonymous(size) && Map(size); | 190 return CreateAnonymous(size) && Map(size); |
| 192 } | 191 } |
| 193 | 192 |
| 194 bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { | 193 bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { |
| 195 // TODO(bsy,sehr): crbug.com/210609 NaCl forces us to round up 64k here, | 194 // TODO(bsy,sehr): crbug.com/210609 NaCl forces us to round up 64k here, |
| 196 // wasting 32k per mapping on average. | 195 // wasting 32k per mapping on average. |
| 197 static const size_t kSectionMask = 65536 - 1; | 196 static const size_t kSectionMask = 65536 - 1; |
| 198 DCHECK(!options.executable); | 197 DCHECK(!options.executable); |
| 199 DCHECK(!mapped_file_.Get()); | 198 DCHECK(!shm_.IsValid()); |
| 200 if (options.size == 0) { | 199 if (options.size == 0) { |
| 201 LogError(SIZE_ZERO, 0); | 200 LogError(SIZE_ZERO, 0); |
| 202 return false; | 201 return false; |
| 203 } | 202 } |
| 204 | 203 |
| 205 // Check maximum accounting for overflow. | 204 // Check maximum accounting for overflow. |
| 206 if (options.size > | 205 if (options.size > |
| 207 static_cast<size_t>(std::numeric_limits<int>::max()) - kSectionMask) { | 206 static_cast<size_t>(std::numeric_limits<int>::max()) - kSectionMask) { |
| 208 LogError(SIZE_TOO_LARGE, 0); | 207 LogError(SIZE_TOO_LARGE, 0); |
| 209 return false; | 208 return false; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 234 | 233 |
| 235 // Windows ignores DACLs on certain unnamed objects (like shared sections). | 234 // Windows ignores DACLs on certain unnamed objects (like shared sections). |
| 236 // So, we generate a random name when we need to enforce read-only. | 235 // So, we generate a random name when we need to enforce read-only. |
| 237 uint64_t rand_values[4]; | 236 uint64_t rand_values[4]; |
| 238 RandBytes(&rand_values, sizeof(rand_values)); | 237 RandBytes(&rand_values, sizeof(rand_values)); |
| 239 name_ = StringPrintf(L"CrSharedMem_%016llx%016llx%016llx%016llx", | 238 name_ = StringPrintf(L"CrSharedMem_%016llx%016llx%016llx%016llx", |
| 240 rand_values[0], rand_values[1], | 239 rand_values[0], rand_values[1], |
| 241 rand_values[2], rand_values[3]); | 240 rand_values[2], rand_values[3]); |
| 242 } | 241 } |
| 243 DCHECK(!name_.empty()); | 242 DCHECK(!name_.empty()); |
| 244 mapped_file_.Set(CreateFileMappingWithReducedPermissions(&sa, rounded_size, | 243 shm_ = SharedMemoryHandle(CreateFileMappingWithReducedPermissions( |
| 245 name_.c_str())); | 244 &sa, rounded_size, name_.c_str())); |
| 246 if (!mapped_file_.IsValid()) { | 245 if (!shm_.IsValid()) { |
| 247 // The error is logged within CreateFileMappingWithReducedPermissions(). | 246 // The error is logged within CreateFileMappingWithReducedPermissions(). |
| 248 return false; | 247 return false; |
| 249 } | 248 } |
| 250 | 249 |
| 251 requested_size_ = options.size; | 250 requested_size_ = options.size; |
| 252 | 251 |
| 253 // Check if the shared memory pre-exists. | 252 // Check if the shared memory pre-exists. |
| 254 if (GetLastError() == ERROR_ALREADY_EXISTS) { | 253 if (GetLastError() == ERROR_ALREADY_EXISTS) { |
| 255 // If the file already existed, set requested_size_ to 0 to show that | 254 // If the file already existed, set requested_size_ to 0 to show that |
| 256 // we don't know the size. | 255 // we don't know the size. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 267 LogError(SUCCESS, ERROR_SUCCESS); | 266 LogError(SUCCESS, ERROR_SUCCESS); |
| 268 return true; | 267 return true; |
| 269 } | 268 } |
| 270 | 269 |
| 271 bool SharedMemory::Delete(const std::string& name) { | 270 bool SharedMemory::Delete(const std::string& name) { |
| 272 // intentionally empty -- there is nothing for us to do on Windows. | 271 // intentionally empty -- there is nothing for us to do on Windows. |
| 273 return true; | 272 return true; |
| 274 } | 273 } |
| 275 | 274 |
| 276 bool SharedMemory::Open(const std::string& name, bool read_only) { | 275 bool SharedMemory::Open(const std::string& name, bool read_only) { |
| 277 DCHECK(!mapped_file_.Get()); | 276 DCHECK(!shm_.IsValid()); |
| 278 DWORD access = FILE_MAP_READ | SECTION_QUERY; | 277 DWORD access = FILE_MAP_READ | SECTION_QUERY; |
| 279 if (!read_only) | 278 if (!read_only) |
| 280 access |= FILE_MAP_WRITE; | 279 access |= FILE_MAP_WRITE; |
| 281 name_ = ASCIIToUTF16(name); | 280 name_ = ASCIIToUTF16(name); |
| 282 read_only_ = read_only; | 281 read_only_ = read_only; |
| 283 mapped_file_.Set( | 282 shm_ = SharedMemoryHandle( |
| 284 OpenFileMapping(access, false, name_.empty() ? nullptr : name_.c_str())); | 283 OpenFileMapping(access, false, name_.empty() ? nullptr : name_.c_str())); |
| 285 if (!mapped_file_.IsValid()) | 284 if (!shm_.IsValid()) |
| 286 return false; | 285 return false; |
| 287 // If a name specified assume it's an external section. | 286 // If a name specified assume it's an external section. |
| 288 if (!name_.empty()) | 287 if (!name_.empty()) |
| 289 external_section_ = true; | 288 external_section_ = true; |
| 290 // Note: size_ is not set in this case. | 289 // Note: size_ is not set in this case. |
| 291 return true; | 290 return true; |
| 292 } | 291 } |
| 293 | 292 |
| 294 bool SharedMemory::MapAt(off_t offset, size_t bytes) { | 293 bool SharedMemory::MapAt(off_t offset, size_t bytes) { |
| 295 if (!mapped_file_.Get()) | 294 if (!shm_.IsValid()) |
| 296 return false; | 295 return false; |
| 297 | 296 |
| 298 if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) | 297 if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) |
| 299 return false; | 298 return false; |
| 300 | 299 |
| 301 if (memory_) | 300 if (memory_) |
| 302 return false; | 301 return false; |
| 303 | 302 |
| 304 if (external_section_ && !IsSectionSafeToMap(mapped_file_.Get())) | 303 if (external_section_ && !IsSectionSafeToMap(shm_.GetHandle())) |
| 305 return false; | 304 return false; |
| 306 | 305 |
| 307 memory_ = MapViewOfFile( | 306 memory_ = MapViewOfFile( |
| 308 mapped_file_.Get(), | 307 shm_.GetHandle(), |
| 309 read_only_ ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, | 308 read_only_ ? FILE_MAP_READ : FILE_MAP_READ | FILE_MAP_WRITE, |
| 310 static_cast<uint64_t>(offset) >> 32, static_cast<DWORD>(offset), bytes); | 309 static_cast<uint64_t>(offset) >> 32, static_cast<DWORD>(offset), bytes); |
| 311 if (memory_ != NULL) { | 310 if (memory_ != NULL) { |
| 312 DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) & | 311 DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) & |
| 313 (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); | 312 (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); |
| 314 mapped_size_ = GetMemorySectionSize(memory_); | 313 mapped_size_ = GetMemorySectionSize(memory_); |
| 315 return true; | 314 return true; |
| 316 } | 315 } |
| 317 return false; | 316 return false; |
| 318 } | 317 } |
| 319 | 318 |
| 320 bool SharedMemory::Unmap() { | 319 bool SharedMemory::Unmap() { |
| 321 if (memory_ == NULL) | 320 if (memory_ == NULL) |
| 322 return false; | 321 return false; |
| 323 | 322 |
| 324 UnmapViewOfFile(memory_); | 323 UnmapViewOfFile(memory_); |
| 325 memory_ = NULL; | 324 memory_ = NULL; |
| 326 return true; | 325 return true; |
| 327 } | 326 } |
| 328 | 327 |
| 329 SharedMemoryHandle SharedMemory::GetReadOnlyHandle() { | 328 SharedMemoryHandle SharedMemory::GetReadOnlyHandle() { |
| 330 HANDLE result; | 329 HANDLE result; |
| 331 ProcessHandle process = GetCurrentProcess(); | 330 ProcessHandle process = GetCurrentProcess(); |
| 332 if (!::DuplicateHandle(process, mapped_file_.Get(), process, &result, | 331 if (!::DuplicateHandle(process, shm_.GetHandle(), process, &result, |
| 333 FILE_MAP_READ | SECTION_QUERY, FALSE, 0)) { | 332 FILE_MAP_READ | SECTION_QUERY, FALSE, 0)) { |
| 334 return SharedMemoryHandle(); | 333 return SharedMemoryHandle(); |
| 335 } | 334 } |
| 336 SharedMemoryHandle handle = SharedMemoryHandle(result); | 335 SharedMemoryHandle handle = SharedMemoryHandle(result); |
| 337 handle.SetOwnershipPassesToIPC(true); | 336 handle.SetOwnershipPassesToIPC(true); |
| 338 return handle; | 337 return handle; |
| 339 } | 338 } |
| 340 | 339 |
| 341 void SharedMemory::Close() { | 340 void SharedMemory::Close() { |
| 342 mapped_file_.Close(); | 341 if (shm_.IsValid()) { |
| 342 shm_.Close(); |
| 343 shm_ = SharedMemoryHandle(); |
| 344 } |
| 343 } | 345 } |
| 344 | 346 |
| 345 SharedMemoryHandle SharedMemory::handle() const { | 347 SharedMemoryHandle SharedMemory::handle() const { |
| 346 return SharedMemoryHandle(mapped_file_.Get()); | 348 return shm_; |
| 347 } | 349 } |
| 348 | 350 |
| 349 SharedMemoryHandle SharedMemory::TakeHandle() { | 351 SharedMemoryHandle SharedMemory::TakeHandle() { |
| 350 SharedMemoryHandle handle(mapped_file_.Take()); | 352 SharedMemoryHandle handle(shm_); |
| 351 handle.SetOwnershipPassesToIPC(true); | 353 handle.SetOwnershipPassesToIPC(true); |
| 354 shm_ = SharedMemoryHandle(); |
| 352 memory_ = nullptr; | 355 memory_ = nullptr; |
| 353 mapped_size_ = 0; | 356 mapped_size_ = 0; |
| 354 return handle; | 357 return handle; |
| 355 } | 358 } |
| 356 | 359 |
| 357 } // namespace base | 360 } // namespace base |
| OLD | NEW |