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 <o3tl/char16_t2wchar_t.hxx>
55 #include <vcl/winscheduler.hxx>
59 class InitializedOleGuard
64 if ( !SUCCEEDED( OleInitialize( nullptr ) ) )
65 throw css::uno::RuntimeException();
68 ~InitializedOleGuard()
77 typedef UINT STDAPICALLTYPE
OleUIInsertObjectA_Type(LPOLEUIINSERTOBJECTA
);
83 using namespace ::com::sun::star
;
84 using namespace ::comphelper
;
86 static uno::Sequence
< sal_Int8
> GetRelatedInternalID_Impl( const uno::Sequence
< sal_Int8
>& aClassID
)
89 if ( MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SW_OLE_EMBED_CLASSID_60
) )
90 || MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SW_OLE_EMBED_CLASSID_8
) ) )
91 return MimeConfigurationHelper::GetSequenceClassID( SO3_SW_CLASSID_60
);
94 if ( MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SC_OLE_EMBED_CLASSID_60
) )
95 || MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SC_OLE_EMBED_CLASSID_8
) ) )
96 return MimeConfigurationHelper::GetSequenceClassID( SO3_SC_CLASSID_60
);
99 if ( MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SIMPRESS_OLE_EMBED_CLASSID_60
) )
100 || MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SIMPRESS_OLE_EMBED_CLASSID_8
) ) )
101 return MimeConfigurationHelper::GetSequenceClassID( SO3_SIMPRESS_CLASSID_60
);
104 if ( MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SDRAW_OLE_EMBED_CLASSID_60
) )
105 || MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SDRAW_OLE_EMBED_CLASSID_8
) ) )
106 return MimeConfigurationHelper::GetSequenceClassID( SO3_SDRAW_CLASSID_60
);
109 if ( MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SCH_OLE_EMBED_CLASSID_60
) )
110 || MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SCH_OLE_EMBED_CLASSID_8
) ) )
111 return MimeConfigurationHelper::GetSequenceClassID( SO3_SCH_CLASSID_60
);
114 if ( MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SM_OLE_EMBED_CLASSID_60
) )
115 || MimeConfigurationHelper::ClassIDsEqual( aClassID
, MimeConfigurationHelper::GetSequenceClassID( SO3_SM_OLE_EMBED_CLASSID_8
) ) )
116 return MimeConfigurationHelper::GetSequenceClassID( SO3_SM_CLASSID_60
);
122 embed::InsertedObjectInfo SAL_CALL
MSOLEDialogObjectCreator::createInstanceByDialog(
123 const uno::Reference
< embed::XStorage
>& xStorage
,
124 const OUString
& sEntName
,
125 const uno::Sequence
< beans::PropertyValue
>& aInObjArgs
)
127 embed::InsertedObjectInfo aObjectInfo
;
128 uno::Sequence
< beans::PropertyValue
> aObjArgs( aInObjArgs
);
132 if ( !xStorage
.is() )
133 throw lang::IllegalArgumentException( "No parent storage is provided!",
134 static_cast< ::cppu::OWeakObject
* >(this),
137 if ( !sEntName
.getLength() )
138 throw lang::IllegalArgumentException( "Empty element name is provided!",
139 static_cast< ::cppu::OWeakObject
* >(this),
142 InitializedOleGuard aGuard
;
144 OLEUIINSERTOBJECTW io
{ sizeof(io
) };
145 io
.hWndOwner
= GetActiveWindow();
147 wchar_t szFile
[MAX_PATH
];
149 io
.lpszFile
= szFile
;
150 io
.cchFile
= std::size(szFile
);
152 io
.dwFlags
= IOF_SELECTCREATENEW
| IOF_DISABLELINK
;
154 // Disable any event loop shortcuts by enabling a real timer.
155 // This way the native windows dialog won't block our own processing.
156 WinScheduler::SetForceRealTimer();
158 UINT uTemp
= OleUIInsertObjectW(&io
);
160 if ( OLEUI_OK
!= uTemp
)
161 throw ucb::CommandAbortedException();
163 if (io
.dwFlags
& IOF_SELECTCREATENEW
)
165 uno::Reference
< embed::XEmbeddedObjectCreator
> xEmbCreator
= embed::EmbeddedObjectCreator::create( m_xContext
);
167 uno::Sequence
< sal_Int8
> aClassID
= MimeConfigurationHelper::GetSequenceClassID( io
.clsid
.Data1
,
179 aClassID
= GetRelatedInternalID_Impl( aClassID
);
181 //TODO: retrieve ClassName
182 aObjectInfo
.Object
.set( xEmbCreator
->createInstanceInitNew( aClassID
, OUString(), xStorage
, sEntName
, aObjArgs
),
187 OUString
aFileName(o3tl::toU(szFile
));
189 if ( osl::FileBase::getFileURLFromSystemPath( aFileName
, aFileURL
) != osl::FileBase::E_None
)
190 throw uno::RuntimeException();
192 uno::Sequence
< beans::PropertyValue
> aMediaDescr
{ comphelper::makePropertyValue("URL",
195 // TODO: use config helper for type detection
196 uno::Reference
< embed::XEmbeddedObjectCreator
> xEmbCreator
;
197 ::comphelper::MimeConfigurationHelper
aHelper( m_xContext
);
199 if ( aHelper
.AddFilterNameCheckOwnFile( aMediaDescr
) )
200 xEmbCreator
= embed::EmbeddedObjectCreator::create( m_xContext
);
202 xEmbCreator
= embed::OLEEmbeddedObjectFactory::create( m_xContext
);
204 if ( !xEmbCreator
.is() )
205 throw uno::RuntimeException();
207 uno::Reference
<task::XStatusIndicator
> xProgress
;
208 OUString aProgressText
;
209 comphelper::SequenceAsHashMap
aMap(aInObjArgs
);
210 auto it
= aMap
.find("StatusIndicator");
211 if (it
!= aMap
.end())
213 it
->second
>>= xProgress
;
215 it
= aMap
.find("StatusIndicatorText");
216 if (it
!= aMap
.end())
218 it
->second
>>= aProgressText
;
222 xProgress
->start(aProgressText
, 100);
225 aObjectInfo
.Object
.set( xEmbCreator
->createInstanceInitFromMediaDescriptor( xStorage
, sEntName
, aMediaDescr
, aObjArgs
),
234 if ( ( io
.dwFlags
& IOF_CHECKDISPLAYASICON
) && io
.hMetaPict
!= nullptr )
236 METAFILEPICT
* pMF
= static_cast<METAFILEPICT
*>(GlobalLock( io
.hMetaPict
));
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);
249 if ( nBufSize
&& nBufSize
== GetMetaFileBitsEx( pMF
->hMF
, nBufSize
, pBuf
+22 ) )
251 datatransfer::DataFlavor
aFlavor(
252 "application/x-openoffice-wmf;windows_formatname=\"Image WMF\"",
254 cppu::UnoType
<uno::Sequence
< sal_Int8
>>::get() );
256 aObjectInfo
.Options
= { { "Icon", css::uno::Any(aMetafile
) },
257 { "IconFormat", css::uno::Any(aFlavor
) } };
260 GlobalUnlock( io
.hMetaPict
);
264 OSL_ENSURE( aObjectInfo
.Object
.is(), "No object was created!" );
265 if ( !aObjectInfo
.Object
.is() )
266 throw uno::RuntimeException();
270 throw lang::NoSupportException(); // TODO:
275 embed::InsertedObjectInfo SAL_CALL
MSOLEDialogObjectCreator::createInstanceInitFromClipboard(
276 const uno::Reference
< embed::XStorage
>& xStorage
,
277 const OUString
& sEntryName
,
278 const uno::Sequence
< beans::PropertyValue
>& aObjectArgs
)
280 embed::InsertedObjectInfo aObjectInfo
;
283 if ( !xStorage
.is() )
284 throw lang::IllegalArgumentException( "No parent storage is provided!",
285 static_cast< ::cppu::OWeakObject
* >(this),
288 if ( !sEntryName
.getLength() )
289 throw lang::IllegalArgumentException( "Empty element name is provided!",
290 static_cast< ::cppu::OWeakObject
* >(this),
293 uno::Reference
< embed::XEmbeddedObject
> xResult(
294 new OleEmbeddedObject( m_xContext
) );
296 uno::Reference
< embed::XEmbedPersist
> xPersist( xResult
, uno::UNO_QUERY_THROW
);
297 xPersist
->setPersistentEntry( xStorage
,
299 embed::EntryInitModes::DEFAULT_INIT
,
300 uno::Sequence
< beans::PropertyValue
>(),
303 aObjectInfo
.Object
= xResult
;
305 // TODO/LATER: in case of iconify object the icon should be stored in aObjectInfo
307 OSL_ENSURE( aObjectInfo
.Object
.is(), "No object was created!" );
308 if ( !aObjectInfo
.Object
.is() )
309 throw uno::RuntimeException();
313 throw lang::NoSupportException(); // TODO:
318 OUString SAL_CALL
MSOLEDialogObjectCreator::getImplementationName()
320 return "com.sun.star.comp.embed.MSOLEObjectSystemCreator";
324 sal_Bool SAL_CALL
MSOLEDialogObjectCreator::supportsService( const OUString
& ServiceName
)
326 return cppu::supportsService(this, ServiceName
);
330 uno::Sequence
< OUString
> SAL_CALL
MSOLEDialogObjectCreator::getSupportedServiceNames()
332 return { "com.sun.star.embed.MSOLEObjectSystemCreator",
333 "com.sun.star.comp.embed.MSOLEObjectSystemCreator" };
336 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
337 embeddedobj_MSOLEDialogObjectCreator_get_implementation(
338 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const&)
340 return cppu::acquire(new MSOLEDialogObjectCreator(context
));
343 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */