w32shm.c (9543B)
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 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; 34 DWORD dwHi, dwLo; 35 PRSharedMemory* shm; 36 DWORD flProtect = (PAGE_READWRITE); 37 SECURITY_ATTRIBUTES sa; 38 LPSECURITY_ATTRIBUTES lpSA = NULL; 39 PSECURITY_DESCRIPTOR pSD = NULL; 40 PACL pACL = NULL; 41 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")); 46 return (NULL); 47 } 48 49 shm = PR_NEWZAP(PRSharedMemory); 50 if (NULL == shm) { 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")); 54 return (NULL); 55 } 56 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")); 62 PR_DELETE(shm); 63 return (NULL); 64 } 65 66 /* copy args to struct */ 67 strcpy(shm->ipcname, ipcname); 68 shm->size = size; 69 shm->mode = mode; 70 shm->flags = flags; 71 shm->ident = _PR_SHM_IDENT; 72 73 if (flags & PR_SHM_CREATE) { 74 dwHi = (DWORD)(((PRUint64)shm->size >> 32) & 0xffffffff); 75 dwLo = (DWORD)(shm->size & 0xffffffff); 76 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; 82 lpSA = &sa; 83 } 84 # ifdef WINCE 85 { 86 /* 87 * This is assuming that the name will never be larger than 88 * MAX_PATH. Should we dynamically allocate? 89 */ 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, 93 wideIpcName); 94 } 95 # else 96 shm->handle = CreateFileMappingA((HANDLE)-1, lpSA, flProtect, dwHi, dwLo, 97 shm->ipcname); 98 # endif 99 if (lpSA != NULL) { 100 _PR_NT_FreeSecurityDescriptorACL(pSD, pACL); 101 } 102 103 if (NULL == shm->handle) { 104 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 105 ("PR_OpenSharedMemory: CreateFileMapping() failed: %s", 106 shm->ipcname)); 107 _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); 108 PR_FREEIF(shm->ipcname) 109 PR_DELETE(shm); 110 return (NULL); 111 } else { 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", 115 shm->ipcname)); 116 PR_SetError(PR_FILE_EXISTS_ERROR, ERROR_ALREADY_EXISTS); 117 CloseHandle(shm->handle); 118 PR_FREEIF(shm->ipcname) 119 PR_DELETE(shm); 120 return (NULL); 121 } else { 122 PR_LOG( 123 _pr_shm_lm, PR_LOG_DEBUG, 124 ("PR_OpenSharedMemory: CreateFileMapping() success: %s, handle: %d", 125 shm->ipcname, shm->handle)); 126 return (shm); 127 } 128 } 129 } else { 130 # ifdef WINCE 131 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); 132 shm->handle = NULL; /* OpenFileMapping not supported */ 133 # else 134 shm->handle = OpenFileMapping(FILE_MAP_WRITE, TRUE, shm->ipcname); 135 # endif 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); 142 PR_DELETE(shm); 143 return (NULL); 144 } else { 145 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 146 ("PR_OpenSharedMemory: OpenFileMapping() success: %s, handle: %d", 147 shm->ipcname, shm->handle)); 148 return (shm); 149 } 150 } 151 /* returns from separate paths */ 152 } 153 154 extern void* _MD_AttachSharedMemory(PRSharedMemory* shm, PRIntn flags) { 155 PRUint32 access = FILE_MAP_WRITE; 156 void* addr; 157 158 PR_ASSERT(shm->ident == _PR_SHM_IDENT); 159 160 if (PR_SHM_READONLY & flags) { 161 access = FILE_MAP_READ; 162 } 163 164 addr = MapViewOfFile(shm->handle, access, 0, 0, shm->size); 165 166 if (NULL == addr) { 167 _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); 168 PR_LOG(_pr_shm_lm, PR_LOG_ERROR, 169 ("_MD_AttachSharedMemory: MapViewOfFile() failed. OSerror: %d", 170 PR_GetOSError())); 171 } 172 173 return (addr); 174 } /* end _MD_ATTACH_SHARED_MEMORY() */ 175 176 extern PRStatus _MD_DetachSharedMemory(PRSharedMemory* shm, void* addr) { 177 PRStatus rc = PR_SUCCESS; 178 BOOL wrc; 179 180 PR_ASSERT(shm->ident == _PR_SHM_IDENT); 181 182 wrc = UnmapViewOfFile(addr); 183 if (FALSE == wrc) { 184 _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); 185 PR_LOG(_pr_shm_lm, PR_LOG_ERROR, 186 ("_MD_DetachSharedMemory: UnmapViewOfFile() failed. OSerror: %d", 187 PR_GetOSError())); 188 rc = PR_FAILURE; 189 } 190 191 return (rc); 192 } 193 194 extern PRStatus _MD_CloseSharedMemory(PRSharedMemory* shm) { 195 PRStatus rc = PR_SUCCESS; 196 BOOL wrc; 197 198 PR_ASSERT(shm->ident == _PR_SHM_IDENT); 199 200 wrc = CloseHandle(shm->handle); 201 if (FALSE == wrc) { 202 _PR_MD_MAP_DEFAULT_ERROR(GetLastError()); 203 PR_LOG(_pr_shm_lm, PR_LOG_ERROR, 204 ("_MD_CloseSharedMemory: CloseHandle() failed. OSerror: %d", 205 PR_GetOSError())); 206 rc = PR_FAILURE; 207 } 208 PR_FREEIF(shm->ipcname); 209 PR_DELETE(shm); 210 211 return (rc); 212 } /* end _MD_CLOSE_SHARED_MEMORY() */ 213 214 extern PRStatus _MD_DeleteSharedMemory(const char* name) { 215 return (PR_SUCCESS); 216 } 217 218 /* 219 ** Windows implementation of anonymous memory (file) map 220 */ 221 extern PRLogModuleInfo* _pr_shma_lm; 222 223 extern PRFileMap* _md_OpenAnonFileMap(const char* dirName, PRSize size, 224 PRFileMapProtect prot) { 225 PRFileMap* fm; 226 HANDLE hFileMap; 227 228 fm = PR_CreateFileMap((PRFileDesc*)-1, size, prot); 229 if (NULL == fm) { 230 PR_LOG(_pr_shma_lm, PR_LOG_DEBUG, 231 ("_md_OpenAnonFileMap(): PR_CreateFileMap(): failed")); 232 goto Finished; 233 } 234 235 /* 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. 240 */ 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")); 247 PR_CloseFileMap(fm); 248 fm = NULL; 249 goto Finished; 250 } 251 CloseHandle(fm->md.hFileMap); 252 fm->md.hFileMap = hFileMap; 253 254 Finished: 255 return (fm); 256 } /* end md_OpenAnonFileMap() */ 257 258 /* 259 ** _md_ExportFileMapAsString() 260 ** 261 */ 262 extern PRStatus _md_ExportFileMapAsString(PRFileMap* fm, PRSize bufSize, 263 char* buf) { 264 PRIntn written; 265 266 written = PR_snprintf(buf, (PRUint32)bufSize, "%d:%" PR_PRIdOSFD ":%ld", 267 (PRIntn)fm->prot, (PROsfd)fm->md.hFileMap, 268 (PRInt32)fm->md.dwAccess); 269 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)); 273 274 return ((written == -1) ? PR_FAILURE : PR_SUCCESS); 275 } /* end _md_ExportFileMapAsString() */ 276 277 /* 278 ** _md_ImportFileMapFromString() 279 ** 280 */ 281 extern PRFileMap* _md_ImportFileMapFromString(const char* fmstring) { 282 PRIntn prot; 283 PROsfd hFileMap; 284 PRInt32 dwAccess; 285 PRFileMap* fm = NULL; 286 287 PR_sscanf(fmstring, "%d:%" PR_SCNdOSFD ":%ld", &prot, &hFileMap, &dwAccess); 288 289 fm = PR_NEWZAP(PRFileMap); 290 if (NULL == fm) { 291 PR_LOG(_pr_shma_lm, PR_LOG_DEBUG, 292 ("_md_ImportFileMapFromString(): PR_NEWZAP(): Failed")); 293 return (fm); 294 } 295 296 fm->prot = (PRFileMapProtect)prot; 297 fm->md.hFileMap = (HANDLE)hFileMap; 298 fm->md.dwAccess = (DWORD)dwAccess; 299 fm->fd = (PRFileDesc*)-1; 300 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)); 305 return (fm); 306 } /* end _md_ImportFileMapFromString() */ 307 308 #else 309 Error !Why is PR_HAVE_WIN32_NAMED_SHARED_MEMORY not defined 310 ? 311 #endif /* PR_HAVE_WIN32_NAMED_SHARED_MEMORY */ 312 /* --- end w32shm.c --- */