322 lines
8.8 KiB
C++
322 lines
8.8 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1994.
|
|
//
|
|
// File: smblock.cxx
|
|
//
|
|
// Contents: Shared memory block code
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 24-Mar-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <ole2int.h>
|
|
#include <smblock.hxx>
|
|
#include <smcreate.hxx>
|
|
|
|
#if DBG == 1
|
|
DECLARE_INFOLEVEL(mem);
|
|
#endif
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSharedMemoryBlock::~CSharedMemoryBlock, public
|
|
//
|
|
// Synopsis: Destructor
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 25-Apr-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CSharedMemoryBlock::~CSharedMemoryBlock()
|
|
{
|
|
CloseSharedFileMapping(_hMem, _pbBase);
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CSharedMemoryBlock::Init
|
|
//
|
|
// Synopsis: Create/get address of shared memory block.
|
|
//
|
|
// Arguments: [pszName] - name of block to allocate
|
|
// [culSize] - size of block to allocate
|
|
//
|
|
// Algorithm: Attempts to open the block first. If this fails then
|
|
// this creates the block of memory. It then puts the
|
|
// address of the block as the first bytes of the block.
|
|
// If the block already exists, the memory is mapped
|
|
// and then the address is read. The memory is then mapped
|
|
// to the address.
|
|
//
|
|
// History: 03-Nov-93 Ricksa Created
|
|
// 07-Jan-94 AlexT No security for CHICAGO
|
|
//
|
|
// Notes: Counts on some outside synchronization to prevent
|
|
// a race in the creation of the memory.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
SCODE CSharedMemoryBlock::Init(
|
|
LPWSTR pszName,
|
|
ULONG culSize,
|
|
ULONG culCommitSize,
|
|
void *pvBase,
|
|
PSECURITY_DESCRIPTOR lpSecDes,
|
|
BOOL fOKToCreate)
|
|
{
|
|
SCODE sc = S_OK;
|
|
|
|
memAssert((_hMem == NULL) &&
|
|
"Attempt to Init CSharedMemoryBlock twice.");
|
|
|
|
//We store a header on the shared memory - this should be
|
|
// transparent to clients.
|
|
culSize = culSize + sizeof(CSharedMemHeader);
|
|
|
|
|
|
if (fOKToCreate)
|
|
{
|
|
// try to create the shared file mapping
|
|
// creates or opens it for Read/Write access.
|
|
|
|
_fReadWrite = TRUE;
|
|
|
|
_hMem = CreateSharedFileMapping(pszName,
|
|
culSize, // size of shared mem
|
|
0, // map size
|
|
pvBase, // base addr
|
|
lpSecDes, // security desc
|
|
PAGE_READWRITE | SEC_RESERVE,
|
|
(void **)&_pbBase, // returned base ptr
|
|
&_fCreated); // created or not
|
|
}
|
|
else
|
|
{
|
|
// try to open the shared file mapping.
|
|
// opens it for read only access, base address unspecified.
|
|
|
|
_fReadWrite = FALSE;
|
|
_fCreated = FALSE;
|
|
|
|
_hMem = OpenSharedFileMapping(pszName,
|
|
0, // map size
|
|
(void **)&_pbBase); // returned base ptr
|
|
}
|
|
|
|
if (_hMem == NULL)
|
|
{
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
|
|
#if DBG == 1
|
|
MEMORY_BASIC_INFORMATION meminf;
|
|
ULONG cbReal;
|
|
|
|
cbReal = VirtualQuery(_pbBase, &meminf, sizeof(MEMORY_BASIC_INFORMATION));
|
|
|
|
memDebugOut((DEB_ITRACE, "cbReal == %lu, Mem Info: Base Address %p, Allocation Base %p, AllocationProtect %lx, Region Size %lu, State %lx, Protect %lx, Type %lx\n",
|
|
cbReal, meminf.BaseAddress, meminf.AllocationBase, meminf.AllocationProtect,
|
|
meminf.RegionSize, meminf.State, meminf.Protect, meminf.Type));
|
|
#endif
|
|
|
|
// Commit the first page
|
|
void *pvResult;
|
|
pvResult = VirtualAlloc(_pbBase, culCommitSize, MEM_COMMIT,
|
|
(_fReadWrite) ? PAGE_READWRITE : PAGE_READONLY);
|
|
if (pvResult == NULL)
|
|
{
|
|
sc = GetScode(HRESULT_FROM_WIN32(GetLastError()));
|
|
memDebugOut((DEB_ERROR, "CSharedMemoryBlock::Commit of %lu bytes"
|
|
" failed with %lx\n", culCommitSize, sc));
|
|
return sc;
|
|
}
|
|
|
|
#if DBG == 1
|
|
cbReal = VirtualQuery(_pbBase, &meminf, sizeof(MEMORY_BASIC_INFORMATION));
|
|
|
|
memDebugOut((DEB_ITRACE, "cbReal == %lu, Mem Info: Base Address %p, Allocation Base %p, AllocationProtect %lx, Region Size %lu, State %lx, Protect %lx, Type %lx\n",
|
|
cbReal, meminf.BaseAddress, meminf.AllocationBase, meminf.AllocationProtect,
|
|
meminf.RegionSize, meminf.State, meminf.Protect, meminf.Type));
|
|
#endif
|
|
|
|
_culCommitSize = culCommitSize;
|
|
_culInitCommitSize = culCommitSize;
|
|
|
|
//If we created the block, mark the size in the header.
|
|
if (_fCreated)
|
|
{
|
|
((CSharedMemHeader *)_pbBase)->SetSize(_culCommitSize);
|
|
}
|
|
else
|
|
{
|
|
sc = Sync();
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
#ifdef RESETOK
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSharedMemoryBlock::Reset, public
|
|
//
|
|
// Synopsis: Reset the shared memory block to its original empty state
|
|
//
|
|
// Arguments: None.
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 04-Apr-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CSharedMemoryBlock::Reset(void)
|
|
{
|
|
#if DBG == 1
|
|
BOOL b;
|
|
#endif
|
|
void *pv;
|
|
|
|
memDebugOut((DEB_ITRACE, "In CSharedMemoryBlock::Reset:%p()\n", this));
|
|
|
|
#if DBG == 1
|
|
b =
|
|
#endif
|
|
VirtualFree(_pbBase, _culCommitSize, MEM_DECOMMIT);
|
|
memAssert(b && "VirtualFree failed.");
|
|
|
|
#if DBG == 1
|
|
if (b == NULL)
|
|
{
|
|
memDebugOut((DEB_ERROR, "VirtualFree failed with %lx\n", GetLastError()));
|
|
}
|
|
#endif
|
|
|
|
pv = VirtualAlloc(_pbBase, , _culInitCommitSize, MEM_COMMIT,
|
|
(_fReadWrite) ? PAGE_READWRITE : PAGE_READONLY);
|
|
if (pv == NULL)
|
|
{
|
|
SCODE sc = GetScode(HRESULT_FROM_WIN32(GetLastError()));
|
|
memDebugOut((DEB_ERROR, "CSharedMemoryBlock::Commit of %lu bytes"
|
|
" failed with %lx\n", _culInitCommitSize, sc));
|
|
return sc;
|
|
}
|
|
|
|
_culCommitSize = _culInitCommitSize;
|
|
((CSharedMemHeader *)_pbBase)->SetSize(_culCommitSize);
|
|
|
|
memDebugOut((DEB_ITRACE, "Out CSharedMemoryBlock::Reset\n"));
|
|
return S_OK;
|
|
}
|
|
#endif //RESETOK
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSharedMemoryBlock::Commit, public
|
|
//
|
|
// Synopsis: Commit the given number of bytes within the block
|
|
//
|
|
// Arguments: [culNewSize] -- Number of bytes to commit
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 29-Mar-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CSharedMemoryBlock::Commit(ULONG culNewSize)
|
|
{
|
|
SCODE sc = S_OK;
|
|
culNewSize = culNewSize + sizeof(CSharedMemHeader);
|
|
|
|
memAssert((culNewSize >= _culCommitSize) &&
|
|
"Attempted to shrink shared memory heap.");
|
|
|
|
if (culNewSize == _culCommitSize)
|
|
{
|
|
return sc;
|
|
}
|
|
|
|
void *pb;
|
|
|
|
pb = VirtualAlloc(_pbBase,
|
|
culNewSize,
|
|
MEM_COMMIT,
|
|
(_fReadWrite) ? PAGE_READWRITE : PAGE_READONLY);
|
|
|
|
if (pb == NULL)
|
|
{
|
|
sc = GetScode(HRESULT_FROM_WIN32(GetLastError()));
|
|
memDebugOut((DEB_ERROR,
|
|
"CSharedMemoryBlock::Commit of %lu bytes failed with %lx\n", culNewSize, sc));
|
|
}
|
|
else
|
|
{
|
|
_culCommitSize = culNewSize;
|
|
|
|
//If the new size is greater than the maximum committed size,
|
|
// update the maximum committed size.
|
|
CSharedMemHeader *psmh = (CSharedMemHeader *)_pbBase;
|
|
if (_culCommitSize > psmh->GetSize())
|
|
{
|
|
psmh->SetSize(_culCommitSize);
|
|
}
|
|
}
|
|
|
|
#if DBG == 1
|
|
MEMORY_BASIC_INFORMATION meminf;
|
|
ULONG cbReal;
|
|
|
|
cbReal = VirtualQuery(_pbBase, &meminf, sizeof(MEMORY_BASIC_INFORMATION));
|
|
|
|
memDebugOut((DEB_ITRACE, "Commit size == %lu, cbReal == %lu, Mem Info: Base Address %p, Allocation Base %p, AllocationProtect %lx, Region Size %lu, State %lx, Protect %lx, Type %lx\n",
|
|
_culCommitSize, cbReal, meminf.BaseAddress, meminf.AllocationBase, meminf.AllocationProtect,
|
|
meminf.RegionSize, meminf.State, meminf.Protect, meminf.Type));
|
|
|
|
if (cbReal != sizeof(MEMORY_BASIC_INFORMATION))
|
|
{
|
|
memDebugOut((DEB_ERROR, "Virtual Query error: %lx\n", GetLastError()));
|
|
}
|
|
|
|
#endif
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSharedMemoryBlock::Sync, public
|
|
//
|
|
// Synopsis: Match committed view to largest committed view
|
|
//
|
|
// Arguments: None.
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 29-Mar-94 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CSharedMemoryBlock::Sync(void)
|
|
{
|
|
CSharedMemHeader *psmh = (CSharedMemHeader *)_pbBase;
|
|
|
|
ULONG culSize = psmh->GetSize();
|
|
|
|
if (culSize != _culCommitSize)
|
|
{
|
|
return Commit(culSize - sizeof(CSharedMemHeader));
|
|
}
|
|
return S_OK;
|
|
}
|