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_dtrans.hxx" 30 31 //------------------------------------------------------------------------ 32 // includes 33 //------------------------------------------------------------------------ 34 #include <osl/diagnose.h> 35 36 #include "..\DTransHelper.hxx" 37 38 #ifndef _TWRAPPERDATAOBJECT_HXX_ 39 #include "XTDo.hxx" 40 #endif 41 42 #if defined _MSC_VER 43 #pragma warning(push,1) 44 #endif 45 #include <windows.h> 46 #include <ole2.h> 47 #if defined _MSC_VER 48 #pragma warning(pop) 49 #endif 50 #include <memory> 51 #include <tchar.h> 52 53 //------------------------------------------------------------------------ 54 // namespace directives 55 //------------------------------------------------------------------------ 56 57 using namespace ::std; 58 59 //============================================================================ 60 // OTWrapperDataObject 61 //============================================================================ 62 63 //------------------------------------------------------------------------ 64 // ctor 65 //------------------------------------------------------------------------ 66 /* 67 in the constructor we enumerate all formats offered by the transferable 68 and convert the formats into formatetc structures 69 if the transferable supports text in different charsets we use either 70 the charset equal to the charset of the current thread or an arbitrary 71 charset supported by the transferable and the system 72 if the transferable supports only unicodetext we offer in addition to 73 this text in the charset of the current thread 74 in order to allow the consumer of the clipboard to query for the charset 75 of the text in the clipboard we offer a CF_LOCALE 76 */ 77 CXTDataObject::CXTDataObject( ) : 78 m_nRefCnt( 0 ) 79 { 80 81 } 82 83 //------------------------------------------------------------------------ 84 // IUnknown->QueryInterface 85 //------------------------------------------------------------------------ 86 87 STDMETHODIMP CXTDataObject::QueryInterface( REFIID iid, LPVOID* ppvObject ) 88 { 89 OSL_ASSERT( NULL != ppvObject ); 90 91 if ( NULL == ppvObject ) 92 return E_INVALIDARG; 93 94 HRESULT hr = E_NOINTERFACE; 95 96 *ppvObject = NULL; 97 98 if ( ( __uuidof( IUnknown ) == iid ) || ( __uuidof( IDataObject ) == iid ) ) 99 { 100 *ppvObject = static_cast< IUnknown* >( this ); 101 ( (LPUNKNOWN)*ppvObject )->AddRef( ); 102 hr = S_OK; 103 } 104 105 return hr; 106 } 107 108 //------------------------------------------------------------------------ 109 // IUnknown->AddRef 110 //------------------------------------------------------------------------ 111 112 STDMETHODIMP_(ULONG) CXTDataObject::AddRef( ) 113 { 114 return static_cast< ULONG >( InterlockedIncrement( &m_nRefCnt ) ); 115 } 116 117 //------------------------------------------------------------------------ 118 // IUnknown->Release 119 //------------------------------------------------------------------------ 120 121 STDMETHODIMP_(ULONG) CXTDataObject::Release( ) 122 { 123 // we need a helper variable because it's 124 // not allowed to access a member variable 125 // after an object is destroyed 126 ULONG nRefCnt = static_cast< ULONG >( InterlockedDecrement( &m_nRefCnt ) ); 127 128 if ( 0 == nRefCnt ) 129 { 130 delete this; 131 } 132 133 return nRefCnt; 134 } 135 136 /*------------------------------------------------------------------------ 137 138 IDataObject->GetData 139 we deliver data only into global memory 140 141 algo: 142 1. convert the given formatect struct into a valid dataflavor 143 2. if the transferable directly supports the requested format 144 2.1. if text data requested add a trailing '\0' in order to prevent 145 problems (windows needs '\0' terminated strings 146 2.2. we expect unicode data as Sequence< sal_Unicode > and all other 147 text and raw data as Sequence< sal_Int8 > 148 149 ------------------------------------------------------------------------*/ 150 151 STDMETHODIMP CXTDataObject::GetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium ) 152 { 153 if ( ( NULL == pFormatetc ) || ( NULL == pmedium ) ) 154 return E_INVALIDARG; 155 156 HRESULT hr = E_FAIL; 157 char pBuff[] = "Test OleClipboard"; 158 159 if ( CF_TEXT == pFormatetc->cfFormat ) 160 { 161 CHGlobalHelper hGlobHlp( TRUE ); 162 163 hGlobHlp.Write( pBuff, sizeof( pBuff ), NULL ); 164 165 pmedium->tymed = TYMED_HGLOBAL; 166 pmedium->hGlobal = hGlobHlp.GetHGlobal( ); 167 pmedium->pUnkForRelease = NULL; 168 169 hr = S_OK; 170 } 171 172 return hr; 173 } 174 175 //------------------------------------------------------------------------ 176 // IDataObject->EnumFormatEtc 177 //------------------------------------------------------------------------ 178 179 STDMETHODIMP CXTDataObject::EnumFormatEtc( DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc ) 180 { 181 if ( ( NULL == ppenumFormatetc ) || ( DATADIR_SET == dwDirection ) ) 182 return E_INVALIDARG; 183 184 *ppenumFormatetc = NULL; 185 186 HRESULT hr = E_FAIL; 187 188 if ( DATADIR_GET == dwDirection ) 189 { 190 *ppenumFormatetc = new CEnumFormatEtc( this ); 191 static_cast< LPUNKNOWN >( *ppenumFormatetc )->AddRef( ); 192 hr = S_OK; 193 } 194 195 return hr; 196 } 197 198 //------------------------------------------------------------------------ 199 // IDataObject->QueryGetData 200 //------------------------------------------------------------------------ 201 202 STDMETHODIMP CXTDataObject::QueryGetData( LPFORMATETC pFormatetc ) 203 { 204 return E_NOTIMPL; 205 } 206 207 //------------------------------------------------------------------------ 208 // IDataObject->GetDataHere 209 //------------------------------------------------------------------------ 210 211 STDMETHODIMP CXTDataObject::GetDataHere( LPFORMATETC, LPSTGMEDIUM ) 212 { 213 return E_NOTIMPL; 214 } 215 216 //------------------------------------------------------------------------ 217 // IDataObject->GetCanonicalFormatEtc 218 //------------------------------------------------------------------------ 219 220 STDMETHODIMP CXTDataObject::GetCanonicalFormatEtc( LPFORMATETC, LPFORMATETC ) 221 { 222 return E_NOTIMPL; 223 } 224 225 //------------------------------------------------------------------------ 226 // IDataObject->SetData 227 //------------------------------------------------------------------------ 228 229 STDMETHODIMP CXTDataObject::SetData( LPFORMATETC, LPSTGMEDIUM, BOOL ) 230 { 231 return E_NOTIMPL; 232 } 233 234 //------------------------------------------------------------------------ 235 // IDataObject->DAdvise 236 //------------------------------------------------------------------------ 237 238 STDMETHODIMP CXTDataObject::DAdvise( LPFORMATETC, DWORD, LPADVISESINK, DWORD * ) 239 { 240 return E_NOTIMPL; 241 } 242 243 //------------------------------------------------------------------------ 244 // IDataObject->DUnadvise 245 //------------------------------------------------------------------------ 246 247 STDMETHODIMP CXTDataObject::DUnadvise( DWORD ) 248 { 249 return E_NOTIMPL; 250 } 251 252 //------------------------------------------------------------------------ 253 // IDataObject->EnumDAdvise 254 //------------------------------------------------------------------------ 255 256 STDMETHODIMP CXTDataObject::EnumDAdvise( LPENUMSTATDATA * ) 257 { 258 return E_NOTIMPL; 259 } 260 261 //------------------------------------------------------------------------ 262 // for our convenience 263 //------------------------------------------------------------------------ 264 265 CXTDataObject::operator IDataObject*( ) 266 { 267 return static_cast< IDataObject* >( this ); 268 } 269 270 271 //============================================================================ 272 // CEnumFormatEtc 273 //============================================================================ 274 275 //---------------------------------------------------------------------------- 276 // ctor 277 //---------------------------------------------------------------------------- 278 279 CEnumFormatEtc::CEnumFormatEtc( LPUNKNOWN pUnkDataObj ) : 280 m_nRefCnt( 0 ), 281 m_pUnkDataObj( pUnkDataObj ), 282 m_nCurrPos( 0 ) 283 { 284 } 285 286 //---------------------------------------------------------------------------- 287 // IUnknown->QueryInterface 288 //---------------------------------------------------------------------------- 289 290 STDMETHODIMP CEnumFormatEtc::QueryInterface( REFIID iid, LPVOID* ppvObject ) 291 { 292 if ( NULL == ppvObject ) 293 return E_INVALIDARG; 294 295 HRESULT hr = E_NOINTERFACE; 296 297 *ppvObject = NULL; 298 299 if ( ( __uuidof( IUnknown ) == iid ) || ( __uuidof( IEnumFORMATETC ) == iid ) ) 300 { 301 *ppvObject = static_cast< IUnknown* >( this ); 302 static_cast< LPUNKNOWN >( *ppvObject )->AddRef( ); 303 hr = S_OK; 304 } 305 306 return hr; 307 } 308 309 //---------------------------------------------------------------------------- 310 // IUnknown->AddRef 311 //---------------------------------------------------------------------------- 312 313 STDMETHODIMP_(ULONG) CEnumFormatEtc::AddRef( ) 314 { 315 // keep the dataobject alive 316 m_pUnkDataObj->AddRef( ); 317 return InterlockedIncrement( &m_nRefCnt ); 318 } 319 320 //---------------------------------------------------------------------------- 321 // IUnknown->Release 322 //---------------------------------------------------------------------------- 323 324 STDMETHODIMP_(ULONG) CEnumFormatEtc::Release( ) 325 { 326 // release the outer dataobject 327 m_pUnkDataObj->Release( ); 328 329 // we need a helper variable because it's 330 // not allowed to access a member variable 331 // after an object is destroyed 332 ULONG nRefCnt = InterlockedDecrement( &m_nRefCnt ); 333 if ( 0 == nRefCnt ) 334 delete this; 335 336 return nRefCnt; 337 } 338 339 //---------------------------------------------------------------------------- 340 // IEnumFORMATETC->Next 341 //---------------------------------------------------------------------------- 342 343 STDMETHODIMP CEnumFormatEtc::Next( ULONG celt, LPFORMATETC rgelt, ULONG* pceltFetched ) 344 { 345 if ( ( 0 != celt ) && ( NULL == rgelt ) ) 346 return E_INVALIDARG; 347 348 ULONG ulFetched = 0; 349 ULONG ulToFetch = celt; 350 HRESULT hr = S_FALSE; 351 352 while( m_nCurrPos < 1 ) 353 { 354 rgelt->cfFormat = CF_TEXT; 355 rgelt->ptd = NULL; 356 rgelt->dwAspect = DVASPECT_CONTENT; 357 rgelt->lindex = -1; 358 rgelt->tymed = TYMED_HGLOBAL; 359 360 ++m_nCurrPos; 361 ++rgelt; 362 --ulToFetch; 363 ++ulFetched; 364 } 365 366 if ( ulFetched == celt ) 367 hr = S_OK; 368 369 if ( NULL != pceltFetched ) 370 { 371 *pceltFetched = ulFetched; 372 } 373 374 return hr; 375 } 376 377 //---------------------------------------------------------------------------- 378 // IEnumFORMATETC->Skip 379 //---------------------------------------------------------------------------- 380 381 STDMETHODIMP CEnumFormatEtc::Skip( ULONG celt ) 382 { 383 HRESULT hr = S_FALSE; 384 385 /* 386 if ( ( m_nCurrPos + celt ) < m_nClipFormats ) 387 { 388 m_nCurrPos += celt; 389 hr = S_OK; 390 } 391 */ 392 393 return hr; 394 } 395 396 //---------------------------------------------------------------------------- 397 // IEnumFORMATETC->Reset 398 //---------------------------------------------------------------------------- 399 400 STDMETHODIMP CEnumFormatEtc::Reset( ) 401 { 402 m_nCurrPos = 0; 403 return S_OK; 404 } 405 406 //---------------------------------------------------------------------------- 407 // IEnumFORMATETC->Clone 408 //---------------------------------------------------------------------------- 409 410 STDMETHODIMP CEnumFormatEtc::Clone( IEnumFORMATETC** ppenum ) 411 { 412 OSL_ASSERT( NULL != ppenum ); 413 414 if ( NULL == ppenum ) 415 return E_INVALIDARG; 416 417 HRESULT hr = E_FAIL; 418 419 *ppenum = NULL; 420 421 CEnumFormatEtc* pCEnumFEtc = new CEnumFormatEtc( m_pUnkDataObj ); 422 if ( NULL != pCEnumFEtc ) 423 { 424 pCEnumFEtc->m_nCurrPos = m_nCurrPos; 425 *ppenum = static_cast< IEnumFORMATETC* >( pCEnumFEtc ); 426 static_cast< LPUNKNOWN >( *ppenum )->AddRef( ); 427 hr = NOERROR; 428 } 429 430 return hr; 431 } 432