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