Source code
Revision control
Copy as Markdown
Other Tools
/* -*- 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
#include <private/primpl.h>
#include <string.h>
#include <prshm.h>
#include <prerr.h>
#include <prmem.h>
#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 --- */