tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 --- */