1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <string_view>
24 #include <com/sun/star/embed/EmbeddedObjectCreator.hpp>
25 #include <com/sun/star/embed/XEmbeddedObject.hpp>
26 #include <com/sun/star/embed/EntryInitModes.hpp>
27 #include <com/sun/star/embed/OLEEmbeddedObjectFactory.hpp>
28 #include <com/sun/star/beans/PropertyValue.hpp>
29 #include <com/sun/star/datatransfer/DataFlavor.hpp>
30 #include <com/sun/star/lang/IllegalArgumentException.hpp>
31 #include <com/sun/star/ucb/CommandAbortedException.hpp>
32 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
34 #include <osl/thread.h>
35 #include <osl/file.hxx>
36 #include <osl/module.hxx>
37 #include <comphelper/classids.hxx>
40 #include <comphelper/mimeconfighelper.hxx>
41 #include <comphelper/processfactory.hxx>
42 #include <comphelper/propertyvalue.hxx>
43 #include <cppuhelper/supportsservice.hxx>
44 #include <cppuhelper/weak.hxx>
45 #include <comphelper/sequenceashashmap.hxx>
47 #include "xdialogcreator.hxx"
48 #include <oleembobj.hxx>
54 #include <vcl/winscheduler.hxx>
58 class InitializedOleGuard
63 if ( !SUCCEEDED( OleInitialize( nullptr ) ) )
64 throw css::uno::RuntimeException();
67 ~InitializedOleGuard()
76 typedef UINT STDAPICALLTYPE
OleUIInsertObjectA_Type(LPOLEUIINSERTOBJECTA
);
82 using namespace ::com::sun::star
;
83 using namespace ::comphelper
;
85 static uno::Sequence
< sal_Int8
> GetRelatedInternalID_Impl( const uno::Sequence
< sal_Int8
>& aClassID
)
88 if ( MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SW_OLE_EMBED_CLASSID_60
) )
89 || MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SW_OLE_EMBED_CLASSID_8
) ) )
90 return MimeConfigurationHelper::GetSequenceClassID( SO3_SW_CLASSID_60
);
93 if ( MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SC_OLE_EMBED_CLASSID_60
) )
94 || MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SC_OLE_EMBED_CLASSID_8
) ) )
95 return MimeConfigurationHelper::GetSequenceClassID( SO3_SC_CLASSID_60
);
98 if ( MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SIMPRESS_OLE_EMBED_CLASSID_60
) )
99 || MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SIMPRESS_OLE_EMBED_CLASSID_8
) ) )
100 return MimeConfigurationHelper::GetSequenceClassID( SO3_SIMPRESS_CLASSID_60
);
103 if ( MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SDRAW_OLE_EMBED_CLASSID_60
) )
104 || MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SDRAW_OLE_EMBED_CLASSID_8
) ) )
105 return MimeConfigurationHelper::GetSequenceClassID( SO3_SDRAW_CLASSID_60
);
108 if ( MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SCH_OLE_EMBED_CLASSID_60
) )
109 || MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SCH_OLE_EMBED_CLASSID_8
) ) )
110 return MimeConfigurationHelper::GetSequenceClassID( SO3_SCH_CLASSID_60
);
113 if ( MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SM_OLE_EMBED_CLASSID_60
) )
114 || MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SM_OLE_EMBED_CLASSID_8
) ) )
115 return MimeConfigurationHelper::GetSequenceClassID( SO3_SM_CLASSID_60
);
121 embed::InsertedObjectInfo SAL_CALL
MSOLEDialogObjectCreator::createInstanceByDialog(
122 const uno::Reference
< embed::XStorage
>& xStorage
,
123 const OUString
& sEntName
,
124 const uno::Sequence
< beans::PropertyValue
>& aInObjArgs
)
126 embed::InsertedObjectInfo aObjectInfo
;
127 uno::Sequence
< beans::PropertyValue
> aObjArgs( aInObjArgs
);
131 if ( !xStorage
.is() )
132 throw lang::IllegalArgumentException( "No parent storage is provided!",
133 static_cast< ::cppu::OWeakObject
* >(this),
136 if ( !sEntName
.getLength() )
137 throw lang::IllegalArgumentException( "Empty element name is provided!",
138 static_cast< ::cppu::OWeakObject
* >(this),
141 InitializedOleGuard aGuard
;
143 OLEUIINSERTOBJECT io
= {};
144 char szFile
[MAX_PATH
];
147 io
.cbStruct
= sizeof(io
);
148 io
.hWndOwner
= GetActiveWindow();
151 io
.lpszFile
= szFile
;
152 io
.cchFile
= MAX_PATH
;
154 io
.dwFlags
= IOF_SELECTCREATENEW
| IOF_DISABLELINK
;
157 ::osl::Module aOleDlgLib
;
158 if( !aOleDlgLib
.load( "oledlg" ))
159 throw uno::RuntimeException();
161 OleUIInsertObjectA_Type
* pInsertFct
= reinterpret_cast<OleUIInsertObjectA_Type
*>(
162 aOleDlgLib
.getSymbol( "OleUIInsertObjectA" ));
164 throw uno::RuntimeException();
166 // Disable any event loop shortcuts by enabling a real timer.
167 // This way the native windows dialog won't block our own processing.
168 WinScheduler::SetForceRealTimer();
170 uTemp
=pInsertFct(&io
);
172 if ( OLEUI_OK
!= uTemp
)
173 throw ucb::CommandAbortedException();
175 if (io
.dwFlags
& IOF_SELECTCREATENEW
)
177 uno::Reference
< embed::XEmbeddedObjectCreator
> xEmbCreator
= embed::EmbeddedObjectCreator::create( m_xContext
);
179 uno::Sequence
< sal_Int8
> aClassID
= MimeConfigurationHelper::GetSequenceClassID( io
.clsid
.Data1
,
191 aClassID
= GetRelatedInternalID_Impl( aClassID
);
193 //TODO: retrieve ClassName
194 aObjectInfo
.Object
.set( xEmbCreator
->createInstanceInitNew( aClassID
, OUString(), xStorage
, sEntName
, aObjArgs
),
200 = OStringToOUString( std::string_view( szFile
), osl_getThreadTextEncoding() );
202 if ( osl::FileBase::getFileURLFromSystemPath( aFileName
, aFileURL
) != osl::FileBase::E_None
)
203 throw uno::RuntimeException();
205 uno::Sequence
< beans::PropertyValue
> aMediaDescr
{ comphelper::makePropertyValue("URL",
208 // TODO: use config helper for type detection
209 uno::Reference
< embed::XEmbeddedObjectCreator
> xEmbCreator
;
210 ::comphelper::MimeConfigurationHelper
aHelper( m_xContext
);
212 if ( aHelper
.AddFilterNameCheckOwnFile( aMediaDescr
) )
213 xEmbCreator
= embed::EmbeddedObjectCreator::create( m_xContext
);
215 xEmbCreator
= embed::OLEEmbeddedObjectFactory::create( m_xContext
);
217 if ( !xEmbCreator
.is() )
218 throw uno::RuntimeException();
220 uno::Reference
<task::XStatusIndicator
> xProgress
;
221 OUString aProgressText
;
222 comphelper::SequenceAsHashMap
aMap(aInObjArgs
);
223 auto it
= aMap
.find("StatusIndicator");
224 if (it
!= aMap
.end())
226 it
->second
>>= xProgress
;
228 it
= aMap
.find("StatusIndicatorText");
229 if (it
!= aMap
.end())
231 it
->second
>>= aProgressText
;
235 xProgress
->start(aProgressText
, 100);
238 aObjectInfo
.Object
.set( xEmbCreator
->createInstanceInitFromMediaDescriptor( xStorage
, sEntName
, aMediaDescr
, aObjArgs
),
247 if ( ( io
.dwFlags
& IOF_CHECKDISPLAYASICON
) && io
.hMetaPict
!= nullptr )
249 METAFILEPICT
* pMF
= static_cast<METAFILEPICT
*>(GlobalLock( io
.hMetaPict
));
252 sal_uInt32 nBufSize
= GetMetaFileBitsEx( pMF
->hMF
, 0, nullptr );
253 uno::Sequence
< sal_Int8
> aMetafile( nBufSize
+ 22 );
254 sal_Int8
* pBuf
= aMetafile
.getArray();
255 *reinterpret_cast<long*>( pBuf
) = 0x9ac6cdd7L
;
256 *reinterpret_cast<short*>( pBuf
+6 ) = SHORT(0);
257 *reinterpret_cast<short*>( pBuf
+8 ) = SHORT(0);
258 *reinterpret_cast<short*>( pBuf
+10 ) = static_cast<SHORT
>(pMF
->xExt
);
259 *reinterpret_cast<short*>( pBuf
+12 ) = static_cast<SHORT
>(pMF
->yExt
);
260 *reinterpret_cast<short*>( pBuf
+14 ) = USHORT(2540);
262 if ( nBufSize
&& nBufSize
== GetMetaFileBitsEx( pMF
->hMF
, nBufSize
, pBuf
+22 ) )
264 datatransfer::DataFlavor
aFlavor(
265 "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"",
267 cppu::UnoType
<uno::Sequence
< sal_Int8
>>::get() );
269 aObjectInfo
.Options
= { { "Icon", css::uno::Any(aMetafile
) },
270 { "IconFormat", css::uno::Any(aFlavor
) } };
273 GlobalUnlock( io
.hMetaPict
);
277 OSL_ENSURE( aObjectInfo
.Object
.is(), "No object was created!" );
278 if ( !aObjectInfo
.Object
.is() )
279 throw uno::RuntimeException();
283 throw lang::NoSupportException(); // TODO:
288 embed::InsertedObjectInfo SAL_CALL
MSOLEDialogObjectCreator::createInstanceInitFromClipboard(
289 const uno::Reference
< embed::XStorage
>& xStorage
,
290 const OUString
& sEntryName
,
291 const uno::Sequence
< beans::PropertyValue
>& aObjectArgs
)
293 embed::InsertedObjectInfo aObjectInfo
;
296 if ( !xStorage
.is() )
297 throw lang::IllegalArgumentException( "No parent storage is provided!",
298 static_cast< ::cppu::OWeakObject
* >(this),
301 if ( !sEntryName
.getLength() )
302 throw lang::IllegalArgumentException( "Empty element name is provided!",
303 static_cast< ::cppu::OWeakObject
* >(this),
306 uno::Reference
< embed::XEmbeddedObject
> xResult(
307 new OleEmbeddedObject( m_xContext
) );
309 uno::Reference
< embed::XEmbedPersist
> xPersist( xResult
, uno::UNO_QUERY_THROW
);
310 xPersist
->setPersistentEntry( xStorage
,
312 embed::EntryInitModes::DEFAULT_INIT
,
313 uno::Sequence
< beans::PropertyValue
>(),
316 aObjectInfo
.Object
= xResult
;
318 // TODO/LATER: in case of iconify object the icon should be stored in aObjectInfo
320 OSL_ENSURE( aObjectInfo
.Object
.is(), "No object was created!" );
321 if ( !aObjectInfo
.Object
.is() )
322 throw uno::RuntimeException();
326 throw lang::NoSupportException(); // TODO:
331 OUString SAL_CALL
MSOLEDialogObjectCreator::getImplementationName()
333 return "com.sun.star.comp.embed.MSOLEObjectSystemCreator";
337 sal_Bool SAL_CALL
MSOLEDialogObjectCreator::supportsService( const OUString
& ServiceName
)
339 return cppu::supportsService(this, ServiceName
);
343 uno::Sequence
< OUString
> SAL_CALL
MSOLEDialogObjectCreator::getSupportedServiceNames()
345 return { "com.sun.star.embed.MSOLEObjectSystemCreator",
346 "com.sun.star.comp.embed.MSOLEObjectSystemCreator" };
349 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
350 embeddedobj_MSOLEDialogObjectCreator_get_implementation(
351 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const&)
353 return cppu::acquire(new MSOLEDialogObjectCreator(context
));
356 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */