1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include <private/primpl.h>
7 #include <string.h>
8 #include <prshm.h>
9 #include <prerr.h>
10 #include <prmem.h>
11
12 #if defined(PR_HAVE_WIN32_NAMED_SHARED_MEMORY)
13
14 extern PRLogModuleInfo *_pr_shm_lm;
15
16 /*
17 * NSPR-to-NT access right mapping table for file-mapping objects.
18 *
19 * The OR of these three access masks must equal FILE_MAP_ALL_ACCESS.
20 * This is because if a file-mapping object with the specified name
21 * exists, CreateFileMapping requests full access to the existing
22 * object.
23 */
24 static DWORD filemapAccessTable[] = {
25 FILE_MAP_ALL_ACCESS & ~FILE_MAP_WRITE, /* read */
26 FILE_MAP_ALL_ACCESS & ~FILE_MAP_READ, /* write */
27 0 /* execute */
28 };
29
_MD_OpenSharedMemory(const char * name,PRSize size,PRIntn flags,PRIntn mode)30 extern PRSharedMemory * _MD_OpenSharedMemory(
31 const char *name,
32 PRSize size,
33 PRIntn flags,
34 PRIntn mode
35 )
36 {
37 char ipcname[PR_IPC_NAME_SIZE];
38 PRStatus rc = PR_SUCCESS;
39 DWORD dwHi, dwLo;
40 PRSharedMemory *shm;
41 DWORD flProtect = ( PAGE_READWRITE );
42 SECURITY_ATTRIBUTES sa;
43 LPSECURITY_ATTRIBUTES lpSA = NULL;
44 PSECURITY_DESCRIPTOR pSD = NULL;
45 PACL pACL = NULL;
46
47 rc = _PR_MakeNativeIPCName( name, ipcname, PR_IPC_NAME_SIZE, _PRIPCShm );
48 if ( PR_FAILURE == rc )
49 {
50 PR_SetError(PR_UNKNOWN_ERROR, 0 );
51 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: name is invalid"));
52 return(NULL);
53 }
54
55 shm = PR_NEWZAP( PRSharedMemory );
56 if ( NULL == shm )
57 {
58 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 );
59 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: New PRSharedMemory out of memory"));
60 return(NULL);
61 }
62
63 shm->ipcname = PR_MALLOC( (PRUint32) (strlen( ipcname ) + 1) );
64 if ( NULL == shm->ipcname )
65 {
66 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 );
67 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: New shm->ipcname out of memory"));
68 PR_DELETE(shm);
69 return(NULL);
70 }
71
72 /* copy args to struct */
73 strcpy( shm->ipcname, ipcname );
74 shm->size = size;
75 shm->mode = mode;
76 shm->flags = flags;
77 shm->ident = _PR_SHM_IDENT;
78
79 if (flags & PR_SHM_CREATE ) {
80 dwHi = (DWORD) (((PRUint64) shm->size >> 32) & 0xffffffff);
81 dwLo = (DWORD) (shm->size & 0xffffffff);
82
83 if (_PR_NT_MakeSecurityDescriptorACL(mode, filemapAccessTable,
84 &pSD, &pACL) == PR_SUCCESS) {
85 sa.nLength = sizeof(sa);
86 sa.lpSecurityDescriptor = pSD;
87 sa.bInheritHandle = FALSE;
88 lpSA = &sa;
89 }
90 #ifdef WINCE
91 {
92 /*
93 * This is assuming that the name will never be larger than
94 * MAX_PATH. Should we dynamically allocate?
95 */
96 PRUnichar wideIpcName[MAX_PATH];
97 MultiByteToWideChar(CP_ACP, 0, shm->ipcname, -1,
98 wideIpcName, MAX_PATH);
99 shm->handle = CreateFileMappingW(
100 (HANDLE)-1,
101 lpSA,
102 flProtect,
103 dwHi,
104 dwLo,
105 wideIpcName);
106 }
107 #else
108 shm->handle = CreateFileMappingA(
109 (HANDLE)-1,
110 lpSA,
111 flProtect,
112 dwHi,
113 dwLo,
114 shm->ipcname);
115 #endif
116 if (lpSA != NULL) {
117 _PR_NT_FreeSecurityDescriptorACL(pSD, pACL);
118 }
119
120 if ( NULL == shm->handle ) {
121 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG,
122 ( "PR_OpenSharedMemory: CreateFileMapping() failed: %s",
123 shm->ipcname ));
124 _PR_MD_MAP_DEFAULT_ERROR( GetLastError());
125 PR_FREEIF( shm->ipcname )
126 PR_DELETE( shm );
127 return(NULL);
128 } else {
129 if (( flags & PR_SHM_EXCL) && ( GetLastError() == ERROR_ALREADY_EXISTS )) {
130 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG,
131 ( "PR_OpenSharedMemory: Request exclusive & already exists",
132 shm->ipcname ));
133 PR_SetError( PR_FILE_EXISTS_ERROR, ERROR_ALREADY_EXISTS );
134 CloseHandle( shm->handle );
135 PR_FREEIF( shm->ipcname )
136 PR_DELETE( shm );
137 return(NULL);
138 } else {
139 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG,
140 ( "PR_OpenSharedMemory: CreateFileMapping() success: %s, handle: %d",
141 shm->ipcname, shm->handle ));
142 return(shm);
143 }
144 }
145 } else {
146 #ifdef WINCE
147 PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 );
148 shm->handle = NULL; /* OpenFileMapping not supported */
149 #else
150 shm->handle = OpenFileMapping( FILE_MAP_WRITE, TRUE, shm->ipcname );
151 #endif
152 if ( NULL == shm->handle ) {
153 _PR_MD_MAP_DEFAULT_ERROR( GetLastError());
154 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG,
155 ( "PR_OpenSharedMemory: OpenFileMapping() failed: %s, error: %d",
156 shm->ipcname, PR_GetOSError()));
157 PR_FREEIF( shm->ipcname );
158 PR_DELETE( shm );
159 return(NULL);
160 } else {
161 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG,
162 ( "PR_OpenSharedMemory: OpenFileMapping() success: %s, handle: %d",
163 shm->ipcname, shm->handle ));
164 return(shm);
165 }
166 }
167 /* returns from separate paths */
168 }
169
_MD_AttachSharedMemory(PRSharedMemory * shm,PRIntn flags)170 extern void * _MD_AttachSharedMemory( PRSharedMemory *shm, PRIntn flags )
171 {
172 PRUint32 access = FILE_MAP_WRITE;
173 void *addr;
174
175 PR_ASSERT( shm->ident == _PR_SHM_IDENT );
176
177 if ( PR_SHM_READONLY & flags ) {
178 access = FILE_MAP_READ;
179 }
180
181 addr = MapViewOfFile( shm->handle,
182 access,
183 0, 0,
184 shm->size );
185
186 if ( NULL == addr ) {
187 _PR_MD_MAP_DEFAULT_ERROR( GetLastError());
188 PR_LOG( _pr_shm_lm, PR_LOG_ERROR,
189 ("_MD_AttachSharedMemory: MapViewOfFile() failed. OSerror: %d", PR_GetOSError()));
190 }
191
192 return( addr );
193 } /* end _MD_ATTACH_SHARED_MEMORY() */
194
195
_MD_DetachSharedMemory(PRSharedMemory * shm,void * addr)196 extern PRStatus _MD_DetachSharedMemory( PRSharedMemory *shm, void *addr )
197 {
198 PRStatus rc = PR_SUCCESS;
199 BOOL wrc;
200
201 PR_ASSERT( shm->ident == _PR_SHM_IDENT );
202
203 wrc = UnmapViewOfFile( addr );
204 if ( FALSE == wrc )
205 {
206 _PR_MD_MAP_DEFAULT_ERROR( GetLastError());
207 PR_LOG( _pr_shm_lm, PR_LOG_ERROR,
208 ("_MD_DetachSharedMemory: UnmapViewOfFile() failed. OSerror: %d", PR_GetOSError()));
209 rc = PR_FAILURE;
210 }
211
212 return( rc );
213 }
214
215
_MD_CloseSharedMemory(PRSharedMemory * shm)216 extern PRStatus _MD_CloseSharedMemory( PRSharedMemory *shm )
217 {
218 PRStatus rc = PR_SUCCESS;
219 BOOL wrc;
220
221 PR_ASSERT( shm->ident == _PR_SHM_IDENT );
222
223 wrc = CloseHandle( shm->handle );
224 if ( FALSE == wrc )
225 {
226 _PR_MD_MAP_DEFAULT_ERROR( GetLastError());
227 PR_LOG( _pr_shm_lm, PR_LOG_ERROR,
228 ("_MD_CloseSharedMemory: CloseHandle() failed. OSerror: %d", PR_GetOSError()));
229 rc = PR_FAILURE;
230 }
231 PR_FREEIF( shm->ipcname );
232 PR_DELETE( shm );
233
234 return( rc );
235 } /* end _MD_CLOSE_SHARED_MEMORY() */
236
_MD_DeleteSharedMemory(const char * name)237 extern PRStatus _MD_DeleteSharedMemory( const char *name )
238 {
239 return( PR_SUCCESS );
240 }
241
242
243 /*
244 ** Windows implementation of anonymous memory (file) map
245 */
246 extern PRLogModuleInfo *_pr_shma_lm;
247
_md_OpenAnonFileMap(const char * dirName,PRSize size,PRFileMapProtect prot)248 extern PRFileMap* _md_OpenAnonFileMap(
249 const char *dirName,
250 PRSize size,
251 PRFileMapProtect prot
252 )
253 {
254 PRFileMap *fm;
255 HANDLE hFileMap;
256
257 fm = PR_CreateFileMap( (PRFileDesc*)-1, size, prot );
258 if ( NULL == fm ) {
259 PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
260 ("_md_OpenAnonFileMap(): PR_CreateFileMap(): failed"));
261 goto Finished;
262 }
263
264 /*
265 ** Make fm->md.hFileMap inheritable. We can't use
266 ** GetHandleInformation and SetHandleInformation
267 ** because these two functions fail with
268 ** ERROR_CALL_NOT_IMPLEMENTED on Win95.
269 */
270 if (DuplicateHandle(GetCurrentProcess(), fm->md.hFileMap,
271 GetCurrentProcess(), &hFileMap,
272 0, TRUE /* inheritable */,
273 DUPLICATE_SAME_ACCESS) == FALSE) {
274 PR_SetError( PR_UNKNOWN_ERROR, GetLastError() );
275 PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
276 ("_md_OpenAnonFileMap(): DuplicateHandle(): failed"));
277 PR_CloseFileMap( fm );
278 fm = NULL;
279 goto Finished;
280 }
281 CloseHandle(fm->md.hFileMap);
282 fm->md.hFileMap = hFileMap;
283
284 Finished:
285 return(fm);
286 } /* end md_OpenAnonFileMap() */
287
288 /*
289 ** _md_ExportFileMapAsString()
290 **
291 */
_md_ExportFileMapAsString(PRFileMap * fm,PRSize bufSize,char * buf)292 extern PRStatus _md_ExportFileMapAsString(
293 PRFileMap *fm,
294 PRSize bufSize,
295 char *buf
296 )
297 {
298 PRIntn written;
299
300 written = PR_snprintf( buf, (PRUint32) bufSize, "%d:%" PR_PRIdOSFD ":%ld",
301 (PRIntn)fm->prot, (PROsfd)fm->md.hFileMap, (PRInt32)fm->md.dwAccess );
302
303 PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
304 ("_md_ExportFileMapAsString(): prot: %x, hFileMap: %x, dwAccess: %x",
305 fm->prot, fm->md.hFileMap, fm->md.dwAccess ));
306
307 return((written == -1)? PR_FAILURE : PR_SUCCESS);
308 } /* end _md_ExportFileMapAsString() */
309
310
311 /*
312 ** _md_ImportFileMapFromString()
313 **
314 */
_md_ImportFileMapFromString(const char * fmstring)315 extern PRFileMap * _md_ImportFileMapFromString(
316 const char *fmstring
317 )
318 {
319 PRIntn prot;
320 PROsfd hFileMap;
321 PRInt32 dwAccess;
322 PRFileMap *fm = NULL;
323
324 PR_sscanf( fmstring, "%d:%" PR_SCNdOSFD ":%ld",
325 &prot, &hFileMap, &dwAccess );
326
327 fm = PR_NEWZAP(PRFileMap);
328 if ( NULL == fm ) {
329 PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
330 ("_md_ImportFileMapFromString(): PR_NEWZAP(): Failed"));
331 return(fm);
332 }
333
334 fm->prot = (PRFileMapProtect)prot;
335 fm->md.hFileMap = (HANDLE)hFileMap;
336 fm->md.dwAccess = (DWORD)dwAccess;
337 fm->fd = (PRFileDesc*)-1;
338
339 PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
340 ("_md_ImportFileMapFromString(): fm: %p, prot: %d, hFileMap: %8.8x, dwAccess: %8.8x, fd: %x",
341 fm, prot, fm->md.hFileMap, fm->md.dwAccess, fm->fd));
342 return(fm);
343 } /* end _md_ImportFileMapFromString() */
344
345 #else
346 Error! Why is PR_HAVE_WIN32_NAMED_SHARED_MEMORY not defined?
347 #endif /* PR_HAVE_WIN32_NAMED_SHARED_MEMORY */
348 /* --- end w32shm.c --- */
349