windows-nt/Source/XPSP1/NT/ds/adsi/router/cstream.cxx
2020-09-26 16:20:57 +08:00

427 lines
11 KiB
C++

#include "oleds.hxx"
#if (!defined(BUILD_FOR_NT40))
#include "atl.h"
#include "cstream.h"
/* -------------------------------------------------------------------------
CStreamMem
------------------------------------------------------------------------- */
//+---------------------------------------------------------------------------
//
// Function: CStreamMem::CStreamMem (constructor)
//
// Synopsis: constructs a CStreamMem object
//
//----------------------------------------------------------------------------
CStreamMem::CStreamMem(void)
{
m_pvData = NULL;
m_cbBufferSize= 0;
m_cbSeek = 0;
memset(&m_statstg,0,sizeof(STATSTG));
m_statstg.type = STGTY_STREAM;
GetSystemTimeAsFileTime(&m_statstg.ctime);
m_hRow = DB_NULL_HROW;
m_fExternalData = true;
}
//+---------------------------------------------------------------------------
//
// Function: CStreamMem::~CStreamMem (destructor)
//
// Synopsis: destructs a CStreamMem object
//
//----------------------------------------------------------------------------
CStreamMem::~CStreamMem(void)
{
}
//+---------------------------------------------------------------------------
//
// Function: CStreamMem::Initialize
//
// Synopsis: Initializes a CStreamMem object
//
// Parameters: pVar Variant of type VT_UI1 | VT_ARRAY containing the bytes
// IRow * pointer to IRow interface
// HROW handle to the row that is creating this stream
//
// Returns: HRESULT
//
//----------------------------------------------------------------------------
HRESULT CStreamMem::Initialize(VARIANT *pVar, IRow* pSourceRow, HROW hRow)
{
ADsAssert (pVar && pSourceRow);
//ADSI uses VT_ARRAY|VT_UI1 for binary data. Make sure we have proper type.
ADsAssert(V_VT(pVar) == (VT_ARRAY | VT_UI1));
HRESULT hr = NOERROR;
auto_leave al(m_cs);
SAFEARRAY *psa;
UINT cDim;
TRYBLOCK
al.EnterCriticalSection();
hr = m_pVar.Attach(pVar);
BAIL_ON_FAILURE(hr);
psa = V_ARRAY(pVar);
cDim = SafeArrayGetDim(psa);
if (cDim != 1)
RRETURN(E_INVALIDARG);
//Get bounds of safearray and determine size
long lLBound, lUBound;
hr = SafeArrayGetLBound(psa, cDim, &lLBound);
BAIL_ON_FAILURE(hr);
hr = SafeArrayGetUBound(psa, cDim, &lUBound);
BAIL_ON_FAILURE(hr);
m_cbBufferSize = lUBound - lLBound + 1;
//Get a pointer to the actual byte data
hr = SafeArrayAccessData(V_ARRAY(pVar), &m_pvData);
BAIL_ON_FAILURE(hr);
hr = SafeArrayUnaccessData(psa);
BAIL_ON_FAILURE(hr);
m_pSourceRow = pSourceRow;
m_pSourceRow->AddRef();
m_hRow = hRow;
//Update stat structure
m_statstg.cbSize.LowPart = m_cbBufferSize;
GetSystemTimeAsFileTime(&m_statstg.mtime);
CATCHBLOCKBAIL(hr)
RRETURN(S_OK);
error:
RRETURN(hr);
}
//////////////////////////////////////////////////////////////////////////////
// IStream
//
//+---------------------------------------------------------------------------
//
// Function: CStreamMem::Read
//
// Synopsis: Reads specified number of bytes from stream.
//
// For more info see IStream documentation.
//----------------------------------------------------------------------------
STDMETHODIMP CStreamMem::Read(
void __RPC_FAR *pv,
ULONG cb,
ULONG __RPC_FAR *pcbRead)
{
if (pv == NULL)
RRETURN(STG_E_INVALIDPOINTER);
auto_leave al(m_cs);
ULONG cbRead = 0;
if( pcbRead != NULL )
*pcbRead = 0;
al.EnterCriticalSection();
// anything to do?
if( cb == 0 ||
m_statstg.cbSize.LowPart == 0 ||
m_cbSeek == m_statstg.cbSize.LowPart )
RRETURN(NOERROR);
// determine amount to copy
cbRead = min(cb,m_statstg.cbSize.LowPart - m_cbSeek);
if( cbRead > 0 )
{
// copy it
CopyMemory(pv,(PBYTE)m_pvData + m_cbSeek,cbRead);
// adjust seek pointer
m_cbSeek += cbRead;
}
// update access time
GetSystemTimeAsFileTime(&m_statstg.atime);
if( pcbRead != NULL )
*pcbRead = cbRead;
RRETURN(NOERROR);
}
//+---------------------------------------------------------------------------
//
// Function: CStreamMem::Write
//
// Synopsis: Writes specified number of bytes to stream.
//
// For more info see IStream documentation.
//----------------------------------------------------------------------------
STDMETHODIMP CStreamMem::Write(
const void __RPC_FAR *pv,
ULONG cb,
ULONG __RPC_FAR *pcbWritten)
{
//DS OLE DB provider is currently read-only.
//It doesn't support writes on its streams.
RRETURN(STG_E_ACCESSDENIED);
}
//+---------------------------------------------------------------------------
//
// Function: CStreamMem::Seek
//
// Synopsis: Sets the current read/write pointer to the given position.
//
// For more info see IStream documentation.
//----------------------------------------------------------------------------
STDMETHODIMP CStreamMem::Seek(
LARGE_INTEGER dlibMove,
DWORD dwOrigin,
ULARGE_INTEGER __RPC_FAR *plibNewPosition)
{
auto_leave al(m_cs);
// can we handle the seek?
if( dlibMove.HighPart != 0 )
RRETURN(STG_E_WRITEFAULT);
al.EnterCriticalSection();
// handle the seek request
switch( dwOrigin)
{
case STREAM_SEEK_SET:
if( dlibMove.LowPart > m_statstg.cbSize.LowPart )
RRETURN(STG_E_INVALIDFUNCTION);
m_cbSeek = dlibMove.LowPart;
break;
case STREAM_SEEK_CUR:
if( dlibMove.LowPart + m_cbSeek > m_statstg.cbSize.LowPart )
RRETURN(STG_E_INVALIDFUNCTION);
m_cbSeek += (int)dlibMove.LowPart;
break;
case STREAM_SEEK_END:
//We are read-only provider. Seeking past the end of stream
//or prior to beginning of stream is not supported
if ( int(dlibMove.LowPart) > 0 ||
(int(dlibMove.LowPart) + int(m_statstg.cbSize.LowPart)) < 0
)
RRETURN(STG_E_INVALIDFUNCTION);
m_cbSeek = m_statstg.cbSize.LowPart + (int)dlibMove.LowPart;
break;
}
// return new seek position
if( plibNewPosition )
{
plibNewPosition->HighPart = 0;
plibNewPosition->LowPart = m_cbSeek;
}
RRETURN(NOERROR);
}
//+---------------------------------------------------------------------------
//
// Function: CStreamMem::SetSize
//
// Synopsis: Sets the size of the stream.
//
// For more info see IStream documentation.
//----------------------------------------------------------------------------
STDMETHODIMP CStreamMem::SetSize(
ULARGE_INTEGER libNewSize)
{
//DS OLE DB provider is currently read-only.
//It doesn't support writes on its streams.
RRETURN(STG_E_ACCESSDENIED);
}
//+---------------------------------------------------------------------------
//
// Function: CStreamMem::CopyTo
//
// Synopsis: Copies specified number of bytes from this stream to another.
//
// For more info see IStream documentation.
//----------------------------------------------------------------------------
STDMETHODIMP CStreamMem::CopyTo(
IStream __RPC_FAR *pstm,
ULARGE_INTEGER cb,
ULARGE_INTEGER __RPC_FAR *pcbRead,
ULARGE_INTEGER __RPC_FAR *pcbWritten)
{
auto_leave al(m_cs);
HRESULT hr = NOERROR;
ULONG cbBytes = 0;
ULONG cbWritten = 0;
if( pstm == NULL )
RRETURN(STG_E_INVALIDPOINTER);
al.EnterCriticalSection();
cbBytes = min(m_statstg.cbSize.LowPart - m_cbSeek,cb.LowPart);
if( pcbRead )
pcbRead->QuadPart = cbBytes;
if( cbBytes == 0 )
RRETURN(NOERROR);
hr = pstm->Write((PBYTE)m_pvData + m_cbSeek,cbBytes,&cbWritten);
if( pcbWritten )
pcbWritten->QuadPart = cbWritten;
RRETURN(hr);
}
//+---------------------------------------------------------------------------
//
// Function: CStreamMem::Commit
//
// Synopsis: Makes changes to this stream permanent.
// Note: This is a no-op since this stream is currently read-only.
//
// For more info see IStream documentation.
//----------------------------------------------------------------------------
STDMETHODIMP CStreamMem::Commit(
DWORD grfCommitFlags)
{
RRETURN(S_OK);
}
//+---------------------------------------------------------------------------
//
// Function: CStreamMem::Revert
//
// Synopsis: Reverts changes to this stream.
//
// For more info see IStream documentation.
//----------------------------------------------------------------------------
STDMETHODIMP CStreamMem::Revert( void)
{
RRETURN(E_NOTIMPL);
}
//+---------------------------------------------------------------------------
//
// Function: CStreamMem::LockRegion
//
// Synopsis: Locks a specified number of bytes in the stream
// starting from a given offset.
//
// For more info see IStream documentation.
//----------------------------------------------------------------------------
STDMETHODIMP CStreamMem::LockRegion(
ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb,
DWORD dwLockType)
{
RRETURN(E_NOTIMPL);
}
//+---------------------------------------------------------------------------
//
// Function: CStreamMem::UnlockRegion
//
// Synopsis: Unlocks a specified number of bytes in the stream
// starting from a given offset.
//
// For more info see IStream documentation.
//----------------------------------------------------------------------------
STDMETHODIMP CStreamMem::UnlockRegion(
ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb,
DWORD dwLockType)
{
RRETURN(E_NOTIMPL);
}
//+---------------------------------------------------------------------------
//
// Function: CStreamMem::Stat
//
// Synopsis: Gets information about the stream: size, modification time etc.
//
// For more info see IStream documentation.
//----------------------------------------------------------------------------
STDMETHODIMP CStreamMem::Stat(
STATSTG __RPC_FAR *pstatstg,
DWORD grfStatFlag)
{
auto_leave al(m_cs);
if( !pstatstg )
RRETURN(STG_E_INVALIDPOINTER);
al.EnterCriticalSection();
memcpy(pstatstg,&m_statstg,sizeof(STATSTG));
al.LeaveCriticalSection();
RRETURN(NOERROR);
}
//+---------------------------------------------------------------------------
//
// Function: CStreamMem::Clone
//
// Synopsis: Creates a new stream object which references the same bytes
// but with its own seek pointer.
//
// For more info see IStream documentation.
//----------------------------------------------------------------------------
STDMETHODIMP CStreamMem::Clone(
IStream __RPC_FAR *__RPC_FAR *ppstm)
{
RRETURN(E_NOTIMPL);
}
///////////////////////////////////////////////////////////////////////////////
//IGetSourceRow
//
//+---------------------------------------------------------------------------
//
// Function: CStreamMem::GetSourceRow
//
// Synopsis: Gets the requested interface on the row object that originaly
// created this stream.
//
// For more info see IGetSourceRow in OLE DB 2.5 documentation.
//----------------------------------------------------------------------------
STDMETHODIMP CStreamMem::GetSourceRow(REFIID riid, IUnknown **ppRow)
{
auto_leave al(m_cs);
al.EnterCriticalSection();
if (m_pSourceRow.get() == NULL)
{
*ppRow = NULL;
RRETURN(DB_E_NOSOURCEOBJECT);
}
HRESULT hr = m_pSourceRow->QueryInterface(riid, (void **)ppRow);
if (FAILED(hr))
RRETURN(E_NOINTERFACE);
RRETURN(S_OK);
}
#endif