xref: /AOO41X/main/sal/workben/clipboardwben/testcopy/XTDataObject.cxx (revision 87d2adbc9cadf14644c3679b041b9226f7630199)
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 
CXTDataObject(LONG nRefCntInitVal)53 CXTDataObject::CXTDataObject( LONG nRefCntInitVal ) :
54     m_nRefCnt( nRefCntInitVal )
55 {
56 }
57 
58 //------------------------------------------------------------------------
59 // dtor
60 //------------------------------------------------------------------------
61 
~CXTDataObject()62 CXTDataObject::~CXTDataObject( )
63 {
64 }
65 
66 //------------------------------------------------------------------------
67 // IUnknown->QueryInterface
68 //------------------------------------------------------------------------
69 
QueryInterface(REFIID iid,LPVOID * ppvObject)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 
STDMETHODIMP_(ULONG)95 STDMETHODIMP_(ULONG) CXTDataObject::AddRef( )
96 {
97     return static_cast< ULONG >( InterlockedIncrement( &m_nRefCnt ) );
98 }
99 
100 //------------------------------------------------------------------------
101 // IUnknown->Release
102 //------------------------------------------------------------------------
103 
STDMETHODIMP_(ULONG)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 
GetData(LPFORMATETC pFormatetc,LPSTGMEDIUM pmedium)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 
EnumFormatEtc(DWORD dwDirection,IEnumFORMATETC ** ppenumFormatetc)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 
QueryGetData(LPFORMATETC pFormatetc)221 STDMETHODIMP CXTDataObject::QueryGetData( LPFORMATETC pFormatetc )
222 {
223     return E_NOTIMPL;
224 }
225 
226 //------------------------------------------------------------------------
227 // IDataObject->GetDataHere
228 //------------------------------------------------------------------------
229 
GetDataHere(LPFORMATETC,LPSTGMEDIUM)230 STDMETHODIMP CXTDataObject::GetDataHere( LPFORMATETC, LPSTGMEDIUM )
231 {
232     return E_NOTIMPL;
233 }
234 
235 //------------------------------------------------------------------------
236 // IDataObject->GetCanonicalFormatEtc
237 //------------------------------------------------------------------------
238 
GetCanonicalFormatEtc(LPFORMATETC,LPFORMATETC)239 STDMETHODIMP CXTDataObject::GetCanonicalFormatEtc( LPFORMATETC, LPFORMATETC )
240 {
241     return E_NOTIMPL;
242 }
243 
244 //------------------------------------------------------------------------
245 // IDataObject->SetData
246 //------------------------------------------------------------------------
247 
SetData(LPFORMATETC,LPSTGMEDIUM,BOOL)248 STDMETHODIMP CXTDataObject::SetData( LPFORMATETC, LPSTGMEDIUM, BOOL )
249 {
250     return E_NOTIMPL;
251 }
252 
253 //------------------------------------------------------------------------
254 // IDataObject->DAdvise
255 //------------------------------------------------------------------------
256 
DAdvise(LPFORMATETC,DWORD,LPADVISESINK,DWORD *)257 STDMETHODIMP CXTDataObject::DAdvise( LPFORMATETC, DWORD, LPADVISESINK, DWORD * )
258 {
259     return E_NOTIMPL;
260 }
261 
262 //------------------------------------------------------------------------
263 // IDataObject->DUnadvise
264 //------------------------------------------------------------------------
265 
DUnadvise(DWORD)266 STDMETHODIMP CXTDataObject::DUnadvise( DWORD )
267 {
268     return E_NOTIMPL;
269 }
270 
271 //------------------------------------------------------------------------
272 // IDataObject->EnumDAdvise
273 //------------------------------------------------------------------------
274 
EnumDAdvise(LPENUMSTATDATA *)275 STDMETHODIMP CXTDataObject::EnumDAdvise( LPENUMSTATDATA * )
276 {
277     return E_NOTIMPL;
278 }
279 
280 //------------------------------------------------------------------------
281 // for our convenience
282 //------------------------------------------------------------------------
283 
operator IDataObject*()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 
CEnumFormatEtc(LPUNKNOWN pUnkDataObj)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 
~CEnumFormatEtc()312 CEnumFormatEtc::~CEnumFormatEtc( )
313 {
314 }
315 
316 //----------------------------------------------------------------------------
317 // IUnknown->QueryInterface
318 //----------------------------------------------------------------------------
319 
QueryInterface(REFIID iid,LPVOID * ppvObject)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 
STDMETHODIMP_(ULONG)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 
STDMETHODIMP_(ULONG)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 
Next(ULONG celt,LPFORMATETC rgelt,ULONG * pceltFetched)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 
Skip(ULONG celt)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 
Reset()434 STDMETHODIMP CEnumFormatEtc::Reset( )
435 {
436     m_nCurrentPos = 0;
437     return S_OK;
438 }
439 
440 //----------------------------------------------------------------------------
441 // IEnumFORMATETC->Clone
442 //----------------------------------------------------------------------------
443 
Clone(IEnumFORMATETC ** ppenum)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