/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #if defined(PR_HAVE_WIN32_NAMED_SHARED_MEMORY) extern PRLogModuleInfo *_pr_shm_lm; /* * NSPR-to-NT access right mapping table for file-mapping objects. * * The OR of these three access masks must equal FILE_MAP_ALL_ACCESS. * This is because if a file-mapping object with the specified name * exists, CreateFileMapping requests full access to the existing * object. */ static DWORD filemapAccessTable[] = { FILE_MAP_ALL_ACCESS & ~FILE_MAP_WRITE, /* read */ FILE_MAP_ALL_ACCESS & ~FILE_MAP_READ, /* write */ 0 /* execute */ }; extern PRSharedMemory * _MD_OpenSharedMemory( const char *name, PRSize size, PRIntn flags, PRIntn mode ) { char ipcname[PR_IPC_NAME_SIZE]; PRStatus rc = PR_SUCCESS; DWORD dwHi, dwLo; PRSharedMemory *shm; DWORD flProtect = ( PAGE_READWRITE ); SECURITY_ATTRIBUTES sa; LPSECURITY_ATTRIBUTES lpSA = NULL; PSECURITY_DESCRIPTOR pSD = NULL; PACL pACL = NULL; rc = _PR_MakeNativeIPCName( name, ipcname, PR_IPC_NAME_SIZE, _PRIPCShm ); if ( PR_FAILURE == rc ) { PR_SetError(PR_UNKNOWN_ERROR, 0 ); PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: name is invalid")); return(NULL); } shm = PR_NEWZAP( PRSharedMemory ); if ( NULL == shm ) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 ); PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: New PRSharedMemory out of memory")); return(NULL); } shm->ipcname = PR_MALLOC( (PRUint32) (strlen( ipcname ) + 1) ); if ( NULL == shm->ipcname ) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 ); PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: New shm->ipcname out of memory")); PR_DELETE(shm); return(NULL); } /* copy args to struct */ strcpy( shm->ipcname, ipcname ); shm->size = size; shm->mode = mode; shm->flags = flags; shm->ident = _PR_SHM_IDENT; if (flags & PR_SHM_CREATE ) { dwHi = (DWORD) (((PRUint64) shm->size >> 32) & 0xffffffff); dwLo = (DWORD) (shm->size & 0xffffffff); if (_PR_NT_MakeSecurityDescriptorACL(mode, filemapAccessTable, &pSD, &pACL) == PR_SUCCESS) { sa.nLength = sizeof(sa); sa.lpSecurityDescriptor = pSD; sa.bInheritHandle = FALSE; lpSA = &sa; } #ifdef WINCE { /* * This is assuming that the name will never be larger than * MAX_PATH. Should we dynamically allocate? */ PRUnichar wideIpcName[MAX_PATH]; MultiByteToWideChar(CP_ACP, 0, shm->ipcname, -1, wideIpcName, MAX_PATH); shm->handle = CreateFileMappingW( (HANDLE)-1, lpSA, flProtect, dwHi, dwLo, wideIpcName); } #else shm->handle = CreateFileMappingA( (HANDLE)-1, lpSA, flProtect, dwHi, dwLo, shm->ipcname); #endif if (lpSA != NULL) { _PR_NT_FreeSecurityDescriptorACL(pSD, pACL); } if ( NULL == shm->handle ) { PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: CreateFileMapping() failed: %s", shm->ipcname )); _PR_MD_MAP_DEFAULT_ERROR( GetLastError()); PR_FREEIF( shm->ipcname ) PR_DELETE( shm ); return(NULL); } else { if (( flags & PR_SHM_EXCL) && ( GetLastError() == ERROR_ALREADY_EXISTS )) { PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: Request exclusive & already exists", shm->ipcname )); PR_SetError( PR_FILE_EXISTS_ERROR, ERROR_ALREADY_EXISTS ); CloseHandle( shm->handle ); PR_FREEIF( shm->ipcname ) PR_DELETE( shm ); return(NULL); } else { PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: CreateFileMapping() success: %s, handle: %d", shm->ipcname, shm->handle )); return(shm); } } } else { #ifdef WINCE PR_SetError( PR_NOT_IMPLEMENTED_ERROR, 0 ); shm->handle = NULL; /* OpenFileMapping not supported */ #else shm->handle = OpenFileMapping( FILE_MAP_WRITE, TRUE, shm->ipcname ); #endif if ( NULL == shm->handle ) { _PR_MD_MAP_DEFAULT_ERROR( GetLastError()); PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: OpenFileMapping() failed: %s, error: %d", shm->ipcname, PR_GetOSError())); PR_FREEIF( shm->ipcname ); PR_DELETE( shm ); return(NULL); } else { PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: OpenFileMapping() success: %s, handle: %d", shm->ipcname, shm->handle )); return(shm); } } /* returns from separate paths */ } extern void * _MD_AttachSharedMemory( PRSharedMemory *shm, PRIntn flags ) { PRUint32 access = FILE_MAP_WRITE; void *addr; PR_ASSERT( shm->ident == _PR_SHM_IDENT ); if ( PR_SHM_READONLY & flags ) { access = FILE_MAP_READ; } addr = MapViewOfFile( shm->handle, access, 0, 0, shm->size ); if ( NULL == addr ) { _PR_MD_MAP_DEFAULT_ERROR( GetLastError()); PR_LOG( _pr_shm_lm, PR_LOG_ERROR, ("_MD_AttachSharedMemory: MapViewOfFile() failed. OSerror: %d", PR_GetOSError())); } return( addr ); } /* end _MD_ATTACH_SHARED_MEMORY() */ extern PRStatus _MD_DetachSharedMemory( PRSharedMemory *shm, void *addr ) { PRStatus rc = PR_SUCCESS; BOOL wrc; PR_ASSERT( shm->ident == _PR_SHM_IDENT ); wrc = UnmapViewOfFile( addr ); if ( FALSE == wrc ) { _PR_MD_MAP_DEFAULT_ERROR( GetLastError()); PR_LOG( _pr_shm_lm, PR_LOG_ERROR, ("_MD_DetachSharedMemory: UnmapViewOfFile() failed. OSerror: %d", PR_GetOSError())); rc = PR_FAILURE; } return( rc ); } extern PRStatus _MD_CloseSharedMemory( PRSharedMemory *shm ) { PRStatus rc = PR_SUCCESS; BOOL wrc; PR_ASSERT( shm->ident == _PR_SHM_IDENT ); wrc = CloseHandle( shm->handle ); if ( FALSE == wrc ) { _PR_MD_MAP_DEFAULT_ERROR( GetLastError()); PR_LOG( _pr_shm_lm, PR_LOG_ERROR, ("_MD_CloseSharedMemory: CloseHandle() failed. OSerror: %d", PR_GetOSError())); rc = PR_FAILURE; } PR_FREEIF( shm->ipcname ); PR_DELETE( shm ); return( rc ); } /* end _MD_CLOSE_SHARED_MEMORY() */ extern PRStatus _MD_DeleteSharedMemory( const char *name ) { return( PR_SUCCESS ); } /* ** Windows implementation of anonymous memory (file) map */ extern PRLogModuleInfo *_pr_shma_lm; extern PRFileMap* _md_OpenAnonFileMap( const char *dirName, PRSize size, PRFileMapProtect prot ) { PRFileMap *fm; HANDLE hFileMap; fm = PR_CreateFileMap( (PRFileDesc*)-1, size, prot ); if ( NULL == fm ) { PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_OpenAnonFileMap(): PR_CreateFileMap(): failed")); goto Finished; } /* ** Make fm->md.hFileMap inheritable. We can't use ** GetHandleInformation and SetHandleInformation ** because these two functions fail with ** ERROR_CALL_NOT_IMPLEMENTED on Win95. */ if (DuplicateHandle(GetCurrentProcess(), fm->md.hFileMap, GetCurrentProcess(), &hFileMap, 0, TRUE /* inheritable */, DUPLICATE_SAME_ACCESS) == FALSE) { PR_SetError( PR_UNKNOWN_ERROR, GetLastError() ); PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_OpenAnonFileMap(): DuplicateHandle(): failed")); PR_CloseFileMap( fm ); fm = NULL; goto Finished; } CloseHandle(fm->md.hFileMap); fm->md.hFileMap = hFileMap; Finished: return(fm); } /* end md_OpenAnonFileMap() */ /* ** _md_ExportFileMapAsString() ** */ extern PRStatus _md_ExportFileMapAsString( PRFileMap *fm, PRSize bufSize, char *buf ) { PRIntn written; written = PR_snprintf( buf, (PRUint32) bufSize, "%d:%" PR_PRIdOSFD ":%ld", (PRIntn)fm->prot, (PROsfd)fm->md.hFileMap, (PRInt32)fm->md.dwAccess ); PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_ExportFileMapAsString(): prot: %x, hFileMap: %x, dwAccess: %x", fm->prot, fm->md.hFileMap, fm->md.dwAccess )); return((written == -1)? PR_FAILURE : PR_SUCCESS); } /* end _md_ExportFileMapAsString() */ /* ** _md_ImportFileMapFromString() ** */ extern PRFileMap * _md_ImportFileMapFromString( const char *fmstring ) { PRIntn prot; PROsfd hFileMap; PRInt32 dwAccess; PRFileMap *fm = NULL; PR_sscanf( fmstring, "%d:%" PR_SCNdOSFD ":%ld", &prot, &hFileMap, &dwAccess ); fm = PR_NEWZAP(PRFileMap); if ( NULL == fm ) { PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_ImportFileMapFromString(): PR_NEWZAP(): Failed")); return(fm); } fm->prot = (PRFileMapProtect)prot; fm->md.hFileMap = (HANDLE)hFileMap; fm->md.dwAccess = (DWORD)dwAccess; fm->fd = (PRFileDesc*)-1; PR_LOG( _pr_shma_lm, PR_LOG_DEBUG, ("_md_ImportFileMapFromString(): fm: %p, prot: %d, hFileMap: %8.8x, dwAccess: %8.8x, fd: %x", fm, prot, fm->md.hFileMap, fm->md.dwAccess, fm->fd)); return(fm); } /* end _md_ImportFileMapFromString() */ #else Error! Why is PR_HAVE_WIN32_NAMED_SHARED_MEMORY not defined? #endif /* PR_HAVE_WIN32_NAMED_SHARED_MEMORY */ /* --- end w32shm.c --- */