NT4/private/ole32/com/inc/smblock.cxx
2020-09-30 17:12:29 +02:00

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;
}