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

476 lines
9.4 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1994.
//
// File: extents.cxx
//
// Contents: Implmentation for CExtentList
//
// Classes: CExtentList
//
// Functions:
//
// History: 1-08-94 kevinro Created
// 31-Jan-95 BruceMa Set size to 0 if E_OUTOFMEMORY
// 17-Jul-95 BruceMa Add mutex to protect AddExtent (Cairo only)
// 10-13-95 stevebl moved mutex to CFileMoniker as part of
// adding general threadsafety to monikers
//
//----------------------------------------------------------------------------
#include <ole2int.h>
#include "extents.hxx"
#include "mnk.h"
CExtentList::CExtentList():
m_pchMonikerExtents(NULL),
m_cbMonikerExtents(0)
{
;
}
CExtentList::~CExtentList()
{
if (m_pchMonikerExtents != NULL)
{
CoTaskMemFree(m_pchMonikerExtents);
}
}
//+---------------------------------------------------------------------------
//
// Method: CExtentList::Copy
//
// Synopsis: Make a copy of a CExtentList
//
// Effects:
//
// Arguments: [newExtent] -- Recieving list
//
// Requires:
//
// Returns:
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: 1-08-94 kevinro Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CExtentList::Copy(CExtentList & newExtent)
{
newExtent.m_cbMonikerExtents = m_cbMonikerExtents;
newExtent.m_pchMonikerExtents = (BYTE *) CoTaskMemAlloc(m_cbMonikerExtents);
if ( newExtent.m_pchMonikerExtents == NULL )
{
newExtent.m_cbMonikerExtents = 0;
return(E_OUTOFMEMORY);
}
memcpy(newExtent.m_pchMonikerExtents,
m_pchMonikerExtents,
m_cbMonikerExtents);
return(NOERROR);
}
//+---------------------------------------------------------------------------
//
// Method: CExtentList::FindExtent
//
// Synopsis: Searches the extent list, looking for a matching extent.
//
// Effects:
//
// Arguments: [usKeyValue] --
//
// Requires:
//
// Returns: NULL not found
// UNALIGNED POINTER to extent.
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: 1-08-94 kevinro Created
//
// Notes:
//
// WARNINGS:
//
// The pointer returned is not aligned.
//
// The pointer will become invalide if an extent is added to the block.
// This falls under the not multi-thread safe category. This is done for
// efficiency reasons, since we don't ever expect to both add and lookup
// at the same time.
//
//----------------------------------------------------------------------------
MONIKEREXTENT UNALIGNED *
CExtentList::FindExtent(USHORT usKeyValue)
{
ULONG ulOffset = 0;
while(ulOffset < m_cbMonikerExtents)
{
MONIKEREXTENT UNALIGNED *pExtent = (MONIKEREXTENT UNALIGNED *)
&m_pchMonikerExtents[ulOffset];
//
// There had better be enough bytes left to look at! If not, there
// is some corruption in the extent block. Not much we can do about
// it, other than return NULL
// If the end minus the pointer is less than sizeof MONIKEREXTENT
// we have a problem.
if( (m_pchMonikerExtents + m_cbMonikerExtents) - ((BYTE*)pExtent ) <
sizeof(MONIKEREXTENT) )
{
return(NULL);
}
//
// Get the key value from the buffer and compare against what we want.
// Be careful about alignment here.
//
if (pExtent->usKeyValue == usKeyValue )
{
return(pExtent);
}
ulOffset += MonikerExtentSize(pExtent);
}
return(NULL);
}
//+---------------------------------------------------------------------------
//
// Method: CExtentList::DeleteExtent
//
// Synopsis: Deletes the given extent if it exists.
//
// Effects:
//
// Arguments: [usKeyValue] --
//
// Requires:
//
// Returns: S_OK -- found and deleted.
// S_FALSE -- not found.
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: 1-08-95 BillMo Created
//
// Notes:
//
//----------------------------------------------------------------------------
#ifdef _TRACKLINK_
HRESULT
CExtentList::DeleteExtent(USHORT usKeyValue)
{
MONIKEREXTENT UNALIGNED *pExtent = FindExtent(usKeyValue);
BYTE *pbExtent = (BYTE *)pExtent;
if (pExtent != NULL)
{
ULONG cbRemove = MonikerExtentSize(pExtent);
BYTE * pbFrom = pbExtent + cbRemove;
MoveMemory(pbExtent,
pbFrom,
m_cbMonikerExtents - (pbFrom - m_pchMonikerExtents));
m_cbMonikerExtents -= cbRemove;
return(S_OK);
}
return(S_FALSE);
}
#endif
//+---------------------------------------------------------------------------
//
// Method: CExtentList::AddExtent
//
// Synopsis: Adds an extent to the list. This function adds a copy
// of the data.
// Effects:
//
// Arguments: [pExtent] --
//
// Requires:
//
// Returns:
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: 1-08-94 kevinro Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT
CExtentList::AddExtent(MONIKEREXTENT const * pExtent)
{
//
// Reallocate the current buffer to make room for the new extent
// The new extent is appended to the end of the current list.
//
ULONG ulNewSize = m_cbMonikerExtents + MonikerExtentSize(pExtent);
BYTE * pchNewBuffer;
pchNewBuffer = (BYTE *)CoTaskMemRealloc(m_pchMonikerExtents,ulNewSize);
if (pchNewBuffer == NULL)
{
return(E_OUTOFMEMORY);
}
m_pchMonikerExtents = pchNewBuffer;
//
// Append new extent
//
memcpy(m_pchMonikerExtents + m_cbMonikerExtents,
pExtent,
MonikerExtentSize(pExtent));
m_cbMonikerExtents = ulNewSize;
return(NOERROR);
}
//+---------------------------------------------------------------------------
//
// Method: CExtentList::PutExtent
//
// Synopsis: Deletes the extent (if it exists) and then adds it back.
//
// Effects:
//
// Arguments: [pExtent] --
//
// Requires:
//
// Returns:
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: 1-15-95 BillMo Created
//
// Notes:
//
//----------------------------------------------------------------------------
#ifdef _TRACKLINK_
HRESULT
CExtentList::PutExtent(MONIKEREXTENT const * pExtent)
{
DeleteExtent(pExtent->usKeyValue);
return(AddExtent(pExtent));
}
#endif
//+---------------------------------------------------------------------------
//
// Function: Save
//
// Synopsis: Save the extent to a stream
//
// Effects: Nice straightforward write of the entire blob to a stream
//
// Arguments: [pStm] -- Stream to write to
//
// Requires:
//
// Returns:
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: 1-08-94 kevinro Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT
CExtentList::Save(IStream * pStm)
{
HRESULT hr;
//
// It must be true that both are zero, or neither is zero
//
Assert( ((m_cbMonikerExtents == 0) && (m_pchMonikerExtents == NULL)) ||
((m_pchMonikerExtents != NULL) && (m_cbMonikerExtents != 0)));
//
// First, write the length, then write the blob
//
hr = pStm->Write((void *)&m_cbMonikerExtents,
sizeof(m_cbMonikerExtents),
NULL);
if (FAILED(hr))
{
return(hr);
}
//
// Only write moniker extents if some exist
//
if (m_cbMonikerExtents != 0)
{
hr = pStm->Write((void *)m_pchMonikerExtents,
m_cbMonikerExtents,
NULL);
}
return(hr);
}
//+---------------------------------------------------------------------------
//
// Method: CExtentList::Load
//
// Synopsis: Load the moniker extents from stream
//
// Effects:
//
// Arguments: [pStm] -- Stream to load from
// [ulSize] -- Size of extents, in bytes
//
// Requires:
//
// Returns:
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: 1-08-94 kevinro Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT
CExtentList::Load(IStream * pStm, ULONG ulSize)
{
HRESULT hr;
//
// In the debugging verision, we should never have an extent larger
// than say about 2k. This should catch any errors
//
Assert( ulSize < (2 * 1024));
//
// Be sure not to drop any memory. This normally should never happen.
//
if (m_pchMonikerExtents != NULL)
{
CoTaskMemFree(m_pchMonikerExtents);
}
m_cbMonikerExtents = ulSize;
m_pchMonikerExtents = (BYTE *)CoTaskMemAlloc(m_cbMonikerExtents);
if (m_pchMonikerExtents == NULL)
{
m_cbMonikerExtents = 0;
return(E_OUTOFMEMORY);
}
hr = StRead(pStm, m_pchMonikerExtents, m_cbMonikerExtents);
return(hr);
}
//+---------------------------------------------------------------------------
//
// Method: CExtentList::GetSize
//
// Synopsis: Returns the size needed to serialize this object
//
// Effects:
//
// Arguments: [pcbSize] --
//
// Requires:
//
// Returns:
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: 1-08-94 kevinro Created
//
// Notes:
//
//----------------------------------------------------------------------------
ULONG
CExtentList::GetSize()
{
return sizeof(m_cbMonikerExtents)+m_cbMonikerExtents;
}