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