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