Back to index

lightning-sunbird  0.9+nobinonly
w32shm.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include <private/primpl.h>       
00039 #include <string.h>
00040 #include <prshm.h>
00041 #include <prerr.h>
00042 #include <prmem.h>
00043 
00044 #if defined(PR_HAVE_WIN32_NAMED_SHARED_MEMORY)
00045 
00046 extern PRLogModuleInfo *_pr_shm_lm;
00047 
00048 /*
00049  * NSPR-to-NT access right mapping table for file-mapping objects.
00050  *
00051  * The OR of these three access masks must equal FILE_MAP_ALL_ACCESS.
00052  * This is because if a file-mapping object with the specified name
00053  * exists, CreateFileMapping requests full access to the existing
00054  * object.
00055  */
00056 static DWORD filemapAccessTable[] = {
00057     FILE_MAP_ALL_ACCESS & ~FILE_MAP_WRITE, /* read */
00058     FILE_MAP_ALL_ACCESS & ~FILE_MAP_READ, /* write */ 
00059     0  /* execute */
00060 };
00061 
00062 extern PRSharedMemory * _MD_OpenSharedMemory( 
00063         const char *name,
00064         PRSize      size,
00065         PRIntn      flags,
00066         PRIntn      mode
00067 )
00068 {
00069     char        ipcname[PR_IPC_NAME_SIZE];
00070     PRStatus    rc = PR_SUCCESS;
00071     DWORD dwHi, dwLo;
00072     PRSharedMemory *shm;
00073     DWORD flProtect = ( PAGE_READWRITE );
00074     SECURITY_ATTRIBUTES sa;
00075     LPSECURITY_ATTRIBUTES lpSA = NULL;
00076     PSECURITY_DESCRIPTOR pSD = NULL;
00077     PACL pACL = NULL;
00078 
00079     rc = _PR_MakeNativeIPCName( name, ipcname, PR_IPC_NAME_SIZE, _PRIPCShm );
00080     if ( PR_FAILURE == rc )
00081     {
00082         PR_SetError(PR_UNKNOWN_ERROR, 0 );
00083         PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: name is invalid")); 
00084         return(NULL);
00085     }
00086 
00087     shm = PR_NEWZAP( PRSharedMemory );
00088     if ( NULL == shm ) 
00089     {
00090         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 );
00091         PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: New PRSharedMemory out of memory")); 
00092         return(NULL);
00093     }
00094 
00095     shm->ipcname = PR_MALLOC( strlen( ipcname ) + 1 );
00096     if ( NULL == shm->ipcname )
00097     {
00098         PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0 );
00099         PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, ( "PR_OpenSharedMemory: New shm->ipcname out of memory")); 
00100         PR_DELETE(shm);
00101         return(NULL);
00102     }
00103 
00104     /* copy args to struct */
00105     strcpy( shm->ipcname, ipcname );
00106     shm->size = size; 
00107     shm->mode = mode;
00108     shm->flags = flags;
00109     shm->ident = _PR_SHM_IDENT;
00110 
00111     if (flags & PR_SHM_CREATE ) {
00112         /* XXX: Not 64bit safe. Fix when WinNT goes 64bit. */
00113         dwHi = 0;
00114         dwLo = shm->size;
00115 
00116         if (_PR_NT_MakeSecurityDescriptorACL(mode, filemapAccessTable,
00117                 &pSD, &pACL) == PR_SUCCESS) {
00118             sa.nLength = sizeof(sa);
00119             sa.lpSecurityDescriptor = pSD;
00120             sa.bInheritHandle = FALSE;
00121             lpSA = &sa;
00122         }
00123         shm->handle = CreateFileMapping(
00124             (HANDLE)-1 ,
00125             lpSA,
00126             flProtect,
00127             dwHi,
00128             dwLo,
00129             shm->ipcname);
00130         if (lpSA != NULL) {
00131             _PR_NT_FreeSecurityDescriptorACL(pSD, pACL);
00132         }
00133 
00134         if ( NULL == shm->handle ) {
00135             PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 
00136                 ( "PR_OpenSharedMemory: CreateFileMapping() failed: %s",
00137                     shm->ipcname )); 
00138             _PR_MD_MAP_DEFAULT_ERROR( GetLastError());
00139             PR_FREEIF( shm->ipcname )
00140             PR_DELETE( shm );
00141             return(NULL);
00142         } else {
00143             if (( flags & PR_SHM_EXCL) && ( GetLastError() == ERROR_ALREADY_EXISTS ))  {
00144                 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 
00145                     ( "PR_OpenSharedMemory: Request exclusive & already exists",
00146                         shm->ipcname )); 
00147                 PR_SetError( PR_FILE_EXISTS_ERROR, ERROR_ALREADY_EXISTS );
00148                 CloseHandle( shm->handle );
00149                 PR_FREEIF( shm->ipcname )
00150                 PR_DELETE( shm );
00151                 return(NULL);
00152             } else {
00153                 PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 
00154                     ( "PR_OpenSharedMemory: CreateFileMapping() success: %s, handle: %d",
00155                         shm->ipcname, shm->handle ));
00156                 return(shm);
00157             }
00158         }
00159     } else {
00160         shm->handle = OpenFileMapping( FILE_MAP_WRITE, TRUE, shm->ipcname );
00161         if ( NULL == shm->handle ) {
00162             _PR_MD_MAP_DEFAULT_ERROR( GetLastError());
00163             PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 
00164                 ( "PR_OpenSharedMemory: OpenFileMapping() failed: %s, error: %d",
00165                     shm->ipcname, PR_GetOSError())); 
00166             PR_FREEIF( shm->ipcname );
00167             PR_DELETE( shm );
00168             return(NULL);
00169         } else {
00170             PR_LOG(_pr_shm_lm, PR_LOG_DEBUG, 
00171                 ( "PR_OpenSharedMemory: OpenFileMapping() success: %s, handle: %d",
00172                     shm->ipcname, shm->handle )); 
00173                 return(shm);
00174         }
00175     }
00176     /* returns from separate paths */
00177 }
00178 
00179 extern void * _MD_AttachSharedMemory( PRSharedMemory *shm, PRIntn flags )
00180 {
00181     PRUint32    access = FILE_MAP_WRITE;
00182     void        *addr;
00183 
00184     PR_ASSERT( shm->ident == _PR_SHM_IDENT );
00185 
00186     if ( PR_SHM_READONLY & flags )
00187         access = FILE_MAP_READ;
00188 
00189     addr = MapViewOfFile( shm->handle,
00190         access,
00191         0, 0,
00192         shm->size );
00193 
00194     if ( NULL == addr ) {
00195         _PR_MD_MAP_DEFAULT_ERROR( GetLastError());
00196         PR_LOG( _pr_shm_lm, PR_LOG_ERROR, 
00197             ("_MD_AttachSharedMemory: MapViewOfFile() failed. OSerror: %d", PR_GetOSError()));
00198     }
00199 
00200     return( addr );
00201 } /* end _MD_ATTACH_SHARED_MEMORY() */
00202 
00203 
00204 extern PRStatus _MD_DetachSharedMemory( PRSharedMemory *shm, void *addr )
00205 {
00206     PRStatus rc = PR_SUCCESS;
00207     BOOL        wrc;
00208 
00209     PR_ASSERT( shm->ident == _PR_SHM_IDENT );
00210 
00211     wrc = UnmapViewOfFile( addr );
00212     if ( FALSE == wrc ) 
00213     {
00214         _PR_MD_MAP_DEFAULT_ERROR( GetLastError());
00215         PR_LOG( _pr_shm_lm, PR_LOG_ERROR, 
00216             ("_MD_DetachSharedMemory: UnmapViewOfFile() failed. OSerror: %d", PR_GetOSError()));
00217         rc = PR_FAILURE;
00218     }
00219 
00220     return( rc );
00221 }
00222 
00223 
00224 extern PRStatus _MD_CloseSharedMemory( PRSharedMemory *shm )
00225 {
00226     PRStatus rc = PR_SUCCESS;
00227     BOOL wrc;
00228 
00229     PR_ASSERT( shm->ident == _PR_SHM_IDENT );
00230 
00231     wrc = CloseHandle( shm->handle );
00232     if ( FALSE == wrc )
00233     {
00234         _PR_MD_MAP_DEFAULT_ERROR( GetLastError());
00235         PR_LOG( _pr_shm_lm, PR_LOG_ERROR, 
00236             ("_MD_CloseSharedMemory: CloseHandle() failed. OSerror: %d", PR_GetOSError()));
00237         rc = PR_FAILURE;
00238     }
00239     PR_FREEIF( shm->ipcname );
00240     PR_DELETE( shm );
00241 
00242     return( rc );
00243 } /* end _MD_CLOSE_SHARED_MEMORY() */
00244 
00245 extern PRStatus _MD_DeleteSharedMemory( const char *name )
00246 {
00247     return( PR_SUCCESS );
00248 }    
00249 
00250 
00251 /*
00252 ** Windows implementation of anonymous memory (file) map
00253 */
00254 extern PRLogModuleInfo *_pr_shma_lm;
00255 
00256 extern PRFileMap* _md_OpenAnonFileMap( 
00257     const char *dirName,
00258     PRSize      size,
00259     PRFileMapProtect prot
00260 )
00261 {
00262     PRFileMap   *fm;
00263     HANDLE      hFileMap;
00264 
00265     fm = PR_CreateFileMap( (PRFileDesc*)-1, size, prot );
00266     if ( NULL == fm )  {
00267         PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
00268             ("_md_OpenAnonFileMap(): PR_CreateFileMap(): failed"));
00269         goto Finished;
00270     }
00271 
00272     /*
00273     ** Make fm->md.hFileMap inheritable. We can't use
00274     ** GetHandleInformation and SetHandleInformation
00275     ** because these two functions fail with
00276     ** ERROR_CALL_NOT_IMPLEMENTED on Win95.
00277     */
00278     if (DuplicateHandle(GetCurrentProcess(), fm->md.hFileMap,
00279             GetCurrentProcess(), &hFileMap,
00280             0, TRUE /* inheritable */,
00281             DUPLICATE_SAME_ACCESS) == FALSE) {
00282         PR_SetError( PR_UNKNOWN_ERROR, GetLastError() );
00283         PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
00284             ("_md_OpenAnonFileMap(): DuplicateHandle(): failed"));
00285         PR_CloseFileMap( fm );
00286         fm = NULL;
00287         goto Finished;
00288     }
00289     CloseHandle(fm->md.hFileMap);
00290     fm->md.hFileMap = hFileMap;
00291 
00292 Finished:    
00293     return(fm);
00294 } /* end md_OpenAnonFileMap() */
00295 
00296 /*
00297 ** _md_ExportFileMapAsString()
00298 **
00299 */
00300 extern PRStatus _md_ExportFileMapAsString(
00301     PRFileMap *fm,
00302     PRSize    bufSize,
00303     char      *buf
00304 )
00305 {
00306     PRIntn  written;
00307 
00308     written = PR_snprintf( buf, bufSize, "%d:%ld:%ld",
00309         (PRIntn)fm->prot, (PRInt32)fm->md.hFileMap, (PRInt32)fm->md.dwAccess );
00310     /* Watch out on the above snprintf(). Windows HANDLE assumes 32bits; windows calls it void* */
00311 
00312     PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
00313         ("_md_ExportFileMapAsString(): prot: %x, hFileMap: %x, dwAccess: %x",
00314             fm->prot, fm->md.hFileMap, fm->md.dwAccess ));
00315         
00316     return((written == -1)? PR_FAILURE : PR_SUCCESS);
00317 } /* end _md_ExportFileMapAsString() */
00318 
00319 
00320 /*
00321 ** _md_ImportFileMapFromString()
00322 **
00323 */
00324 extern PRFileMap * _md_ImportFileMapFromString(
00325     const char *fmstring
00326 )
00327 {
00328     PRIntn  prot;
00329     PRInt32 hFileMap;
00330     PRInt32 dwAccess;
00331     PRFileMap *fm = NULL;
00332 
00333     PR_sscanf( fmstring, "%d:%ld:%ld", &prot, &hFileMap, &dwAccess  );
00334 
00335     fm = PR_NEWZAP(PRFileMap);
00336     if ( NULL == fm ) {
00337         PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
00338             ("_md_ImportFileMapFromString(): PR_NEWZAP(): Failed"));
00339         return(fm);
00340     }
00341 
00342     fm->prot = (PRFileMapProtect)prot;
00343     fm->md.hFileMap = (HANDLE)hFileMap;  /* Assumes HANDLE is 32bit */
00344     fm->md.dwAccess = (DWORD)dwAccess;
00345     fm->fd = (PRFileDesc*)-1;
00346 
00347     PR_LOG( _pr_shma_lm, PR_LOG_DEBUG,
00348         ("_md_ImportFileMapFromString(): fm: %p, prot: %d, hFileMap: %8.8x, dwAccess: %8.8x, fd: %x",
00349             fm, prot, fm->md.hFileMap, fm->md.dwAccess, fm->fd));
00350     return(fm);
00351 } /* end _md_ImportFileMapFromString() */
00352 
00353 #else
00354 Error! Why is PR_HAVE_WIN32_NAMED_SHARED_MEMORY not defined? 
00355 #endif /* PR_HAVE_WIN32_NAMED_SHARED_MEMORY */
00356 /* --- end w32shm.c --- */