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