1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sal.hxx" 30 31 //------------------------------------------------------------------------ 32 // includes 33 //------------------------------------------------------------------------ 34 #include <osl/diagnose.h> 35 36 #ifndef _TWRAPPERDATAOBJECT_HXX_ 37 #include "XTDataObject.hxx" 38 #endif 39 40 #include <windows.h> 41 #include <ole2.h> 42 #include <memory> 43 44 //------------------------------------------------------------------------ 45 // namespace directives 46 //------------------------------------------------------------------------ 47 48 49 //============================================================================ 50 // OTWrapperDataObject 51 //============================================================================ 52 53 //------------------------------------------------------------------------ 54 // ctor 55 //------------------------------------------------------------------------ 56 57 CXTDataObject::CXTDataObject( LONG nRefCntInitVal ) : 58 m_nRefCnt( nRefCntInitVal ) 59 { 60 } 61 62 //------------------------------------------------------------------------ 63 // dtor 64 //------------------------------------------------------------------------ 65 66 CXTDataObject::~CXTDataObject( ) 67 { 68 } 69 70 //------------------------------------------------------------------------ 71 // IUnknown->QueryInterface 72 //------------------------------------------------------------------------ 73 74 STDMETHODIMP CXTDataObject::QueryInterface( REFIID iid, LPVOID* ppvObject ) 75 { 76 OSL_ASSERT( NULL != ppvObject ); 77 78 if ( NULL == ppvObject ) 79 return E_INVALIDARG; 80 81 HRESULT hr = E_NOINTERFACE; 82 83 *ppvObject = NULL; 84 85 if ( ( __uuidof( IUnknown ) == iid ) || ( __uuidof( IDataObject ) == iid ) ) 86 { 87 *ppvObject = static_cast< IUnknown* >( this ); 88 ( (LPUNKNOWN)*ppvObject )->AddRef( ); 89 hr = S_OK; 90 } 91 92 return hr; 93 } 94 95 //------------------------------------------------------------------------ 96 // IUnknown->AddRef 97 //------------------------------------------------------------------------ 98 99 STDMETHODIMP_(ULONG) CXTDataObject::AddRef( ) 100 { 101 return static_cast< ULONG >( InterlockedIncrement( &m_nRefCnt ) ); 102 } 103 104 //------------------------------------------------------------------------ 105 // IUnknown->Release 106 //------------------------------------------------------------------------ 107 108 STDMETHODIMP_(ULONG) CXTDataObject::Release( ) 109 { 110 // we need a helper variable because it's 111 // not allowed to access a member variable 112 // after an object is destroyed 113 ULONG nRefCnt = static_cast< ULONG >( InterlockedDecrement( &m_nRefCnt ) ); 114 115 if ( 0 == nRefCnt ) 116 { 117 delete this; 118 } 119 120 return nRefCnt; 121 } 122 123 //------------------------------------------------------------------------ 124 // IDataObject->GetData 125 // warning: 'goto' ahead (to easy error handling without using exceptions) 126 //------------------------------------------------------------------------ 127 128 STDMETHODIMP CXTDataObject::GetData(LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium ) 129 { 130 OSL_ASSERT( ( NULL != pFormatetc ) && 131 ( !IsBadReadPtr( (LPVOID)pFormatetc, sizeof( FORMATETC ) ) ) ); 132 OSL_ASSERT( ( NULL != pmedium ) && 133 ( !IsBadWritePtr( (LPVOID)pmedium, sizeof( STGMEDIUM ) ) ) ); 134 135 if ( ( NULL == pFormatetc ) || ( NULL == pmedium ) ) 136 return E_INVALIDARG; 137 138 HRESULT hr = E_FAIL; 139 140 if ( CF_TEXT == pFormatetc->cfFormat ) 141 { 142 char buff[] = "Hello World, How are you!"; 143 LPSTREAM lpStream; 144 145 hr = CreateStreamOnHGlobal( NULL, FALSE, &lpStream ); 146 if ( SUCCEEDED( hr ) ) 147 { 148 hr = lpStream->Write( buff, sizeof( buff ) * sizeof( char ), NULL ); 149 if ( SUCCEEDED( hr ) ) 150 { 151 HGLOBAL hGlob; 152 153 GetHGlobalFromStream( lpStream, &hGlob ); 154 155 pmedium->tymed = TYMED_HGLOBAL; 156 pmedium->hGlobal = hGlob; 157 pmedium->pUnkForRelease = NULL; 158 } 159 lpStream->Release( ); 160 hr = S_OK; 161 } 162 else 163 { 164 pmedium->tymed = TYMED_NULL; 165 } 166 } 167 else if ( CF_UNICODETEXT == pFormatetc->cfFormat ) 168 { 169 WCHAR buff[] = L"Hello World, How are you!"; 170 LPSTREAM lpStream; 171 172 hr = CreateStreamOnHGlobal( NULL, FALSE, &lpStream ); 173 if ( SUCCEEDED( hr ) ) 174 { 175 hr = lpStream->Write( buff, sizeof( buff ) * sizeof( WCHAR ), NULL ); 176 if ( SUCCEEDED( hr ) ) 177 { 178 HGLOBAL hGlob; 179 180 GetHGlobalFromStream( lpStream, &hGlob ); 181 182 pmedium->tymed = TYMED_HGLOBAL; 183 pmedium->hGlobal = hGlob; 184 pmedium->pUnkForRelease = NULL; 185 } 186 lpStream->Release( ); 187 hr = S_OK; 188 } 189 else 190 { 191 pmedium->tymed = TYMED_NULL; 192 } 193 } 194 195 return hr; 196 } 197 198 //------------------------------------------------------------------------ 199 // IDataObject->EnumFormatEtc 200 //------------------------------------------------------------------------ 201 202 STDMETHODIMP CXTDataObject::EnumFormatEtc( DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc ) 203 { 204 if ( ( NULL == ppenumFormatetc ) || ( DATADIR_SET == dwDirection ) ) 205 return E_INVALIDARG; 206 207 *ppenumFormatetc = NULL; 208 209 HRESULT hr = E_FAIL; 210 211 if ( DATADIR_GET == dwDirection ) 212 { 213 *ppenumFormatetc = new CEnumFormatEtc( this ); 214 static_cast< LPUNKNOWN >( *ppenumFormatetc )->AddRef( ); 215 hr = S_OK; 216 } 217 218 return hr; 219 } 220 221 //------------------------------------------------------------------------ 222 // IDataObject->QueryGetData 223 //------------------------------------------------------------------------ 224 225 STDMETHODIMP CXTDataObject::QueryGetData( LPFORMATETC pFormatetc ) 226 { 227 return E_NOTIMPL; 228 } 229 230 //------------------------------------------------------------------------ 231 // IDataObject->GetDataHere 232 //------------------------------------------------------------------------ 233 234 STDMETHODIMP CXTDataObject::GetDataHere( LPFORMATETC, LPSTGMEDIUM ) 235 { 236 return E_NOTIMPL; 237 } 238 239 //------------------------------------------------------------------------ 240 // IDataObject->GetCanonicalFormatEtc 241 //------------------------------------------------------------------------ 242 243 STDMETHODIMP CXTDataObject::GetCanonicalFormatEtc( LPFORMATETC, LPFORMATETC ) 244 { 245 return E_NOTIMPL; 246 } 247 248 //------------------------------------------------------------------------ 249 // IDataObject->SetData 250 //------------------------------------------------------------------------ 251 252 STDMETHODIMP CXTDataObject::SetData( LPFORMATETC, LPSTGMEDIUM, BOOL ) 253 { 254 return E_NOTIMPL; 255 } 256 257 //------------------------------------------------------------------------ 258 // IDataObject->DAdvise 259 //------------------------------------------------------------------------ 260 261 STDMETHODIMP CXTDataObject::DAdvise( LPFORMATETC, DWORD, LPADVISESINK, DWORD * ) 262 { 263 return E_NOTIMPL; 264 } 265 266 //------------------------------------------------------------------------ 267 // IDataObject->DUnadvise 268 //------------------------------------------------------------------------ 269 270 STDMETHODIMP CXTDataObject::DUnadvise( DWORD ) 271 { 272 return E_NOTIMPL; 273 } 274 275 //------------------------------------------------------------------------ 276 // IDataObject->EnumDAdvise 277 //------------------------------------------------------------------------ 278 279 STDMETHODIMP CXTDataObject::EnumDAdvise( LPENUMSTATDATA * ) 280 { 281 return E_NOTIMPL; 282 } 283 284 //------------------------------------------------------------------------ 285 // for our convenience 286 //------------------------------------------------------------------------ 287 288 CXTDataObject::operator IDataObject*( ) 289 { 290 return static_cast< IDataObject* >( this ); 291 } 292 293 294 //============================================================================ 295 // CEnumFormatEtc 296 //============================================================================ 297 298 299 //---------------------------------------------------------------------------- 300 // ctor 301 //---------------------------------------------------------------------------- 302 303 CEnumFormatEtc::CEnumFormatEtc( LPUNKNOWN pUnkDataObj ) : 304 m_nRefCnt( 0 ), 305 m_pUnkDataObj( pUnkDataObj ), 306 m_nCurrentPos( 0 ) 307 { 308 m_cfFormats[0] = CF_UNICODETEXT; 309 m_cfFormats[1] = CF_TEXT; 310 } 311 312 //---------------------------------------------------------------------------- 313 // dtor 314 //---------------------------------------------------------------------------- 315 316 CEnumFormatEtc::~CEnumFormatEtc( ) 317 { 318 } 319 320 //---------------------------------------------------------------------------- 321 // IUnknown->QueryInterface 322 //---------------------------------------------------------------------------- 323 324 STDMETHODIMP CEnumFormatEtc::QueryInterface( REFIID iid, LPVOID* ppvObject ) 325 { 326 if ( NULL == ppvObject ) 327 return E_INVALIDARG; 328 329 HRESULT hr = E_NOINTERFACE; 330 331 *ppvObject = NULL; 332 333 if ( ( __uuidof( IUnknown ) == iid ) || ( __uuidof( IEnumFORMATETC ) == iid ) ) 334 { 335 *ppvObject = static_cast< IUnknown* >( this ); 336 static_cast< LPUNKNOWN >( *ppvObject )->AddRef( ); 337 hr = S_OK; 338 } 339 340 return hr; 341 } 342 343 //---------------------------------------------------------------------------- 344 // IUnknown->AddRef 345 //---------------------------------------------------------------------------- 346 347 STDMETHODIMP_(ULONG) CEnumFormatEtc::AddRef( ) 348 { 349 // keep the dataobject alive 350 m_pUnkDataObj->AddRef( ); 351 return InterlockedIncrement( &m_nRefCnt ); 352 } 353 354 //---------------------------------------------------------------------------- 355 // IUnknown->Release 356 //---------------------------------------------------------------------------- 357 358 STDMETHODIMP_(ULONG) CEnumFormatEtc::Release( ) 359 { 360 // release the outer dataobject 361 m_pUnkDataObj->Release( ); 362 363 // we need a helper variable because it's 364 // not allowed to access a member variable 365 // after an object is destroyed 366 ULONG nRefCnt = InterlockedDecrement( &m_nRefCnt ); 367 if ( 0 == nRefCnt ) 368 delete this; 369 370 return nRefCnt; 371 } 372 373 //---------------------------------------------------------------------------- 374 // IEnumFORMATETC->Next 375 //---------------------------------------------------------------------------- 376 377 STDMETHODIMP CEnumFormatEtc::Next( ULONG celt, LPFORMATETC rgelt, ULONG* pceltFetched ) 378 { 379 OSL_ASSERT( ( ( celt > 0 ) && ( NULL != rgelt ) ) || 380 ( ( 0 == celt ) && ( NULL == rgelt ) ) ); 381 382 if ( ( 0 != celt ) && ( NULL == rgelt ) ) 383 return E_INVALIDARG; 384 385 ULONG ulFetched = 0; 386 ULONG ulToFetch = celt; 387 HRESULT hr = S_FALSE; 388 389 while( ( m_nCurrentPos < sizeof( m_cfFormats ) ) && ( ulToFetch > 0 ) ) 390 { 391 OSL_ASSERT( !IsBadWritePtr( (LPVOID)rgelt, sizeof( FORMATETC ) ) ); 392 393 rgelt->cfFormat = m_cfFormats[m_nCurrentPos]; 394 rgelt->ptd = NULL; 395 rgelt->dwAspect = DVASPECT_CONTENT; 396 rgelt->lindex = -1; 397 rgelt->tymed = TYMED_HGLOBAL; 398 399 ++m_nCurrentPos; 400 ++rgelt; 401 --ulToFetch; 402 ++ulFetched; 403 } 404 405 if ( ulFetched == celt ) 406 hr = S_OK; 407 408 if ( NULL != pceltFetched ) 409 { 410 OSL_ASSERT( !IsBadWritePtr( (LPVOID)pceltFetched, sizeof( ULONG ) ) ); 411 *pceltFetched = ulFetched; 412 } 413 414 return hr; 415 } 416 417 //---------------------------------------------------------------------------- 418 // IEnumFORMATETC->Skip 419 //---------------------------------------------------------------------------- 420 421 STDMETHODIMP CEnumFormatEtc::Skip( ULONG celt ) 422 { 423 HRESULT hr = S_FALSE; 424 425 if ( ( m_nCurrentPos + celt ) < sizeof( m_cfFormats ) ) 426 { 427 m_nCurrentPos += celt; 428 hr = S_OK; 429 } 430 431 return hr; 432 } 433 434 //---------------------------------------------------------------------------- 435 // IEnumFORMATETC->Reset 436 //---------------------------------------------------------------------------- 437 438 STDMETHODIMP CEnumFormatEtc::Reset( ) 439 { 440 m_nCurrentPos = 0; 441 return S_OK; 442 } 443 444 //---------------------------------------------------------------------------- 445 // IEnumFORMATETC->Clone 446 //---------------------------------------------------------------------------- 447 448 STDMETHODIMP CEnumFormatEtc::Clone( IEnumFORMATETC** ppenum ) 449 { 450 OSL_ASSERT( NULL != ppenum ); 451 452 if ( NULL == ppenum ) 453 return E_INVALIDARG; 454 455 HRESULT hr = E_FAIL; 456 457 *ppenum = NULL; 458 459 CEnumFormatEtc* pCEnumFEtc = new CEnumFormatEtc( m_pUnkDataObj ); 460 if ( NULL != pCEnumFEtc ) 461 { 462 pCEnumFEtc->m_nCurrentPos = m_nCurrentPos; 463 *ppenum = static_cast< IEnumFORMATETC* >( pCEnumFEtc ); 464 static_cast< LPUNKNOWN >( *ppenum )->AddRef( ); 465 hr = NOERROR; 466 } 467 468 return hr; 469 } 470 471