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_embeddedobj.hxx"
30 #include <com/sun/star/embed/XEmbedObjectCreator.hpp>
31 #include <com/sun/star/embed/XEmbeddedObject.hpp>
32 #include <com/sun/star/embed/EntryInitModes.hpp>
33 #include <com/sun/star/beans/PropertyValue.hpp>
34 #include <com/sun/star/datatransfer/DataFlavor.hpp>
35 #include <com/sun/star/ucb/CommandAbortedException.hpp>
36 
37 
38 #include <osl/thread.h>
39 #include <osl/file.hxx>
40 #include <vos/module.hxx>
41 #include <comphelper/classids.hxx>
42 
43 #include "platform.h"
44 #include <comphelper/mimeconfighelper.hxx>
45 
46 #include "xdialogcreator.hxx"
47 #include "oleembobj.hxx"
48 // LLA: tip from FS
49 // #include <confighelper.hxx>
50 #include <xdialogcreator.hxx>
51 #include <oleembobj.hxx>
52 
53 
54 #ifdef WNT
55 
56 #include <oledlg.h>
57 
58 class InitializedOleGuard
59 {
60 public:
61 	InitializedOleGuard()
62 	{
63 		if ( !SUCCEEDED( OleInitialize( NULL ) ) )
64 			throw ::com::sun::star::uno::RuntimeException();
65 	}
66 
67 	~InitializedOleGuard()
68 	{
69 		OleUninitialize();
70 	}
71 };
72 
73 extern "C" {
74 typedef UINT STDAPICALLTYPE OleUIInsertObjectA_Type(LPOLEUIINSERTOBJECTA);
75 }
76 
77 #endif
78 
79 
80 using namespace ::com::sun::star;
81 using namespace ::comphelper;
82 //-------------------------------------------------------------------------
83 uno::Sequence< sal_Int8 > GetRelatedInternalID_Impl( const uno::Sequence< sal_Int8 >& aClassID )
84 {
85 	// Writer
86 	if ( MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SW_OLE_EMBED_CLASSID_60 ) )
87 	  || MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SW_OLE_EMBED_CLASSID_8 ) ) )
88 		return MimeConfigurationHelper::GetSequenceClassID( SO3_SW_CLASSID_60 );
89 
90 	// Calc
91 	if ( MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SC_OLE_EMBED_CLASSID_60 ) )
92 	  || MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SC_OLE_EMBED_CLASSID_8 ) ) )
93 		return MimeConfigurationHelper::GetSequenceClassID( SO3_SC_CLASSID_60 );
94 
95 	// Impress
96 	if ( MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SIMPRESS_OLE_EMBED_CLASSID_60 ) )
97 	  || MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ) ) )
98 		return MimeConfigurationHelper::GetSequenceClassID( SO3_SIMPRESS_CLASSID_60 );
99 
100 	// Draw
101 	if ( MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SDRAW_OLE_EMBED_CLASSID_60 ) )
102 	  || MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SDRAW_OLE_EMBED_CLASSID_8 ) ) )
103 		return MimeConfigurationHelper::GetSequenceClassID( SO3_SDRAW_CLASSID_60 );
104 
105 	// Chart
106 	if ( MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SCH_OLE_EMBED_CLASSID_60 ) )
107 	  || MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SCH_OLE_EMBED_CLASSID_8 ) ) )
108 		return MimeConfigurationHelper::GetSequenceClassID( SO3_SCH_CLASSID_60 );
109 
110 	// Math
111 	if ( MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SM_OLE_EMBED_CLASSID_60 ) )
112 	  || MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SM_OLE_EMBED_CLASSID_8 ) ) )
113 		return MimeConfigurationHelper::GetSequenceClassID( SO3_SM_CLASSID_60 );
114 
115 	return aClassID;
116 }
117 
118 //-------------------------------------------------------------------------
119 uno::Sequence< ::rtl::OUString > SAL_CALL MSOLEDialogObjectCreator::impl_staticGetSupportedServiceNames()
120 {
121     uno::Sequence< ::rtl::OUString > aRet(2);
122     aRet[0] = ::rtl::OUString::createFromAscii("com.sun.star.embed.MSOLEObjectSystemCreator");
123     aRet[1] = ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.MSOLEObjectSystemCreator");
124     return aRet;
125 }
126 
127 //-------------------------------------------------------------------------
128 ::rtl::OUString SAL_CALL MSOLEDialogObjectCreator::impl_staticGetImplementationName()
129 {
130     return ::rtl::OUString::createFromAscii("com.sun.star.comp.embed.MSOLEObjectSystemCreator");
131 }
132 
133 //-------------------------------------------------------------------------
134 uno::Reference< uno::XInterface > SAL_CALL MSOLEDialogObjectCreator::impl_staticCreateSelfInstance(
135 			const uno::Reference< lang::XMultiServiceFactory >& xServiceManager )
136 {
137 	return uno::Reference< uno::XInterface >( *new MSOLEDialogObjectCreator( xServiceManager ) );
138 }
139 
140 //-------------------------------------------------------------------------
141 embed::InsertedObjectInfo SAL_CALL MSOLEDialogObjectCreator::createInstanceByDialog(
142 			const uno::Reference< embed::XStorage >& xStorage,
143 			const ::rtl::OUString& sEntName,
144 			const uno::Sequence< beans::PropertyValue >& aInObjArgs )
145 	throw ( lang::IllegalArgumentException,
146 			io::IOException,
147 			uno::Exception,
148 			uno::RuntimeException )
149 {
150 	embed::InsertedObjectInfo aObjectInfo;
151 	uno::Sequence< beans::PropertyValue > aObjArgs( aInObjArgs );
152 
153 #ifdef WNT
154 
155 	if ( !xStorage.is() )
156 		throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ),
157 											uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
158 											1 );
159 
160 	if ( !sEntName.getLength() )
161 		throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ),
162 											uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
163 											2 );
164 
165 	InitializedOleGuard aGuard;
166 
167 	OLEUIINSERTOBJECT io;
168 	char szFile[MAX_PATH];
169 	UINT uTemp;
170 
171 	memset(&io, 0, sizeof(io));
172 
173 	io.cbStruct = sizeof(io);
174 	io.hWndOwner = GetActiveWindow();
175 
176 	szFile[0] = 0;
177 	io.lpszFile = szFile;
178 	io.cchFile = MAX_PATH;
179 
180 	io.dwFlags = IOF_SELECTCREATENEW | IOF_DISABLELINK;
181 
182 
183 	::vos::OModule aOleDlgLib;
184 	if( !aOleDlgLib.load( ::rtl::OUString::createFromAscii( "oledlg" ) ) )
185 		throw uno::RuntimeException();
186 
187 	OleUIInsertObjectA_Type * pInsertFct = (OleUIInsertObjectA_Type *)
188 								aOleDlgLib.getSymbol( ::rtl::OUString::createFromAscii( "OleUIInsertObjectA" ) );
189 	if( !pInsertFct )
190 		throw uno::RuntimeException();
191 
192 	uTemp=pInsertFct(&io);
193 
194 	if ( OLEUI_OK == uTemp )
195 	{
196 		if (io.dwFlags & IOF_SELECTCREATENEW)
197 		{
198 			uno::Reference< embed::XEmbedObjectCreator > xEmbCreator(
199 						m_xFactory->createInstance(
200 								::rtl::OUString::createFromAscii( "com.sun.star.embed.EmbeddedObjectCreator" ) ),
201 						uno::UNO_QUERY );
202 			if ( !xEmbCreator.is() )
203 				throw uno::RuntimeException();
204 
205 			uno::Sequence< sal_Int8 > aClassID = MimeConfigurationHelper::GetSequenceClassID( io.clsid.Data1,
206 																	 io.clsid.Data2,
207 																	 io.clsid.Data3,
208 																	 io.clsid.Data4[0],
209 																	 io.clsid.Data4[1],
210 																	 io.clsid.Data4[2],
211 																	 io.clsid.Data4[3],
212 																	 io.clsid.Data4[4],
213 																	 io.clsid.Data4[5],
214 																	 io.clsid.Data4[6],
215 																	 io.clsid.Data4[7] );
216 
217 			aClassID = GetRelatedInternalID_Impl( aClassID );
218 
219 			//TODO: retrieve ClassName
220 			::rtl::OUString aClassName;
221 			aObjectInfo.Object = uno::Reference< embed::XEmbeddedObject >(
222 							xEmbCreator->createInstanceInitNew( aClassID, aClassName, xStorage, sEntName, aObjArgs ),
223 							uno::UNO_QUERY );
224 		}
225 		else
226 		{
227 			::rtl::OUString aFileName = ::rtl::OStringToOUString( ::rtl::OString( szFile ), osl_getThreadTextEncoding() );
228     		rtl::OUString aFileURL;
229         	if ( osl::FileBase::getFileURLFromSystemPath( aFileName, aFileURL ) != osl::FileBase::E_None )
230 				throw uno::RuntimeException();
231 
232 			uno::Sequence< beans::PropertyValue > aMediaDescr( 1 );
233 			aMediaDescr[0].Name = ::rtl::OUString::createFromAscii( "URL" );
234 			aMediaDescr[0].Value <<= aFileURL;
235 
236 			// TODO: use config helper for type detection
237 			uno::Reference< embed::XEmbedObjectCreator > xEmbCreator;
238 			::comphelper::MimeConfigurationHelper aHelper( m_xFactory );
239 
240 			if ( aHelper.AddFilterNameCheckOwnFile( aMediaDescr ) )
241 				xEmbCreator = uno::Reference< embed::XEmbedObjectCreator >(
242 						m_xFactory->createInstance(
243 								::rtl::OUString::createFromAscii( "com.sun.star.embed.EmbeddedObjectCreator" ) ),
244 						uno::UNO_QUERY );
245 			else
246 				xEmbCreator = uno::Reference< embed::XEmbedObjectCreator >(
247 						m_xFactory->createInstance(
248 								::rtl::OUString::createFromAscii( "com.sun.star.embed.OLEEmbeddedObjectFactory" ) ),
249 						uno::UNO_QUERY );
250 
251 			if ( !xEmbCreator.is() )
252 				throw uno::RuntimeException();
253 
254 			aObjectInfo.Object = uno::Reference< embed::XEmbeddedObject >(
255 							xEmbCreator->createInstanceInitFromMediaDescriptor( xStorage, sEntName, aMediaDescr, aObjArgs ),
256 							uno::UNO_QUERY );
257 		}
258 
259 		if ( ( io.dwFlags & IOF_CHECKDISPLAYASICON) && io.hMetaPict != NULL )
260 		{
261 			METAFILEPICT* pMF = ( METAFILEPICT* )GlobalLock( io.hMetaPict );
262 			if ( pMF )
263 			{
264 				sal_uInt32 nBufSize = GetMetaFileBitsEx( pMF->hMF, 0, NULL );
265 				uno::Sequence< sal_Int8 > aMetafile( nBufSize + 22 );
266 				sal_uInt8* pBuf = (sal_uInt8*)( aMetafile.getArray() );
267 				*( (long* )pBuf ) = 0x9ac6cdd7L;
268 				*( (short* )( pBuf+6 )) = ( SHORT ) 0;
269 				*( (short* )( pBuf+8 )) = ( SHORT ) 0;
270 				*( (short* )( pBuf+10 )) = ( SHORT ) pMF->xExt;
271 				*( (short* )( pBuf+12 )) = ( SHORT ) pMF->yExt;
272 				*( (short* )( pBuf+14 )) = ( USHORT ) 2540;
273 
274 				if ( nBufSize && nBufSize == GetMetaFileBitsEx( pMF->hMF, nBufSize, pBuf+22 ) )
275 				{
276 					datatransfer::DataFlavor aFlavor(
277                         ::rtl::OUString::createFromAscii( "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"" ),
278 						::rtl::OUString::createFromAscii( "Image WMF" ),
279 						getCppuType( ( const uno::Sequence< sal_Int8 >* ) 0 ) );
280 
281 					aObjectInfo.Options.realloc( 2 );
282 					aObjectInfo.Options[0].Name = ::rtl::OUString::createFromAscii( "Icon" );
283 					aObjectInfo.Options[0].Value <<= aMetafile;
284 					aObjectInfo.Options[1].Name = ::rtl::OUString::createFromAscii( "IconFormat" );
285 					aObjectInfo.Options[1].Value <<= aFlavor;
286 				}
287 
288 				GlobalUnlock( io.hMetaPict );
289 			}
290 		}
291 	}
292 	else
293 		throw ucb::CommandAbortedException();
294 
295 #else
296 	throw lang::NoSupportException(); // TODO:
297 #endif
298 
299 	OSL_ENSURE( aObjectInfo.Object.is(), "No object was created!\n" );
300 	if ( !aObjectInfo.Object.is() )
301 		throw uno::RuntimeException();
302 
303 	return aObjectInfo;
304 }
305 
306 //-------------------------------------------------------------------------
307 embed::InsertedObjectInfo SAL_CALL MSOLEDialogObjectCreator::createInstanceInitFromClipboard(
308 				const uno::Reference< embed::XStorage >& xStorage,
309 				const ::rtl::OUString& sEntryName,
310 				const uno::Sequence< beans::PropertyValue >& aObjectArgs )
311 		throw ( lang::IllegalArgumentException,
312 				io::IOException,
313 				uno::Exception,
314 				uno::RuntimeException )
315 {
316 	embed::InsertedObjectInfo aObjectInfo;
317 
318 #ifdef WNT
319 
320 	if ( !xStorage.is() )
321 		throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "No parent storage is provided!\n" ),
322 											uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
323 											1 );
324 
325 	if ( !sEntryName.getLength() )
326 		throw lang::IllegalArgumentException( ::rtl::OUString::createFromAscii( "Empty element name is provided!\n" ),
327 											uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >(this) ),
328 											2 );
329 
330 	uno::Reference< embed::XEmbeddedObject > xResult(
331 					static_cast< ::cppu::OWeakObject* > ( new OleEmbeddedObject( m_xFactory ) ),
332 					uno::UNO_QUERY );
333 
334 	uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY );
335 
336 	if ( !xPersist.is() )
337 		throw uno::RuntimeException(); // TODO: the interface must be supported by own document objects
338 
339 	xPersist->setPersistentEntry( xStorage,
340 									sEntryName,
341 									embed::EntryInitModes::DEFAULT_INIT,
342 									uno::Sequence< beans::PropertyValue >(),
343 									aObjectArgs );
344 
345 	aObjectInfo.Object = xResult;
346 
347 	// TODO/LATER: in case of iconifie object the icon should be stored in aObjectInfo
348 #else
349 	throw lang::NoSupportException(); // TODO:
350 #endif
351 
352 	OSL_ENSURE( aObjectInfo.Object.is(), "No object was created!\n" );
353 	if ( !aObjectInfo.Object.is() )
354 		throw uno::RuntimeException();
355 
356 	return aObjectInfo;
357 }
358 
359 //-------------------------------------------------------------------------
360 ::rtl::OUString SAL_CALL MSOLEDialogObjectCreator::getImplementationName()
361 	throw ( uno::RuntimeException )
362 {
363 	return impl_staticGetImplementationName();
364 }
365 
366 //-------------------------------------------------------------------------
367 sal_Bool SAL_CALL MSOLEDialogObjectCreator::supportsService( const ::rtl::OUString& ServiceName )
368 	throw ( uno::RuntimeException )
369 {
370 	uno::Sequence< ::rtl::OUString > aSeq = impl_staticGetSupportedServiceNames();
371 
372 	for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ )
373     	if ( ServiceName.compareTo( aSeq[nInd] ) == 0 )
374         	return sal_True;
375 
376 	return sal_False;
377 }
378 
379 //-------------------------------------------------------------------------
380 uno::Sequence< ::rtl::OUString > SAL_CALL MSOLEDialogObjectCreator::getSupportedServiceNames()
381 	throw ( uno::RuntimeException )
382 {
383 	return impl_staticGetSupportedServiceNames();
384 }
385 
386