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