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/. */
6 #include <private/primpl.h>
12 #if defined(PR_HAVE_WIN32_NAMED_SHARED_MEMORY)
14 extern PRLogModuleInfo
* _pr_shm_lm
;
17 * NSPR-to-NT access right mapping table for file-mapping objects.
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
24 static DWORD filemapAccessTable
[] = {
25 FILE_MAP_ALL_ACCESS
& ~FILE_MAP_WRITE
, /* read */
26 FILE_MAP_ALL_ACCESS
& ~FILE_MAP_READ
, /* write */
30 extern PRSharedMemory
* _MD_OpenSharedMemory(const char* name
, PRSize size
,
31 PRIntn flags
, PRIntn mode
) {
32 char ipcname
[PR_IPC_NAME_SIZE
];
33 PRStatus rc
= PR_SUCCESS
;
36 DWORD flProtect
= (PAGE_READWRITE
);
37 SECURITY_ATTRIBUTES sa
;
38 LPSECURITY_ATTRIBUTES lpSA
= NULL
;
39 PSECURITY_DESCRIPTOR pSD
= NULL
;
42 rc
= _PR_MakeNativeIPCName(name
, ipcname
, PR_IPC_NAME_SIZE
, _PRIPCShm
);
43 if (PR_FAILURE
== rc
) {
44 PR_SetError(PR_UNKNOWN_ERROR
, 0);
45 PR_LOG(_pr_shm_lm
, PR_LOG_DEBUG
, ("PR_OpenSharedMemory: name is invalid"));
49 shm
= PR_NEWZAP(PRSharedMemory
);
51 PR_SetError(PR_OUT_OF_MEMORY_ERROR
, 0);
52 PR_LOG(_pr_shm_lm
, PR_LOG_DEBUG
,
53 ("PR_OpenSharedMemory: New PRSharedMemory out of memory"));
57 shm
->ipcname
= PR_MALLOC((PRUint32
)(strlen(ipcname
) + 1));
58 if (NULL
== shm
->ipcname
) {
59 PR_SetError(PR_OUT_OF_MEMORY_ERROR
, 0);
60 PR_LOG(_pr_shm_lm
, PR_LOG_DEBUG
,
61 ("PR_OpenSharedMemory: New shm->ipcname out of memory"));
66 /* copy args to struct */
67 strcpy(shm
->ipcname
, ipcname
);
71 shm
->ident
= _PR_SHM_IDENT
;
73 if (flags
& PR_SHM_CREATE
) {
74 dwHi
= (DWORD
)(((PRUint64
)shm
->size
>> 32) & 0xffffffff);
75 dwLo
= (DWORD
)(shm
->size
& 0xffffffff);
77 if (_PR_NT_MakeSecurityDescriptorACL(mode
, filemapAccessTable
, &pSD
,
78 &pACL
) == PR_SUCCESS
) {
79 sa
.nLength
= sizeof(sa
);
80 sa
.lpSecurityDescriptor
= pSD
;
81 sa
.bInheritHandle
= FALSE
;
87 * This is assuming that the name will never be larger than
88 * MAX_PATH. Should we dynamically allocate?
90 PRUnichar wideIpcName
[MAX_PATH
];
91 MultiByteToWideChar(CP_ACP
, 0, shm
->ipcname
, -1, wideIpcName
, MAX_PATH
);
92 shm
->handle
= CreateFileMappingW((HANDLE
)-1, lpSA
, flProtect
, dwHi
, dwLo
,
96 shm
->handle
= CreateFileMappingA((HANDLE
)-1, lpSA
, flProtect
, dwHi
, dwLo
,
100 _PR_NT_FreeSecurityDescriptorACL(pSD
, pACL
);
103 if (NULL
== shm
->handle
) {
104 PR_LOG(_pr_shm_lm
, PR_LOG_DEBUG
,
105 ("PR_OpenSharedMemory: CreateFileMapping() failed: %s",
107 _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
108 PR_FREEIF(shm
->ipcname
)
112 if ((flags
& PR_SHM_EXCL
) && (GetLastError() == ERROR_ALREADY_EXISTS
)) {
113 PR_LOG(_pr_shm_lm
, PR_LOG_DEBUG
,
114 ("PR_OpenSharedMemory: Request exclusive & already exists",
116 PR_SetError(PR_FILE_EXISTS_ERROR
, ERROR_ALREADY_EXISTS
);
117 CloseHandle(shm
->handle
);
118 PR_FREEIF(shm
->ipcname
)
123 _pr_shm_lm
, PR_LOG_DEBUG
,
124 ("PR_OpenSharedMemory: CreateFileMapping() success: %s, handle: %d",
125 shm
->ipcname
, shm
->handle
));
131 PR_SetError(PR_NOT_IMPLEMENTED_ERROR
, 0);
132 shm
->handle
= NULL
; /* OpenFileMapping not supported */
134 shm
->handle
= OpenFileMapping(FILE_MAP_WRITE
, TRUE
, shm
->ipcname
);
136 if (NULL
== shm
->handle
) {
137 _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
138 PR_LOG(_pr_shm_lm
, PR_LOG_DEBUG
,
139 ("PR_OpenSharedMemory: OpenFileMapping() failed: %s, error: %d",
140 shm
->ipcname
, PR_GetOSError()));
141 PR_FREEIF(shm
->ipcname
);
145 PR_LOG(_pr_shm_lm
, PR_LOG_DEBUG
,
146 ("PR_OpenSharedMemory: OpenFileMapping() success: %s, handle: %d",
147 shm
->ipcname
, shm
->handle
));
151 /* returns from separate paths */
154 extern void* _MD_AttachSharedMemory(PRSharedMemory
* shm
, PRIntn flags
) {
155 PRUint32 access
= FILE_MAP_WRITE
;
158 PR_ASSERT(shm
->ident
== _PR_SHM_IDENT
);
160 if (PR_SHM_READONLY
& flags
) {
161 access
= FILE_MAP_READ
;
164 addr
= MapViewOfFile(shm
->handle
, access
, 0, 0, shm
->size
);
167 _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
168 PR_LOG(_pr_shm_lm
, PR_LOG_ERROR
,
169 ("_MD_AttachSharedMemory: MapViewOfFile() failed. OSerror: %d",
174 } /* end _MD_ATTACH_SHARED_MEMORY() */
176 extern PRStatus
_MD_DetachSharedMemory(PRSharedMemory
* shm
, void* addr
) {
177 PRStatus rc
= PR_SUCCESS
;
180 PR_ASSERT(shm
->ident
== _PR_SHM_IDENT
);
182 wrc
= UnmapViewOfFile(addr
);
184 _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
185 PR_LOG(_pr_shm_lm
, PR_LOG_ERROR
,
186 ("_MD_DetachSharedMemory: UnmapViewOfFile() failed. OSerror: %d",
194 extern PRStatus
_MD_CloseSharedMemory(PRSharedMemory
* shm
) {
195 PRStatus rc
= PR_SUCCESS
;
198 PR_ASSERT(shm
->ident
== _PR_SHM_IDENT
);
200 wrc
= CloseHandle(shm
->handle
);
202 _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
203 PR_LOG(_pr_shm_lm
, PR_LOG_ERROR
,
204 ("_MD_CloseSharedMemory: CloseHandle() failed. OSerror: %d",
208 PR_FREEIF(shm
->ipcname
);
212 } /* end _MD_CLOSE_SHARED_MEMORY() */
214 extern PRStatus
_MD_DeleteSharedMemory(const char* name
) {
219 ** Windows implementation of anonymous memory (file) map
221 extern PRLogModuleInfo
* _pr_shma_lm
;
223 extern PRFileMap
* _md_OpenAnonFileMap(const char* dirName
, PRSize size
,
224 PRFileMapProtect prot
) {
228 fm
= PR_CreateFileMap((PRFileDesc
*)-1, size
, prot
);
230 PR_LOG(_pr_shma_lm
, PR_LOG_DEBUG
,
231 ("_md_OpenAnonFileMap(): PR_CreateFileMap(): failed"));
236 ** Make fm->md.hFileMap inheritable. We can't use
237 ** GetHandleInformation and SetHandleInformation
238 ** because these two functions fail with
239 ** ERROR_CALL_NOT_IMPLEMENTED on Win95.
241 if (DuplicateHandle(GetCurrentProcess(), fm
->md
.hFileMap
, GetCurrentProcess(),
242 &hFileMap
, 0, TRUE
/* inheritable */,
243 DUPLICATE_SAME_ACCESS
) == FALSE
) {
244 PR_SetError(PR_UNKNOWN_ERROR
, GetLastError());
245 PR_LOG(_pr_shma_lm
, PR_LOG_DEBUG
,
246 ("_md_OpenAnonFileMap(): DuplicateHandle(): failed"));
251 CloseHandle(fm
->md
.hFileMap
);
252 fm
->md
.hFileMap
= hFileMap
;
256 } /* end md_OpenAnonFileMap() */
259 ** _md_ExportFileMapAsString()
262 extern PRStatus
_md_ExportFileMapAsString(PRFileMap
* fm
, PRSize bufSize
,
266 written
= PR_snprintf(buf
, (PRUint32
)bufSize
, "%d:%" PR_PRIdOSFD
":%ld",
267 (PRIntn
)fm
->prot
, (PROsfd
)fm
->md
.hFileMap
,
268 (PRInt32
)fm
->md
.dwAccess
);
270 PR_LOG(_pr_shma_lm
, PR_LOG_DEBUG
,
271 ("_md_ExportFileMapAsString(): prot: %x, hFileMap: %x, dwAccess: %x",
272 fm
->prot
, fm
->md
.hFileMap
, fm
->md
.dwAccess
));
274 return ((written
== -1) ? PR_FAILURE
: PR_SUCCESS
);
275 } /* end _md_ExportFileMapAsString() */
278 ** _md_ImportFileMapFromString()
281 extern PRFileMap
* _md_ImportFileMapFromString(const char* fmstring
) {
285 PRFileMap
* fm
= NULL
;
287 PR_sscanf(fmstring
, "%d:%" PR_SCNdOSFD
":%ld", &prot
, &hFileMap
, &dwAccess
);
289 fm
= PR_NEWZAP(PRFileMap
);
291 PR_LOG(_pr_shma_lm
, PR_LOG_DEBUG
,
292 ("_md_ImportFileMapFromString(): PR_NEWZAP(): Failed"));
296 fm
->prot
= (PRFileMapProtect
)prot
;
297 fm
->md
.hFileMap
= (HANDLE
)hFileMap
;
298 fm
->md
.dwAccess
= (DWORD
)dwAccess
;
299 fm
->fd
= (PRFileDesc
*)-1;
301 PR_LOG(_pr_shma_lm
, PR_LOG_DEBUG
,
302 ("_md_ImportFileMapFromString(): fm: %p, prot: %d, hFileMap: %8.8x, "
303 "dwAccess: %8.8x, fd: %x",
304 fm
, prot
, fm
->md
.hFileMap
, fm
->md
.dwAccess
, fm
->fd
));
306 } /* end _md_ImportFileMapFromString() */
309 Error
!Why is PR_HAVE_WIN32_NAMED_SHARED_MEMORY
not defined
311 #endif /* PR_HAVE_WIN32_NAMED_SHARED_MEMORY */
312 /* --- end w32shm.c --- */