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_dtrans.hxx"
30 
31 //------------------------------------------------------------------------
32 // includes
33 //------------------------------------------------------------------------
34 #include <osl/diagnose.h>
35 
36 #include "..\DTransHelper.hxx"
37 
38 #ifndef _TWRAPPERDATAOBJECT_HXX_
39 #include "XTDo.hxx"
40 #endif
41 
42 #if defined _MSC_VER
43 #pragma warning(push,1)
44 #endif
45 #include <windows.h>
46 #include <ole2.h>
47 #if defined _MSC_VER
48 #pragma warning(pop)
49 #endif
50 #include <memory>
51 #include <tchar.h>
52 
53 //------------------------------------------------------------------------
54 // namespace directives
55 //------------------------------------------------------------------------
56 
57 using namespace ::std;
58 
59 //============================================================================
60 // OTWrapperDataObject
61 //============================================================================
62 
63 //------------------------------------------------------------------------
64 // ctor
65 //------------------------------------------------------------------------
66 /*
67 	in the constructor we enumerate all formats offered by the transferable
68 	and convert the formats into formatetc structures
69 	if the transferable supports text in different charsets we use either
70 	the charset equal to the charset of the current thread or an arbitrary
71 	charset supported by the transferable and the system
72 	if the transferable supports only unicodetext we offer in addition to
73 	this text in the charset of the current thread
74 	in order to allow the consumer of the clipboard to query for the charset
75 	of the text in the clipboard we offer a CF_LOCALE
76 */
77 CXTDataObject::CXTDataObject( ) :
78 	m_nRefCnt( 0 )
79 {
80 
81 }
82 
83 //------------------------------------------------------------------------
84 // IUnknown->QueryInterface
85 //------------------------------------------------------------------------
86 
87 STDMETHODIMP CXTDataObject::QueryInterface( REFIID iid, LPVOID* ppvObject )
88 {
89 	OSL_ASSERT( NULL != ppvObject );
90 
91 	if ( NULL == ppvObject )
92 		return E_INVALIDARG;
93 
94 	HRESULT hr = E_NOINTERFACE;
95 
96 	*ppvObject = NULL;
97 
98 	if ( ( __uuidof( IUnknown ) == iid ) || ( __uuidof( IDataObject ) == iid ) )
99 	{
100 		*ppvObject = static_cast< IUnknown* >( this );
101 		( (LPUNKNOWN)*ppvObject )->AddRef( );
102 		hr = S_OK;
103 	}
104 
105 	return hr;
106 }
107 
108 //------------------------------------------------------------------------
109 // IUnknown->AddRef
110 //------------------------------------------------------------------------
111 
112 STDMETHODIMP_(ULONG) CXTDataObject::AddRef( )
113 {
114 	return static_cast< ULONG >( InterlockedIncrement( &m_nRefCnt ) );
115 }
116 
117 //------------------------------------------------------------------------
118 // IUnknown->Release
119 //------------------------------------------------------------------------
120 
121 STDMETHODIMP_(ULONG) CXTDataObject::Release( )
122 {
123 	// we need a helper variable because it's
124 	// not allowed to access a member variable
125 	// after an object is destroyed
126 	ULONG nRefCnt = static_cast< ULONG >( InterlockedDecrement( &m_nRefCnt ) );
127 
128 	if ( 0 == nRefCnt )
129 	{
130 		delete this;
131 	}
132 
133 	return nRefCnt;
134 }
135 
136 /*------------------------------------------------------------------------
137 
138  IDataObject->GetData
139  we deliver data only into global memory
140 
141  algo:
142  1. convert the given formatect struct into a valid dataflavor
143  2. if the transferable directly supports the requested format
144  2.1. if text data requested add a trailing '\0' in order to prevent
145 		problems (windows needs '\0' terminated strings
146  2.2. we expect unicode data as Sequence< sal_Unicode > and all other
147 	    text and raw data as Sequence< sal_Int8 >
148 
149 ------------------------------------------------------------------------*/
150 
151 STDMETHODIMP CXTDataObject::GetData( LPFORMATETC pFormatetc, LPSTGMEDIUM pmedium )
152 {
153 	if ( ( NULL == pFormatetc ) || ( NULL == pmedium ) )
154 		return E_INVALIDARG;
155 
156 	HRESULT hr = E_FAIL;
157 	char    pBuff[] = "Test OleClipboard";
158 
159 	if ( CF_TEXT == pFormatetc->cfFormat )
160 	{
161 		CHGlobalHelper hGlobHlp( TRUE );
162 
163 		hGlobHlp.Write( pBuff, sizeof( pBuff ), NULL );
164 
165 		pmedium->tymed          = TYMED_HGLOBAL;
166 		pmedium->hGlobal        = hGlobHlp.GetHGlobal( );
167 		pmedium->pUnkForRelease = NULL;
168 
169 		hr = S_OK;
170 	}
171 
172 	return hr;
173 }
174 
175 //------------------------------------------------------------------------
176 // IDataObject->EnumFormatEtc
177 //------------------------------------------------------------------------
178 
179 STDMETHODIMP CXTDataObject::EnumFormatEtc( DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc )
180 {
181 	if ( ( NULL == ppenumFormatetc ) || ( DATADIR_SET == dwDirection ) )
182 		return E_INVALIDARG;
183 
184 	*ppenumFormatetc = NULL;
185 
186 	HRESULT hr = E_FAIL;
187 
188 	if ( DATADIR_GET == dwDirection )
189 	{
190 		*ppenumFormatetc = new CEnumFormatEtc( this );
191 		static_cast< LPUNKNOWN >( *ppenumFormatetc )->AddRef( );
192 		hr = S_OK;
193 	}
194 
195 	return hr;
196 }
197 
198 //------------------------------------------------------------------------
199 // IDataObject->QueryGetData
200 //------------------------------------------------------------------------
201 
202 STDMETHODIMP CXTDataObject::QueryGetData( LPFORMATETC pFormatetc )
203 {
204 	return E_NOTIMPL;
205 }
206 
207 //------------------------------------------------------------------------
208 // IDataObject->GetDataHere
209 //------------------------------------------------------------------------
210 
211 STDMETHODIMP CXTDataObject::GetDataHere( LPFORMATETC, LPSTGMEDIUM )
212 {
213 	return E_NOTIMPL;
214 }
215 
216 //------------------------------------------------------------------------
217 // IDataObject->GetCanonicalFormatEtc
218 //------------------------------------------------------------------------
219 
220 STDMETHODIMP CXTDataObject::GetCanonicalFormatEtc( LPFORMATETC, LPFORMATETC )
221 {
222 	return E_NOTIMPL;
223 }
224 
225 //------------------------------------------------------------------------
226 // IDataObject->SetData
227 //------------------------------------------------------------------------
228 
229 STDMETHODIMP CXTDataObject::SetData( LPFORMATETC, LPSTGMEDIUM, BOOL )
230 {
231 	return E_NOTIMPL;
232 }
233 
234 //------------------------------------------------------------------------
235 // IDataObject->DAdvise
236 //------------------------------------------------------------------------
237 
238 STDMETHODIMP CXTDataObject::DAdvise( LPFORMATETC, DWORD, LPADVISESINK, DWORD * )
239 {
240 	return E_NOTIMPL;
241 }
242 
243 //------------------------------------------------------------------------
244 // IDataObject->DUnadvise
245 //------------------------------------------------------------------------
246 
247 STDMETHODIMP CXTDataObject::DUnadvise( DWORD )
248 {
249 	return E_NOTIMPL;
250 }
251 
252 //------------------------------------------------------------------------
253 // IDataObject->EnumDAdvise
254 //------------------------------------------------------------------------
255 
256 STDMETHODIMP CXTDataObject::EnumDAdvise( LPENUMSTATDATA * )
257 {
258 	return E_NOTIMPL;
259 }
260 
261 //------------------------------------------------------------------------
262 // for our convenience
263 //------------------------------------------------------------------------
264 
265 CXTDataObject::operator IDataObject*( )
266 {
267 	return static_cast< IDataObject* >( this );
268 }
269 
270 
271 //============================================================================
272 // CEnumFormatEtc
273 //============================================================================
274 
275 //----------------------------------------------------------------------------
276 // ctor
277 //----------------------------------------------------------------------------
278 
279 CEnumFormatEtc::CEnumFormatEtc( LPUNKNOWN pUnkDataObj ) :
280 	m_nRefCnt( 0 ),
281 	m_pUnkDataObj( pUnkDataObj ),
282 	m_nCurrPos( 0 )
283 {
284 }
285 
286 //----------------------------------------------------------------------------
287 // IUnknown->QueryInterface
288 //----------------------------------------------------------------------------
289 
290 STDMETHODIMP CEnumFormatEtc::QueryInterface( REFIID iid, LPVOID* ppvObject )
291 {
292 	if ( NULL == ppvObject )
293 		return E_INVALIDARG;
294 
295 	HRESULT hr = E_NOINTERFACE;
296 
297 	*ppvObject = NULL;
298 
299 	if ( ( __uuidof( IUnknown ) == iid ) || ( __uuidof( IEnumFORMATETC ) == iid ) )
300 	{
301 		*ppvObject = static_cast< IUnknown* >( this );
302 		static_cast< LPUNKNOWN >( *ppvObject )->AddRef( );
303 		hr = S_OK;
304 	}
305 
306 	return hr;
307 }
308 
309 //----------------------------------------------------------------------------
310 // IUnknown->AddRef
311 //----------------------------------------------------------------------------
312 
313 STDMETHODIMP_(ULONG) CEnumFormatEtc::AddRef( )
314 {
315 	// keep the dataobject alive
316 	m_pUnkDataObj->AddRef( );
317 	return InterlockedIncrement( &m_nRefCnt );
318 }
319 
320 //----------------------------------------------------------------------------
321 // IUnknown->Release
322 //----------------------------------------------------------------------------
323 
324 STDMETHODIMP_(ULONG) CEnumFormatEtc::Release( )
325 {
326 	// release the outer dataobject
327 	m_pUnkDataObj->Release( );
328 
329 	// we need a helper variable because it's
330 	// not allowed to access a member variable
331 	// after an object is destroyed
332 	ULONG nRefCnt = InterlockedDecrement( &m_nRefCnt );
333 	if ( 0 == nRefCnt )
334 		delete this;
335 
336 	return nRefCnt;
337 }
338 
339 //----------------------------------------------------------------------------
340 // IEnumFORMATETC->Next
341 //----------------------------------------------------------------------------
342 
343 STDMETHODIMP CEnumFormatEtc::Next( ULONG celt, LPFORMATETC rgelt, ULONG* pceltFetched )
344 {
345 	if ( ( 0 != celt ) && ( NULL == rgelt ) )
346 		return E_INVALIDARG;
347 
348 	ULONG   ulFetched = 0;
349 	ULONG   ulToFetch = celt;
350 	HRESULT hr        = S_FALSE;
351 
352 	while( m_nCurrPos < 1 )
353 	{
354 		rgelt->cfFormat = CF_TEXT;
355 		rgelt->ptd      = NULL;
356 		rgelt->dwAspect = DVASPECT_CONTENT;
357 		rgelt->lindex   = -1;
358 		rgelt->tymed    = TYMED_HGLOBAL;
359 
360 		++m_nCurrPos;
361 		++rgelt;
362 		--ulToFetch;
363 		++ulFetched;
364 	}
365 
366 	if ( ulFetched == celt )
367 		hr = S_OK;
368 
369 	if ( NULL != pceltFetched )
370 	{
371 		*pceltFetched = ulFetched;
372 	}
373 
374 	return hr;
375 }
376 
377 //----------------------------------------------------------------------------
378 // IEnumFORMATETC->Skip
379 //----------------------------------------------------------------------------
380 
381 STDMETHODIMP CEnumFormatEtc::Skip( ULONG celt )
382 {
383 	HRESULT hr = S_FALSE;
384 
385 	/*
386 	if ( ( m_nCurrPos + celt ) < m_nClipFormats )
387 	{
388 		m_nCurrPos += celt;
389 		hr = S_OK;
390 	}
391 	*/
392 
393 	return hr;
394 }
395 
396 //----------------------------------------------------------------------------
397 // IEnumFORMATETC->Reset
398 //----------------------------------------------------------------------------
399 
400 STDMETHODIMP CEnumFormatEtc::Reset( )
401 {
402 	m_nCurrPos = 0;
403 	return S_OK;
404 }
405 
406 //----------------------------------------------------------------------------
407 // IEnumFORMATETC->Clone
408 //----------------------------------------------------------------------------
409 
410 STDMETHODIMP CEnumFormatEtc::Clone( IEnumFORMATETC** ppenum )
411 {
412 	OSL_ASSERT( NULL != ppenum );
413 
414 	if ( NULL == ppenum )
415 		return E_INVALIDARG;
416 
417 	HRESULT hr = E_FAIL;
418 
419 	*ppenum = NULL;
420 
421 	CEnumFormatEtc* pCEnumFEtc = new CEnumFormatEtc( m_pUnkDataObj );
422 	if ( NULL != pCEnumFEtc )
423 	{
424 		pCEnumFEtc->m_nCurrPos = m_nCurrPos;
425 		*ppenum = static_cast< IEnumFORMATETC* >( pCEnumFEtc );
426 		static_cast< LPUNKNOWN >( *ppenum )->AddRef( );
427 		hr = NOERROR;
428 	}
429 
430 	return hr;
431 }
432