blob: 327567985022a9ac0ca18995c73bccb3bbdff88a [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sal.hxx"
//------------------------------------------------------------------------
// includes
//------------------------------------------------------------------------
#include <osl/diagnose.h>
#ifndef _TWRAPPERDATAOBJECT_HXX_
#include "XTDataObject.hxx"
#endif
#include <windows.h>
#include <ole2.h>
#include <memory>
//------------------------------------------------------------------------
// namespace directives
//------------------------------------------------------------------------
//============================================================================
// OTWrapperDataObject
//============================================================================
//------------------------------------------------------------------------
// ctor
//------------------------------------------------------------------------
CXTDataObject::CXTDataObject( LONG nRefCntInitVal ) :
m_nRefCnt( nRefCntInitVal )
{
}
//------------------------------------------------------------------------
// dtor
//------------------------------------------------------------------------
CXTDataObject::~CXTDataObject( )
{
}
//------------------------------------------------------------------------
// IUnknown->QueryInterface
//------------------------------------------------------------------------
STDMETHODIMP CXTDataObject::QueryInterface( REFIID iid, LPVOID* ppvObject )
{
OSL_ASSERT( NULL != ppvObject );
if ( NULL == ppvObject )
return E_INVALIDARG;
HRESULT hr = E_NOINTERFACE;
*ppvObject = NULL;
if ( ( __uuidof( IUnknown ) == iid ) || ( __uuidof( IDataObject ) == iid ) )
{
*ppvObject = static_cast< IUnknown* >( this );
( (LPUNKNOWN)*ppvObject )->AddRef( );
hr = S_OK;
}
return hr;
}
//------------------------------------------------------------------------
// IUnknown->AddRef
//------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CXTDataObject::AddRef( )
{
return static_cast< ULONG >( InterlockedIncrement( &m_nRefCnt ) );
}
//------------------------------------------------------------------------
// IUnknown->Release
//------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CXTDataObject::Release( )
{
// we need a helper variable because it's
// not allowed to access a member variable
// after an object is destroyed
ULONG nRefCnt = static_cast< ULONG >( InterlockedDecrement( &m_nRefCnt ) );
if ( 0 == nRefCnt )
{
delete this;
}
return nRefCnt;
}
//------------------------------------------------------------------------
// IDataObject->GetData
// warning: 'goto' ahead (to easy error handling without using exceptions)
//------------------------------------------------------------------------
STDMETHODIMP CXTDataObject::GetData(LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium )
{
OSL_ASSERT( ( NULL != pFormatetc ) &&
( !IsBadReadPtr( (LPVOID)pFormatetc, sizeof( FORMATETC ) ) ) );
OSL_ASSERT( ( NULL != pmedium ) &&
( !IsBadWritePtr( (LPVOID)pmedium, sizeof( STGMEDIUM ) ) ) );
if ( ( NULL == pFormatetc ) || ( NULL == pmedium ) )
return E_INVALIDARG;
HRESULT hr = E_FAIL;
if ( CF_TEXT == pFormatetc->cfFormat )
{
char buff[] = "Hello World, How are you!";
LPSTREAM lpStream;
hr = CreateStreamOnHGlobal( NULL, FALSE, &lpStream );
if ( SUCCEEDED( hr ) )
{
hr = lpStream->Write( buff, sizeof( buff ) * sizeof( char ), NULL );
if ( SUCCEEDED( hr ) )
{
HGLOBAL hGlob;
GetHGlobalFromStream( lpStream, &hGlob );
pmedium->tymed = TYMED_HGLOBAL;
pmedium->hGlobal = hGlob;
pmedium->pUnkForRelease = NULL;
}
lpStream->Release( );
hr = S_OK;
}
else
{
pmedium->tymed = TYMED_NULL;
}
}
else if ( CF_UNICODETEXT == pFormatetc->cfFormat )
{
WCHAR buff[] = L"Hello World, How are you!";
LPSTREAM lpStream;
hr = CreateStreamOnHGlobal( NULL, FALSE, &lpStream );
if ( SUCCEEDED( hr ) )
{
hr = lpStream->Write( buff, sizeof( buff ) * sizeof( WCHAR ), NULL );
if ( SUCCEEDED( hr ) )
{
HGLOBAL hGlob;
GetHGlobalFromStream( lpStream, &hGlob );
pmedium->tymed = TYMED_HGLOBAL;
pmedium->hGlobal = hGlob;
pmedium->pUnkForRelease = NULL;
}
lpStream->Release( );
hr = S_OK;
}
else
{
pmedium->tymed = TYMED_NULL;
}
}
return hr;
}
//------------------------------------------------------------------------
// IDataObject->EnumFormatEtc
//------------------------------------------------------------------------
STDMETHODIMP CXTDataObject::EnumFormatEtc( DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc )
{
if ( ( NULL == ppenumFormatetc ) || ( DATADIR_SET == dwDirection ) )
return E_INVALIDARG;
*ppenumFormatetc = NULL;
HRESULT hr = E_FAIL;
if ( DATADIR_GET == dwDirection )
{
*ppenumFormatetc = new CEnumFormatEtc( this );
static_cast< LPUNKNOWN >( *ppenumFormatetc )->AddRef( );
hr = S_OK;
}
return hr;
}
//------------------------------------------------------------------------
// IDataObject->QueryGetData
//------------------------------------------------------------------------
STDMETHODIMP CXTDataObject::QueryGetData( LPFORMATETC pFormatetc )
{
return E_NOTIMPL;
}
//------------------------------------------------------------------------
// IDataObject->GetDataHere
//------------------------------------------------------------------------
STDMETHODIMP CXTDataObject::GetDataHere( LPFORMATETC, LPSTGMEDIUM )
{
return E_NOTIMPL;
}
//------------------------------------------------------------------------
// IDataObject->GetCanonicalFormatEtc
//------------------------------------------------------------------------
STDMETHODIMP CXTDataObject::GetCanonicalFormatEtc( LPFORMATETC, LPFORMATETC )
{
return E_NOTIMPL;
}
//------------------------------------------------------------------------
// IDataObject->SetData
//------------------------------------------------------------------------
STDMETHODIMP CXTDataObject::SetData( LPFORMATETC, LPSTGMEDIUM, BOOL )
{
return E_NOTIMPL;
}
//------------------------------------------------------------------------
// IDataObject->DAdvise
//------------------------------------------------------------------------
STDMETHODIMP CXTDataObject::DAdvise( LPFORMATETC, DWORD, LPADVISESINK, DWORD * )
{
return E_NOTIMPL;
}
//------------------------------------------------------------------------
// IDataObject->DUnadvise
//------------------------------------------------------------------------
STDMETHODIMP CXTDataObject::DUnadvise( DWORD )
{
return E_NOTIMPL;
}
//------------------------------------------------------------------------
// IDataObject->EnumDAdvise
//------------------------------------------------------------------------
STDMETHODIMP CXTDataObject::EnumDAdvise( LPENUMSTATDATA * )
{
return E_NOTIMPL;
}
//------------------------------------------------------------------------
// for our convenience
//------------------------------------------------------------------------
CXTDataObject::operator IDataObject*( )
{
return static_cast< IDataObject* >( this );
}
//============================================================================
// CEnumFormatEtc
//============================================================================
//----------------------------------------------------------------------------
// ctor
//----------------------------------------------------------------------------
CEnumFormatEtc::CEnumFormatEtc( LPUNKNOWN pUnkDataObj ) :
m_nRefCnt( 0 ),
m_pUnkDataObj( pUnkDataObj ),
m_nCurrentPos( 0 )
{
m_cfFormats[0] = CF_UNICODETEXT;
m_cfFormats[1] = CF_TEXT;
}
//----------------------------------------------------------------------------
// dtor
//----------------------------------------------------------------------------
CEnumFormatEtc::~CEnumFormatEtc( )
{
}
//----------------------------------------------------------------------------
// IUnknown->QueryInterface
//----------------------------------------------------------------------------
STDMETHODIMP CEnumFormatEtc::QueryInterface( REFIID iid, LPVOID* ppvObject )
{
if ( NULL == ppvObject )
return E_INVALIDARG;
HRESULT hr = E_NOINTERFACE;
*ppvObject = NULL;
if ( ( __uuidof( IUnknown ) == iid ) || ( __uuidof( IEnumFORMATETC ) == iid ) )
{
*ppvObject = static_cast< IUnknown* >( this );
static_cast< LPUNKNOWN >( *ppvObject )->AddRef( );
hr = S_OK;
}
return hr;
}
//----------------------------------------------------------------------------
// IUnknown->AddRef
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CEnumFormatEtc::AddRef( )
{
// keep the dataobject alive
m_pUnkDataObj->AddRef( );
return InterlockedIncrement( &m_nRefCnt );
}
//----------------------------------------------------------------------------
// IUnknown->Release
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CEnumFormatEtc::Release( )
{
// release the outer dataobject
m_pUnkDataObj->Release( );
// we need a helper variable because it's
// not allowed to access a member variable
// after an object is destroyed
ULONG nRefCnt = InterlockedDecrement( &m_nRefCnt );
if ( 0 == nRefCnt )
delete this;
return nRefCnt;
}
//----------------------------------------------------------------------------
// IEnumFORMATETC->Next
//----------------------------------------------------------------------------
STDMETHODIMP CEnumFormatEtc::Next( ULONG celt, LPFORMATETC rgelt, ULONG* pceltFetched )
{
OSL_ASSERT( ( ( celt > 0 ) && ( NULL != rgelt ) ) ||
( ( 0 == celt ) && ( NULL == rgelt ) ) );
if ( ( 0 != celt ) && ( NULL == rgelt ) )
return E_INVALIDARG;
ULONG ulFetched = 0;
ULONG ulToFetch = celt;
HRESULT hr = S_FALSE;
while( ( m_nCurrentPos < sizeof( m_cfFormats ) ) && ( ulToFetch > 0 ) )
{
OSL_ASSERT( !IsBadWritePtr( (LPVOID)rgelt, sizeof( FORMATETC ) ) );
rgelt->cfFormat = m_cfFormats[m_nCurrentPos];
rgelt->ptd = NULL;
rgelt->dwAspect = DVASPECT_CONTENT;
rgelt->lindex = -1;
rgelt->tymed = TYMED_HGLOBAL;
++m_nCurrentPos;
++rgelt;
--ulToFetch;
++ulFetched;
}
if ( ulFetched == celt )
hr = S_OK;
if ( NULL != pceltFetched )
{
OSL_ASSERT( !IsBadWritePtr( (LPVOID)pceltFetched, sizeof( ULONG ) ) );
*pceltFetched = ulFetched;
}
return hr;
}
//----------------------------------------------------------------------------
// IEnumFORMATETC->Skip
//----------------------------------------------------------------------------
STDMETHODIMP CEnumFormatEtc::Skip( ULONG celt )
{
HRESULT hr = S_FALSE;
if ( ( m_nCurrentPos + celt ) < sizeof( m_cfFormats ) )
{
m_nCurrentPos += celt;
hr = S_OK;
}
return hr;
}
//----------------------------------------------------------------------------
// IEnumFORMATETC->Reset
//----------------------------------------------------------------------------
STDMETHODIMP CEnumFormatEtc::Reset( )
{
m_nCurrentPos = 0;
return S_OK;
}
//----------------------------------------------------------------------------
// IEnumFORMATETC->Clone
//----------------------------------------------------------------------------
STDMETHODIMP CEnumFormatEtc::Clone( IEnumFORMATETC** ppenum )
{
OSL_ASSERT( NULL != ppenum );
if ( NULL == ppenum )
return E_INVALIDARG;
HRESULT hr = E_FAIL;
*ppenum = NULL;
CEnumFormatEtc* pCEnumFEtc = new CEnumFormatEtc( m_pUnkDataObj );
if ( NULL != pCEnumFEtc )
{
pCEnumFEtc->m_nCurrentPos = m_nCurrentPos;
*ppenum = static_cast< IEnumFORMATETC* >( pCEnumFEtc );
static_cast< LPUNKNOWN >( *ppenum )->AddRef( );
hr = NOERROR;
}
return hr;
}