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