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