1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20 #include <com/sun/star/embed/EmbeddedObjectCreator.hpp>
21 #include <com/sun/star/embed/XEmbeddedObject.hpp>
22 #include <com/sun/star/embed/EntryInitModes.hpp>
23 #include <com/sun/star/embed/OLEEmbeddedObjectFactory.hpp>
24 #include <com/sun/star/beans/PropertyValue.hpp>
25 #include <com/sun/star/datatransfer/DataFlavor.hpp>
26 #include <com/sun/star/lang/IllegalArgumentException.hpp>
27 #include <com/sun/star/ucb/CommandAbortedException.hpp>
28
29 #include <osl/thread.h>
30 #include <osl/file.hxx>
31 #include <osl/module.hxx>
32 #include <comphelper/classids.hxx>
33
34 #include "platform.h"
35 #include <comphelper/mimeconfighelper.hxx>
36 #include <comphelper/processfactory.hxx>
37 #include <cppuhelper/supportsservice.hxx>
38
39 #include "xdialogcreator.hxx"
40 #include <oleembobj.hxx>
41
42
43 #ifdef _WIN32
44
45 #include <oledlg.h>
46 #include <vcl/winscheduler.hxx>
47
48 class InitializedOleGuard
49 {
50 public:
InitializedOleGuard()51 InitializedOleGuard()
52 {
53 if ( !SUCCEEDED( OleInitialize( nullptr ) ) )
54 throw css::uno::RuntimeException();
55 }
56
~InitializedOleGuard()57 ~InitializedOleGuard()
58 {
59 OleUninitialize();
60 }
61 };
62
63 extern "C" {
64 typedef UINT STDAPICALLTYPE OleUIInsertObjectA_Type(LPOLEUIINSERTOBJECTA);
65 }
66
67 #endif
68
69
70 using namespace ::com::sun::star;
71 using namespace ::comphelper;
72
GetRelatedInternalID_Impl(const uno::Sequence<sal_Int8> & aClassID)73 static uno::Sequence< sal_Int8 > GetRelatedInternalID_Impl( const uno::Sequence< sal_Int8 >& aClassID )
74 {
75 // Writer
76 if ( MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SW_OLE_EMBED_CLASSID_60 ) )
77 || MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SW_OLE_EMBED_CLASSID_8 ) ) )
78 return MimeConfigurationHelper::GetSequenceClassID( SO3_SW_CLASSID_60 );
79
80 // Calc
81 if ( MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SC_OLE_EMBED_CLASSID_60 ) )
82 || MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SC_OLE_EMBED_CLASSID_8 ) ) )
83 return MimeConfigurationHelper::GetSequenceClassID( SO3_SC_CLASSID_60 );
84
85 // Impress
86 if ( MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SIMPRESS_OLE_EMBED_CLASSID_60 ) )
87 || MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ) ) )
88 return MimeConfigurationHelper::GetSequenceClassID( SO3_SIMPRESS_CLASSID_60 );
89
90 // Draw
91 if ( MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SDRAW_OLE_EMBED_CLASSID_60 ) )
92 || MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SDRAW_OLE_EMBED_CLASSID_8 ) ) )
93 return MimeConfigurationHelper::GetSequenceClassID( SO3_SDRAW_CLASSID_60 );
94
95 // Chart
96 if ( MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SCH_OLE_EMBED_CLASSID_60 ) )
97 || MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SCH_OLE_EMBED_CLASSID_8 ) ) )
98 return MimeConfigurationHelper::GetSequenceClassID( SO3_SCH_CLASSID_60 );
99
100 // Math
101 if ( MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SM_OLE_EMBED_CLASSID_60 ) )
102 || MimeConfigurationHelper::ClassIDsEqual( aClassID, MimeConfigurationHelper::GetSequenceClassID( SO3_SM_OLE_EMBED_CLASSID_8 ) ) )
103 return MimeConfigurationHelper::GetSequenceClassID( SO3_SM_CLASSID_60 );
104
105 return aClassID;
106 }
107
108
impl_staticGetSupportedServiceNames()109 uno::Sequence< OUString > MSOLEDialogObjectCreator::impl_staticGetSupportedServiceNames()
110 {
111 uno::Sequence< OUString > aRet(2);
112 aRet[0] = "com.sun.star.embed.MSOLEObjectSystemCreator";
113 aRet[1] = "com.sun.star.comp.embed.MSOLEObjectSystemCreator";
114 return aRet;
115 }
116
117
impl_staticGetImplementationName()118 OUString MSOLEDialogObjectCreator::impl_staticGetImplementationName()
119 {
120 return "com.sun.star.comp.embed.MSOLEObjectSystemCreator";
121 }
122
123
impl_staticCreateSelfInstance(const uno::Reference<lang::XMultiServiceFactory> & xServiceManager)124 uno::Reference< uno::XInterface > MSOLEDialogObjectCreator::impl_staticCreateSelfInstance(
125 const uno::Reference< lang::XMultiServiceFactory >& xServiceManager )
126 {
127 return uno::Reference< uno::XInterface >( *new MSOLEDialogObjectCreator( xServiceManager ) );
128 }
129
130
createInstanceByDialog(const uno::Reference<embed::XStorage> & xStorage,const OUString & sEntName,const uno::Sequence<beans::PropertyValue> & aInObjArgs)131 embed::InsertedObjectInfo SAL_CALL MSOLEDialogObjectCreator::createInstanceByDialog(
132 const uno::Reference< embed::XStorage >& xStorage,
133 const OUString& sEntName,
134 const uno::Sequence< beans::PropertyValue >& aInObjArgs )
135 {
136 embed::InsertedObjectInfo aObjectInfo;
137 uno::Sequence< beans::PropertyValue > aObjArgs( aInObjArgs );
138
139 #ifdef _WIN32
140
141 if ( !xStorage.is() )
142 throw lang::IllegalArgumentException( "No parent storage is provided!",
143 static_cast< ::cppu::OWeakObject* >(this),
144 1 );
145
146 if ( !sEntName.getLength() )
147 throw lang::IllegalArgumentException( "Empty element name is provided!",
148 static_cast< ::cppu::OWeakObject* >(this),
149 2 );
150
151 InitializedOleGuard aGuard;
152
153 OLEUIINSERTOBJECT io = {};
154 char szFile[MAX_PATH];
155 UINT uTemp;
156
157 io.cbStruct = sizeof(io);
158 io.hWndOwner = GetActiveWindow();
159
160 szFile[0] = 0;
161 io.lpszFile = szFile;
162 io.cchFile = MAX_PATH;
163
164 io.dwFlags = IOF_SELECTCREATENEW | IOF_DISABLELINK;
165
166
167 ::osl::Module aOleDlgLib;
168 if( !aOleDlgLib.load( "oledlg" ))
169 throw uno::RuntimeException();
170
171 OleUIInsertObjectA_Type * pInsertFct = reinterpret_cast<OleUIInsertObjectA_Type *>(
172 aOleDlgLib.getSymbol( "OleUIInsertObjectA" ));
173 if( !pInsertFct )
174 throw uno::RuntimeException();
175
176 // Disable any event loop shortcuts by enabling a real timer.
177 // This way the native windows dialog won't block our own processing.
178 WinScheduler::SetForceRealTimer();
179
180 uTemp=pInsertFct(&io);
181
182 if ( OLEUI_OK != uTemp )
183 throw ucb::CommandAbortedException();
184
185 if (io.dwFlags & IOF_SELECTCREATENEW)
186 {
187 uno::Reference< embed::XEmbeddedObjectCreator > xEmbCreator = embed::EmbeddedObjectCreator::create( comphelper::getComponentContext(m_xFactory) );
188
189 uno::Sequence< sal_Int8 > aClassID = MimeConfigurationHelper::GetSequenceClassID( io.clsid.Data1,
190 io.clsid.Data2,
191 io.clsid.Data3,
192 io.clsid.Data4[0],
193 io.clsid.Data4[1],
194 io.clsid.Data4[2],
195 io.clsid.Data4[3],
196 io.clsid.Data4[4],
197 io.clsid.Data4[5],
198 io.clsid.Data4[6],
199 io.clsid.Data4[7] );
200
201 aClassID = GetRelatedInternalID_Impl( aClassID );
202
203 //TODO: retrieve ClassName
204 aObjectInfo.Object.set( xEmbCreator->createInstanceInitNew( aClassID, OUString(), xStorage, sEntName, aObjArgs ),
205 uno::UNO_QUERY );
206 }
207 else
208 {
209 OUString aFileName = OStringToOUString( OString( szFile ), osl_getThreadTextEncoding() );
210 OUString aFileURL;
211 if ( osl::FileBase::getFileURLFromSystemPath( aFileName, aFileURL ) != osl::FileBase::E_None )
212 throw uno::RuntimeException();
213
214 uno::Sequence< beans::PropertyValue > aMediaDescr( 1 );
215 aMediaDescr[0].Name = "URL";
216 aMediaDescr[0].Value <<= aFileURL;
217
218 // TODO: use config helper for type detection
219 uno::Reference< embed::XEmbeddedObjectCreator > xEmbCreator;
220 ::comphelper::MimeConfigurationHelper aHelper( comphelper::getComponentContext(m_xFactory) );
221
222 if ( aHelper.AddFilterNameCheckOwnFile( aMediaDescr ) )
223 xEmbCreator = embed::EmbeddedObjectCreator::create( comphelper::getComponentContext(m_xFactory) );
224 else
225 xEmbCreator = embed::OLEEmbeddedObjectFactory::create( comphelper::getComponentContext(m_xFactory) );
226
227 if ( !xEmbCreator.is() )
228 throw uno::RuntimeException();
229
230 aObjectInfo.Object.set( xEmbCreator->createInstanceInitFromMediaDescriptor( xStorage, sEntName, aMediaDescr, aObjArgs ),
231 uno::UNO_QUERY );
232 }
233
234 if ( ( io.dwFlags & IOF_CHECKDISPLAYASICON) && io.hMetaPict != nullptr )
235 {
236 METAFILEPICT* pMF = static_cast<METAFILEPICT*>(GlobalLock( io.hMetaPict ));
237 if ( pMF )
238 {
239 sal_uInt32 nBufSize = GetMetaFileBitsEx( pMF->hMF, 0, nullptr );
240 uno::Sequence< sal_Int8 > aMetafile( nBufSize + 22 );
241 sal_Int8* pBuf = aMetafile.getArray();
242 *reinterpret_cast<long*>( pBuf ) = 0x9ac6cdd7L;
243 *reinterpret_cast<short*>( pBuf+6 ) = SHORT(0);
244 *reinterpret_cast<short*>( pBuf+8 ) = SHORT(0);
245 *reinterpret_cast<short*>( pBuf+10 ) = static_cast<SHORT>(pMF->xExt);
246 *reinterpret_cast<short*>( pBuf+12 ) = static_cast<SHORT>(pMF->yExt);
247 *reinterpret_cast<short*>( pBuf+14 ) = USHORT(2540);
248
249 if ( nBufSize && nBufSize == GetMetaFileBitsEx( pMF->hMF, nBufSize, pBuf+22 ) )
250 {
251 datatransfer::DataFlavor aFlavor(
252 "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"",
253 "Image WMF",
254 cppu::UnoType<uno::Sequence< sal_Int8 >>::get() );
255
256 aObjectInfo.Options.realloc( 2 );
257 aObjectInfo.Options[0].Name = "Icon";
258 aObjectInfo.Options[0].Value <<= aMetafile;
259 aObjectInfo.Options[1].Name = "IconFormat";
260 aObjectInfo.Options[1].Value <<= aFlavor;
261 }
262
263 GlobalUnlock( io.hMetaPict );
264 }
265 }
266
267 OSL_ENSURE( aObjectInfo.Object.is(), "No object was created!" );
268 if ( !aObjectInfo.Object.is() )
269 throw uno::RuntimeException();
270
271 return aObjectInfo;
272 #else
273 throw lang::NoSupportException(); // TODO:
274 #endif
275 }
276
277
createInstanceInitFromClipboard(const uno::Reference<embed::XStorage> & xStorage,const OUString & sEntryName,const uno::Sequence<beans::PropertyValue> & aObjectArgs)278 embed::InsertedObjectInfo SAL_CALL MSOLEDialogObjectCreator::createInstanceInitFromClipboard(
279 const uno::Reference< embed::XStorage >& xStorage,
280 const OUString& sEntryName,
281 const uno::Sequence< beans::PropertyValue >& aObjectArgs )
282 {
283 embed::InsertedObjectInfo aObjectInfo;
284
285 #ifdef _WIN32
286 if ( !xStorage.is() )
287 throw lang::IllegalArgumentException( "No parent storage is provided!",
288 static_cast< ::cppu::OWeakObject* >(this),
289 1 );
290
291 if ( !sEntryName.getLength() )
292 throw lang::IllegalArgumentException( "Empty element name is provided!",
293 static_cast< ::cppu::OWeakObject* >(this),
294 2 );
295
296 uno::Reference< embed::XEmbeddedObject > xResult(
297 static_cast< ::cppu::OWeakObject* > ( new OleEmbeddedObject( m_xFactory ) ),
298 uno::UNO_QUERY );
299
300 uno::Reference< embed::XEmbedPersist > xPersist( xResult, uno::UNO_QUERY_THROW );
301 xPersist->setPersistentEntry( xStorage,
302 sEntryName,
303 embed::EntryInitModes::DEFAULT_INIT,
304 uno::Sequence< beans::PropertyValue >(),
305 aObjectArgs );
306
307 aObjectInfo.Object = xResult;
308
309 // TODO/LATER: in case of iconify object the icon should be stored in aObjectInfo
310
311 OSL_ENSURE( aObjectInfo.Object.is(), "No object was created!" );
312 if ( !aObjectInfo.Object.is() )
313 throw uno::RuntimeException();
314
315 return aObjectInfo;
316 #else
317 throw lang::NoSupportException(); // TODO:
318 #endif
319 }
320
321
getImplementationName()322 OUString SAL_CALL MSOLEDialogObjectCreator::getImplementationName()
323 {
324 return impl_staticGetImplementationName();
325 }
326
327
supportsService(const OUString & ServiceName)328 sal_Bool SAL_CALL MSOLEDialogObjectCreator::supportsService( const OUString& ServiceName )
329 {
330 return cppu::supportsService(this, ServiceName);
331 }
332
333
getSupportedServiceNames()334 uno::Sequence< OUString > SAL_CALL MSOLEDialogObjectCreator::getSupportedServiceNames()
335 {
336 return impl_staticGetSupportedServiceNames();
337 }
338
339 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
340