208 lines
5.9 KiB
C
208 lines
5.9 KiB
C
//---------------------------------------------------------------------------
|
|
//
|
|
// Copyright (c) Microsoft Corporation 1991-1995
|
|
//
|
|
// File: shared.c
|
|
//
|
|
// History:
|
|
// 06-07-95 BobDay Created.
|
|
//
|
|
// This file contains a set of routines for the management of shared memory.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
#include "priv.h"
|
|
#pragma hdrstop
|
|
|
|
//---------------------------------------------------------------------------
|
|
// SHAllocShared - Allocates a handle (in a given process) to a copy of a
|
|
// memory block in this process.
|
|
// SHFreeShared - Releases the handle (and the copy of the memory block)
|
|
//
|
|
// SHLockShared - Maps a handle (from a given process) into a memory block
|
|
// in this process. Has the option of transfering the handle
|
|
// to this process, thereby deleting it from the given process
|
|
// SHUnlockShared - Opposite of SHLockShared, unmaps the memory block
|
|
//---------------------------------------------------------------------------
|
|
HANDLE SHMapHandle(HANDLE hData, DWORD dwSource, DWORD dwDest, DWORD dwDesiredAccess, DWORD dwFlags)
|
|
{
|
|
HANDLE hMap = NULL;
|
|
HANDLE hSource;
|
|
|
|
// Under certain (valid) circumstances it is possible for DDE to
|
|
// use :0:pid as the shared memory handle, which we should ignore.
|
|
if (hData != NULL)
|
|
{
|
|
|
|
if (dwSource == GetCurrentProcessId())
|
|
hSource = GetCurrentProcess();
|
|
else
|
|
hSource = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwSource);
|
|
|
|
if (hSource)
|
|
{
|
|
HANDLE hDest;
|
|
if (dwDest == GetCurrentProcessId())
|
|
hDest = GetCurrentProcess();
|
|
else
|
|
hDest = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwDest);
|
|
|
|
if (hDest)
|
|
{
|
|
if (!DuplicateHandle(hSource, hData, hDest, &hMap,
|
|
dwDesiredAccess, FALSE, dwFlags | DUPLICATE_SAME_ACCESS))
|
|
{
|
|
// may change the value...
|
|
hMap = NULL;
|
|
}
|
|
|
|
CloseHandle(hDest);
|
|
}
|
|
|
|
CloseHandle(hSource);
|
|
}
|
|
}
|
|
|
|
return hMap;
|
|
}
|
|
|
|
void _FillHeader(SHMAPHEADER *pmh, DWORD dwSize, DWORD dwSrcId, DWORD dwDstId, void *pvData)
|
|
{
|
|
pmh->dwSize = dwSize;
|
|
pmh->dwSig = MAPHEAD_SIG;
|
|
pmh->dwSrcId = dwSrcId;
|
|
pmh->dwDstId = dwDstId;
|
|
|
|
if (pvData)
|
|
memcpy((pmh + 1), pvData, dwSize);
|
|
}
|
|
|
|
HANDLE _AllocShared(DWORD dwSize, DWORD dwSrcId, DWORD dwDstId, void *pvData, void **ppvLock)
|
|
{
|
|
HANDLE hShared = NULL;
|
|
//
|
|
// Make a filemapping handle with this data in it.
|
|
//
|
|
HANDLE hData = CreateFileMapping((HANDLE)-1, NULL, PAGE_READWRITE, 0,
|
|
dwSize + sizeof(SHMAPHEADER),NULL);
|
|
if (hData)
|
|
{
|
|
SHMAPHEADER *pmh = MapViewOfFile(hData, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
|
|
|
|
if (pmh)
|
|
{
|
|
_FillHeader(pmh, dwSize, dwSrcId, dwDstId, pvData);
|
|
|
|
hShared = SHMapHandle(hData, dwSrcId, dwDstId, FILE_MAP_ALL_ACCESS, DUPLICATE_SAME_ACCESS);
|
|
|
|
if (hShared && ppvLock)
|
|
*ppvLock = (pmh+1);
|
|
else
|
|
UnmapViewOfFile(pmh);
|
|
}
|
|
|
|
CloseHandle(hData);
|
|
}
|
|
|
|
return hShared;
|
|
}
|
|
|
|
#if SHAREDLOCAL
|
|
HANDLE _AllocLocal(DWORD dwSize, DWORD dwSrcId, void *pvData, void **ppvLock)
|
|
{
|
|
SHMAPHEADER *pmh = LocalAlloc(LPTR, dwSize + sizeof(SHMAPHEADER));
|
|
if (pmh)
|
|
{
|
|
_FillHeader(pmh, dwSize, dwSrcId, dwSrcId, pvData);
|
|
|
|
if (ppvLock)
|
|
*ppvLock = (pmh+1);
|
|
}
|
|
|
|
return pmh;
|
|
}
|
|
|
|
|
|
LWSTDAPI_(HANDLE) SHAllocSharedEx(DWORD dwSize, DWORD dwDstId, void *pvData, void **ppvLock)
|
|
{
|
|
DWORD dwSrcId = GetCurrentProcessId();
|
|
|
|
if (fAllowLocal && dwDstId == dwSrcId)
|
|
{
|
|
return _AllocLocal(dwSize, dwSrcId, pvData, ppvLock);
|
|
}
|
|
else
|
|
{
|
|
return _AllocShared(dwSize, dwSrcId, dwDstId, pvData, ppvLock);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
HANDLE SHAllocShared(void *pvData, DWORD dwSize, DWORD dwOtherProcId)
|
|
{
|
|
return _AllocShared(dwSize, GetCurrentProcessId(), dwOtherProcId, pvData, NULL);
|
|
}
|
|
|
|
LWSTDAPI_(void *) SHLockSharedEx(HANDLE hData, DWORD dwOtherProcId, BOOL fWrite)
|
|
{
|
|
HANDLE hMapped = SHMapHandle(hData, dwOtherProcId, GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,0);
|
|
|
|
if (hMapped)
|
|
{
|
|
//
|
|
// Now map that new process specific handle and close it
|
|
//
|
|
DWORD dwAccess = fWrite ? FILE_MAP_WRITE | FILE_MAP_READ : FILE_MAP_READ;
|
|
SHMAPHEADER *pmh = (SHMAPHEADER *) MapViewOfFile(hMapped, dwAccess, 0, 0, 0);
|
|
|
|
CloseHandle(hMapped);
|
|
|
|
if (pmh)
|
|
{
|
|
ASSERT(pmh->dwSig == MAPHEAD_SIG);
|
|
return (void *)(pmh+1);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
LWSTDAPI_(void *) SHLockShared(HANDLE hData, DWORD dwOtherProcId)
|
|
{
|
|
return SHLockSharedEx(hData, dwOtherProcId, TRUE);
|
|
}
|
|
|
|
LWSTDAPI_(BOOL) SHUnlockShared(void *pvData)
|
|
{
|
|
SHMAPHEADER *pmh = ((SHMAPHEADER *)pvData) - 1;
|
|
|
|
// Only assert on Whistler or higher, on downlevel machines SHUnlockShared would sometimes be called
|
|
// without this header (the return value from SHAllocShared, for example) and we would fault.
|
|
ASSERT(!IsOS(OS_WHISTLERORGREATER) || pmh->dwSig == MAPHEAD_SIG);
|
|
|
|
//
|
|
// Now just unmap the view of the file
|
|
//
|
|
return UnmapViewOfFile(pmh);
|
|
}
|
|
|
|
BOOL SHFreeShared(HANDLE hData, DWORD dwOtherProcId)
|
|
{
|
|
if (hData)
|
|
{
|
|
//
|
|
// The below call closes the original handle in whatever process it
|
|
// came from.
|
|
//
|
|
HANDLE hMapped = SHMapHandle(hData, dwOtherProcId, GetCurrentProcessId(),
|
|
FILE_MAP_ALL_ACCESS, DUPLICATE_CLOSE_SOURCE);
|
|
|
|
//
|
|
// Now free up the local handle
|
|
//
|
|
return CloseHandle(hMapped);
|
|
}
|
|
else
|
|
{
|
|
return TRUE; // vacuous success, closing a NULL handle
|
|
}
|
|
}
|