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 <sal/config.h>
21 #include <sal/log.hxx>
22
23 #include <shutdownicon.hxx>
24 #include <sfx2/strings.hrc>
25 #include <sfx2/app.hxx>
26 #include <svtools/imagemgr.hxx>
27 #include <com/sun/star/task/InteractionHandler.hpp>
28 #include <com/sun/star/frame/Desktop.hpp>
29 #include <com/sun/star/frame/TerminationVetoException.hpp>
30 #include <com/sun/star/frame/XDispatchResultListener.hpp>
31 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
32 #include <com/sun/star/frame/XFramesSupplier.hpp>
33 #include <com/sun/star/frame/XFrame.hpp>
34 #include <com/sun/star/util/URLTransformer.hpp>
35 #include <com/sun/star/util/XURLTransformer.hpp>
36 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
37 #include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
38 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
39 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
40 #include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp>
41 #include <com/sun/star/ui/dialogs/ControlActions.hpp>
42 #include <com/sun/star/document/MacroExecMode.hpp>
43 #include <com/sun/star/document/UpdateDocMode.hpp>
44 #include <sfx2/filedlghelper.hxx>
45 #include <sfx2/docfilt.hxx>
46 #include <sfx2/fcontnr.hxx>
47 #include <comphelper/processfactory.hxx>
48 #include <comphelper/propertyvalue.hxx>
49 #include <cppuhelper/implbase.hxx>
50 #include <cppuhelper/supportsservice.hxx>
51 #include <comphelper/extract.hxx>
52 #include <officecfg/Office/Common.hxx>
53 #include <tools/urlobj.hxx>
54 #include <tools/debug.hxx>
55 #include <osl/diagnose.h>
56 #include <osl/file.hxx>
57 #include <osl/module.hxx>
58 #include <rtl/ref.hxx>
59 #include <utility>
60 #include <vcl/svapp.hxx>
61
62 #include <sfx2/sfxresid.hxx>
63
64 using namespace ::com::sun::star;
65 using namespace ::com::sun::star::uno;
66 using namespace ::com::sun::star::frame;
67 using namespace ::com::sun::star::container;
68 using namespace ::com::sun::star::lang;
69 using namespace ::com::sun::star::beans;
70 using namespace ::com::sun::star::util;
71 using namespace ::com::sun::star::ui::dialogs;
72 using namespace ::sfx2;
73
74 class SfxNotificationListener_Impl : public cppu::WeakImplHelper< XDispatchResultListener >
75 {
76 public:
77 virtual void SAL_CALL dispatchFinished( const DispatchResultEvent& aEvent ) override;
78 virtual void SAL_CALL disposing( const EventObject& aEvent ) override;
79 };
80
dispatchFinished(const DispatchResultEvent &)81 void SAL_CALL SfxNotificationListener_Impl::dispatchFinished( const DispatchResultEvent& )
82 {
83 ShutdownIcon::LeaveModalMode();
84 }
85
disposing(const EventObject &)86 void SAL_CALL SfxNotificationListener_Impl::disposing( const EventObject& )
87 {
88 }
89
getImplementationName()90 OUString SAL_CALL ShutdownIcon::getImplementationName()
91 {
92 return u"com.sun.star.comp.desktop.QuickstartWrapper"_ustr;
93 }
94
supportsService(OUString const & ServiceName)95 sal_Bool SAL_CALL ShutdownIcon::supportsService(OUString const & ServiceName)
96 {
97 return cppu::supportsService(this, ServiceName);
98 }
99
getSupportedServiceNames()100 css::uno::Sequence<OUString> SAL_CALL ShutdownIcon::getSupportedServiceNames()
101 {
102 return { u"com.sun.star.office.Quickstart"_ustr };
103 }
104
105 bool ShutdownIcon::bModalMode = false;
106 rtl::Reference<ShutdownIcon> ShutdownIcon::pShutdownIcon;
107
initSystray()108 void ShutdownIcon::initSystray()
109 {
110 if (m_bInitialized)
111 return;
112 m_bInitialized = true;
113
114 #ifdef ENABLE_QUICKSTART_APPLET
115 # ifdef _WIN32
116 win32_init_sys_tray();
117 # elif defined MACOSX
118 aqua_init_systray();
119 # endif // MACOSX
120 #endif // ENABLE_QUICKSTART_APPLET
121 }
122
deInitSystray()123 void ShutdownIcon::deInitSystray()
124 {
125 if (!m_bInitialized)
126 return;
127
128 #ifdef ENABLE_QUICKSTART_APPLET
129 # ifdef _WIN32
130 win32_shutdown_sys_tray();
131 # elif defined MACOSX
132 aqua_shutdown_systray();
133 # endif // MACOSX
134 #endif // ENABLE_QUICKSTART_APPLET
135
136 m_bVeto = false;
137
138 m_pFileDlg.reset();
139 m_bInitialized = false;
140 }
141
UseSystemFileDialog()142 static bool UseSystemFileDialog()
143 {
144 return !Application::IsHeadlessModeEnabled() && officecfg::Office::Common::Misc::UseSystemFileDialog::get();
145 }
146
ShutdownIcon(css::uno::Reference<XComponentContext> xContext)147 ShutdownIcon::ShutdownIcon( css::uno::Reference< XComponentContext > xContext ) :
148 m_bVeto ( false ),
149 m_bListenForTermination ( false ),
150 m_bSystemDialogs(UseSystemFileDialog()),
151 m_xContext(std::move( xContext )),
152 m_bInitialized( false )
153 {
154 }
155
~ShutdownIcon()156 ShutdownIcon::~ShutdownIcon()
157 {
158 deInitSystray();
159 }
160
161
OpenURL(const OUString & aURL,const OUString & rTarget,const Sequence<PropertyValue> & aArgs)162 void ShutdownIcon::OpenURL( const OUString& aURL, const OUString& rTarget, const Sequence< PropertyValue >& aArgs )
163 {
164 if ( !getInstance() || !getInstance()->m_xDesktop.is() )
165 return;
166
167 css::uno::Reference < XDispatchProvider > xDispatchProvider = getInstance()->m_xDesktop;
168 if ( !xDispatchProvider.is() )
169 return;
170
171 css::util::URL aDispatchURL;
172 aDispatchURL.Complete = aURL;
173
174 css::uno::Reference< util::XURLTransformer > xURLTransformer( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
175 try
176 {
177 css::uno::Reference< css::frame::XDispatch > xDispatch;
178
179 xURLTransformer->parseStrict( aDispatchURL );
180 xDispatch = xDispatchProvider->queryDispatch( aDispatchURL, rTarget, 0 );
181 if ( xDispatch.is() )
182 xDispatch->dispatch( aDispatchURL, aArgs );
183 }
184 catch ( css::uno::RuntimeException& )
185 {
186 throw;
187 }
188 catch ( css::uno::Exception& )
189 {
190 }
191 }
192
193
FileOpen()194 void ShutdownIcon::FileOpen()
195 {
196 if ( getInstance() && getInstance()->m_xDesktop.is() )
197 {
198 ::SolarMutexGuard aGuard;
199 EnterModalMode();
200 getInstance()->StartFileDialog();
201 }
202 }
203
204
FromTemplate()205 void ShutdownIcon::FromTemplate()
206 {
207 ShutdownIcon::FromCommand( ".uno:NewDoc" );
208 }
209
FromCommand(const OUString & rCommand)210 void ShutdownIcon::FromCommand( const OUString& rCommand )
211 {
212 if ( !getInstance() || !getInstance()->m_xDesktop.is() )
213 return;
214
215 css::uno::Reference < css::frame::XFramesSupplier > xDesktop = getInstance()->m_xDesktop;
216 css::uno::Reference < css::frame::XFrame > xFrame( xDesktop->getActiveFrame() );
217 if ( !xFrame.is() )
218 xFrame = xDesktop;
219
220 URL aTargetURL;
221 aTargetURL.Complete = rCommand;
222 css::uno::Reference< util::XURLTransformer > xTrans( util::URLTransformer::create( ::comphelper::getProcessComponentContext() ) );
223 xTrans->parseStrict( aTargetURL );
224
225 css::uno::Reference < css::frame::XDispatchProvider > xProv( xFrame, UNO_QUERY );
226 css::uno::Reference < css::frame::XDispatch > xDisp;
227 if ( xProv.is() )
228 {
229 xDisp = xProv->queryDispatch( aTargetURL, u"_self"_ustr, 0 );
230 }
231 if ( !xDisp.is() )
232 return;
233
234 Sequence<PropertyValue> aArgs { comphelper::makePropertyValue(u"Referer"_ustr, u"private:user"_ustr) };
235 css::uno::Reference< css::frame::XNotifyingDispatch > xNotifier(xDisp, UNO_QUERY);
236 if (xNotifier.is())
237 {
238 EnterModalMode();
239 xNotifier->dispatchWithNotification(aTargetURL, aArgs, new SfxNotificationListener_Impl);
240 }
241 else
242 xDisp->dispatch( aTargetURL, aArgs );
243 }
244
GetUrlDescription(std::u16string_view aUrl)245 OUString ShutdownIcon::GetUrlDescription( std::u16string_view aUrl )
246 {
247 return SvFileInformationManager::GetDescription( INetURLObject( aUrl ) );
248 }
249
StartFileDialog()250 void ShutdownIcon::StartFileDialog()
251 {
252 ::SolarMutexGuard aGuard;
253
254 bool bDirty = m_bSystemDialogs != UseSystemFileDialog();
255
256 if ( m_pFileDlg && bDirty )
257 {
258 // Destroy instance as changing the system file dialog setting
259 // forces us to create a new FileDialogHelper instance!
260 m_pFileDlg.reset();
261 }
262
263 if ( !m_pFileDlg )
264 m_pFileDlg.reset( new FileDialogHelper(
265 ui::dialogs::TemplateDescription::FILEOPEN_READONLY_VERSION,
266 FileDialogFlags::MultiSelection, OUString(), SfxFilterFlags::NONE, SfxFilterFlags::NONE, nullptr ) );
267 m_pFileDlg->StartExecuteModal( LINK( this, ShutdownIcon, DialogClosedHdl_Impl ) );
268 }
269
270 IMPL_LINK( ShutdownIcon, DialogClosedHdl_Impl, FileDialogHelper*, /*unused*/, void )
271 {
272 DBG_ASSERT( m_pFileDlg, "ShutdownIcon, DialogClosedHdl_Impl(): no file dialog" );
273
274 // use constructor for filling up filters automatically!
275 if ( ERRCODE_NONE == m_pFileDlg->GetError() )
276 {
277 css::uno::Reference< XFilePicker3 > xPicker = m_pFileDlg->GetFilePicker();
278
279 try
280 {
281
282 if ( xPicker.is() )
283 {
284
285 css::uno::Reference < XFilePickerControlAccess > xPickerControls ( xPicker, UNO_QUERY );
286
287 Sequence< OUString > sFiles = xPicker->getSelectedFiles();
288 int nFiles = sFiles.getLength();
289
290 css::uno::Reference < css::task::XInteractionHandler2 > xInteraction(
291 task::InteractionHandler::createWithParent(::comphelper::getProcessComponentContext(), nullptr) );
292
293 int nArgs=3;
294 Sequence< PropertyValue > aArgs{
295 comphelper::makePropertyValue(u"InteractionHandler"_ustr, xInteraction),
296 comphelper::makePropertyValue(u"MacroExecutionMode"_ustr, sal_Int16(css::document::MacroExecMode::USE_CONFIG)),
297 comphelper::makePropertyValue(u"UpdateDocMode"_ustr, sal_Int16(css::document::UpdateDocMode::ACCORDING_TO_CONFIG))
298 };
299
300 // use the filedlghelper to get the current filter name,
301 // because it removes the extensions before you get the filter name.
302 OUString aFilterName( m_pFileDlg->GetCurrentFilter() );
303
304 if ( xPickerControls.is() )
305 {
306
307 // Set readonly flag
308
309 bool bReadOnly = false;
310
311
312 xPickerControls->getValue( ExtendedFilePickerElementIds::CHECKBOX_READONLY, 0 ) >>= bReadOnly;
313
314 // Only set property if readonly is set to TRUE
315
316 if ( bReadOnly )
317 {
318 aArgs.realloc( ++nArgs );
319 auto pArgs = aArgs.getArray();
320 pArgs[nArgs-1].Name = "ReadOnly";
321 pArgs[nArgs-1].Value <<= bReadOnly;
322 }
323
324 // Get version string
325
326 sal_Int32 iVersion = -1;
327
328 xPickerControls->getValue( ExtendedFilePickerElementIds::LISTBOX_VERSION, ControlActions::GET_SELECTED_ITEM_INDEX ) >>= iVersion;
329
330 if ( iVersion >= 0 )
331 {
332 sal_Int16 uVersion = static_cast<sal_Int16>(iVersion);
333
334 aArgs.realloc( ++nArgs );
335 auto pArgs = aArgs.getArray();
336 pArgs[nArgs-1].Name = "Version";
337 pArgs[nArgs-1].Value <<= uVersion;
338 }
339
340 // Retrieve the current filter
341
342 if ( aFilterName.isEmpty() )
343 xPickerControls->getValue( CommonFilePickerElementIds::LISTBOX_FILTER, ControlActions::GET_SELECTED_ITEM ) >>= aFilterName;
344
345 }
346
347
348 // Convert UI filter name to internal filter name
349
350 if ( !aFilterName.isEmpty() )
351 {
352 std::shared_ptr<const SfxFilter> pFilter = SfxGetpApp()->GetFilterMatcher().GetFilter4UIName( aFilterName, SfxFilterFlags::NONE, SfxFilterFlags::NOTINFILEDLG );
353
354 if ( pFilter )
355 {
356 aFilterName = pFilter->GetFilterName();
357
358 if ( !aFilterName.isEmpty() )
359 {
360 aArgs.realloc( ++nArgs );
361 auto pArgs = aArgs.getArray();
362 pArgs[nArgs-1].Name = "FilterName";
363 pArgs[nArgs-1].Value <<= aFilterName;
364 }
365 }
366 }
367
368 if ( 1 == nFiles )
369 OpenURL( sFiles[0], u"_default"_ustr, aArgs );
370 else
371 {
372 OUString aBaseDirURL = sFiles[0];
373 if ( !aBaseDirURL.isEmpty() && !aBaseDirURL.endsWith("/") )
374 aBaseDirURL += "/";
375
376 int iFiles;
377 for ( iFiles = 1; iFiles < nFiles; iFiles++ )
378 {
379 OUString aURL = aBaseDirURL + sFiles[iFiles];
380 OpenURL( aURL, u"_default"_ustr, aArgs );
381 }
382 }
383 }
384 }
385 catch ( ... )
386 {
387 }
388 }
389
390 #ifdef _WIN32
391 // Destroy dialog to prevent problems with custom controls
392 // This fix is dependent on the dialog settings. Destroying the dialog here will
393 // crash the non-native dialog implementation! Therefore make this dependent on
394 // the settings.
395 if (UseSystemFileDialog())
396 {
397 m_pFileDlg.reset();
398 }
399 #endif
400
401 LeaveModalMode();
402 }
403
404
addTerminateListener()405 void ShutdownIcon::addTerminateListener()
406 {
407 ShutdownIcon* pInst = getInstance();
408 if ( ! pInst)
409 return;
410
411 if (pInst->m_bListenForTermination)
412 return;
413
414 css::uno::Reference< XDesktop2 > xDesktop = pInst->m_xDesktop;
415 if ( ! xDesktop.is())
416 return;
417
418 xDesktop->addTerminateListener( pInst );
419 pInst->m_bListenForTermination = true;
420 }
421
422
terminateDesktop()423 void ShutdownIcon::terminateDesktop()
424 {
425 ShutdownIcon* pInst = getInstance();
426 if ( ! pInst)
427 return;
428
429 css::uno::Reference< XDesktop2 > xDesktop = pInst->m_xDesktop;
430 if ( ! xDesktop.is())
431 return;
432
433 // always remove ourselves as listener
434 pInst->m_bListenForTermination = true;
435 xDesktop->removeTerminateListener( pInst );
436
437 // terminate desktop only if no tasks exist
438 css::uno::Reference< XIndexAccess > xTasks = xDesktop->getFrames();
439 if( xTasks.is() && xTasks->getCount() < 1 )
440 Application::Quit();
441
442 // remove the instance pointer
443 ShutdownIcon::pShutdownIcon = nullptr;
444 }
445
446
getInstance()447 ShutdownIcon* ShutdownIcon::getInstance()
448 {
449 OSL_ASSERT( pShutdownIcon );
450 return pShutdownIcon.get();
451 }
452
453
createInstance()454 ShutdownIcon* ShutdownIcon::createInstance()
455 {
456 if (pShutdownIcon)
457 return pShutdownIcon.get();
458
459 try {
460 rtl::Reference<ShutdownIcon> pIcon(new ShutdownIcon( comphelper::getProcessComponentContext() ));
461 pIcon->init ();
462 pShutdownIcon = std::move(pIcon);
463 } catch (...) {
464 }
465
466 return pShutdownIcon.get();
467 }
468
init()469 void ShutdownIcon::init()
470 {
471 css::uno::Reference < XDesktop2 > xDesktop = Desktop::create( m_xContext );
472 std::unique_lock aGuard(m_aMutex);
473 m_xDesktop = std::move(xDesktop);
474 }
475
disposing(std::unique_lock<std::mutex> &)476 void ShutdownIcon::disposing(std::unique_lock<std::mutex>&)
477 {
478 m_xContext.clear();
479 m_xDesktop.clear();
480
481 deInitSystray();
482 }
483
484 // XEventListener
disposing(const css::lang::EventObject &)485 void SAL_CALL ShutdownIcon::disposing( const css::lang::EventObject& )
486 {
487 }
488
489 // XTerminateListener
queryTermination(const css::lang::EventObject &)490 void SAL_CALL ShutdownIcon::queryTermination( const css::lang::EventObject& )
491 {
492 SAL_INFO("sfx.appl", "ShutdownIcon::queryTermination: veto is " << m_bVeto);
493 std::unique_lock aGuard( m_aMutex );
494
495 if ( m_bVeto )
496 throw css::frame::TerminationVetoException();
497 }
498
499
notifyTermination(const css::lang::EventObject &)500 void SAL_CALL ShutdownIcon::notifyTermination( const css::lang::EventObject& )
501 {
502 }
503
504
initialize(const css::uno::Sequence<css::uno::Any> & aArguments)505 void SAL_CALL ShutdownIcon::initialize( const css::uno::Sequence< css::uno::Any>& aArguments )
506 {
507 std::unique_lock aGuard( m_aMutex );
508
509 // third argument only sets veto, everything else will be ignored!
510 if (aArguments.getLength() > 2)
511 {
512 bool bVeto = ::cppu::any2bool(aArguments[2]);
513 m_bVeto = bVeto;
514 return;
515 }
516
517 if ( aArguments.getLength() > 0 )
518 {
519 if ( !ShutdownIcon::pShutdownIcon )
520 {
521 try
522 {
523 bool bQuickstart = ::cppu::any2bool( aArguments[0] );
524 if( !bQuickstart && !GetAutostart() )
525 return;
526 aGuard.unlock();
527 init ();
528 aGuard.lock();
529 if ( !m_xDesktop.is() )
530 return;
531
532 /* Create a sub-classed instance - foo */
533 ShutdownIcon::pShutdownIcon = this;
534 initSystray();
535 }
536 catch(const css::lang::IllegalArgumentException&)
537 {
538 }
539 }
540 }
541 if ( aArguments.getLength() > 1 )
542 {
543 bool bAutostart = ::cppu::any2bool( aArguments[1] );
544 if (bAutostart && !GetAutostart())
545 SetAutostart( true );
546 if (!bAutostart && GetAutostart())
547 SetAutostart( false );
548 }
549
550 }
551
552
EnterModalMode()553 void ShutdownIcon::EnterModalMode()
554 {
555 bModalMode = true;
556 }
557
558
LeaveModalMode()559 void ShutdownIcon::LeaveModalMode()
560 {
561 bModalMode = false;
562 }
563
564 #ifdef _WIN32
565 // defined in shutdowniconw32.cxx
566 #elif defined MACOSX
567 // defined in shutdowniconaqua.cxx
568 #else
IsQuickstarterInstalled()569 bool ShutdownIcon::IsQuickstarterInstalled()
570 {
571 return false;
572 }
573 #endif
574
575
576 #ifdef ENABLE_QUICKSTART_APPLET
577 #ifdef _WIN32
getShortcutName()578 OUString ShutdownIcon::getShortcutName()
579 {
580 return GetAutostartFolderNameW32() + "\\" + SfxResId(STR_QUICKSTART_LNKNAME) + ".lnk";
581 }
582 #endif // _WIN32
583 #endif
584
GetAutostart()585 bool ShutdownIcon::GetAutostart( )
586 {
587 #if defined MACOSX
588 return true;
589 #elif defined ENABLE_QUICKSTART_APPLET
590 bool bRet = false;
591 OUString aShortcut( getShortcutName() );
592 OUString aShortcutUrl;
593 osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
594 osl::File f( aShortcutUrl );
595 osl::File::RC error = f.open( osl_File_OpenFlag_Read );
596 if( error == osl::File::E_None )
597 {
598 f.close();
599 bRet = true;
600 }
601 return bRet;
602 #else // ENABLE_QUICKSTART_APPLET
603 return false;
604 #endif
605 }
606
SetAutostart(bool bActivate)607 void ShutdownIcon::SetAutostart( bool bActivate )
608 {
609 #ifdef ENABLE_QUICKSTART_APPLET
610 #ifndef MACOSX
611 OUString aShortcut( getShortcutName() );
612 #endif
613
614 if( bActivate && IsQuickstarterInstalled() )
615 {
616 #ifdef _WIN32
617 EnableAutostartW32( aShortcut );
618 #endif
619 }
620 else
621 {
622 #ifndef MACOSX
623 OUString aShortcutUrl;
624 ::osl::File::getFileURLFromSystemPath( aShortcut, aShortcutUrl );
625 ::osl::File::remove( aShortcutUrl );
626 #endif
627 }
628 #else
629 (void)bActivate; // unused variable
630 #endif // ENABLE_QUICKSTART_APPLET
631 }
632
633 const ::sal_Int32 PROPHANDLE_TERMINATEVETOSTATE = 0;
634
635 // XFastPropertySet
setFastPropertyValue(::sal_Int32 nHandle,const css::uno::Any & aValue)636 void SAL_CALL ShutdownIcon::setFastPropertyValue( ::sal_Int32 nHandle,
637 const css::uno::Any& aValue )
638 {
639 switch(nHandle)
640 {
641 case PROPHANDLE_TERMINATEVETOSTATE :
642 {
643 // use new value in case it's a valid information only
644 bool bState( false );
645 if (! (aValue >>= bState))
646 return;
647
648 m_bVeto = bState;
649 if (m_bVeto && ! m_bListenForTermination)
650 addTerminateListener();
651 }
652 break;
653
654 default :
655 throw css::beans::UnknownPropertyException(OUString::number(nHandle));
656 }
657 }
658
659 // XFastPropertySet
getFastPropertyValue(::sal_Int32 nHandle)660 css::uno::Any SAL_CALL ShutdownIcon::getFastPropertyValue( ::sal_Int32 nHandle )
661 {
662 css::uno::Any aValue;
663 switch(nHandle)
664 {
665 case PROPHANDLE_TERMINATEVETOSTATE :
666 {
667 bool bState = (m_bListenForTermination && m_bVeto);
668 aValue <<= bState;
669 }
670 break;
671
672 default :
673 throw css::beans::UnknownPropertyException(OUString::number(nHandle));
674 }
675
676 return aValue;
677 }
678
679 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_desktop_QuickstartWrapper_get_implementation(css::uno::XComponentContext * context,css::uno::Sequence<css::uno::Any> const &)680 com_sun_star_comp_desktop_QuickstartWrapper_get_implementation(
681 css::uno::XComponentContext *context,
682 css::uno::Sequence<css::uno::Any> const &)
683 {
684 return cppu::acquire(new ShutdownIcon(context));
685 }
686
687 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
688