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