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