Use COMReference to handle COM pointers in CreateShortcut
[LibreOffice.git] / embeddedobj / source / msole / xdialogcreator.cxx
blob74b267eca22fb5d61921d0756da2cf0d61cf603a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
39 #include "platform.h"
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>
51 #ifdef _WIN32
53 #include <oledlg.h>
54 #include <o3tl/char16_t2wchar_t.hxx>
55 #include <vcl/winscheduler.hxx>
57 namespace {
59 class InitializedOleGuard
61 public:
62 InitializedOleGuard()
64 if ( !SUCCEEDED( OleInitialize( nullptr ) ) )
65 throw css::uno::RuntimeException();
68 ~InitializedOleGuard()
70 OleUninitialize();
76 extern "C" {
77 typedef UINT STDAPICALLTYPE OleUIInsertObjectA_Type(LPOLEUIINSERTOBJECTA);
80 #endif
83 using namespace ::com::sun::star;
84 using namespace ::comphelper;
86 static uno::Sequence< sal_Int8 > GetRelatedInternalID_Impl( const uno::Sequence< sal_Int8 >& aClassID )
88 // Writer
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 );
93 // Calc
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 );
98 // Impress
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 );
103 // Draw
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 );
108 // Chart
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 );
113 // Math
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 );
118 return aClassID;
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 );
130 #ifdef _WIN32
132 if ( !xStorage.is() )
133 throw lang::IllegalArgumentException( "No parent storage is provided!",
134 static_cast< ::cppu::OWeakObject* >(this),
135 1 );
137 if ( !sEntName.getLength() )
138 throw lang::IllegalArgumentException( "Empty element name is provided!",
139 static_cast< ::cppu::OWeakObject* >(this),
140 2 );
142 InitializedOleGuard aGuard;
144 OLEUIINSERTOBJECTW io{ sizeof(io) };
145 io.hWndOwner = GetActiveWindow();
147 wchar_t szFile[MAX_PATH];
148 szFile[0] = 0;
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,
168 io.clsid.Data2,
169 io.clsid.Data3,
170 io.clsid.Data4[0],
171 io.clsid.Data4[1],
172 io.clsid.Data4[2],
173 io.clsid.Data4[3],
174 io.clsid.Data4[4],
175 io.clsid.Data4[5],
176 io.clsid.Data4[6],
177 io.clsid.Data4[7] );
179 aClassID = GetRelatedInternalID_Impl( aClassID );
181 //TODO: retrieve ClassName
182 aObjectInfo.Object.set( xEmbCreator->createInstanceInitNew( aClassID, OUString(), xStorage, sEntName, aObjArgs ),
183 uno::UNO_QUERY );
185 else
187 OUString aFileName(o3tl::toU(szFile));
188 OUString aFileURL;
189 if ( osl::FileBase::getFileURLFromSystemPath( aFileName, aFileURL ) != osl::FileBase::E_None )
190 throw uno::RuntimeException();
192 uno::Sequence< beans::PropertyValue > aMediaDescr{ comphelper::makePropertyValue("URL",
193 aFileURL) };
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 );
201 else
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;
220 if (xProgress.is())
222 xProgress->start(aProgressText, 100);
225 aObjectInfo.Object.set( xEmbCreator->createInstanceInitFromMediaDescriptor( xStorage, sEntName, aMediaDescr, aObjArgs ),
226 uno::UNO_QUERY );
228 if (xProgress.is())
230 xProgress->end();
234 if ( ( io.dwFlags & IOF_CHECKDISPLAYASICON) && io.hMetaPict != nullptr )
236 METAFILEPICT* pMF = static_cast<METAFILEPICT*>(GlobalLock( io.hMetaPict ));
237 if ( pMF )
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\"",
253 "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();
268 return aObjectInfo;
269 #else
270 throw lang::NoSupportException(); // TODO:
271 #endif
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;
282 #ifdef _WIN32
283 if ( !xStorage.is() )
284 throw lang::IllegalArgumentException( "No parent storage is provided!",
285 static_cast< ::cppu::OWeakObject* >(this),
286 1 );
288 if ( !sEntryName.getLength() )
289 throw lang::IllegalArgumentException( "Empty element name is provided!",
290 static_cast< ::cppu::OWeakObject* >(this),
291 2 );
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,
298 sEntryName,
299 embed::EntryInitModes::DEFAULT_INIT,
300 uno::Sequence< beans::PropertyValue >(),
301 aObjectArgs );
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();
311 return aObjectInfo;
312 #else
313 throw lang::NoSupportException(); // TODO:
314 #endif
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: */