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 #if defined(_MSC_VER) && (_MSC_VER > 1310)
28 #pragma warning(disable : 4917 4555)
29 #endif
30 
31 // actually this workaround should be in presys.h!
32 //#define UINT64 USE_WIN_UINT64
33 //#define INT64 USE_WIN_INT64
34 //#define UINT32 USE_WIN_UINT32
35 //#define INT32 USE_WIN_INT32
36 
37 //#include <tools/presys.h>
38 #include "embeddoc.hxx"
39 //#include <tools/postsys.h>
40 
41 //#undef UINT64
42 //#undef INT64
43 //#undef UINT32
44 //#undef INT32
45 
46 
47 #include <com/sun/star/uno/Any.h>
48 #include <com/sun/star/uno/Exception.hpp>
49 #include <com/sun/star/datatransfer/XTransferable.hpp>
50 
51 
52 #include <osl/thread.h>
53 
54 using namespace ::com::sun::star;
55 
56 //===============================================================================
57 // EmbedDocument_Impl
58 //===============================================================================
59 
60 sal_uInt64 EmbedDocument_Impl::getMetaFileHandle_Impl( sal_Bool isEnhMeta )
61 {
62 	sal_uInt64 pResult = NULL;
63 
64 	uno::Reference< datatransfer::XTransferable > xTransferable( m_pDocHolder->GetDocument(), uno::UNO_QUERY );
65 	if ( xTransferable.is() )
66 	{
67 		uno::Sequence< sal_Int8 > aMetaBuffer;
68 		datatransfer::DataFlavor aFlavor;
69 
70 		if ( isEnhMeta )
71 		{
72 			aFlavor.MimeType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
73 												"application/x-openoffice-emf;windows_formatname=\"Image EMF\"" ) );
74 			aFlavor.HumanPresentableName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Enhanced Windows MetaFile" ) );
75 		}
76 		else
77 		{
78 			aFlavor.MimeType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
79 												"application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" ) );
80 			aFlavor.HumanPresentableName = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Windows GDIMetaFile" ) );
81 		}
82 
83 		aFlavor.DataType = getCppuType( (const sal_uInt64*) 0 );
84 
85 		uno::Any aAny = xTransferable->getTransferData( aFlavor );
86 		aAny >>= pResult;
87 	}
88 
89 	return pResult;
90 }
91 
92 //-------------------------------------------------------------------------------
93 // IDataObject
94 
95 STDMETHODIMP EmbedDocument_Impl::GetData( FORMATETC * pFormatetc, STGMEDIUM * pMedium )
96 {
97 	if ( !pFormatetc )
98 		return DV_E_FORMATETC;
99 
100 	if ( !pMedium )
101 		return STG_E_MEDIUMFULL;
102 
103 	if ( pFormatetc->dwAspect == DVASPECT_THUMBNAIL
104 	  || pFormatetc->dwAspect == DVASPECT_ICON
105 	  || pFormatetc->dwAspect == DVASPECT_DOCPRINT )
106 		return DV_E_DVASPECT;
107 
108 	if ( pFormatetc->cfFormat == CF_ENHMETAFILE )
109 	{
110 		if ( !( pFormatetc->tymed & TYMED_ENHMF ) )
111 			return DV_E_TYMED;
112 
113 		HENHMETAFILE hMeta = reinterpret_cast<HENHMETAFILE>( getMetaFileHandle_Impl( sal_True ) );
114 
115 		if ( hMeta )
116 		{
117 			pMedium->tymed = TYMED_ENHMF;
118 			pMedium->hEnhMetaFile = hMeta;
119 			pMedium->pUnkForRelease = NULL;
120 
121 			return S_OK;
122 		}
123 
124 		return STG_E_MEDIUMFULL;
125 	}
126 	else if ( pFormatetc->cfFormat == CF_METAFILEPICT )
127 	{
128 	  	if ( !( pFormatetc->tymed & TYMED_MFPICT ) )
129 			return DV_E_TYMED;
130 
131 		HGLOBAL hMeta = reinterpret_cast<HGLOBAL>( getMetaFileHandle_Impl( sal_False ) );
132 
133 		if ( hMeta )
134 		{
135 			pMedium->tymed = TYMED_MFPICT;
136 			pMedium->hMetaFilePict = hMeta;
137 			pMedium->pUnkForRelease = NULL;
138 
139 			return S_OK;
140 		}
141 
142 		return STG_E_MEDIUMFULL;
143 	}
144 	else
145 	{
146 		CLIPFORMAT cf_embSource = (CLIPFORMAT)RegisterClipboardFormatA( "Embed Source" );
147 		CLIPFORMAT cf_embObj = (CLIPFORMAT)RegisterClipboardFormatA( "Embedded Object" );
148 		if ( pFormatetc->cfFormat == cf_embSource || pFormatetc->cfFormat == cf_embObj )
149 		{
150 			if ( !( pFormatetc->tymed & TYMED_ISTORAGE ) )
151 				return DV_E_TYMED;
152 
153 			CComPtr< IStorage > pNewStg;
154 			HRESULT hr = StgCreateDocfile( NULL, STGM_CREATE | STGM_READWRITE | STGM_DELETEONRELEASE, 0, &pNewStg );
155 			if ( FAILED( hr ) || !pNewStg ) return STG_E_MEDIUMFULL;
156 
157 			hr = SaveTo_Impl( pNewStg );
158 			if ( FAILED( hr ) ) return STG_E_MEDIUMFULL;
159 
160 			pMedium->tymed = TYMED_ISTORAGE;
161 			pMedium->pstg = pNewStg;
162 			pMedium->pstg->AddRef();
163 			pMedium->pUnkForRelease = ( IUnknown* )pNewStg;
164 
165 			return S_OK;
166 		}
167 	}
168 
169 	return DV_E_FORMATETC;
170 }
171 
172 STDMETHODIMP EmbedDocument_Impl::GetDataHere( FORMATETC * pFormatetc, STGMEDIUM * pMedium )
173 {
174 	if ( !pFormatetc )
175 		return DV_E_FORMATETC;
176 
177 	if ( !pMedium )
178 		return STG_E_MEDIUMFULL;
179 
180 	if ( pFormatetc->dwAspect == DVASPECT_THUMBNAIL
181 	  || pFormatetc->dwAspect == DVASPECT_ICON
182 	  || pFormatetc->dwAspect == DVASPECT_DOCPRINT )
183 		return DV_E_DVASPECT;
184 
185 	CLIPFORMAT cf_embSource = (CLIPFORMAT)RegisterClipboardFormatA( "Embed Source" );
186 	CLIPFORMAT cf_embObj = (CLIPFORMAT)RegisterClipboardFormatA( "Embedded Object" );
187 
188 	if ( pFormatetc->cfFormat == cf_embSource || pFormatetc->cfFormat == cf_embObj )
189 	{
190 		if ( !( pFormatetc->tymed & TYMED_ISTORAGE ) )
191 			return DV_E_TYMED;
192 
193 		if ( !pMedium->pstg ) return STG_E_MEDIUMFULL;
194 
195 		HRESULT hr = SaveTo_Impl( pMedium->pstg );
196 		if ( FAILED( hr ) ) return STG_E_MEDIUMFULL;
197 
198 		pMedium->tymed = TYMED_ISTORAGE;
199 		pMedium->pUnkForRelease = NULL;
200 
201 		return S_OK;
202 	}
203 
204 	return DV_E_FORMATETC;
205 }
206 
207 STDMETHODIMP EmbedDocument_Impl::QueryGetData( FORMATETC * pFormatetc )
208 {
209 	if ( pFormatetc )
210 	{
211 		if ( pFormatetc->dwAspect == DVASPECT_THUMBNAIL
212 		  || pFormatetc->dwAspect == DVASPECT_ICON
213 		  || pFormatetc->dwAspect == DVASPECT_DOCPRINT )
214 			return DV_E_DVASPECT;
215 
216 		if ( pFormatetc->cfFormat == CF_ENHMETAFILE )
217 		{
218 			if ( !( pFormatetc->tymed & TYMED_ENHMF ) )
219 				return DV_E_TYMED;
220 
221 			return S_OK;
222 		}
223 		else if ( pFormatetc->cfFormat == CF_METAFILEPICT )
224 		{
225 	  		if ( !( pFormatetc->tymed & TYMED_MFPICT ) )
226 				return DV_E_TYMED;
227 
228 			return S_OK;
229 		}
230 		else
231 		{
232 			CLIPFORMAT cf_embSource = (CLIPFORMAT)RegisterClipboardFormatA( "Embed Source" );
233 			CLIPFORMAT cf_embObj = (CLIPFORMAT)RegisterClipboardFormatA( "Embedded Object" );
234 			if ( pFormatetc->cfFormat == cf_embSource || pFormatetc->cfFormat == cf_embObj )
235 			{
236 				if ( !( pFormatetc->tymed & TYMED_ISTORAGE ) )
237 					return DV_E_TYMED;
238 
239 				return S_OK;
240 			}
241 		}
242 	}
243 
244 	return DV_E_FORMATETC;
245 
246 }
247 
248 STDMETHODIMP EmbedDocument_Impl::GetCanonicalFormatEtc( FORMATETC * pFormatetcIn, FORMATETC * pFormatetcOut )
249 {
250 	if ( !pFormatetcIn || !pFormatetcOut )
251 		return DV_E_FORMATETC;
252 
253 	pFormatetcOut->ptd = NULL;
254 	pFormatetcOut->cfFormat = pFormatetcIn->cfFormat;
255 	pFormatetcOut->dwAspect = DVASPECT_CONTENT;
256 
257 	if ( pFormatetcIn->cfFormat == CF_ENHMETAFILE )
258 	{
259 		pFormatetcOut->tymed = TYMED_ENHMF;
260 		return S_OK;
261 	}
262 	else if ( pFormatetcIn->cfFormat == CF_METAFILEPICT )
263 	{
264   		pFormatetcOut->tymed = TYMED_MFPICT;
265 		return S_OK;
266 	}
267 	else
268 	{
269 		CLIPFORMAT cf_embSource = (CLIPFORMAT)RegisterClipboardFormatA( "Embed Source" );
270 		CLIPFORMAT cf_embObj = (CLIPFORMAT)RegisterClipboardFormatA( "Embedded Object" );
271 		if ( pFormatetcIn->cfFormat == cf_embSource || pFormatetcIn->cfFormat == cf_embObj )
272 		{
273 			pFormatetcOut->tymed = TYMED_ISTORAGE;
274 			return S_OK;
275 		}
276 	}
277 
278 	return DV_E_FORMATETC;
279 }
280 
281 STDMETHODIMP EmbedDocument_Impl::SetData( FORMATETC * /*pFormatetc*/, STGMEDIUM * /*pMedium*/, BOOL /*fRelease*/ )
282 {
283 	return E_NOTIMPL;
284 }
285 
286 STDMETHODIMP EmbedDocument_Impl::EnumFormatEtc( DWORD dwDirection, IEnumFORMATETC ** /*ppFormatetc*/ )
287 {
288 	if ( dwDirection == DATADIR_GET )
289 		return OLE_S_USEREG;
290 
291 	return E_NOTIMPL;
292 }
293 
294 STDMETHODIMP EmbedDocument_Impl::DAdvise( FORMATETC * pFormatetc, DWORD advf, IAdviseSink * pAdvSink, DWORD * pdwConnection )
295 {
296 	if ( !m_pDAdviseHolder )
297 		if ( !SUCCEEDED( CreateDataAdviseHolder( &m_pDAdviseHolder ) ) || !m_pDAdviseHolder )
298 			return E_OUTOFMEMORY;
299 
300 	return m_pDAdviseHolder->Advise( (IDataObject*)this, pFormatetc, advf, pAdvSink, pdwConnection );
301 }
302 
303 STDMETHODIMP EmbedDocument_Impl::DUnadvise( DWORD dwConnection )
304 {
305 	if ( !m_pDAdviseHolder )
306 		if ( !SUCCEEDED( CreateDataAdviseHolder( &m_pDAdviseHolder ) ) || !m_pDAdviseHolder )
307 			return E_OUTOFMEMORY;
308 
309 	return m_pDAdviseHolder->Unadvise( dwConnection );
310 }
311 
312 STDMETHODIMP EmbedDocument_Impl::EnumDAdvise( IEnumSTATDATA ** ppenumAdvise )
313 {
314 	if ( !m_pDAdviseHolder )
315 		if ( !SUCCEEDED( CreateDataAdviseHolder( &m_pDAdviseHolder ) ) || !m_pDAdviseHolder )
316 			return E_OUTOFMEMORY;
317 
318 	return m_pDAdviseHolder->EnumAdvise( ppenumAdvise );
319 }
320 
321 // Fix strange warnings about some
322 // ATL::CAxHostWindow::QueryInterface|AddRef|Releae functions.
323 // warning C4505: 'xxx' : unreferenced local function has been removed
324 #if defined(_MSC_VER)
325 #pragma warning(disable: 4505)
326 #endif
327