xref: /trunk/main/desktop/source/app/app.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_desktop.hxx"
26 
27 #include <cstdlib>
28 #include <vector>
29 
30 #include <memory>
31 #include <unistd.h>
32 #include "app.hxx"
33 #include "desktop.hrc"
34 #include "appinit.hxx"
35 #include "officeipcthread.hxx"
36 #include "cmdlineargs.hxx"
37 #include "desktopresid.hxx"
38 #include "dispatchwatcher.hxx"
39 #include "configinit.hxx"
40 #include "lockfile.hxx"
41 #include "checkinstall.hxx"
42 #include "cmdlinehelp.hxx"
43 #include "userinstall.hxx"
44 #include "desktopcontext.hxx"
45 #include "exithelper.hxx"
46 #include "../migration/pages.hxx"
47 
48 #include <svtools/javacontext.hxx>
49 #include <com/sun/star/frame/XSessionManagerListener.hpp>
50 #include <com/sun/star/frame/XSynchronousDispatch.hpp>
51 #include <com/sun/star/document/CorruptedFilterConfigurationException.hpp>
52 #include <com/sun/star/configuration/CorruptedConfigurationException.hpp>
53 #include <com/sun/star/frame/XStorable.hpp>
54 #include <com/sun/star/util/XModifiable.hpp>
55 #include <com/sun/star/util/XFlushable.hpp>
56 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
57 #include <com/sun/star/beans/XPropertySet.hpp>
58 #include <com/sun/star/lang/XComponent.hpp>
59 #include <com/sun/star/uno/RuntimeException.hpp>
60 #include <com/sun/star/io/IOException.hpp>
61 #include <com/sun/star/lang/IllegalArgumentException.hpp>
62 #include <com/sun/star/lang/WrappedTargetException.hpp>
63 #include <com/sun/star/frame/XDesktop.hpp>
64 #include <com/sun/star/frame/XComponentLoader.hpp>
65 #include <com/sun/star/view/XPrintable.hpp>
66 #include <com/sun/star/lang/XInitialization.hpp>
67 #include <com/sun/star/frame/XFramesSupplier.hpp>
68 #include <com/sun/star/awt/XTopWindow.hpp>
69 #include <com/sun/star/util/XURLTransformer.hpp>
70 #include <com/sun/star/util/URL.hpp>
71 #include <com/sun/star/util/XCloseable.hpp>
72 #include <com/sun/star/frame/XDispatch.hpp>
73 #include <com/sun/star/frame/XDispatchProvider.hpp>
74 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
75 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
76 #include <com/sun/star/configuration/MissingBootstrapFileException.hpp>
77 #include <com/sun/star/configuration/InvalidBootstrapFileException.hpp>
78 #include <com/sun/star/configuration/InstallationIncompleteException.hpp>
79 #include <com/sun/star/configuration/backend/BackendSetupException.hpp>
80 #include <com/sun/star/configuration/backend/BackendAccessException.hpp>
81 #include <com/sun/star/container/XEnumeration.hpp>
82 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
83 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
84 #include <com/sun/star/task/XJobExecutor.hpp>
85 #include <com/sun/star/task/XRestartManager.hpp>
86 #ifndef _COM_SUN_STAR_TASK_XJOBEXECUTOR_HPP_
87 #include <com/sun/star/task/XJob.hpp>
88 #endif
89 #include <com/sun/star/beans/XPropertySet.hpp>
90 #include <com/sun/star/beans/NamedValue.hpp>
91 #include <com/sun/star/task/XJob.hpp>
92 #include <com/sun/star/document/XEventListener.hpp>
93 #include <com/sun/star/ui/XUIElementFactoryRegistration.hpp>
94 #include <com/sun/star/frame/XUIControllerRegistration.hpp>
95 
96 #include <com/sun/star/java/XJavaVM.hpp>
97 #include <tools/testtoolloader.hxx>
98 #include <tools/solar.h>
99 #ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_
100 #include <toolkit/helper/vclunohelper.hxx>
101 #endif
102 #include <vos/security.hxx>
103 #include <vos/ref.hxx>
104 #include <comphelper/processfactory.hxx>
105 #include <comphelper/componentcontext.hxx>
106 #include <comphelper/configurationhelper.hxx>
107 #ifndef _UTL__HXX_
108 #include <unotools/configmgr.hxx>
109 #endif
110 #include <unotools/configitem.hxx>
111 #include <unotools/confignode.hxx>
112 #include <unotools/ucbhelper.hxx>
113 #include <tools/tempfile.hxx>
114 #include <tools/urlobj.hxx>
115 #include <unotools/moduleoptions.hxx>
116 #include <osl/module.h>
117 #include <osl/file.hxx>
118 #include <osl/signal.h>
119 #include <osl/thread.hxx>
120 #include <rtl/uuid.h>
121 #include <rtl/uri.hxx>
122 #include <unotools/pathoptions.hxx>
123 #include <svl/languageoptions.hxx>
124 #include <unotools/internaloptions.hxx>
125 #include <svtools/miscopt.hxx>
126 #include <svtools/menuoptions.hxx>
127 #include <unotools/syslocaleoptions.hxx>
128 #include <unotools/syslocale.hxx>
129 #include <svl/folderrestriction.hxx>
130 #include <svl/eitem.hxx>
131 #include <svl/itemset.hxx>
132 #include <unotools/tempfile.hxx>
133 #include <rtl/logfile.hxx>
134 #include <rtl/ustrbuf.hxx>
135 #include <rtl/strbuf.hxx>
136 #include <rtl/bootstrap.hxx>
137 #include <rtl/instance.hxx>
138 #include <unotools/configmgr.hxx>
139 #include <vcl/help.hxx>
140 #include <vcl/msgbox.hxx>
141 #include <vcl/bitmap.hxx>
142 #include <vcl/stdtext.hxx>
143 #include <vcl/msgbox.hxx>
144 #include <sfx2/sfx.hrc>
145 #include <sfx2/app.hxx>
146 #include <ucbhelper/contentbroker.hxx>
147 #include <unotools/bootstrap.hxx>
148 #include <cppuhelper/bootstrap.hxx>
149 
150 #include "vos/process.hxx"
151 
152 #include <svtools/fontsubstconfig.hxx>
153 #include <svtools/accessibilityoptions.hxx>
154 #include <svtools/apearcfg.hxx>
155 #include <unotools/misccfg.hxx>
156 #include <svtools/filter.hxx>
157 
158 #include "langselect.hxx"
159 
160 #include "com/sun/star/deployment/ExtensionManager.hpp"
161 #include "com/sun/star/deployment/XExtensionManager.hpp"
162 #include "com/sun/star/task/XInteractionApprove.hpp"
163 #include "com/sun/star/task/XInteractionAbort.hpp"
164 #include "cppuhelper/compbase3.hxx"
165 #include <hash_set>
166 
167 #include "com/sun/star/deployment/VersionException.hpp"
168 #include <dp_gui_handleversionexception.hxx>
169 
170 #if defined MACOSX
171 #include <errno.h>
172 #include <sys/wait.h>
173 #endif
174 
175 #define DEFINE_CONST_UNICODE(CONSTASCII)        UniString(RTL_CONSTASCII_USTRINGPARAM(CONSTASCII))
176 #define OUSTR(x)                                ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(x))
177 #define U2S(STRING)                             ::rtl::OUStringToOString(STRING, RTL_TEXTENCODING_UTF8)
178 
179 using namespace vos;
180 using namespace rtl;
181 
182 using namespace ::com::sun::star::uno;
183 using namespace ::com::sun::star::util;
184 using namespace ::com::sun::star::lang;
185 using namespace ::com::sun::star::beans;
186 using namespace ::com::sun::star::frame;
187 using namespace ::com::sun::star::document;
188 using namespace ::com::sun::star::view;
189 using namespace ::com::sun::star::task;
190 using namespace ::com::sun::star::system;
191 using namespace ::com::sun::star::ui::dialogs;
192 using namespace ::com::sun::star::container;
193 
194 namespace css = ::com::sun::star;
195 
196 ResMgr*                 desktop::Desktop::pResMgr = 0;
197 
198 namespace {
199 
200 /** Write a marker file that is basically empty (just a single
201     character to prevent it from being deleted.)  Its time of last
202     modification is its only important feature.
203 
204     This is a simplified version of the function in
205     dp_extensionmanager.cxx.  It uses direct file access instead of
206     the UCB.  May prove to be too simple, but then again, it may not.
207 */
writeLastModified(::rtl::OUString & rsURL)208 bool writeLastModified (::rtl::OUString& rsURL)
209 {
210     try
211     {
212         // Remove the file if it already exists.
213         ::osl::File::remove(rsURL);
214 
215         ::osl::File aFile (rsURL);
216         if (aFile.open(OpenFlag_Create | OpenFlag_Write) != ::osl::File::E_None)
217             return false;
218 
219         const char aBuffer[] = "1";
220         sal_uInt64 nBytesWritten (0);
221         if (aFile.write(aBuffer, strlen(aBuffer), nBytesWritten) != ::osl::File::E_None)
222             return false;
223 
224         if (aFile.close() != ::osl::File::E_None)
225             return false;
226 
227         return true;
228     }
229     catch(...)
230     {
231     }
232     return false;
233 }
234 
235 } // end of anonymous namespace
236 
237 
238 
239 namespace desktop
240 {
241 
242 static SalMainPipeExchangeSignalHandler* pSignalHandler = 0;
243 static sal_Bool _bCrashReporterEnabled = sal_True;
244 
245 static const ::rtl::OUString CFG_PACKAGE_COMMON_HELP   ( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.Office.Common/Help"));
246 
247 static ::rtl::OUString getBrandSharePreregBundledPathURL();
248 // #i119950# Add a option that not to display the "Fatal Error" on dialog title
249 void FatalError(const ::rtl::OUString& sMessage, const sal_Bool isDisplayErrorString = sal_True);
250 // ----------------------------------------------------------------------------
251 
GetDesktopResManager()252 ResMgr* Desktop::GetDesktopResManager()
253 {
254     if ( !Desktop::pResMgr )
255     {
256         const char* pMgrName = "dkt";
257 
258         // Create desktop resource manager and bootstrap process
259         // was successful. Use default way to get language specific message.
260         if ( Application::IsInExecute() )
261             Desktop::pResMgr = ResMgr::CreateResMgr( pMgrName);
262 
263         if ( !Desktop::pResMgr )
264         {
265             // Use VCL to get the correct language specific message as we
266             // are in the bootstrap process and not able to get the installed
267             // language!!
268 /*
269             LanguageType aLanguageType = LANGUAGE_DONTKNOW;
270 
271             Desktop::pResMgr = ResMgr::SearchCreateResMgr( pMgrName, aLanguageType );
272             AllSettings as = GetSettings();
273             as.SetUILanguage(aLanguageType);
274             SetSettings(as);
275 */
276             // LanguageSelection langselect;
277             OUString aUILocaleString = LanguageSelection::getLanguageString();
278             sal_Int32 nIndex = 0;
279             OUString aLanguage = aUILocaleString.getToken( 0, '-', nIndex);
280             OUString aCountry = aUILocaleString.getToken( 0, '-', nIndex);
281             OUString aVariant = aUILocaleString.getToken( 0, '-', nIndex);
282 
283             ::com::sun::star::lang::Locale aLocale( aLanguage, aCountry, aVariant );
284 
285             Desktop::pResMgr = ResMgr::SearchCreateResMgr( pMgrName, aLocale);
286             AllSettings as = GetSettings();
287             as.SetUILocale(aLocale);
288             SetSettings(as);
289         }
290     }
291 
292     return Desktop::pResMgr;
293 }
294 
295 // ----------------------------------------------------------------------------
296 // Get a message string securely. There is a fallback string if the resource
297 // is not available.
298 
GetMsgString(sal_uInt16 nId,const OUString & aFaultBackMsg)299 OUString Desktop::GetMsgString( sal_uInt16 nId, const OUString& aFaultBackMsg )
300 {
301     ResMgr* resMgr = GetDesktopResManager();
302     if ( !resMgr )
303         return aFaultBackMsg;
304     else
305         return OUString( String( ResId( nId, *resMgr )));
306 }
307 
MakeStartupErrorMessage(OUString const & aErrorMessage)308 OUString MakeStartupErrorMessage(OUString const & aErrorMessage)
309 {
310     OUStringBuffer    aDiagnosticMessage( 100 );
311 
312     ResMgr* pResMgr = Desktop::GetDesktopResManager();
313     if ( pResMgr )
314         aDiagnosticMessage.append( OUString(String(ResId(STR_BOOTSTRAP_ERR_CANNOT_START, *pResMgr))) );
315     else
316         aDiagnosticMessage.appendAscii( "The program cannot be started." );
317 
318     aDiagnosticMessage.appendAscii( "\n" );
319 
320     aDiagnosticMessage.append( aErrorMessage );
321 
322     return aDiagnosticMessage.makeStringAndClear();
323 }
324 
MakeStartupConfigAccessErrorMessage(OUString const & aInternalErrMsg)325 OUString MakeStartupConfigAccessErrorMessage( OUString const & aInternalErrMsg )
326 {
327     OUStringBuffer aDiagnosticMessage( 200 );
328 
329     ResMgr* pResMgr = Desktop::GetDesktopResManager();
330     if ( pResMgr )
331         aDiagnosticMessage.append( OUString(String(ResId(STR_BOOTSTRAP_ERR_CFG_DATAACCESS, *pResMgr ))) );
332     else
333         aDiagnosticMessage.appendAscii( "The program cannot be started." );
334 
335     if ( aInternalErrMsg.getLength() > 0 )
336     {
337         aDiagnosticMessage.appendAscii( "\n\n" );
338         if ( pResMgr )
339             aDiagnosticMessage.append( OUString(String(ResId(STR_INTERNAL_ERRMSG, *pResMgr ))) );
340         else
341             aDiagnosticMessage.appendAscii( "The following internal error has occurred:\n\n" );
342         aDiagnosticMessage.append( aInternalErrMsg );
343     }
344 
345     return aDiagnosticMessage.makeStringAndClear();
346 }
347 
348 //=============================================================================
349 // shows a simple error box with the given message ... but exits from these process !
350 //
351 // Fatal errors can't be solved by the process ... nor any recovery can help.
352 // Mostly the installation was damaged and must be repaired manually .. or by calling
353 // setup again.
354 //
355 // On the other side we must make sure that no further actions will be possible within
356 // the current office process ! No pipe requests, no menu/toolbar/shortcut actions
357 // are allowed. Otherwise we will force a "crash inside a crash".
358 //
359 // That's why we have to use a special native message box here which does not use yield :-)
360 //=============================================================================
FatalError(const::rtl::OUString & sMessage,const sal_Bool isDisplayErrorString)361 void FatalError(const ::rtl::OUString& sMessage, const sal_Bool isDisplayErrorString)
362 {
363     ::rtl::OUString sProductKey = ::utl::Bootstrap::getProductKey();
364     if ( ! sProductKey.getLength())
365     {
366         ::vos::OStartupInfo aInfo;
367         aInfo.getExecutableFile( sProductKey );
368 
369         ::sal_uInt32 nLastIndex = sProductKey.lastIndexOf('/');
370         if ( nLastIndex > 0 )
371             sProductKey = sProductKey.copy( nLastIndex+1 );
372     }
373 
374     ::rtl::OUStringBuffer sTitle (128);
375     sTitle.append      (sProductKey     );
376     if (isDisplayErrorString) {
377         sTitle.appendAscii (" - Fatal Error");
378     }
379     Application::ShowNativeErrorBox (sTitle.makeStringAndClear (), sMessage);
380     _exit(ExitHelper::E_FATAL_ERROR);
381 }
382 
ShouldSuppressUI(CommandLineArgs * pCmdLine)383 static bool ShouldSuppressUI(CommandLineArgs* pCmdLine)
384 {
385     return  pCmdLine->IsInvisible() ||
386             pCmdLine->IsHeadless() ||
387             pCmdLine->IsQuickstart();
388 }
389 
GetCommandLineArgs()390 CommandLineArgs* Desktop::GetCommandLineArgs()
391 {
392     static CommandLineArgs* pArgs = 0;
393     if ( !pArgs )
394     {
395         ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
396         if ( !pArgs )
397             pArgs = new CommandLineArgs;
398     }
399 
400     return pArgs;
401 }
402 
InitConfiguration()403 sal_Bool InitConfiguration()
404 {
405     RTL_LOGFILE_CONTEXT( aLog, "desktop (jb99855) ::InitConfiguration" );
406 
407     Reference< XMultiServiceFactory > xProvider( CreateApplicationConfigurationProvider( ) );
408     return xProvider.is();
409 }
410 
411 namespace
412 {
413     struct BrandName
414         : public rtl::Static< String, BrandName > {};
415     struct FullProductname
416         : public rtl::Static< String, FullProductname > {};
417     struct Version
418         : public rtl::Static< String, Version > {};
419     struct AboutBoxVersion
420         : public rtl::Static< String, AboutBoxVersion > {};
421     struct OOOVendor
422         : public rtl::Static< String, OOOVendor > {};
423     struct Extension
424         : public rtl::Static< String, Extension > {};
425     struct XMLFileFormatName
426         : public rtl::Static< String, XMLFileFormatName > {};
427     struct XMLFileFormatVersion
428         : public rtl::Static< String, XMLFileFormatVersion > {};
429     struct WriterCompatibilityVersionOOo11
430         : public rtl::Static< String, WriterCompatibilityVersionOOo11 > {};
431 }
432 
ReplaceStringHookProc(UniString & rStr)433 void ReplaceStringHookProc( UniString& rStr )
434 {
435     static int nAll = 0, nPro = 0;
436 
437     nAll++;
438     if ( ( rStr.SearchAscii( "%PRODUCT" ) != STRING_NOTFOUND ) ||
439          ( rStr.SearchAscii( "%FULLPRODUCT" ) != STRING_NOTFOUND ) )
440     {
441         String &rBrandName = BrandName::get();
442         String& rFullProductname = FullProductname::get();
443         String &rVersion = Version::get();
444         String &rAboutBoxVersion = AboutBoxVersion::get();
445         String &rExtension = Extension::get();
446         String &rXMLFileFormatName = XMLFileFormatName::get();
447         String &rXMLFileFormatVersion = XMLFileFormatVersion::get();
448 
449         if ( !rBrandName.Len() )
450         {
451             rtl::OUString aTmp;
452             Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTNAME );
453             aRet >>= aTmp;
454             rBrandName = aTmp;
455 
456             aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::FULLPRODUCTNAME );
457             aRet >>= aTmp;
458             rFullProductname = aTmp;
459 
460             aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTXMLFILEFORMATNAME );
461             aRet >>= aTmp;
462             rXMLFileFormatName = aTmp;
463 
464             aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTXMLFILEFORMATVERSION );
465             aRet >>= aTmp;
466             rXMLFileFormatVersion = aTmp;
467 
468             aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTVERSION );
469             aRet >>= aTmp;
470             rVersion = aTmp;
471 
472             aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::ABOUTBOXPRODUCTVERSION );
473             aRet >>= aTmp;
474             rAboutBoxVersion = aTmp;
475 
476             if ( !rExtension.Len() )
477             {
478                 aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::PRODUCTEXTENSION );
479                 aRet >>= aTmp;
480                 rExtension = aTmp;
481             }
482         }
483 
484         nPro++;
485         rStr.SearchAndReplaceAllAscii( "%PRODUCTNAME", rBrandName );
486         rStr.SearchAndReplaceAllAscii( "%FULLPRODUCTNAME", rFullProductname );
487         rStr.SearchAndReplaceAllAscii( "%PRODUCTVERSION", rVersion );
488         rStr.SearchAndReplaceAllAscii( "%ABOUTBOXPRODUCTVERSION", rAboutBoxVersion );
489         rStr.SearchAndReplaceAllAscii( "%PRODUCTEXTENSION", rExtension );
490         rStr.SearchAndReplaceAllAscii( "%PRODUCTXMLFILEFORMATNAME", rXMLFileFormatName );
491         rStr.SearchAndReplaceAllAscii( "%PRODUCTXMLFILEFORMATVERSION", rXMLFileFormatVersion );
492     }
493     if ( rStr.SearchAscii( "%OOOVENDOR" ) != STRING_NOTFOUND )
494     {
495         String &rOOOVendor = OOOVendor::get();
496 
497         if ( !rOOOVendor.Len() )
498         {
499             rtl::OUString aTmp;
500             Any aRet = ::utl::ConfigManager::GetDirectConfigProperty(
501                     ::utl::ConfigManager::OOOVENDOR );
502             aRet >>= aTmp;
503             rOOOVendor = aTmp;
504 
505         }
506         rStr.SearchAndReplaceAllAscii( "%OOOVENDOR" ,rOOOVendor );
507     }
508 
509     if ( rStr.SearchAscii( "%WRITERCOMPATIBILITYVERSIONOOO11" ) != STRING_NOTFOUND )
510     {
511         String &rWriterCompatibilityVersionOOo11 = WriterCompatibilityVersionOOo11::get();
512         if ( !rWriterCompatibilityVersionOOo11.Len() )
513         {
514             rtl::OUString aTmp;
515             Any aRet = ::utl::ConfigManager::GetDirectConfigProperty(
516                     ::utl::ConfigManager::WRITERCOMPATIBILITYVERSIONOOO11 );
517             aRet >>= aTmp;
518             rWriterCompatibilityVersionOOo11 = aTmp;
519         }
520 
521         rStr.SearchAndReplaceAllAscii( "%WRITERCOMPATIBILITYVERSIONOOO11",
522                                         rWriterCompatibilityVersionOOo11 );
523     }
524 }
525 
526 static const char      pLastSyncFileName[]     = "lastsynchronized";
527 static const sal_Int32 nStrLenLastSync         = 16;
528 
needsSynchronization(::rtl::OUString const & baseSynchronizedURL,::rtl::OUString const & userSynchronizedURL)529 static bool needsSynchronization(
530     ::rtl::OUString const & baseSynchronizedURL, ::rtl::OUString const & userSynchronizedURL )
531 {
532     bool bNeedsSync( false );
533 
534     ::osl::DirectoryItem itemUserFile;
535     ::osl::File::RC err1 =
536           ::osl::DirectoryItem::get(userSynchronizedURL, itemUserFile);
537 
538     //If it does not exist, then there is nothing to be done
539     if (err1 == ::osl::File::E_NOENT)
540     {
541         return true;
542     }
543     else if (err1 != ::osl::File::E_None)
544     {
545         OSL_ENSURE(0, "Cannot access lastsynchronized in user layer");
546         return true; //sync just in case
547     }
548 
549     //If last synchronized does not exist in base layer, then do nothing
550     ::osl::DirectoryItem itemBaseFile;
551     ::osl::File::RC err2 = ::osl::DirectoryItem::get(baseSynchronizedURL, itemBaseFile);
552     if (err2 == ::osl::File::E_NOENT)
553     {
554         return true;
555 
556     }
557     else if (err2 != ::osl::File::E_None)
558     {
559         OSL_ENSURE(0, "Cannot access file lastsynchronized in base layer");
560         return true; //sync just in case
561     }
562 
563     //compare the modification time of the extension folder and the last
564     //modified file
565     ::osl::FileStatus statUser(FileStatusMask_ModifyTime);
566     ::osl::FileStatus statBase(FileStatusMask_ModifyTime);
567     if (itemUserFile.getFileStatus(statUser) == ::osl::File::E_None)
568     {
569         if (itemBaseFile.getFileStatus(statBase) == ::osl::File::E_None)
570         {
571             TimeValue timeUser = statUser.getModifyTime();
572             TimeValue timeBase = statBase.getModifyTime();
573 
574             if (timeUser.Seconds < timeBase.Seconds)
575                 bNeedsSync = true;
576         }
577         else
578         {
579             OSL_ASSERT(0);
580             bNeedsSync = true;
581         }
582     }
583     else
584     {
585         OSL_ASSERT(0);
586         bNeedsSync = true;
587     }
588 
589     return bNeedsSync;
590 }
591 
getBrandSharePreregBundledPathURL()592 static ::rtl::OUString getBrandSharePreregBundledPathURL()
593 {
594     ::rtl::OUString url(
595         RTL_CONSTASCII_USTRINGPARAM("$OOO_BASE_DIR/share/prereg/bundled"));
596 
597     ::rtl::Bootstrap::expandMacros(url);
598     return url;
599 }
600 
getUserBundledExtPathURL()601 static ::rtl::OUString getUserBundledExtPathURL()
602 {
603     ::rtl::OUString folder( RTL_CONSTASCII_USTRINGPARAM( "$BUNDLED_EXTENSIONS_USER" ));
604     ::rtl::Bootstrap::expandMacros(folder);
605 
606     return folder;
607 }
608 
getLastSyncFileURLFromBrandInstallation()609 static ::rtl::OUString getLastSyncFileURLFromBrandInstallation()
610 {
611     ::rtl::OUString aURL = getBrandSharePreregBundledPathURL();
612     ::sal_Int32    nLastIndex         = aURL.lastIndexOf('/');
613 
614     ::rtl::OUStringBuffer aTmp( aURL );
615 
616     if ( nLastIndex != aURL.getLength()-1 )
617         aTmp.appendAscii( "/" );
618     aTmp.appendAscii( pLastSyncFileName );
619 
620     return aTmp.makeStringAndClear();
621 }
622 
getLastSyncFileURLFromUserInstallation()623 static ::rtl::OUString getLastSyncFileURLFromUserInstallation()
624 {
625     ::rtl::OUString aUserBundledPathURL = getUserBundledExtPathURL();
626     ::sal_Int32    nLastIndex          = aUserBundledPathURL.lastIndexOf('/');
627 
628     ::rtl::OUStringBuffer aTmp( aUserBundledPathURL );
629 
630     if ( nLastIndex != aUserBundledPathURL.getLength()-1 )
631         aTmp.appendAscii( "/" );
632     aTmp.appendAscii( pLastSyncFileName );
633 
634     return aTmp.makeStringAndClear();
635 }
636 //Checks if the argument src is the folder of the help or configuration
637 //backend in the prereg folder
excludeTmpFilesAndFolders(const rtl::OUString & src)638 static bool excludeTmpFilesAndFolders(const rtl::OUString & src)
639 {
640     const char helpBackend[] = "com.sun.star.comp.deployment.help.PackageRegistryBackend";
641     const char configBackend[] = "com.sun.star.comp.deployment.configuration.PackageRegistryBackend";
642     if (src.endsWithAsciiL(helpBackend, sizeof(helpBackend) - 1 )
643         || src.endsWithAsciiL(configBackend, sizeof(configBackend) - 1))
644     {
645         return true;
646     }
647     return false;
648 }
649 
650 //If we are about to copy the contents of some special folder as determined
651 //by excludeTmpFilesAndFolders, then we omit those files or folders with a name
652 //derived from temporary folders.
isExcludedFileOrFolder(const rtl::OUString & name)653 static bool isExcludedFileOrFolder( const rtl::OUString & name)
654 {
655     char const * allowed[] = {
656         "backenddb.xml",
657         "configmgr.ini",
658         "registered_packages.db"
659     };
660 
661     const unsigned int size = sizeof(allowed) / sizeof (char const *);
662     bool bExclude = true;
663     for (unsigned int i= 0; i < size; i ++)
664     {
665         ::rtl::OUString allowedName = ::rtl::OUString::createFromAscii(allowed[i]);
666         if (allowedName.equals(name))
667         {
668             bExclude = false;
669             break;
670         }
671     }
672     return bExclude;
673 }
674 
copy_prereg_bundled_recursive(const rtl::OUString & srcUnqPath,const rtl::OUString & dstUnqPath,sal_Int32 TypeToCopy)675 static osl::FileBase::RC copy_prereg_bundled_recursive(
676     const rtl::OUString& srcUnqPath,
677     const rtl::OUString& dstUnqPath,
678     sal_Int32            TypeToCopy )
679 throw()
680 {
681     osl::FileBase::RC err = osl::FileBase::E_None;
682 
683     if( TypeToCopy == -1 ) // Document
684     {
685         err = osl::File::copy( srcUnqPath,dstUnqPath );
686     }
687     else if( TypeToCopy == +1 ) // Folder
688     {
689         osl::Directory aDir( srcUnqPath );
690         err = aDir.open();
691         if ( err != osl::FileBase::E_None )
692             return err;
693 
694         err = osl::Directory::create( dstUnqPath );
695         osl::FileBase::RC next = err;
696         if( err == osl::FileBase::E_None ||
697             err == osl::FileBase::E_EXIST )
698         {
699             err = osl::FileBase::E_None;
700             sal_Int32 n_Mask = FileStatusMask_FileURL | FileStatusMask_FileName | FileStatusMask_Type;
701 
702             osl::DirectoryItem aDirItem;
703             bool bExcludeFiles = excludeTmpFilesAndFolders(srcUnqPath);
704 
705             while( err == osl::FileBase::E_None && ( next = aDir.getNextItem( aDirItem ) ) == osl::FileBase::E_None )
706             {
707                 sal_Bool IsDoc = false;
708                 sal_Bool bFilter = false;
709                 osl::FileStatus aFileStatus( n_Mask );
710                 aDirItem.getFileStatus( aFileStatus );
711                 if( aFileStatus.isValid( FileStatusMask_Type ) )
712                     IsDoc = aFileStatus.getFileType() == osl::FileStatus::Regular;
713 
714                 // Getting the information for the next recursive copy
715                 sal_Int32 newTypeToCopy = IsDoc ? -1 : +1;
716 
717                 rtl::OUString newSrcUnqPath;
718                 if( aFileStatus.isValid( FileStatusMask_FileURL ) )
719                     newSrcUnqPath = aFileStatus.getFileURL();
720 
721                 rtl::OUString newDstUnqPath = dstUnqPath;
722                 rtl::OUString tit;
723                 if( aFileStatus.isValid( FileStatusMask_FileName ) )
724                 {
725                     ::rtl::OUString aFileName = aFileStatus.getFileName();
726                     tit = rtl::Uri::encode( aFileName,
727                                             rtl_UriCharClassPchar,
728                                             rtl_UriEncodeIgnoreEscapes,
729                                             RTL_TEXTENCODING_UTF8 );
730 
731                     // Special treatment for "lastsychronized" file. Must not be
732                     // copied from the bundled folder!
733                     //Also do not copy *.tmp files and *.tmp_ folders. This affects the files/folders
734                     //from the help and configuration backend
735                     if ( IsDoc && (aFileName.equalsAscii( pLastSyncFileName )
736                                    || bExcludeFiles && isExcludedFileOrFolder(aFileName)))
737                         bFilter = true;
738                     else if (!IsDoc && bExcludeFiles && isExcludedFileOrFolder(aFileName))
739                         bFilter = true;
740                 }
741 
742                 if( newDstUnqPath.lastIndexOf( sal_Unicode('/') ) != newDstUnqPath.getLength()-1 )
743                     newDstUnqPath += rtl::OUString::createFromAscii( "/" );
744 
745                 newDstUnqPath += tit;
746 
747                 if (( newSrcUnqPath != dstUnqPath ) && !bFilter )
748                     err = copy_prereg_bundled_recursive( newSrcUnqPath,newDstUnqPath, newTypeToCopy );
749             }
750 
751             if( err == osl::FileBase::E_None && next != osl::FileBase::E_NOENT )
752                 err = next;
753         }
754         aDir.close();
755     }
756 
757     return err;
758 }
759 
760 
761 //====================================================================================
762 
763 // MinimalCommandEnv: a tribute owed to ExtensionManager being an UNO stronghold
764 class MinimalCommandEnv
765     : public ::cppu::WeakImplHelper3< css::ucb::XCommandEnvironment,
766                                       css::task::XInteractionHandler,
767                                       css::ucb::XProgressHandler >
768 {
769 public:
770     // XCommandEnvironment
getInteractionHandler()771     virtual css::uno::Reference< css::task::XInteractionHandler> SAL_CALL getInteractionHandler()
772     { return this;}
getProgressHandler()773     virtual css::uno::Reference< css::ucb::XProgressHandler> SAL_CALL getProgressHandler()
774     { return this;}
775 
776     // XInteractionHandler
777     virtual void SAL_CALL handle( const css::uno::Reference< css::task::XInteractionRequest>&);
778 
779     // XProgressHandler
push(const css::uno::Any &)780     virtual void SAL_CALL push( const css::uno::Any& /*Status*/)
781     {}
update(const css::uno::Any &)782     virtual void SAL_CALL update( const css::uno::Any& /*Status*/)
783     {}
pop()784     virtual void SAL_CALL pop()
785     {}
786 };
787 
788 // MinimalCommandEnv's XInteractionHandler simply approves
handle(css::uno::Reference<css::task::XInteractionRequest> const & xRequest)789 void MinimalCommandEnv::handle(
790     css::uno::Reference< css::task::XInteractionRequest> const& xRequest)
791 {
792     bool bApprove = true;
793 
794     css::deployment::VersionException verExc;
795     if ( xRequest->getRequest() >>= verExc )
796     {
797         // choose newest version, if an extension is already been installed.
798         const bool bChooseNewestVersion = true;
799         bApprove = handleVersionException( verExc, 0, bChooseNewestVersion );
800     }
801 
802     const css::uno::Sequence< css::uno::Reference< css::task::XInteractionContinuation > > conts( xRequest->getContinuations());
803     const css::uno::Reference< css::task::XInteractionContinuation>* pConts = conts.getConstArray();
804     const sal_Int32 len = conts.getLength();
805     for( sal_Int32 pos = 0; pos < len; ++pos )
806     {
807         if ( bApprove )
808         {
809             css::uno::Reference< css::task::XInteractionApprove> xInteractionApprove( pConts[ pos ], css::uno::UNO_QUERY);
810             if( xInteractionApprove.is())
811             {
812                 xInteractionApprove->select();
813                 // don't query again for ongoing continuations:
814                 break;
815             }
816         }
817         else
818         {
819             css::uno::Reference< css::task::XInteractionAbort > xInteractionAbort( pConts[ pos ], css::uno::UNO_QUERY );
820             if (xInteractionAbort.is())
821             {
822                 xInteractionAbort->select();
823                 // don't query again for ongoing continuations:
824                 break;
825             }
826         }
827     }
828 }
829 
830 
831 /** Check if installBundledExtensionBlobs() has to be run.
832     It uses the time stamps of a marker file (rsMarkerURL) on the one
833     hand and of the files in the given directory on the other.
834     Returns </TRUE> when either the marker does not yet exist or any
835     file in the given directory is newer than the marker.
836 */
needsInstallBundledExtensionBlobs(const::rtl::OUString & rsMarkerURL,const::rtl::OUString & rsDirectoryURL)837 static bool needsInstallBundledExtensionBlobs (
838     const ::rtl::OUString& rsMarkerURL,
839     const ::rtl::OUString& rsDirectoryURL)
840 {
841     ::osl::DirectoryItem aMarkerItem;
842     if (::osl::DirectoryItem::get(rsMarkerURL, aMarkerItem) == ::osl::File::E_NOENT)
843     {
844         // Marker does not exist.  Extensions where never installed.
845         return true;
846     }
847 
848     ::osl::FileStatus aMarkerStat (FileStatusMask_ModifyTime);
849     if (aMarkerItem.getFileStatus(aMarkerStat) != ::osl::File::E_None)
850     {
851         // Can not get marker state.  Reason?
852         return true;
853     }
854 
855     const TimeValue aMarkerModifyTime (aMarkerStat.getModifyTime());
856 
857     ::osl::Directory aDirectory (rsDirectoryURL);
858     if (aDirectory.open() != osl::File::E_None)
859     {
860         // No extension directory.  Nothing to be done.
861         return false;
862     }
863 
864     // Check the date of each extension in the given directory.  If
865     // any of them is newer than the marker file then an installation
866     // is necessary.
867     ::osl::DirectoryItem aDirectoryItem;
868     while (aDirectory.getNextItem(aDirectoryItem) == osl::File::E_None)
869     {
870         ::osl::FileStatus aFileStat (FileStatusMask_ModifyTime);
871         if (aDirectoryItem.getFileStatus(aFileStat) != ::osl::File::E_None)
872             continue;
873         if (aFileStat.getFileType() != ::osl::FileStatus::Regular)
874             continue;
875         if (aFileStat.getModifyTime().Seconds > aMarkerModifyTime.Seconds)
876         {
877             aDirectory.close();
878             return true;
879         }
880     }
881     aDirectory.close();
882 
883     // Also check the last modification time of the containing
884     // directory.  This ensures installation after an update of
885     // OpenOffice.  Without it the extensions have the date on which
886     // they where built, not the date on which they where installed.
887     if (::osl::DirectoryItem::get(rsDirectoryURL, aDirectoryItem) == osl::File::E_None)
888     {
889         ::osl::FileStatus aDirectoryStat (FileStatusMask_ModifyTime);
890         const ::osl::FileBase::RC eResult (aDirectoryItem.getFileStatus(aDirectoryStat));
891         if (eResult == ::osl::File::E_None)
892         {
893             if (aDirectoryStat.getModifyTime().Seconds > aMarkerModifyTime.Seconds)
894                 return true;
895         }
896     }
897 
898     // No file in the directory is newer than the marker.
899     return false;
900 }
901 
902 
903 // install bundled but non-pre-registered extension blobs
installBundledExtensionBlobs()904 static void installBundledExtensionBlobs()
905 {
906     rtl::OUString aDirUrl( OUSTR("$OOO_BASE_DIR/share/extensions/install"));
907     ::rtl::Bootstrap::expandMacros( aDirUrl);
908 
909     // Find out if we can exit early: only when there is an extension file newer
910     // than the marker we have to install any extension.
911     ::rtl::OUString sMarkerURL (RTL_CONSTASCII_USTRINGPARAM("$BUNDLED_EXTENSIONS_USER/lastsynchronized.bundled"));
912     ::rtl::Bootstrap::expandMacros(sMarkerURL);
913     if ( ! needsInstallBundledExtensionBlobs(sMarkerURL, aDirUrl))
914         return;
915     writeLastModified(sMarkerURL);
916 
917     // get the ExtensionManager
918     ::css::uno::Reference< ::css::uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
919     ::css::uno::Reference< ::css::deployment::XExtensionManager> xEM = ::css::deployment::ExtensionManager::get( xContext);
920     // provide the minimal set of requirements to call ExtensionManager's methods
921     MinimalCommandEnv* pMiniCmdEnv = new MinimalCommandEnv;
922     ::css::uno::Reference< css::ucb::XCommandEnvironment> xCmdEnv( static_cast< cppu::OWeakObject*>(pMiniCmdEnv), css::uno::UNO_QUERY);
923     ::css::uno::Reference< ::css::task::XAbortChannel> xAbortChannel;
924 
925     const ::css::beans::NamedValue aNamedProps( OUSTR("SUPPRESS_LICENSE"), ::css::uno::makeAny( OUSTR("1")));
926     const ::css::uno::Sequence< ::css::beans::NamedValue> xProperties( &aNamedProps, 1);
927 
928     // iterate over the bundled extension blobs
929     ::osl::Directory aDir( aDirUrl);
930     ::osl::File::RC rc = aDir.open();
931     while( rc == osl::File::E_None)
932     {
933         ::osl::DirectoryItem aDI;
934         if( aDir.getNextItem( aDI) != osl::File::E_None)
935             break;
936         ::osl::FileStatus aFileStat( FileStatusMask_Type | FileStatusMask_FileURL);
937         if( aDI.getFileStatus( aFileStat) != ::osl::File::E_None)
938             continue;
939         if( aFileStat.getFileType() != ::osl::FileStatus::Regular)
940             continue;
941         try
942         {
943             // request to install the extension blob
944             xEM->addExtension( aFileStat.getFileURL(), xProperties, OUSTR("user"), xAbortChannel, xCmdEnv);
945         }
946         // ExtensionManager problems are not worth to die for here
947         catch( css::uno::RuntimeException&)
948         {}
949         catch( css::deployment::DeploymentException&)
950         {}
951         catch ( css::ucb::CommandFailedException& )
952         {
953         }
954         catch ( css::ucb::CommandAbortedException& )
955         {
956         }
957         catch ( css::lang::IllegalArgumentException& )
958         {
959         }
960     }
961 }
962 
963 //=============================================================================
964 
Desktop()965 Desktop::Desktop()
966 : m_bServicesRegistered( false )
967 , m_aBootstrapError( BE_OK )
968 , m_pLockfile( NULL )
969 {
970     RTL_LOGFILE_TRACE( "desktop (cd100003) ::Desktop::Desktop" );
971 }
972 
~Desktop()973 Desktop::~Desktop()
974 {
975 }
976 
Init()977 void Desktop::Init()
978 {
979     RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::Init" );
980     SetBootstrapStatus(BS_OK);
981 
982     // Check for lastsynchronized file for pre-registered bundled extensions in the user directory
983     // and test if synchronization is necessary!
984     {
985         ::rtl::OUString aUserLastSyncFilePathURL = getLastSyncFileURLFromUserInstallation();
986         ::rtl::OUString aPreregSyncFilePathURL = getLastSyncFileURLFromBrandInstallation();
987 
988         if ( needsSynchronization( aPreregSyncFilePathURL, aUserLastSyncFilePathURL ))
989         {
990             rtl::OUString aUserPath = getUserBundledExtPathURL();
991             rtl::OUString aPreregBundledPath = getBrandSharePreregBundledPathURL();
992 
993             // copy bundled folder to the user directory
994             osl::FileBase::RC rc = osl::Directory::createPath(aUserPath);
995             (void) rc;
996             copy_prereg_bundled_recursive( aPreregBundledPath, aUserPath, +1 );
997         }
998     }
999 
1000     // create service factory...
1001     Reference < XMultiServiceFactory > rSMgr = CreateApplicationServiceManager();
1002     if( rSMgr.is() )
1003     {
1004         ::comphelper::setProcessServiceFactory( rSMgr );
1005     }
1006     else
1007     {
1008         SetBootstrapError( BE_UNO_SERVICEMANAGER );
1009     }
1010 
1011     if ( GetBootstrapError() == BE_OK )
1012     {
1013         // prepare language
1014         if ( !LanguageSelection::prepareLanguage() )
1015         {
1016             if ( LanguageSelection::getStatus() == LanguageSelection::LS_STATUS_CANNOT_DETERMINE_LANGUAGE )
1017                 SetBootstrapError( BE_LANGUAGE_MISSING );
1018             else
1019                 SetBootstrapError( BE_OFFICECONFIG_BROKEN );
1020         }
1021     }
1022 
1023     if ( GetBootstrapError() == BE_OK )
1024     {
1025         CommandLineArgs* pCmdLineArgs = GetCommandLineArgs();
1026 #ifdef UNX
1027     //  check whether we need to print cmdline help
1028     if ( pCmdLineArgs->IsHelp() ) {
1029         displayCmdlineHelp();
1030         SetBootstrapStatus(BS_TERMINATE);
1031     }
1032 #endif
1033         // start ipc thread only for non-remote offices
1034         RTL_LOGFILE_CONTEXT( aLog2, "desktop (cd100003) ::OfficeIPCThread::EnableOfficeIPCThread" );
1035         OfficeIPCThread::Status aStatus = OfficeIPCThread::EnableOfficeIPCThread();
1036         if ( aStatus == OfficeIPCThread::IPC_STATUS_BOOTSTRAP_ERROR )
1037         {
1038             SetBootstrapError( BE_PATHINFO_MISSING );
1039 
1040         }
1041         else if ( aStatus == OfficeIPCThread::IPC_STATUS_MULTI_TS_ERROR )
1042         {
1043             SetBootstrapError( BE_MUTLISESSION_NOT_SUPPROTED );
1044         }
1045         else if ( aStatus == OfficeIPCThread::IPC_STATUS_2ND_OFFICE )
1046         {
1047             // 2nd office startup should terminate after sending cmdlineargs through pipe
1048             SetBootstrapStatus(BS_TERMINATE);
1049         }
1050         else if ( pCmdLineArgs->IsHelp() )
1051         {
1052             // disable IPC thread in an instance that is just showing a help message
1053             OfficeIPCThread::DisableOfficeIPCThread();
1054         }
1055         pSignalHandler = new SalMainPipeExchangeSignalHandler;
1056     }
1057 }
1058 
DeInit()1059 void Desktop::DeInit()
1060 {
1061     RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::DeInit" );
1062 
1063     try {
1064         // instead of removing of the configManager just let it commit all the changes
1065         RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" );
1066         utl::ConfigManager::GetConfigManager()->StoreConfigItems();
1067         FlushConfiguration();
1068         RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" );
1069 
1070         // close splashscreen if it's still open
1071         CloseSplashScreen();
1072         Reference<XMultiServiceFactory> xXMultiServiceFactory(::comphelper::getProcessServiceFactory());
1073         DestroyApplicationServiceManager( xXMultiServiceFactory );
1074         // nobody should get a destroyd service factory...
1075         ::comphelper::setProcessServiceFactory( NULL );
1076 
1077         // clear lockfile
1078         if (m_pLockfile != NULL)
1079             m_pLockfile->clean();
1080 
1081         OfficeIPCThread::DisableOfficeIPCThread();
1082         if( pSignalHandler )
1083             DELETEZ( pSignalHandler );
1084     } catch (RuntimeException&) {
1085         // someone threw an exception during shutdown
1086         // this will leave some garbage behind..
1087     }
1088 
1089     RTL_LOGFILE_CONTEXT_TRACE( aLog, "FINISHED WITH Destop::DeInit" );
1090 }
1091 
QueryExit()1092 sal_Bool Desktop::QueryExit()
1093 {
1094     try
1095     {
1096         RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" );
1097         utl::ConfigManager::GetConfigManager()->StoreConfigItems();
1098         RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- store config items" );
1099     }
1100     catch ( RuntimeException& )
1101     {
1102     }
1103 
1104     const sal_Char SUSPEND_QUICKSTARTVETO[] = "SuspendQuickstartVeto";
1105 
1106     Reference< ::com::sun::star::frame::XDesktop >
1107             xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ),
1108                 UNO_QUERY );
1109 
1110     Reference < ::com::sun::star::beans::XPropertySet > xPropertySet( xDesktop, UNO_QUERY );
1111     if ( xPropertySet.is() )
1112     {
1113         Any a;
1114         a <<= (sal_Bool)sal_True;
1115         xPropertySet->setPropertyValue( OUSTRING(RTL_CONSTASCII_USTRINGPARAM( SUSPEND_QUICKSTARTVETO )), a );
1116     }
1117 
1118     sal_Bool bExit = ( !xDesktop.is() || xDesktop->terminate() );
1119 
1120 
1121     if ( !bExit && xPropertySet.is() )
1122     {
1123         Any a;
1124         a <<= (sal_Bool)sal_False;
1125         xPropertySet->setPropertyValue( OUSTRING(RTL_CONSTASCII_USTRINGPARAM( SUSPEND_QUICKSTARTVETO )), a );
1126     }
1127     else
1128     {
1129         FlushConfiguration();
1130         try
1131         {
1132             // it is no problem to call DisableOfficeIPCThread() more than once
1133             // it also looks to be threadsafe
1134             OfficeIPCThread::DisableOfficeIPCThread();
1135         }
1136         catch ( RuntimeException& )
1137         {
1138         }
1139 
1140         if (m_pLockfile != NULL) m_pLockfile->clean();
1141     }
1142 
1143     return bExit;
1144 }
1145 
HandleBootstrapPathErrors(::utl::Bootstrap::Status aBootstrapStatus,const OUString & aDiagnosticMessage)1146 void Desktop::HandleBootstrapPathErrors( ::utl::Bootstrap::Status aBootstrapStatus, const OUString& aDiagnosticMessage )
1147 {
1148     if ( aBootstrapStatus != ::utl::Bootstrap::DATA_OK )
1149     {
1150         sal_Bool            bWorkstationInstallation = sal_False;
1151         ::rtl::OUString        aBaseInstallURL;
1152         ::rtl::OUString        aUserInstallURL;
1153         ::rtl::OUString        aProductKey;
1154         ::rtl::OUString        aTemp;
1155         ::vos::OStartupInfo aInfo;
1156 
1157         aInfo.getExecutableFile( aProductKey );
1158         sal_uInt32     lastIndex = aProductKey.lastIndexOf('/');
1159         if ( lastIndex > 0 )
1160             aProductKey = aProductKey.copy( lastIndex+1 );
1161 
1162         aTemp = ::utl::Bootstrap::getProductKey( aProductKey );
1163         if ( aTemp.getLength() > 0 )
1164             aProductKey = aTemp;
1165 
1166         ::utl::Bootstrap::PathStatus aBaseInstallStatus = ::utl::Bootstrap::locateBaseInstallation( aBaseInstallURL );
1167         ::utl::Bootstrap::PathStatus aUserInstallStatus = ::utl::Bootstrap::locateUserInstallation( aUserInstallURL );
1168 
1169         if (( aBaseInstallStatus == ::utl::Bootstrap::PATH_EXISTS &&
1170               aUserInstallStatus == ::utl::Bootstrap::PATH_EXISTS        ))
1171         {
1172             if ( aBaseInstallURL != aUserInstallURL )
1173                 bWorkstationInstallation = sal_True;
1174         }
1175 
1176         OUString        aMessage;
1177         OUStringBuffer    aBuffer( 100 );
1178         aBuffer.append( aDiagnosticMessage );
1179 
1180         aBuffer.appendAscii( "\n" );
1181 
1182         ErrorBox aBootstrapFailedBox( NULL, WB_OK, aMessage );
1183         aBootstrapFailedBox.SetText( aProductKey );
1184         aBootstrapFailedBox.Execute();
1185     }
1186 }
1187 
1188 // Create a error message depending on bootstrap failure code and an optional file url
CreateErrorMsgString(utl::Bootstrap::FailureCode nFailureCode,const::rtl::OUString & aFileURL)1189 ::rtl::OUString    Desktop::CreateErrorMsgString(
1190     utl::Bootstrap::FailureCode nFailureCode,
1191     const ::rtl::OUString& aFileURL )
1192 {
1193     OUString        aMsg;
1194     OUString        aFilePath;
1195     sal_Bool        bFileInfo = sal_True;
1196 
1197     switch ( nFailureCode )
1198     {
1199         /// the shared installation directory could not be located
1200         case ::utl::Bootstrap::MISSING_INSTALL_DIRECTORY:
1201         {
1202             aMsg = GetMsgString( STR_BOOTSTRAP_ERR_PATH_INVALID,
1203                         OUString( RTL_CONSTASCII_USTRINGPARAM( "The installation path is not available." )) );
1204             bFileInfo = sal_False;
1205         }
1206         break;
1207 
1208         /// the bootstrap INI file could not be found or read
1209         case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE:
1210         {
1211             aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_MISSING,
1212                         OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration file \"$1\" is missing." )) );
1213         }
1214         break;
1215 
1216         /// the bootstrap INI is missing a required entry
1217         /// the bootstrap INI contains invalid data
1218          case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY:
1219          case ::utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY:
1220         {
1221             aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_CORRUPT,
1222                         OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration file \"$1\" is corrupt." )) );
1223         }
1224         break;
1225 
1226         /// the version locator INI file could not be found or read
1227         case ::utl::Bootstrap::MISSING_VERSION_FILE:
1228         {
1229             aMsg = GetMsgString( STR_BOOTSTRAP_ERR_FILE_MISSING,
1230                         OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration file \"$1\" is missing." )) );
1231         }
1232         break;
1233 
1234         /// the version locator INI has no entry for this version
1235          case ::utl::Bootstrap::MISSING_VERSION_FILE_ENTRY:
1236         {
1237             aMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_SUPPORT,
1238                         OUString( RTL_CONSTASCII_USTRINGPARAM( "The main configuration file \"$1\" does not support the current version." )) );
1239         }
1240         break;
1241 
1242         /// the user installation directory does not exist
1243            case ::utl::Bootstrap::MISSING_USER_DIRECTORY:
1244         {
1245             aMsg = GetMsgString( STR_BOOTSTRAP_ERR_DIR_MISSING,
1246                         OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration directory \"$1\" is missing." )) );
1247         }
1248         break;
1249 
1250         /// some bootstrap data was invalid in unexpected ways
1251         case ::utl::Bootstrap::INVALID_BOOTSTRAP_DATA:
1252         {
1253             aMsg = GetMsgString( STR_BOOTSTRAP_ERR_INTERNAL,
1254                         OUString( RTL_CONSTASCII_USTRINGPARAM( "An internal failure occurred." )) );
1255             bFileInfo = sal_False;
1256         }
1257         break;
1258 
1259         case ::utl::Bootstrap::INVALID_VERSION_FILE_ENTRY:
1260         {
1261             // This needs to be improved, see #i67575#:
1262             aMsg = OUString(
1263                 RTL_CONSTASCII_USTRINGPARAM( "Invalid version file entry" ) );
1264             bFileInfo = sal_False;
1265         }
1266         break;
1267 
1268         case ::utl::Bootstrap::NO_FAILURE:
1269         {
1270             OSL_ASSERT(false);
1271         }
1272         break;
1273     }
1274 
1275     if ( bFileInfo )
1276     {
1277         String aMsgString( aMsg );
1278 
1279         osl::File::getSystemPathFromFileURL( aFileURL, aFilePath );
1280 
1281         aMsgString.SearchAndReplaceAscii( "$1", aFilePath );
1282         aMsg = aMsgString;
1283     }
1284 
1285     return MakeStartupErrorMessage( aMsg );
1286 }
1287 
HandleBootstrapErrors(BootstrapError aBootstrapError)1288 void Desktop::HandleBootstrapErrors( BootstrapError aBootstrapError )
1289 {
1290     if ( aBootstrapError == BE_MUTLISESSION_NOT_SUPPROTED ) {
1291         OUString        aMessage;
1292         aMessage = GetMsgString( STR_BOOTSTRAP_ERR_MULTISESSION,
1293                         OUString( RTL_CONSTASCII_USTRINGPARAM( "You have another instance running in a different terminal session. Close that instance and then try again." )) );
1294         FatalError(aMessage,sal_False);
1295 
1296     } else if ( aBootstrapError == BE_PATHINFO_MISSING )
1297     {
1298         OUString                    aErrorMsg;
1299         OUString                    aBuffer;
1300         utl::Bootstrap::Status        aBootstrapStatus;
1301         utl::Bootstrap::FailureCode    nFailureCode;
1302 
1303         aBootstrapStatus = ::utl::Bootstrap::checkBootstrapStatus( aBuffer, nFailureCode );
1304         if ( aBootstrapStatus != ::utl::Bootstrap::DATA_OK )
1305         {
1306             switch ( nFailureCode )
1307             {
1308                 case ::utl::Bootstrap::MISSING_INSTALL_DIRECTORY:
1309                 case ::utl::Bootstrap::INVALID_BOOTSTRAP_DATA:
1310                 {
1311                     aErrorMsg = CreateErrorMsgString( nFailureCode, OUString() );
1312                 }
1313                 break;
1314 
1315                 /// the bootstrap INI file could not be found or read
1316                 /// the bootstrap INI is missing a required entry
1317                 /// the bootstrap INI contains invalid data
1318                  case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE_ENTRY:
1319                  case ::utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY:
1320                 case ::utl::Bootstrap::MISSING_BOOTSTRAP_FILE:
1321                 {
1322                     OUString aBootstrapFileURL;
1323 
1324                     utl::Bootstrap::locateBootstrapFile( aBootstrapFileURL );
1325                     aErrorMsg = CreateErrorMsgString( nFailureCode, aBootstrapFileURL );
1326                 }
1327                 break;
1328 
1329                 /// the version locator INI file could not be found or read
1330                 /// the version locator INI has no entry for this version
1331                 /// the version locator INI entry is not a valid directory URL
1332                    case ::utl::Bootstrap::INVALID_VERSION_FILE_ENTRY:
1333                  case ::utl::Bootstrap::MISSING_VERSION_FILE_ENTRY:
1334                  case ::utl::Bootstrap::MISSING_VERSION_FILE:
1335                 {
1336                     OUString aVersionFileURL;
1337 
1338                     utl::Bootstrap::locateVersionFile( aVersionFileURL );
1339                     aErrorMsg = CreateErrorMsgString( nFailureCode, aVersionFileURL );
1340                 }
1341                 break;
1342 
1343                 /// the user installation directory does not exist
1344                    case ::utl::Bootstrap::MISSING_USER_DIRECTORY:
1345                 {
1346                     OUString aUserInstallationURL;
1347 
1348                     utl::Bootstrap::locateUserInstallation( aUserInstallationURL );
1349                     aErrorMsg = CreateErrorMsgString( nFailureCode, aUserInstallationURL );
1350                 }
1351                 break;
1352 
1353                 case ::utl::Bootstrap::NO_FAILURE:
1354                 {
1355                     OSL_ASSERT(false);
1356                 }
1357                 break;
1358             }
1359 
1360             HandleBootstrapPathErrors( aBootstrapStatus, aErrorMsg );
1361         }
1362     }
1363     else if ( aBootstrapError == BE_UNO_SERVICEMANAGER || aBootstrapError == BE_UNO_SERVICE_CONFIG_MISSING )
1364     {
1365         // Uno service manager is not available. VCL needs a uno service manager to display a message box!!!
1366         // Currently we are not able to display a message box with a service manager due to this limitations inside VCL.
1367 
1368         // When UNO is not properly initialized, all kinds of things can fail
1369         // and cause the process to crash (e.g., a call to GetMsgString may
1370         // crash when somewhere deep within that call Any::operator <= is used
1371         // with a PropertyValue, and no binary UNO type description for
1372         // PropertyValue is available).  To give the user a hint even if
1373         // generating and displaying a message box below crashes, print a
1374         // hard-coded message on stderr first:
1375         fputs(
1376             aBootstrapError == BE_UNO_SERVICEMANAGER
1377             ? ("The application cannot be started. " "\n"
1378                "The component manager is not available." "\n")
1379                 // STR_BOOTSTRAP_ERR_CANNOT_START, STR_BOOTSTRAP_ERR_NO_SERVICE
1380             : ("The application cannot be started. " "\n"
1381                "The configuration service is not available." "\n"),
1382                 // STR_BOOTSTRAP_ERR_CANNOT_START,
1383                 // STR_BOOTSTRAP_ERR_NO_CFG_SERVICE
1384             stderr);
1385 
1386         // First sentence. We cannot bootstrap office further!
1387         OUString            aMessage;
1388         OUStringBuffer        aDiagnosticMessage( 100 );
1389 
1390         OUString aErrorMsg;
1391 
1392         if ( aBootstrapError == BE_UNO_SERVICEMANAGER )
1393             aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_SERVICE,
1394                             OUString( RTL_CONSTASCII_USTRINGPARAM( "The service manager is not available." )) );
1395         else
1396             aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_NO_CFG_SERVICE,
1397                             OUString( RTL_CONSTASCII_USTRINGPARAM( "The configuration service is not available." )) );
1398 
1399         aDiagnosticMessage.append( aErrorMsg );
1400         aDiagnosticMessage.appendAscii( "\n" );
1401 
1402         // Due to the fact the we haven't a backup applicat.rdb file anymore it is not possible to
1403         // repair the installation with the setup executable besides the office executable. Now
1404         // we have to ask the user to start the setup on CD/installation directory manually!!
1405         OUString aStartSetupManually( GetMsgString(
1406             STR_ASK_START_SETUP_MANUALLY,
1407             OUString( RTL_CONSTASCII_USTRINGPARAM( "Start setup application to repair the installation from CD, or the folder containing the installation packages." )) ));
1408 
1409         aDiagnosticMessage.append( aStartSetupManually );
1410         aMessage = MakeStartupErrorMessage( aDiagnosticMessage.makeStringAndClear() );
1411 
1412         FatalError( aMessage);
1413     }
1414     else if ( aBootstrapError == BE_OFFICECONFIG_BROKEN )
1415     {
1416         OUString aMessage;
1417         OUStringBuffer aDiagnosticMessage( 100 );
1418         OUString aErrorMsg;
1419         aErrorMsg = GetMsgString( STR_CONFIG_ERR_ACCESS_GENERAL,
1420             OUString( RTL_CONSTASCII_USTRINGPARAM( "A general error occurred while accessing your central configuration." )) );
1421         aDiagnosticMessage.append( aErrorMsg );
1422         aMessage = MakeStartupErrorMessage( aDiagnosticMessage.makeStringAndClear() );
1423         FatalError(aMessage);
1424     }
1425     else if ( aBootstrapError == BE_USERINSTALL_FAILED )
1426     {
1427         OUString aMessage;
1428         OUStringBuffer aDiagnosticMessage( 100 );
1429         OUString aErrorMsg;
1430         aErrorMsg = GetMsgString( STR_BOOTSTRAP_ERR_INTERNAL,
1431             OUString( RTL_CONSTASCII_USTRINGPARAM( "User installation could not be completed" )) );
1432         aDiagnosticMessage.append( aErrorMsg );
1433         aMessage = MakeStartupErrorMessage( aDiagnosticMessage.makeStringAndClear() );
1434         FatalError(aMessage);
1435     }
1436     else if ( aBootstrapError == BE_LANGUAGE_MISSING )
1437     {
1438         OUString aMessage;
1439         OUStringBuffer aDiagnosticMessage( 100 );
1440         OUString aErrorMsg;
1441         aErrorMsg = GetMsgString(
1442             //@@@ FIXME: should use an own resource string => #i36213#
1443             STR_BOOTSTRAP_ERR_LANGUAGE_MISSING,
1444             OUString( RTL_CONSTASCII_USTRINGPARAM(
1445                 "Language could not be determined." )) );
1446         aDiagnosticMessage.append( aErrorMsg );
1447         aMessage = MakeStartupErrorMessage(
1448             aDiagnosticMessage.makeStringAndClear() );
1449         FatalError(aMessage);
1450     }
1451     else if (( aBootstrapError == BE_USERINSTALL_NOTENOUGHDISKSPACE ) ||
1452              ( aBootstrapError == BE_USERINSTALL_NOWRITEACCESS      ))
1453     {
1454         OUString       aUserInstallationURL;
1455         OUString       aUserInstallationPath;
1456         OUString       aMessage;
1457         OUString       aErrorMsg;
1458         OUStringBuffer aDiagnosticMessage( 100 );
1459 
1460         utl::Bootstrap::locateUserInstallation( aUserInstallationURL );
1461 
1462         if ( aBootstrapError == BE_USERINSTALL_NOTENOUGHDISKSPACE )
1463             aErrorMsg = GetMsgString(
1464                 STR_BOOSTRAP_ERR_NOTENOUGHDISKSPACE,
1465                 OUString( RTL_CONSTASCII_USTRINGPARAM(
1466                     "User installation could not be completed due to insufficient free disk space." )) );
1467         else
1468             aErrorMsg = GetMsgString(
1469                 STR_BOOSTRAP_ERR_NOACCESSRIGHTS,
1470                 OUString( RTL_CONSTASCII_USTRINGPARAM(
1471                     "User installation could not be processed due to missing access rights." )) );
1472 
1473         osl::File::getSystemPathFromFileURL( aUserInstallationURL, aUserInstallationPath );
1474 
1475         aDiagnosticMessage.append( aErrorMsg );
1476         aDiagnosticMessage.append( aUserInstallationPath );
1477         aMessage = MakeStartupErrorMessage(
1478             aDiagnosticMessage.makeStringAndClear() );
1479         FatalError(aMessage);
1480     }
1481 
1482     return;
1483 }
1484 
1485 
retrieveCrashReporterState()1486 void Desktop::retrieveCrashReporterState()
1487 {
1488     static const ::rtl::OUString CFG_PACKAGE_RECOVERY   = ::rtl::OUString::createFromAscii("org.openoffice.Office.Recovery/");
1489     static const ::rtl::OUString CFG_PATH_CRASHREPORTER = ::rtl::OUString::createFromAscii("CrashReporter"                  );
1490     static const ::rtl::OUString CFG_ENTRY_ENABLED      = ::rtl::OUString::createFromAscii("Enabled"                        );
1491 
1492     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory();
1493 
1494     sal_Bool bEnabled( sal_True );
1495     if ( xSMGR.is() )
1496     {
1497         css::uno::Any aVal = ::comphelper::ConfigurationHelper::readDirectKey(
1498                                     xSMGR,
1499                                     CFG_PACKAGE_RECOVERY,
1500                                     CFG_PATH_CRASHREPORTER,
1501                                     CFG_ENTRY_ENABLED,
1502                                     ::comphelper::ConfigurationHelper::E_READONLY);
1503         aVal >>= bEnabled;
1504     }
1505     _bCrashReporterEnabled = bEnabled;
1506 }
1507 
isUIOnSessionShutdownAllowed()1508 sal_Bool Desktop::isUIOnSessionShutdownAllowed()
1509 {
1510     static const ::rtl::OUString CFG_PACKAGE_RECOVERY = ::rtl::OUString::createFromAscii("org.openoffice.Office.Recovery/");
1511     static const ::rtl::OUString CFG_PATH_SESSION     = ::rtl::OUString::createFromAscii("SessionShutdown"                );
1512     static const ::rtl::OUString CFG_ENTRY_UIENABLED  = ::rtl::OUString::createFromAscii("DocumentStoreUIEnabled"         );
1513 
1514     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory();
1515 
1516     sal_Bool bResult = sal_False;
1517     if ( xSMGR.is() )
1518     {
1519         css::uno::Any aVal = ::comphelper::ConfigurationHelper::readDirectKey(
1520                                     xSMGR,
1521                                     CFG_PACKAGE_RECOVERY,
1522                                     CFG_PATH_SESSION,
1523                                     CFG_ENTRY_UIENABLED,
1524                                     ::comphelper::ConfigurationHelper::E_READONLY);
1525         aVal >>= bResult;
1526     }
1527 
1528     return bResult;
1529 }
1530 
1531 //-----------------------------------------------
1532 /** @short  check if crash reporter feature is enabled or
1533             disabled.
1534 */
isCrashReporterEnabled()1535 sal_Bool Desktop::isCrashReporterEnabled()
1536 {
1537     return _bCrashReporterEnabled;
1538 }
1539 
1540 //-----------------------------------------------
1541 /** @short  check if recovery must be started or not.
1542 
1543     @param  bCrashed [boolean ... out!]
1544             the office crashed last times.
1545             But may be there are no recovery data.
1546             Useful to trigger the error report tool without
1547             showing the recovery UI.
1548 
1549     @param  bRecoveryDataExists [boolean ... out!]
1550             there exists some recovery data.
1551 
1552     @param  bSessionDataExists [boolean ... out!]
1553             there exists some session data.
1554             Because the user may be logged out last time from it's
1555             unix session...
1556 */
impl_checkRecoveryState(sal_Bool & bCrashed,sal_Bool & bRecoveryDataExists,sal_Bool & bSessionDataExists)1557 void impl_checkRecoveryState(sal_Bool& bCrashed           ,
1558                              sal_Bool& bRecoveryDataExists,
1559                              sal_Bool& bSessionDataExists )
1560 {
1561     static const ::rtl::OUString SERVICENAME_RECOVERYCORE = ::rtl::OUString::createFromAscii("com.sun.star.frame.AutoRecovery");
1562     static const ::rtl::OUString PROP_CRASHED             = ::rtl::OUString::createFromAscii("Crashed"                        );
1563     static const ::rtl::OUString PROP_EXISTSRECOVERY      = ::rtl::OUString::createFromAscii("ExistsRecoveryData"             );
1564     static const ::rtl::OUString PROP_EXISTSSESSION       = ::rtl::OUString::createFromAscii("ExistsSessionData"              );
1565     static const ::rtl::OUString CFG_PACKAGE_RECOVERY     = ::rtl::OUString::createFromAscii("org.openoffice.Office.Recovery/");
1566     static const ::rtl::OUString CFG_PATH_RECOVERYINFO    = ::rtl::OUString::createFromAscii("RecoveryInfo"                   );
1567 
1568     bCrashed            = sal_False;
1569     bRecoveryDataExists = sal_False;
1570     bSessionDataExists  = sal_False;
1571 
1572     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory();
1573     try
1574     {
1575         css::uno::Reference< css::beans::XPropertySet > xRecovery(
1576             xSMGR->createInstance(SERVICENAME_RECOVERYCORE),
1577             css::uno::UNO_QUERY_THROW);
1578 
1579         xRecovery->getPropertyValue(PROP_CRASHED       ) >>= bCrashed           ;
1580         xRecovery->getPropertyValue(PROP_EXISTSRECOVERY) >>= bRecoveryDataExists;
1581         xRecovery->getPropertyValue(PROP_EXISTSSESSION ) >>= bSessionDataExists ;
1582     }
1583     catch(const css::uno::Exception&) {}
1584 }
1585 
1586 //-----------------------------------------------
1587 /*  @short  start the recovery wizard.
1588 
1589     @param  bEmergencySave
1590             differs between EMERGENCY_SAVE and RECOVERY
1591 */
impl_callRecoveryUI(sal_Bool bEmergencySave,sal_Bool bCrashed,sal_Bool bExistsRecoveryData)1592 sal_Bool impl_callRecoveryUI(sal_Bool bEmergencySave     ,
1593                              sal_Bool bCrashed           ,
1594                              sal_Bool bExistsRecoveryData)
1595 {
1596     static ::rtl::OUString SERVICENAME_RECOVERYUI = ::rtl::OUString::createFromAscii("com.sun.star.comp.svx.RecoveryUI"          );
1597     static ::rtl::OUString SERVICENAME_URLPARSER  = ::rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer"          );
1598     static ::rtl::OUString COMMAND_EMERGENCYSAVE  = ::rtl::OUString::createFromAscii("vnd.sun.star.autorecovery:/doEmergencySave");
1599     static ::rtl::OUString COMMAND_RECOVERY       = ::rtl::OUString::createFromAscii("vnd.sun.star.autorecovery:/doAutoRecovery" );
1600     static ::rtl::OUString COMMAND_CRASHREPORT    = ::rtl::OUString::createFromAscii("vnd.sun.star.autorecovery:/doCrashReport"  );
1601 
1602     css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory();
1603 
1604     css::uno::Reference< css::frame::XSynchronousDispatch > xRecoveryUI(
1605         xSMGR->createInstance(SERVICENAME_RECOVERYUI),
1606         css::uno::UNO_QUERY_THROW);
1607 
1608     css::uno::Reference< css::util::XURLTransformer > xURLParser(
1609         xSMGR->createInstance(SERVICENAME_URLPARSER),
1610         css::uno::UNO_QUERY_THROW);
1611 
1612     css::util::URL aURL;
1613     if (bEmergencySave)
1614         aURL.Complete = COMMAND_EMERGENCYSAVE;
1615     else
1616     {
1617         if (bExistsRecoveryData)
1618             aURL.Complete = COMMAND_RECOVERY;
1619         else
1620         if (bCrashed && Desktop::isCrashReporterEnabled() )
1621             aURL.Complete = COMMAND_CRASHREPORT;
1622     }
1623 
1624     sal_Bool bRet = sal_False;
1625     if ( aURL.Complete.getLength() > 0 )
1626     {
1627         xURLParser->parseStrict(aURL);
1628 
1629         css::uno::Any aRet = xRecoveryUI->dispatchWithReturnValue(aURL, css::uno::Sequence< css::beans::PropertyValue >());
1630         aRet >>= bRet;
1631     }
1632     return bRet;
1633 }
1634 
1635 /*
1636  * Save all open documents so they will be reopened
1637  * the next time the application is started
1638  *
1639  * returns sal_True if at least one document could be saved...
1640  *
1641  */
1642 
1643 sal_Bool Desktop::_bTasksSaved = sal_False;
1644 
SaveTasks()1645 sal_Bool Desktop::SaveTasks()
1646 {
1647     return impl_callRecoveryUI(
1648         sal_True , // sal_True => force emergency save
1649         sal_False, // 2. and 3. param not used if 1. = true!
1650         sal_False);
1651 }
1652 
1653 namespace {
1654 
restartOnMac(bool passArguments)1655 void restartOnMac(bool passArguments) {
1656 #if defined MACOSX
1657     OfficeIPCThread::DisableOfficeIPCThread();
1658     rtl::OUString execUrl;
1659     OSL_VERIFY(osl_getExecutableFile(&execUrl.pData) == osl_Process_E_None);
1660     rtl::OUString execPath;
1661     rtl::OString execPath8;
1662     if ((osl::FileBase::getSystemPathFromFileURL(execUrl, execPath)
1663          != osl::FileBase::E_None) ||
1664         !execPath.convertToString(
1665             &execPath8, osl_getThreadTextEncoding(),
1666             (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
1667              RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
1668     {
1669         std::abort();
1670     }
1671     std::vector< rtl::OString > args;
1672     args.push_back(execPath8);
1673     bool wait = false;
1674     if (passArguments) {
1675         sal_uInt32 n = osl_getCommandArgCount();
1676         for (sal_uInt32 i = 0; i < n; ++i) {
1677             rtl::OUString arg;
1678             OSL_VERIFY(osl_getCommandArg(i, &arg.pData) == osl_Process_E_None);
1679             if (arg.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("-accept="))) {
1680                 wait = true;
1681             }
1682             rtl::OString arg8;
1683             if (!arg.convertToString(
1684                     &arg8, osl_getThreadTextEncoding(),
1685                     (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
1686                      RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
1687             {
1688                 std::abort();
1689             }
1690             args.push_back(arg8);
1691         }
1692     }
1693     std::vector< char const * > argPtrs;
1694     for (std::vector< rtl::OString >::iterator i(args.begin()); i != args.end();
1695          ++i)
1696     {
1697         argPtrs.push_back(i->getStr());
1698     }
1699     argPtrs.push_back(0);
1700     execv(execPath8.getStr(), const_cast< char ** >(&argPtrs[0]));
1701     if (errno == ENOTSUP) { // happens when multithreaded on OS X < 10.6
1702         pid_t pid = fork();
1703         if (pid == 0) {
1704             execv(execPath8.getStr(), const_cast< char ** >(&argPtrs[0]));
1705         } else if (pid > 0) {
1706             // Two simultaneously running soffice processes lead to two dock
1707             // icons, so avoid waiting here unless it must be assumed that the
1708             // process invoking soffice itself wants to wait for soffice to
1709             // finish:
1710             if (!wait) {
1711                 return;
1712             }
1713             int stat;
1714             if (waitpid(pid, &stat, 0) == pid && WIFEXITED(stat)) {
1715                 _exit(WEXITSTATUS(stat));
1716             }
1717         }
1718     }
1719     std::abort();
1720 #else
1721     (void) passArguments; // avoid warnings
1722 #endif
1723 }
1724 
1725 }
1726 
Exception(sal_uInt16 nError)1727 sal_uInt16 Desktop::Exception(sal_uInt16 nError)
1728 {
1729     // protect against recursive calls
1730     static sal_Bool bInException = sal_False;
1731 
1732     sal_uInt16 nOldMode = Application::GetSystemWindowMode();
1733     Application::SetSystemWindowMode( nOldMode & ~SYSTEMWINDOW_MODE_NOAUTOMODE );
1734     Application::SetDefDialogParent( NULL );
1735 
1736     if ( bInException )
1737     {
1738         String aDoubleExceptionString;
1739         Application::Abort( aDoubleExceptionString );
1740     }
1741 
1742     bInException = sal_True;
1743     CommandLineArgs* pArgs = GetCommandLineArgs();
1744 
1745     // save all modified documents ... if it's allowed doing so.
1746     sal_Bool bRestart                           = sal_False;
1747     sal_Bool bAllowRecoveryAndSessionManagement = (
1748                                                     ( !pArgs->IsNoRestore()                    ) && // some use cases of office must work without recovery
1749                                                     ( !pArgs->IsHeadless()                     ) &&
1750                                                     ( !pArgs->IsServer()                       ) &&
1751                                                     (( nError & EXC_MAJORTYPE ) != EXC_DISPLAY ) && // recovery can't work without UI ... but UI layer seems to be the reason for this crash
1752                                                     ( Application::IsInExecute()               )    // crashes during startup and shutdown should be ignored (they indicates a corrupt installation ...)
1753                                                   );
1754     if ( bAllowRecoveryAndSessionManagement )
1755         bRestart = SaveTasks();
1756 
1757     FlushConfiguration();
1758 
1759     switch( nError & EXC_MAJORTYPE )
1760     {
1761         case EXC_RSCNOTLOADED:
1762         {
1763             String aResExceptionString;
1764             Application::Abort( aResExceptionString );
1765             break;
1766         }
1767 
1768         case EXC_SYSOBJNOTCREATED:
1769         {
1770             String aSysResExceptionString;
1771             Application::Abort( aSysResExceptionString );
1772             break;
1773         }
1774 
1775         default:
1776         {
1777             if (m_pLockfile != NULL) {
1778                 m_pLockfile->clean();
1779             }
1780             if( bRestart )
1781             {
1782                 OfficeIPCThread::DisableOfficeIPCThread();
1783                 if( pSignalHandler )
1784                     DELETEZ( pSignalHandler );
1785                 restartOnMac(false);
1786                 _exit( ExitHelper::E_CRASH_WITH_RESTART );
1787             }
1788             else
1789             {
1790                 Application::Abort( String() );
1791             }
1792 
1793             break;
1794         }
1795     }
1796 
1797     OSL_ASSERT(false); // unreachable
1798     return 0;
1799 }
1800 
AppEvent(const ApplicationEvent & rAppEvent)1801 void Desktop::AppEvent( const ApplicationEvent& rAppEvent )
1802 {
1803     HandleAppEvent( rAppEvent );
1804 }
1805 
1806 struct ExecuteGlobals
1807 {
1808     Reference < css::document::XEventListener > xGlobalBroadcaster;
1809     sal_Bool bRestartRequested;
1810     sal_Bool bUseSystemFileDialog;
1811     std::auto_ptr<SvtLanguageOptions> pLanguageOptions;
1812     std::auto_ptr<SvtPathOptions> pPathOptions;
1813 
ExecuteGlobalsdesktop::ExecuteGlobals1814     ExecuteGlobals()
1815     : bRestartRequested( sal_False )
1816     , bUseSystemFileDialog( sal_True )
1817     {}
1818 };
1819 
1820 static ExecuteGlobals* pExecGlobals = NULL;
1821 
Main()1822 void Desktop::Main()
1823 {
1824     pExecGlobals = new ExecuteGlobals();
1825 
1826     RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::Main" );
1827 
1828     // Remember current context object
1829     com::sun::star::uno::ContextLayer layer(
1830         com::sun::star::uno::getCurrentContext() );
1831 
1832     BootstrapError eError = GetBootstrapError();
1833     if ( eError != BE_OK )
1834     {
1835         HandleBootstrapErrors( eError );
1836         return;
1837     }
1838 
1839     BootstrapStatus eStatus = GetBootstrapStatus();
1840     if (eStatus == BS_TERMINATE) {
1841         return;
1842     }
1843 
1844     // Detect desktop environment - need to do this as early as possible
1845     com::sun::star::uno::setCurrentContext(
1846         new DesktopContext( com::sun::star::uno::getCurrentContext() ) );
1847 
1848     CommandLineArgs* pCmdLineArgs = GetCommandLineArgs();
1849 
1850     // setup configuration error handling
1851     ConfigurationErrorHandler aConfigErrHandler;
1852     if (!ShouldSuppressUI(pCmdLineArgs))
1853         aConfigErrHandler.activate();
1854 
1855     ResMgr::SetReadStringHook( ReplaceStringHookProc );
1856 
1857     // Startup screen
1858     RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main { OpenSplashScreen" );
1859     OpenSplashScreen();
1860     RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main } OpenSplashScreen" );
1861 
1862     {
1863         UserInstall::UserInstallError instErr_fin = UserInstall::finalize();
1864         if ( instErr_fin != UserInstall::E_None)
1865         {
1866             OSL_ENSURE(sal_False, "userinstall failed");
1867             if ( instErr_fin == UserInstall::E_NoDiskSpace )
1868                 HandleBootstrapErrors( BE_USERINSTALL_NOTENOUGHDISKSPACE );
1869             else if ( instErr_fin == UserInstall::E_NoWriteAccess )
1870                 HandleBootstrapErrors( BE_USERINSTALL_NOWRITEACCESS );
1871             else
1872                 HandleBootstrapErrors( BE_USERINSTALL_FAILED );
1873             return;
1874         }
1875         // refresh path information
1876         utl::Bootstrap::reloadData();
1877         SetSplashScreenProgress(25);
1878     }
1879 
1880     Reference< XMultiServiceFactory > xSMgr =
1881         ::comphelper::getProcessServiceFactory();
1882 
1883     Reference< ::com::sun::star::task::XRestartManager > xRestartManager;
1884     int         nAcquireCount( 0 );
1885     try
1886     {
1887         RegisterServices( xSMgr );
1888 
1889         //SetSplashScreenProgress(15);
1890 
1891 #ifndef UNX
1892         if ( pCmdLineArgs->IsHelp() ) {
1893             displayCmdlineHelp();
1894             return;
1895         }
1896 #endif
1897 
1898         // check user installation directory for lockfile so we can be sure
1899         // there is no other instance using our data files from a remote host
1900         RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main -> Lockfile" );
1901         m_pLockfile = new Lockfile;
1902         if ( !pCmdLineArgs->IsHeadless() && !pCmdLineArgs->IsInvisible() &&
1903              !pCmdLineArgs->IsNoLockcheck() && !m_pLockfile->check( Lockfile_execWarning )) {
1904             // Lockfile exists, and user clicked 'no'
1905             return;
1906         }
1907         RTL_LOGFILE_CONTEXT_TRACE( aLog, "desktop (lo119109) Desktop::Main <- Lockfile" );
1908 
1909         // check if accessibility is enabled but not working and allow to quit
1910         RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ GetEnableATToolSupport" );
1911         if( Application::GetSettings().GetMiscSettings().GetEnableATToolSupport() )
1912         {
1913             sal_Bool bQuitApp (sal_False);
1914 
1915             if( !InitAccessBridge( true, bQuitApp ) )
1916                 if( bQuitApp )
1917                     return;
1918         }
1919         RTL_LOGFILE_CONTEXT_TRACE( aLog, "} GetEnableATToolSupport" );
1920 
1921         // terminate if requested...
1922         if( pCmdLineArgs->IsTerminateAfterInit() ) return;
1923 
1924         //  Read the common configuration items for optimization purpose
1925         if ( !InitializeConfiguration() ) return;
1926 
1927         //SetSplashScreenProgress(20);
1928 
1929         // set static variable to enabled/disable crash reporter
1930         retrieveCrashReporterState();
1931         const bool bCrashReporterEnabled = isCrashReporterEnabled();
1932         osl_setErrorReporting( !bCrashReporterEnabled );
1933 
1934         // create title string
1935         sal_Bool bCheckOk = sal_False;
1936         ::com::sun::star::lang::Locale aLocale;
1937         const char* pMgrName = "ofa";
1938     ResMgr* pLabelResMgr = ResMgr::SearchCreateResMgr( pMgrName, aLocale );
1939         String aTitle = pLabelResMgr ? String( ResId( RID_APPTITLE, *pLabelResMgr ) ) : String();
1940         delete pLabelResMgr;
1941 
1942         // Check for StarOffice/Suite specific extensions runs also with OpenOffice installation sets
1943         OUString aTitleString( aTitle );
1944         bCheckOk = CheckInstallation( aTitleString );
1945         if ( !bCheckOk )
1946             return;
1947         else
1948             aTitle = aTitleString;
1949 
1950 #ifdef DBG_UTIL
1951         //include version ID in non product builds
1952         ::rtl::OUString aDefault;
1953         aTitle += DEFINE_CONST_UNICODE(" [");
1954         String aVerId( utl::Bootstrap::getBuildIdData( aDefault ));
1955         aTitle += aVerId;
1956         aTitle += ']';
1957 #endif
1958 
1959         SetDisplayName( aTitle );
1960         RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ create SvtPathOptions and SvtLanguageOptions" );
1961         pExecGlobals->pPathOptions.reset( new SvtPathOptions);
1962         SetSplashScreenProgress(40);
1963         RTL_LOGFILE_CONTEXT_TRACE( aLog, "} create SvtPathOptions and SvtLanguageOptions" );
1964 
1965         // Check special env variable #111015#
1966         std::vector< String > aUnrestrictedFolders;
1967         svt::getUnrestrictedFolders( aUnrestrictedFolders );
1968 
1969         if ( aUnrestrictedFolders.size() > 0 )
1970         {
1971             // Set different working directory. The first entry is
1972             // the new work path.
1973             String aWorkPath = aUnrestrictedFolders[0];
1974             SvtPathOptions().SetWorkPath( aWorkPath );
1975         }
1976 
1977         // create service for loading SFX (still needed in startup)
1978         pExecGlobals->xGlobalBroadcaster = Reference < css::document::XEventListener >
1979             ( xSMgr->createInstance(
1980             DEFINE_CONST_UNICODE( "com.sun.star.frame.GlobalEventBroadcaster" ) ), UNO_QUERY );
1981 
1982         /* ensure existence of a default window that messages can be dispatched to
1983            This is for the benefit of testtool which uses PostUserEvent extensively
1984            and else can deadlock while creating this window from another tread while
1985            the main thread is not yet in the event loop.
1986         */
1987         Application::GetDefaultDevice();
1988 
1989         // initialize test-tool library (if available)
1990         RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ tools::InitTestToolLib" );
1991         tools::InitTestToolLib();
1992         RTL_LOGFILE_CONTEXT_TRACE( aLog, "} tools::InitTestToolLib" );
1993 
1994         // Check if bundled or shared extensions were added /removed
1995         // and process those extensions (has to be done before checking
1996         // the extension dependencies!
1997         SynchronizeExtensionRepositories();
1998         bool bAbort = CheckExtensionDependencies();
1999         if ( bAbort )
2000             return;
2001 
2002         {
2003             ::comphelper::ComponentContext aContext( xSMgr );
2004             xRestartManager.set( aContext.getSingleton( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.OfficeRestartManager" ) ) ), UNO_QUERY );
2005         }
2006 
2007         // check whether the shutdown is caused by restart
2008         pExecGlobals->bRestartRequested = ( xRestartManager.is() && xRestartManager->isRestartRequested( sal_True ) );
2009 
2010         // First Start Wizard allowed ?
2011         if ( ! pCmdLineArgs->IsNoFirstStartWizard() && !pExecGlobals->bRestartRequested )
2012         {
2013             RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ FirstStartWizard" );
2014 
2015             if (IsFirstStartWizardNeeded())
2016             {
2017                 Reference< XJob > xFirstStartJob( xSMgr->createInstance(
2018                     DEFINE_CONST_UNICODE( "com.sun.star.comp.desktop.FirstStart" ) ), UNO_QUERY );
2019                 if (xFirstStartJob.is())
2020                 {
2021                     sal_Bool bDone = sal_False;
2022                     Sequence< NamedValue > lArgs(2);
2023                     lArgs[0].Name    = ::rtl::OUString::createFromAscii("LicenseNeedsAcceptance");
2024                     lArgs[0].Value <<= LicenseNeedsAcceptance();
2025                     lArgs[1].Name    = ::rtl::OUString::createFromAscii("LicensePath");
2026                     lArgs[1].Value <<= GetLicensePath();
2027 
2028                     xFirstStartJob->execute(lArgs) >>= bDone;
2029                     if ( !bDone )
2030                     {
2031                         doShutdown();
2032                         return;
2033                     }
2034                     // mark first start as done
2035                     FinishFirstStart();
2036                 }
2037             }
2038 
2039             RTL_LOGFILE_CONTEXT_TRACE( aLog, "} FirstStartWizard" );
2040         }
2041 
2042         // process non-pre-registered extensions
2043         installBundledExtensionBlobs();
2044 
2045         // keep a language options instance...
2046         pExecGlobals->pLanguageOptions.reset( new SvtLanguageOptions(sal_True));
2047 
2048         if (pExecGlobals->xGlobalBroadcaster.is())
2049         {
2050             css::document::EventObject aEvent;
2051             aEvent.EventName = ::rtl::OUString::createFromAscii("OnStartApp");
2052             pExecGlobals->xGlobalBroadcaster->notifyEvent(aEvent);
2053         }
2054 
2055         SetSplashScreenProgress(50);
2056 
2057         // Backing Component
2058         sal_Bool bCrashed            = sal_False;
2059         sal_Bool bExistsRecoveryData = sal_False;
2060         sal_Bool bExistsSessionData  = sal_False;
2061 
2062         RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ impl_checkRecoveryState" );
2063         impl_checkRecoveryState(bCrashed, bExistsRecoveryData, bExistsSessionData);
2064         RTL_LOGFILE_CONTEXT_TRACE( aLog, "} impl_checkRecoveryState" );
2065 
2066         {
2067             ::comphelper::ComponentContext aContext( xSMgr );
2068             xRestartManager.set( aContext.getSingleton( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.OfficeRestartManager" ) ) ), UNO_QUERY );
2069         }
2070 
2071         // check whether the shutdown is caused by restart
2072         pExecGlobals->bRestartRequested = ( xRestartManager.is() && xRestartManager->isRestartRequested( sal_True ) );
2073 
2074         if ( pCmdLineArgs->IsHeadless() )
2075         {
2076             // Ensure that we use not the system file dialogs as
2077             // headless mode relies on Application::EnableHeadlessMode()
2078             // which does only work for VCL dialogs!!
2079             SvtMiscOptions aMiscOptions;
2080             pExecGlobals->bUseSystemFileDialog = aMiscOptions.UseSystemFileDialog();
2081             aMiscOptions.SetUseSystemFileDialog( sal_False );
2082         }
2083 
2084         if ( !pExecGlobals->bRestartRequested )
2085         {
2086             if ((!pCmdLineArgs->IsNoDefault() &&
2087                  !pCmdLineArgs->WantsToLoadDocument() &&
2088                  !pCmdLineArgs->IsInvisible() &&
2089                  !pCmdLineArgs->IsHeadless() &&
2090                  !pCmdLineArgs->IsQuickstart()) &&
2091                 (SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::E_SSTARTMODULE)) &&
2092                 (!bExistsRecoveryData                                                  ) &&
2093                 (!bExistsSessionData                                                   ) &&
2094                 (!Application::AnyInput( INPUT_APPEVENT )                              ))
2095             {
2096                  RTL_LOGFILE_CONTEXT_TRACE( aLog, "{ create BackingComponent" );
2097                  Reference< XFrame > xDesktopFrame( xSMgr->createInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ))), UNO_QUERY );
2098                  if (xDesktopFrame.is())
2099                  {
2100                    Reference< XFrame > xBackingFrame;
2101                    Reference< ::com::sun::star::awt::XWindow > xContainerWindow;
2102 
2103                    xBackingFrame = xDesktopFrame->findFrame(OUString( RTL_CONSTASCII_USTRINGPARAM( "_blank" )), 0);
2104                    if (xBackingFrame.is())
2105                        xContainerWindow = xBackingFrame->getContainerWindow();
2106                    if (xContainerWindow.is())
2107                    {
2108                        // set the WB_EXT_DOCUMENT style. Normally, this is done by the TaskCreator service when a "_blank"
2109                        // frame/window is created. Since we do not use the TaskCreator here, we need to mimic its behavior,
2110                        // otherwise documents loaded into this frame will later on miss functionality depending on the style.
2111                        Window* pContainerWindow = VCLUnoHelper::GetWindow( xContainerWindow );
2112                        OSL_ENSURE( pContainerWindow, "Desktop::Main: no implementation access to the frame's container window!" );
2113                        pContainerWindow->SetExtendedStyle( pContainerWindow->GetExtendedStyle() | WB_EXT_DOCUMENT );
2114 
2115                        SetSplashScreenProgress(75);
2116                        Sequence< Any > lArgs(1);
2117                        lArgs[0] <<= xContainerWindow;
2118 
2119                        Reference< XController > xBackingComp(
2120                            xSMgr->createInstanceWithArguments(OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.StartModule") ), lArgs), UNO_QUERY);
2121                         if (xBackingComp.is())
2122                         {
2123                             Reference< ::com::sun::star::awt::XWindow > xBackingWin(xBackingComp, UNO_QUERY);
2124                             // Attention: You MUST(!) call setComponent() before you call attachFrame().
2125                             // Because the backing component set the property "IsBackingMode" of the frame
2126                             // to true inside attachFrame(). But setComponent() reset this state everytimes ...
2127                             xBackingFrame->setComponent(xBackingWin, xBackingComp);
2128                             SetSplashScreenProgress(100);
2129                             xBackingComp->attachFrame(xBackingFrame);
2130                             CloseSplashScreen();
2131                             xContainerWindow->setVisible(sal_True);
2132                         }
2133                     }
2134                 }
2135                 RTL_LOGFILE_CONTEXT_TRACE( aLog, "} create BackingComponent" );
2136             }
2137         }
2138     }
2139     catch ( com::sun::star::lang::WrappedTargetException& wte )
2140     {
2141         com::sun::star::uno::Exception te;
2142         wte.TargetException >>= te;
2143         FatalError( MakeStartupConfigAccessErrorMessage(wte.Message + te.Message) );
2144         return;
2145     }
2146     catch ( com::sun::star::uno::Exception& e )
2147     {
2148         FatalError( MakeStartupErrorMessage(e.Message) );
2149         return;
2150     }
2151 
2152     SvtFontSubstConfig().Apply();
2153 
2154     SvtTabAppearanceCfg aAppearanceCfg;
2155     aAppearanceCfg.SetInitialized();
2156     aAppearanceCfg.SetApplicationDefaults( this );
2157     SvtAccessibilityOptions aOptions;
2158     aOptions.SetVCLSettings();
2159 
2160     if ( !pExecGlobals->bRestartRequested )
2161     {
2162         Application::SetFilterHdl( LINK( this, Desktop, ImplInitFilterHdl ) );
2163         sal_Bool bTerminateRequested = sal_False;
2164 
2165         // Preload function depends on an initialized sfx application!
2166         SetSplashScreenProgress(75);
2167 
2168         // use system window dialogs
2169         Application::SetSystemWindowMode( SYSTEMWINDOW_MODE_DIALOG );
2170 
2171     //    SetSplashScreenProgress(80);
2172 
2173         if ( !bTerminateRequested && !pCmdLineArgs->IsInvisible() &&
2174              !pCmdLineArgs->IsNoQuickstart() )
2175             InitializeQuickstartMode( xSMgr );
2176 
2177         RTL_LOGFILE_CONTEXT( aLog2, "desktop (cd100003) createInstance com.sun.star.frame.Desktop" );
2178         try
2179         {
2180             Reference< XDesktop > xDesktop( xSMgr->createInstance(
2181                 OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.Desktop" ))), UNO_QUERY );
2182             if ( xDesktop.is() )
2183                 xDesktop->addTerminateListener( new OfficeIPCThreadController );
2184             SetSplashScreenProgress(100);
2185         }
2186         catch ( com::sun::star::uno::Exception& e )
2187         {
2188             FatalError( MakeStartupErrorMessage(e.Message) );
2189             return;
2190         }
2191 
2192         // Post user event to startup first application component window
2193         // We have to send this OpenClients message short before execute() to
2194         // minimize the risk that this message overtakes type detection construction!!
2195         Application::PostUserEvent( LINK( this, Desktop, OpenClients_Impl ) );
2196 
2197         // Post event to enable acceptors
2198         Application::PostUserEvent( LINK( this, Desktop, EnableAcceptors_Impl) );
2199 
2200         // The configuration error handler currently is only for startup
2201         aConfigErrHandler.deactivate();
2202 
2203        // Acquire solar mutex just before we enter our message loop
2204         if ( nAcquireCount )
2205             Application::AcquireSolarMutex( nAcquireCount );
2206 
2207         // call Application::Execute to process messages in vcl message loop
2208         RTL_LOGFILE_PRODUCT_TRACE( "PERFORMANCE - enter Application::Execute()" );
2209 
2210         try
2211         {
2212             // The JavaContext contains an interaction handler which is used when
2213             // the creation of a Java Virtual Machine fails
2214             com::sun::star::uno::ContextLayer layer2(
2215                 new svt::JavaContext( com::sun::star::uno::getCurrentContext() ) );
2216 
2217             // check whether the shutdown is caused by restart just before entering the Execute
2218             pExecGlobals->bRestartRequested = pExecGlobals->bRestartRequested || ( xRestartManager.is() && xRestartManager->isRestartRequested( sal_True ) );
2219 
2220             if ( !pExecGlobals->bRestartRequested )
2221             {
2222                 // if this run of the office is triggered by restart, some additional actions should be done
2223                 DoRestartActionsIfNecessary( !pCmdLineArgs->IsInvisible() && !pCmdLineArgs->IsNoQuickstart() );
2224 
2225                 Execute();
2226             }
2227         }
2228         catch(const com::sun::star::document::CorruptedFilterConfigurationException& exFilterCfg)
2229         {
2230             OfficeIPCThread::SetDowning();
2231             FatalError( MakeStartupErrorMessage(exFilterCfg.Message) );
2232         }
2233         catch(const com::sun::star::configuration::CorruptedConfigurationException& exAnyCfg)
2234         {
2235             OfficeIPCThread::SetDowning();
2236             FatalError( MakeStartupErrorMessage(exAnyCfg.Message) );
2237         }
2238         catch( const ::com::sun::star::uno::Exception& exUNO)
2239         {
2240             OfficeIPCThread::SetDowning();
2241             FatalError( exUNO.Message);
2242         }
2243         catch( const std::exception& exSTD)
2244         {
2245             OfficeIPCThread::SetDowning();
2246             FatalError( OUString::createFromAscii( exSTD.what()));
2247         }
2248         catch( ...)
2249         {
2250             OfficeIPCThread::SetDowning();
2251             FatalError( OUString(RTL_CONSTASCII_USTRINGPARAM( "Caught Unknown Exception: Aborting!")));
2252         }
2253     }
2254     // CAUTION: you do not necessarily get here e.g. on the Mac.
2255     // please put all deinitialization code into doShutdown
2256     doShutdown();
2257 }
2258 
doShutdown()2259 void Desktop::doShutdown()
2260 {
2261     if( ! pExecGlobals )
2262         return;
2263 
2264     if ( pExecGlobals->bRestartRequested )
2265         SetRestartState();
2266 
2267     if (pExecGlobals->xGlobalBroadcaster.is())
2268     {
2269         css::document::EventObject aEvent;
2270         aEvent.EventName = ::rtl::OUString::createFromAscii("OnCloseApp");
2271         pExecGlobals->xGlobalBroadcaster->notifyEvent(aEvent);
2272     }
2273 
2274     delete pResMgr, pResMgr = NULL;
2275     // Restore old value
2276     CommandLineArgs* pCmdLineArgs = GetCommandLineArgs();
2277     if ( pCmdLineArgs->IsHeadless() )
2278         SvtMiscOptions().SetUseSystemFileDialog( pExecGlobals->bUseSystemFileDialog );
2279 
2280     // remove temp directory
2281     RemoveTemporaryDirectory();
2282     FlushConfiguration();
2283     // The acceptors in the AcceptorMap must be released (in DeregisterServices)
2284     // with the solar mutex unlocked, to avoid deadlock:
2285     sal_uLong nAcquireCount = Application::ReleaseSolarMutex();
2286     DeregisterServices();
2287     Application::AcquireSolarMutex(nAcquireCount);
2288     tools::DeInitTestToolLib();
2289     // be sure that path/language options gets destroyed before
2290     // UCB is deinitialized
2291     RTL_LOGFILE_CONTEXT_TRACE( aLog, "-> dispose path/language options" );
2292     pExecGlobals->pLanguageOptions.reset( 0 );
2293     pExecGlobals->pPathOptions.reset( 0 );
2294     RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- dispose path/language options" );
2295 
2296     RTL_LOGFILE_CONTEXT_TRACE( aLog, "-> deinit ucb" );
2297     ::ucbhelper::ContentBroker::deinitialize();
2298     RTL_LOGFILE_CONTEXT_TRACE( aLog, "<- deinit ucb" );
2299 
2300     sal_Bool bRR = pExecGlobals->bRestartRequested;
2301     delete pExecGlobals, pExecGlobals = NULL;
2302 
2303     RTL_LOGFILE_CONTEXT_TRACE( aLog, "FINISHED WITH Destop::Main" );
2304     if ( bRR )
2305     {
2306         restartOnMac(true);
2307         // wouldn't the solution be more clean if SalMain returns the exit code to the system?
2308         _exit( ExitHelper::E_NORMAL_RESTART );
2309     }
2310 }
2311 
IMPL_LINK(Desktop,ImplInitFilterHdl,ConvertData *,pData)2312 IMPL_LINK( Desktop, ImplInitFilterHdl, ConvertData*, pData )
2313 {
2314     return GraphicFilter::GetGraphicFilter()->GetFilterCallback().Call( pData );
2315 }
2316 
InitializeConfiguration()2317 sal_Bool Desktop::InitializeConfiguration()
2318 {
2319     sal_Bool bOk = sal_False;
2320 
2321     try
2322     {
2323         bOk = InitConfiguration();
2324     }
2325     catch( ::com::sun::star::lang::ServiceNotRegisteredException& )
2326     {
2327         this->HandleBootstrapErrors( Desktop::BE_UNO_SERVICE_CONFIG_MISSING );
2328     }
2329     catch( ::com::sun::star::configuration::MissingBootstrapFileException& e )
2330     {
2331         OUString aMsg( CreateErrorMsgString( utl::Bootstrap::MISSING_BOOTSTRAP_FILE,
2332                                                 e.BootstrapFileURL ));
2333         HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_USER_INSTALL, aMsg );
2334     }
2335     catch( ::com::sun::star::configuration::InvalidBootstrapFileException& e )
2336     {
2337         OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_FILE_ENTRY,
2338                                                 e.BootstrapFileURL ));
2339         HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg );
2340     }
2341     catch( ::com::sun::star::configuration::InstallationIncompleteException& )
2342     {
2343         OUString aVersionFileURL;
2344         OUString aMsg;
2345         utl::Bootstrap::PathStatus aPathStatus = utl::Bootstrap::locateVersionFile( aVersionFileURL );
2346         if ( aPathStatus == utl::Bootstrap::PATH_EXISTS )
2347             aMsg = CreateErrorMsgString( utl::Bootstrap::MISSING_VERSION_FILE_ENTRY, aVersionFileURL );
2348         else
2349             aMsg = CreateErrorMsgString( utl::Bootstrap::MISSING_VERSION_FILE, aVersionFileURL );
2350 
2351         HandleBootstrapPathErrors( ::utl::Bootstrap::MISSING_USER_INSTALL, aMsg );
2352     }
2353     catch ( com::sun::star::configuration::backend::BackendAccessException& exception)
2354     {
2355         // [cm122549] It is assumed in this case that the message
2356         // coming from InitConfiguration (in fact CreateApplicationConf...)
2357         // is suitable for display directly.
2358         FatalError( MakeStartupErrorMessage( exception.Message ) );
2359     }
2360     catch ( com::sun::star::configuration::backend::BackendSetupException& exception)
2361     {
2362         // [cm122549] It is assumed in this case that the message
2363         // coming from InitConfiguration (in fact CreateApplicationConf...)
2364         // is suitable for display directly.
2365         FatalError( MakeStartupErrorMessage( exception.Message ) );
2366     }
2367     catch ( ::com::sun::star::configuration::CannotLoadConfigurationException& )
2368     {
2369         OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_DATA,
2370                                                 OUString() ));
2371         HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg );
2372     }
2373     catch( ::com::sun::star::uno::Exception& )
2374     {
2375         OUString aMsg( CreateErrorMsgString( utl::Bootstrap::INVALID_BOOTSTRAP_DATA,
2376                                                 OUString() ));
2377         HandleBootstrapPathErrors( ::utl::Bootstrap::INVALID_BASE_INSTALL, aMsg );
2378     }
2379 
2380     return bOk;
2381 }
2382 
FlushConfiguration()2383 void Desktop::FlushConfiguration()
2384 {
2385     Reference < XFlushable > xCFGFlush( ::utl::ConfigManager::GetConfigManager()->GetConfigurationProvider(), UNO_QUERY );
2386     if (xCFGFlush.is())
2387     {
2388         xCFGFlush->flush();
2389     }
2390     else
2391     {
2392         // because there is no method to flush the configuration data, we must dispose the ConfigManager
2393         Reference < XComponent > xCFGDispose( ::utl::ConfigManager::GetConfigManager()->GetConfigurationProvider(), UNO_QUERY );
2394         if (xCFGDispose.is())
2395             xCFGDispose->dispose();
2396     }
2397 }
2398 
InitializeQuickstartMode(Reference<XMultiServiceFactory> & rSMgr)2399 sal_Bool Desktop::InitializeQuickstartMode( Reference< XMultiServiceFactory >& rSMgr )
2400 {
2401     try
2402     {
2403         // the shutdown icon sits in the systray and allows the user to keep
2404         // the office instance running for quicker restart
2405         // this will only be activated if -quickstart was specified on cmdline
2406         RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) createInstance com.sun.star.office.Quickstart" );
2407 
2408         sal_Bool bQuickstart = GetCommandLineArgs()->IsQuickstart();
2409         if ( !bQuickstart )
2410         {
2411             SfxItemSet aOptSet( SFX_APP()->GetPool(), SID_ATTR_QUICKLAUNCHER, SID_ATTR_QUICKLAUNCHER );
2412             SFX_APP()->GetOptions(aOptSet);
2413             const SfxPoolItem* pItem;
2414             if ( SFX_ITEM_SET == aOptSet.GetItemState( SID_ATTR_QUICKLAUNCHER, sal_False, &pItem ) )
2415                 bQuickstart = ((const SfxBoolItem*)pItem)->GetValue();
2416         }
2417 
2418         Sequence< Any > aSeq( 1 );
2419         aSeq[0] <<= bQuickstart;
2420 
2421         // Try to instantiate quickstart service. This service is not mandatory, so
2422         // do nothing if service is not available
2423 
2424         // #i105753# the following if was invented for performance
2425         // unfortunately this broke the QUARTZ behavior which is to always run
2426         // in quickstart mode since Mac applications do not usually quit
2427         // when the last document closes
2428         #ifndef QUARTZ
2429         if ( bQuickstart )
2430         #endif
2431         {
2432             Reference < XComponent > xQuickstart( rSMgr->createInstanceWithArguments(
2433                                                 DEFINE_CONST_UNICODE( "com.sun.star.office.Quickstart" ), aSeq ),
2434                                                 UNO_QUERY );
2435         }
2436         return sal_True;
2437     }
2438     catch( ::com::sun::star::uno::Exception& )
2439     {
2440         return sal_False;
2441     }
2442 }
2443 
SystemSettingsChanging(AllSettings & rSettings,Window *)2444 void Desktop::SystemSettingsChanging( AllSettings& rSettings, Window* )
2445 {
2446     if ( !SvtTabAppearanceCfg::IsInitialized () )
2447         return;
2448 
2449 #   define DRAGFULL_OPTION_ALL \
2450          ( DRAGFULL_OPTION_WINDOWMOVE | DRAGFULL_OPTION_WINDOWSIZE  \
2451          | DRAGFULL_OPTION_OBJECTMOVE  | DRAGFULL_OPTION_OBJECTSIZE \
2452          | DRAGFULL_OPTION_DOCKING     | DRAGFULL_OPTION_SPLIT      \
2453          | DRAGFULL_OPTION_SCROLL )
2454 #   define DRAGFULL_OPTION_NONE ((sal_uInt32)~DRAGFULL_OPTION_ALL)
2455 
2456     StyleSettings hStyleSettings   = rSettings.GetStyleSettings();
2457     MouseSettings hMouseSettings = rSettings.GetMouseSettings();
2458 
2459     sal_uInt32 nDragFullOptions = hStyleSettings.GetDragFullOptions();
2460 
2461     SvtTabAppearanceCfg aAppearanceCfg;
2462     sal_uInt16 nGet = aAppearanceCfg.GetDragMode();
2463     switch ( nGet )
2464     {
2465     case DragFullWindow:
2466         nDragFullOptions |= DRAGFULL_OPTION_ALL;
2467         break;
2468     case DragFrame:
2469         nDragFullOptions &= DRAGFULL_OPTION_NONE;
2470         break;
2471     case DragSystemDep:
2472     default:
2473         break;
2474     }
2475 
2476     sal_uInt32 nFollow = hMouseSettings.GetFollow();
2477     hMouseSettings.SetFollow( aAppearanceCfg.IsMenuMouseFollow() ? (nFollow|MOUSE_FOLLOW_MENU) : (nFollow&~MOUSE_FOLLOW_MENU));
2478     rSettings.SetMouseSettings(hMouseSettings);
2479 
2480     sal_Bool bUseImagesInMenus = hStyleSettings.GetUseImagesInMenus();
2481 
2482     SvtMenuOptions aMenuOpt;
2483     nGet = aMenuOpt.GetMenuIconsState();
2484     switch ( nGet )
2485     {
2486         case 0:
2487             bUseImagesInMenus = sal_False;
2488             break;
2489         case 1:
2490             bUseImagesInMenus = sal_True;
2491             break;
2492         case 2:
2493         default:
2494             break;
2495     }
2496     hStyleSettings.SetUseImagesInMenus(bUseImagesInMenus);
2497 
2498     hStyleSettings.SetDragFullOptions( nDragFullOptions );
2499     rSettings.SetStyleSettings ( hStyleSettings );
2500 }
2501 
2502 // ========================================================================
IMPL_LINK(Desktop,AsyncInitFirstRun,void *,EMPTYARG)2503 IMPL_LINK( Desktop, AsyncInitFirstRun, void*, EMPTYARG )
2504 {
2505     DoFirstRunInitializations();
2506     return 0L;
2507 }
2508 
2509 // ========================================================================
2510 
2511 class ExitTimer : public Timer
2512 {
2513   public:
ExitTimer()2514     ExitTimer()
2515     {
2516         SetTimeout(500);
2517         Start();
2518     }
Timeout()2519     virtual void Timeout()
2520     {
2521         exit(42);
2522     }
2523 };
2524 
IMPL_LINK(Desktop,OpenClients_Impl,void *,EMPTYARG)2525 IMPL_LINK( Desktop, OpenClients_Impl, void*, EMPTYARG )
2526 {
2527     RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "PERFORMANCE - DesktopOpenClients_Impl()" );
2528 
2529     // #114963#
2530     // Enable IPC thread before OpenClients
2531     //
2532     // This is because it is possible for another client to connect during the OpenClients() call.
2533     // This can happen on Windows when document is printed (not opened) and another client wants to print (when printing multiple documents).
2534     // If the IPC thread is enabled after OpenClients, then the client will not be processed because the application will exit after printing. i.e OfficeIPCThread::AreRequestsPending() will always return false
2535     //
2536     // ALSO:
2537     //
2538     // Multiple clients may request simultaneous connections.
2539     // When this server closes down it attempts to recreate the pipe (in DisableOfficeIPCThread()).
2540     // It's possible that the client has a pending connection request.
2541     // When the IPC thread is not running, this connection locks (because maPipe.accept()) is never called
2542     OfficeIPCThread::SetReady();
2543     OpenClients();
2544 
2545     // CloseStartupScreen();
2546     CloseSplashScreen();
2547     CheckFirstRun( );
2548     EnableOleAutomation();
2549 
2550     if (getenv ("OOO_EXIT_POST_STARTUP"))
2551         new ExitTimer();
2552     return 0;
2553 }
2554 
2555 // enable acceptors
IMPL_LINK(Desktop,EnableAcceptors_Impl,void *,EMPTYARG)2556 IMPL_LINK( Desktop, EnableAcceptors_Impl, void*, EMPTYARG )
2557 {
2558     enableAcceptors();
2559     return 0;
2560 }
2561 
2562 
2563 // Registers a COM class factory of the service manager with the Windows operating system.
EnableOleAutomation()2564 void Desktop::EnableOleAutomation()
2565 {
2566       RTL_LOGFILE_CONTEXT( aLog, "desktop (jl97489) ::Desktop::EnableOleAutomation" );
2567 #ifdef WNT
2568     Reference< XMultiServiceFactory > xSMgr=  comphelper::getProcessServiceFactory();
2569     xSMgr->createInstance(DEFINE_CONST_UNICODE("com.sun.star.bridge.OleApplicationRegistration"));
2570     xSMgr->createInstance(DEFINE_CONST_UNICODE("com.sun.star.comp.ole.EmbedServer"));
2571 #endif
2572 }
2573 
CheckOEM()2574 sal_Bool Desktop::CheckOEM()
2575 {
2576     Reference<XMultiServiceFactory> rFactory = ::comphelper::getProcessServiceFactory();
2577     Reference<XJob> rOemJob(rFactory->createInstance(
2578         OUString::createFromAscii("com.sun.star.office.OEMPreloadJob")),
2579         UNO_QUERY );
2580     Sequence<NamedValue> args;
2581     sal_Bool bResult = sal_False;
2582     if (rOemJob.is()) {
2583         Any aResult = rOemJob->execute(args);
2584         aResult >>= bResult;
2585         return bResult;
2586     } else {
2587         return sal_True;
2588     }
2589 }
2590 
PreloadModuleData(CommandLineArgs * pArgs)2591 void Desktop::PreloadModuleData( CommandLineArgs* pArgs )
2592 {
2593     Reference< XMultiServiceFactory > rFactory = ::comphelper::getProcessServiceFactory();
2594 
2595     Sequence < com::sun::star::beans::PropertyValue > args(1);
2596     args[0].Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Hidden"));
2597     args[0].Value <<= sal_True;
2598     Reference < XComponentLoader > xLoader( ::comphelper::getProcessServiceFactory()->createInstance(
2599         ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ), UNO_QUERY );
2600 
2601     if ( !xLoader.is() )
2602         return;
2603 
2604     if ( pArgs->IsWriter() )
2605     {
2606         try
2607         {
2608             Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/swriter"),
2609                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW );
2610             xDoc->close( sal_False );
2611         }
2612         catch ( com::sun::star::uno::Exception& )
2613         {
2614         }
2615     }
2616     if ( pArgs->IsCalc() )
2617     {
2618         try
2619         {
2620             Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/scalc"),
2621                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW );
2622             xDoc->close( sal_False );
2623         }
2624         catch ( com::sun::star::uno::Exception& )
2625         {
2626         }
2627     }
2628     if ( pArgs->IsDraw() )
2629     {
2630         try
2631         {
2632             Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/sdraw"),
2633                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW );
2634             xDoc->close( sal_False );
2635         }
2636         catch ( com::sun::star::uno::Exception& )
2637         {
2638         }
2639     }
2640     if ( pArgs->IsImpress() )
2641     {
2642         try
2643         {
2644             Reference < ::com::sun::star::util::XCloseable > xDoc( xLoader->loadComponentFromURL( DEFINE_CONST_UNICODE("private:factory/simpress"),
2645                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_blank")), 0, args ), UNO_QUERY_THROW );
2646             xDoc->close( sal_False );
2647         }
2648         catch ( com::sun::star::uno::Exception& )
2649         {
2650         }
2651     }
2652 }
2653 
PreloadConfigurationData()2654 void Desktop::PreloadConfigurationData()
2655 {
2656     Reference< XMultiServiceFactory > rFactory = ::comphelper::getProcessServiceFactory();
2657     Reference< XNameAccess > xNameAccess( rFactory->createInstance(
2658         DEFINE_CONST_UNICODE( "com.sun.star.frame.UICommandDescription" )), UNO_QUERY );
2659 
2660     rtl::OUString aWriterDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextDocument" ));
2661     rtl::OUString aCalcDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.SpreadsheetDocument" ));
2662     rtl::OUString aDrawDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.DrawingDocument" ));
2663     rtl::OUString aImpressDoc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.presentation.PresentationDocument" ));
2664 
2665     // preload commands configuration
2666     if ( xNameAccess.is() )
2667     {
2668         Any a;
2669         Reference< XNameAccess > xCmdAccess;
2670 
2671         try
2672         {
2673             a = xNameAccess->getByName( aWriterDoc );
2674             a >>= xCmdAccess;
2675             if ( xCmdAccess.is() )
2676             {
2677                 xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:BasicShapes" ));
2678                 xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:EditGlossary" ));
2679             }
2680         }
2681         catch ( ::com::sun::star::uno::Exception& )
2682         {
2683         }
2684 
2685         try
2686         {
2687             a = xNameAccess->getByName( aCalcDoc );
2688             a >>= xCmdAccess;
2689             if ( xCmdAccess.is() )
2690                 xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:InsertObjectStarMath" ));
2691         }
2692         catch ( ::com::sun::star::uno::Exception& )
2693         {
2694         }
2695 
2696         try
2697         {
2698             // draw and impress share the same configuration file (DrawImpressCommands.xcu)
2699             a = xNameAccess->getByName( aDrawDoc );
2700             a >>= xCmdAccess;
2701             if ( xCmdAccess.is() )
2702                 xCmdAccess->getByName( DEFINE_CONST_UNICODE( ".uno:Polygon" ));
2703         }
2704         catch ( ::com::sun::star::uno::Exception& )
2705         {
2706         }
2707     }
2708 
2709     // preload window state configuration
2710     xNameAccess = Reference< XNameAccess >( rFactory->createInstance(
2711                     DEFINE_CONST_UNICODE( "com.sun.star.ui.WindowStateConfiguration" )), UNO_QUERY );
2712     if ( xNameAccess.is() )
2713     {
2714         Any a;
2715         Reference< XNameAccess > xWindowAccess;
2716         try
2717         {
2718             a = xNameAccess->getByName( aWriterDoc );
2719             a >>= xWindowAccess;
2720             if ( xWindowAccess.is() )
2721                 xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" ));
2722         }
2723         catch ( ::com::sun::star::uno::Exception& )
2724         {
2725         }
2726         try
2727         {
2728             a = xNameAccess->getByName( aCalcDoc );
2729             a >>= xWindowAccess;
2730             if ( xWindowAccess.is() )
2731                 xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" ));
2732         }
2733         catch ( ::com::sun::star::uno::Exception& )
2734         {
2735         }
2736         try
2737         {
2738             a = xNameAccess->getByName( aDrawDoc );
2739             a >>= xWindowAccess;
2740             if ( xWindowAccess.is() )
2741                 xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" ));
2742         }
2743         catch ( ::com::sun::star::uno::Exception& )
2744         {
2745         }
2746         try
2747         {
2748             a = xNameAccess->getByName( aImpressDoc );
2749             a >>= xWindowAccess;
2750             if ( xWindowAccess.is() )
2751                 xWindowAccess->getByName( DEFINE_CONST_UNICODE( "private:resource/toolbar/standardbar" ));
2752         }
2753         catch ( ::com::sun::star::uno::Exception& )
2754         {
2755         }
2756     }
2757 
2758     // preload user interface element factories
2759     Sequence< Sequence< css::beans::PropertyValue > > aSeqSeqPropValue;
2760     Reference< ::com::sun::star::ui::XUIElementFactoryRegistration > xUIElementFactory(
2761         rFactory->createInstance(
2762             DEFINE_CONST_UNICODE( "com.sun.star.ui.UIElementFactoryManager" )),
2763             UNO_QUERY );
2764     if ( xUIElementFactory.is() )
2765     {
2766         try
2767         {
2768             aSeqSeqPropValue = xUIElementFactory->getRegisteredFactories();
2769         }
2770         catch ( ::com::sun::star::uno::Exception& )
2771         {
2772         }
2773     }
2774 
2775     // preload popup menu controller factories. As all controllers are in the same
2776     // configuration file they also get preloaded!
2777     Reference< ::com::sun::star::frame::XUIControllerRegistration > xPopupMenuControllerFactory(
2778         rFactory->createInstance(
2779             DEFINE_CONST_UNICODE( "com.sun.star.frame.PopupMenuControllerFactory" )),
2780             UNO_QUERY );
2781     if ( xPopupMenuControllerFactory.is() )
2782     {
2783         try
2784         {
2785             xPopupMenuControllerFactory->hasController(
2786                         DEFINE_CONST_UNICODE( ".uno:CharFontName" ),
2787                         OUString() );
2788         }
2789         catch ( ::com::sun::star::uno::Exception& )
2790         {
2791         }
2792     }
2793 
2794     // preload filter configuration
2795     Sequence< OUString > aSeq;
2796     xNameAccess = Reference< XNameAccess >( rFactory->createInstance(
2797                     DEFINE_CONST_UNICODE( "com.sun.star.document.FilterFactory" )), UNO_QUERY );
2798     if ( xNameAccess.is() )
2799     {
2800         try
2801         {
2802              aSeq = xNameAccess->getElementNames();
2803         }
2804         catch ( ::com::sun::star::uno::Exception& )
2805         {
2806         }
2807     }
2808 
2809     // preload type detection configuration
2810     xNameAccess = Reference< XNameAccess >( rFactory->createInstance(
2811                     DEFINE_CONST_UNICODE( "com.sun.star.document.TypeDetection" )), UNO_QUERY );
2812     if ( xNameAccess.is() )
2813     {
2814         try
2815         {
2816              aSeq = xNameAccess->getElementNames();
2817         }
2818         catch ( ::com::sun::star::uno::Exception& )
2819         {
2820         }
2821     }
2822 
2823     static const OUString sConfigSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) );
2824     static const OUString sAccessSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationAccess" ) );
2825 
2826     // get configuration provider
2827     Reference< XMultiServiceFactory > xConfigProvider;
2828     xConfigProvider = Reference< XMultiServiceFactory > (
2829                 rFactory->createInstance( sConfigSrvc ),UNO_QUERY );
2830 
2831     if ( xConfigProvider.is() )
2832     {
2833         // preload writer configuration
2834         Sequence< Any > theArgs(1);
2835         theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Writer/MailMergeWizard" );
2836         try
2837         {
2838             xNameAccess = Reference< XNameAccess >(
2839                 xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY );
2840         }
2841         catch (::com::sun::star::uno::Exception& )
2842         {
2843         }
2844 
2845         // WriterWeb
2846         theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.WriterWeb/Content" );
2847         try
2848         {
2849             xNameAccess = Reference< XNameAccess >(
2850                 xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY );
2851         }
2852         catch (::com::sun::star::uno::Exception& )
2853         {
2854         }
2855 
2856         // preload compatibility
2857         theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Compatibility/WriterCompatibilityVersion" );
2858         try
2859         {
2860             xNameAccess = Reference< XNameAccess >(
2861                 xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY );
2862         }
2863         catch (::com::sun::star::uno::Exception& )
2864         {
2865         }
2866 
2867         // preload calc configuration
2868         theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Calc/Content" );
2869         try
2870         {
2871             xNameAccess = Reference< XNameAccess >(
2872                 xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY );
2873         }
2874         catch (::com::sun::star::uno::Exception& )
2875         {
2876         }
2877 
2878         // preload impress configuration
2879         theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.UI.Effects/UserInterface" );
2880         try
2881         {
2882             xNameAccess = Reference< XNameAccess >(
2883                 xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY );
2884         }
2885         catch (::com::sun::star::uno::Exception& )
2886         {
2887         }
2888 
2889         theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Impress/Layout" );
2890         try
2891         {
2892             xNameAccess = Reference< XNameAccess >(
2893                 xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY );
2894         }
2895         catch (::com::sun::star::uno::Exception& )
2896         {
2897         }
2898 
2899         // preload draw configuration
2900         theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Draw/Layout" );
2901         try
2902         {
2903             xNameAccess = Reference< XNameAccess >(
2904                 xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY );
2905         }
2906         catch (::com::sun::star::uno::Exception& )
2907         {
2908         }
2909 
2910         // preload ui configuration
2911         theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.UI/FilterClassification" );
2912         try
2913         {
2914             xNameAccess = Reference< XNameAccess >(
2915                 xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY );
2916         }
2917         catch (::com::sun::star::uno::Exception& )
2918         {
2919         }
2920 
2921         // preload addons configuration
2922         theArgs[ 0 ] <<= OUString::createFromAscii( "org.openoffice.Office.Addons/AddonUI" );
2923         try
2924         {
2925             xNameAccess = Reference< XNameAccess >(
2926                 xConfigProvider->createInstanceWithArguments( sAccessSrvc, theArgs ), UNO_QUERY );
2927         }
2928         catch (::com::sun::star::uno::Exception& )
2929         {
2930         }
2931     }
2932 }
2933 
OpenClients()2934 void Desktop::OpenClients()
2935 {
2936 
2937     // check if a document has been recovered - if there is one or if a document was loaded by cmdline, no default document
2938     // should be created
2939     Reference < XComponent > xFirst;
2940     sal_Bool bLoaded = sal_False;
2941 
2942     CommandLineArgs* pArgs = GetCommandLineArgs();
2943     SvtInternalOptions  aInternalOptions;
2944 
2945     Reference<XMultiServiceFactory> rFactory = ::comphelper::getProcessServiceFactory();
2946 
2947     if (!pArgs->IsQuickstart()) {
2948         sal_Bool bShowHelp = sal_False;
2949         ::rtl::OUStringBuffer aHelpURLBuffer;
2950         if (pArgs->IsHelpWriter()) {
2951             bShowHelp = sal_True;
2952             aHelpURLBuffer.appendAscii("vnd.sun.star.help://swriter/start");
2953         } else if (pArgs->IsHelpCalc()) {
2954             bShowHelp = sal_True;
2955             aHelpURLBuffer.appendAscii("vnd.sun.star.help://scalc/start");
2956         } else if (pArgs->IsHelpDraw()) {
2957             bShowHelp = sal_True;
2958             aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdraw/start");
2959         } else if (pArgs->IsHelpImpress()) {
2960             bShowHelp = sal_True;
2961             aHelpURLBuffer.appendAscii("vnd.sun.star.help://simpress/start");
2962         } else if (pArgs->IsHelpBase()) {
2963             bShowHelp = sal_True;
2964             aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdatabase/start");
2965         } else if (pArgs->IsHelpBasic()) {
2966             bShowHelp = sal_True;
2967             aHelpURLBuffer.appendAscii("vnd.sun.star.help://sbasic/start");
2968         } else if (pArgs->IsHelpMath()) {
2969             bShowHelp = sal_True;
2970             aHelpURLBuffer.appendAscii("vnd.sun.star.help://smath/start");
2971         }
2972         if (bShowHelp) {
2973             Help *pHelp = Application::GetHelp();
2974 
2975             Any aRet = ::utl::ConfigManager::GetDirectConfigProperty( ::utl::ConfigManager::LOCALE );
2976             rtl::OUString aTmp;
2977             aRet >>= aTmp;
2978             aHelpURLBuffer.appendAscii("?Language=");
2979             aHelpURLBuffer.append(aTmp);
2980 #if defined UNX
2981             aHelpURLBuffer.appendAscii("&System=UNX");
2982 #elif defined WNT
2983             aHelpURLBuffer.appendAscii("&System=WIN");
2984 #elif defined OS2
2985             aHelpURLBuffer.appendAscii("&System=OS2");
2986 #endif
2987             pHelp->Start(aHelpURLBuffer.makeStringAndClear(), NULL);
2988             return;
2989         }
2990     }
2991     else
2992     {
2993         OUString            aIniName;
2994         ::vos::OStartupInfo aInfo;
2995 
2996         aInfo.getExecutableFile( aIniName );
2997         sal_uInt32     lastIndex = aIniName.lastIndexOf('/');
2998         if ( lastIndex > 0 )
2999         {
3000             aIniName    = aIniName.copy( 0, lastIndex+1 );
3001             aIniName    += OUString( RTL_CONSTASCII_USTRINGPARAM( "perftune" ));
3002 #if defined(WNT) || defined(OS2)
3003             aIniName    += OUString( RTL_CONSTASCII_USTRINGPARAM( ".ini" ));
3004 #else
3005             aIniName    += OUString( RTL_CONSTASCII_USTRINGPARAM( "rc" ));
3006 #endif
3007         }
3008 
3009         rtl::Bootstrap aPerfTuneIniFile( aIniName );
3010 
3011         OUString aDefault( RTL_CONSTASCII_USTRINGPARAM( "0" ));
3012         OUString aPreloadData;
3013 
3014         aPerfTuneIniFile.getFrom( OUString( RTL_CONSTASCII_USTRINGPARAM( "QuickstartPreloadConfiguration" )), aPreloadData, aDefault );
3015         if ( aPreloadData.equalsAscii( "1" ))
3016         {
3017             if ( pArgs->IsWriter()  ||
3018                  pArgs->IsCalc()    ||
3019                  pArgs->IsDraw()    ||
3020                  pArgs->IsImpress()    )
3021             {
3022                 PreloadModuleData( pArgs );
3023             }
3024 
3025             PreloadConfigurationData();
3026         }
3027     }
3028 
3029     // Disable AutoSave feature in case "-norestore" or a similar command line switch is set on the command line.
3030     // The reason behind: AutoSave/EmergencySave/AutoRecovery share the same data.
3031     // But the require that all documents, which are saved as backup should exists inside
3032     // memory. May be this mechanism will be inconsistent if the configuration exists ...
3033     // but no document inside memory correspond to this data.
3034     // Further it's not acceptable to recover such documents without any UI. It can
3035     // need some time, where the user won't see any results and wait for finishing the office startup ...
3036     sal_Bool bAllowRecoveryAndSessionManagement = (
3037                                                     ( !pArgs->IsNoRestore() ) &&
3038                                                     ( !pArgs->IsHeadless()  ) &&
3039                                                     ( !pArgs->IsServer()    )
3040                                                   );
3041 
3042     if ( ! bAllowRecoveryAndSessionManagement )
3043     {
3044         try
3045         {
3046             Reference< XDispatch > xRecovery(
3047                     ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.AutoRecovery")) ),
3048                     ::com::sun::star::uno::UNO_QUERY_THROW );
3049 
3050             Reference< XURLTransformer > xParser(
3051                     ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer")) ),
3052                     ::com::sun::star::uno::UNO_QUERY_THROW );
3053 
3054             css::util::URL aCmd;
3055             aCmd.Complete = ::rtl::OUString::createFromAscii("vnd.sun.star.autorecovery:/disableRecovery");
3056             xParser->parseStrict(aCmd);
3057 
3058             xRecovery->dispatch(aCmd, css::uno::Sequence< css::beans::PropertyValue >());
3059         }
3060         catch(const css::uno::Exception& e)
3061         {
3062             OUString aMessage = OUString::createFromAscii("Could not disable AutoRecovery.\n")
3063                 + e.Message;
3064             OSL_ENSURE(sal_False, OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr());
3065         }
3066     }
3067     else
3068     {
3069         sal_Bool bCrashed            = sal_False;
3070         sal_Bool bExistsRecoveryData = sal_False;
3071         sal_Bool bExistsSessionData  = sal_False;
3072 
3073         impl_checkRecoveryState(bCrashed, bExistsRecoveryData, bExistsSessionData);
3074 
3075         if ( !getenv ("OOO_DISABLE_RECOVERY") &&
3076             ( ! bLoaded ) &&
3077             (
3078                 ( bExistsRecoveryData ) || // => crash with files    => recovery
3079                 ( bCrashed            )    // => crash without files => error report
3080             )
3081            )
3082         {
3083             try
3084             {
3085                 impl_callRecoveryUI(
3086                     sal_False          , // false => force recovery instead of emergency save
3087                     bCrashed           ,
3088                     bExistsRecoveryData);
3089                 /* TODO we can't be sure, that at least one document could be recovered here successfully
3090                     So we set bLoaded=sal_True to suppress opening of the default document.
3091                     But we should make it more safe. Otherwise we have an office without an UI ...
3092                     ...
3093                     Maybe we can check the desktop if some documents are existing there.
3094                  */
3095                 Reference< XFramesSupplier > xTasksSupplier(
3096                         ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ),
3097                         ::com::sun::star::uno::UNO_QUERY_THROW );
3098                 Reference< XElementAccess > xList( xTasksSupplier->getFrames(), UNO_QUERY_THROW );
3099                 if ( xList->hasElements() )
3100                     bLoaded = sal_True;
3101             }
3102             catch(const css::uno::Exception& e)
3103             {
3104                 OUString aMessage = OUString::createFromAscii("Error during recovery\n")
3105                     + e.Message;
3106                 OSL_ENSURE(sal_False, OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr());
3107             }
3108         }
3109 
3110         Reference< XInitialization > xSessionListener;
3111         try
3112         {
3113             xSessionListener = Reference< XInitialization >(::comphelper::getProcessServiceFactory()->createInstance(
3114                         OUString::createFromAscii("com.sun.star.frame.SessionListener")), UNO_QUERY_THROW);
3115 
3116             // specifies whether the UI-interaction on Session shutdown is allowed
3117             sal_Bool bAllowUI = isUIOnSessionShutdownAllowed();
3118             css::beans::NamedValue aProperty( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "AllowUserInteractionOnQuit" ) ),
3119                                               css::uno::makeAny( bAllowUI ) );
3120             css::uno::Sequence< css::uno::Any > aArgs( 1 );
3121             aArgs[0] <<= aProperty;
3122 
3123             xSessionListener->initialize( aArgs );
3124         }
3125         catch(const com::sun::star::uno::Exception& e)
3126         {
3127             OUString aMessage = OUString::createFromAscii("Registration of session listener failed\n")
3128                 + e.Message;
3129             OSL_ENSURE(sal_False, OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr());
3130         }
3131 
3132         if (
3133             ( ! bLoaded            ) &&
3134             (   bExistsSessionData )
3135            )
3136         {
3137             // session management
3138             try
3139             {
3140                 Reference< XSessionManagerListener > r(xSessionListener, UNO_QUERY_THROW);
3141                 bLoaded = r->doRestore();
3142             }
3143             catch(const com::sun::star::uno::Exception& e)
3144             {
3145                 OUString aMessage = OUString::createFromAscii("Error in session management\n")
3146                     + e.Message;
3147                 OSL_ENSURE(sal_False, OUStringToOString(aMessage, RTL_TEXTENCODING_ASCII_US).getStr());
3148             }
3149         }
3150     }
3151 
3152     OfficeIPCThread::EnableRequests();
3153 
3154     sal_Bool bShutdown( sal_False );
3155     if ( !pArgs->IsServer() )
3156     {
3157         ProcessDocumentsRequest aRequest(pArgs->getCwdUrl());
3158         aRequest.pcProcessed = NULL;
3159 
3160         pArgs->GetOpenList( aRequest.aOpenList );
3161         pArgs->GetViewList( aRequest.aViewList );
3162         pArgs->GetStartList( aRequest.aStartList );
3163         pArgs->GetPrintList( aRequest.aPrintList );
3164         pArgs->GetPrintToList( aRequest.aPrintToList );
3165         pArgs->GetPrinterName( aRequest.aPrinterName );
3166         pArgs->GetForceOpenList( aRequest.aForceOpenList );
3167         pArgs->GetForceNewList( aRequest.aForceNewList );
3168 
3169         if ( aRequest.aOpenList.getLength() > 0 ||
3170              aRequest.aViewList.getLength() > 0 ||
3171              aRequest.aStartList.getLength() > 0 ||
3172              aRequest.aPrintList.getLength() > 0 ||
3173              aRequest.aForceOpenList.getLength() > 0 ||
3174              aRequest.aForceNewList.getLength() > 0 ||
3175              ( aRequest.aPrintToList.getLength() > 0 && aRequest.aPrinterName.getLength() > 0 ))
3176         {
3177             bLoaded = sal_True;
3178 
3179             if ( pArgs->HasModuleParam() )
3180             {
3181                 SvtModuleOptions    aOpt;
3182 
3183                 // Support command line parameters to start a module (as preselection)
3184                 if ( pArgs->IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
3185                     aRequest.aModule = aOpt.GetFactoryName( SvtModuleOptions::E_WRITER );
3186                 else if ( pArgs->IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
3187                     aRequest.aModule = aOpt.GetFactoryName( SvtModuleOptions::E_CALC );
3188                 else if ( pArgs->IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
3189                     aRequest.aModule= aOpt.GetFactoryName( SvtModuleOptions::E_IMPRESS );
3190                 else if ( pArgs->IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
3191                     aRequest.aModule= aOpt.GetFactoryName( SvtModuleOptions::E_DRAW );
3192             }
3193 
3194             // check for printing disabled
3195             if( ( aRequest.aPrintList.getLength() || aRequest.aPrintToList.getLength() )
3196                 && Application::GetSettings().GetMiscSettings().GetDisablePrinting() )
3197             {
3198                 aRequest.aPrintList = rtl::OUString();
3199                 aRequest.aPrintToList = rtl::OUString();
3200                 ResMgr* pDtResMgr = GetDesktopResManager();
3201                 if( pDtResMgr )
3202                 {
3203                     ErrorBox aBox( NULL, ResId( EBX_ERR_PRINTDISABLED, *pDtResMgr ) );
3204                     aBox.Execute();
3205                 }
3206             }
3207 
3208             // Process request
3209             bShutdown = OfficeIPCThread::ExecuteCmdLineRequests( aRequest );
3210         }
3211     }
3212 
3213     // Don't do anything if we have successfully called terminate at desktop
3214     if ( bShutdown )
3215         return;
3216 
3217     // no default document if a document was loaded by recovery or by command line or if soffice is used as server
3218     Reference< XFramesSupplier > xTasksSupplier(
3219             ::comphelper::getProcessServiceFactory()->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ),
3220             ::com::sun::star::uno::UNO_QUERY_THROW );
3221     Reference< XElementAccess > xList( xTasksSupplier->getFrames(), UNO_QUERY_THROW );
3222     if ( xList->hasElements() || pArgs->IsServer() )
3223         return;
3224 
3225     if ( pArgs->IsQuickstart() || pArgs->IsInvisible() || pArgs->IsBean() || Application::AnyInput( INPUT_APPEVENT ) )
3226         // soffice was started as tray icon ...
3227         return;
3228     {
3229         OpenDefault();
3230     }
3231 }
3232 
OpenDefault()3233 void Desktop::OpenDefault()
3234 {
3235 
3236     RTL_LOGFILE_CONTEXT( aLog, "desktop (cd100003) ::Desktop::OpenDefault" );
3237 
3238     ::rtl::OUString        aName;
3239     SvtModuleOptions    aOpt;
3240 
3241     CommandLineArgs* pArgs = GetCommandLineArgs();
3242     if ( pArgs->IsNoDefault() ) return;
3243     if ( pArgs->HasModuleParam() )
3244     {
3245         // Support new command line parameters to start a module
3246         if ( pArgs->IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
3247             aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITER );
3248         else if ( pArgs->IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
3249             aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_CALC );
3250         else if ( pArgs->IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
3251             aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_IMPRESS );
3252         else if ( pArgs->IsBase() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) )
3253             aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DATABASE );
3254         else if ( pArgs->IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
3255             aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DRAW );
3256         else if ( pArgs->IsMath() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SMATH ) )
3257             aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_MATH );
3258         else if ( pArgs->IsGlobal() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
3259             aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITERGLOBAL );
3260         else if ( pArgs->IsWeb() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
3261             aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITERWEB );
3262     }
3263 
3264     if ( !aName.getLength() )
3265     {
3266         // Old way to create a default document
3267         if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
3268             aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_WRITER );
3269         else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
3270             aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_CALC );
3271         else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
3272             aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_IMPRESS );
3273         else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SDATABASE ) )
3274             aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DATABASE );
3275         else if ( aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
3276             aName = aOpt.GetFactoryEmptyDocumentURL( SvtModuleOptions::E_DRAW );
3277         else
3278             return;
3279     }
3280 
3281     ProcessDocumentsRequest aRequest(pArgs->getCwdUrl());
3282     aRequest.pcProcessed = NULL;
3283     aRequest.aOpenList   = aName;
3284     OfficeIPCThread::ExecuteCmdLineRequests( aRequest );
3285 }
3286 
3287 
GetURL_Impl(const String & rName,boost::optional<rtl::OUString> const & cwdUrl)3288 String GetURL_Impl(
3289     const String& rName, boost::optional< rtl::OUString > const & cwdUrl )
3290 {
3291     // if rName is a vnd.sun.star.script URL do not attempt to parse it
3292     // as INetURLObj does not handle their URLs
3293     if (rName.CompareToAscii("vnd.sun.star.script" , 19) == COMPARE_EQUAL)
3294     {
3295         return rName;
3296     }
3297 
3298     // don't touch file urls, those should already be in internal form
3299     // they won't get better here (#112849#)
3300     if (rName.CompareToAscii("file:" , 5) == COMPARE_EQUAL)
3301     {
3302         return rName;
3303     }
3304 
3305     if ( rName.CompareToAscii("service:" , 8) == COMPARE_EQUAL )
3306     {
3307         return rName;
3308     }
3309 
3310     // Add path seperator to these directory and make given URL (rName) absolute by using of current working directory
3311     // Attention: "setFianlSlash()" is necessary for calling "smartRel2Abs()"!!!
3312     // Otherwise last part will be ignored and wrong result will be returned!!!
3313     // "smartRel2Abs()" interpret given URL as file not as path. So he truncate last element to get the base path ...
3314     // But if we add a seperator - he doesn't do it anymore.
3315     INetURLObject aObj;
3316     if (cwdUrl) {
3317         aObj.SetURL(*cwdUrl);
3318         aObj.setFinalSlash();
3319     }
3320 
3321     // Use the provided parameters for smartRel2Abs to support the usage of '%' in system paths.
3322     // Otherwise this char won't get encoded and we are not able to load such files later,
3323     // see #110156#
3324     bool bWasAbsolute;
3325     INetURLObject aURL     = aObj.smartRel2Abs( rName, bWasAbsolute, false, INetURLObject::WAS_ENCODED,
3326                                                 RTL_TEXTENCODING_UTF8, true );
3327     String        aFileURL = aURL.GetMainURL(INetURLObject::NO_DECODE);
3328 
3329     ::osl::FileStatus aStatus( FileStatusMask_FileURL );
3330     ::osl::DirectoryItem aItem;
3331     if( ::osl::FileBase::E_None == ::osl::DirectoryItem::get( aFileURL, aItem ) &&
3332         ::osl::FileBase::E_None == aItem.getFileStatus( aStatus ) )
3333             aFileURL = aStatus.getFileURL();
3334 
3335     return aFileURL;
3336 }
3337 
HandleAppEvent(const ApplicationEvent & rAppEvent)3338 void Desktop::HandleAppEvent( const ApplicationEvent& rAppEvent )
3339 {
3340     if ( rAppEvent.GetEvent() == "APPEAR" && !GetCommandLineArgs()->IsInvisible() )
3341     {
3342         css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory();
3343 
3344         // find active task - the active task is always a visible task
3345         ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFramesSupplier >
3346                 xDesktop( xSMGR->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ),
3347                 ::com::sun::star::uno::UNO_QUERY );
3348         ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xTask = xDesktop->getActiveFrame();
3349         if ( !xTask.is() )
3350         {
3351             // get any task if there is no active one
3352             ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > xList( xDesktop->getFrames(), ::com::sun::star::uno::UNO_QUERY );
3353             if ( xList->getCount()>0 )
3354                 xList->getByIndex(0) >>= xTask;
3355         }
3356 
3357         if ( xTask.is() )
3358         {
3359             Reference< com::sun::star::awt::XTopWindow > xTop( xTask->getContainerWindow(), UNO_QUERY );
3360             xTop->toFront();
3361         }
3362         else
3363         {
3364             // no visible task that could be activated found
3365             Reference< XFrame > xBackingFrame;
3366             Reference< ::com::sun::star::awt::XWindow > xContainerWindow;
3367             ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xDesktopFrame( xDesktop, UNO_QUERY );
3368 
3369             xBackingFrame = xDesktopFrame->findFrame(OUString( RTL_CONSTASCII_USTRINGPARAM( "_blank" )), 0);
3370             if (xBackingFrame.is())
3371                 xContainerWindow = xBackingFrame->getContainerWindow();
3372             if (xContainerWindow.is())
3373             {
3374                 Sequence< Any > lArgs(1);
3375                 lArgs[0] <<= xContainerWindow;
3376                 Reference< XController > xBackingComp(
3377                     xSMGR->createInstanceWithArguments(OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.StartModule") ), lArgs),
3378                     UNO_QUERY);
3379                 if (xBackingComp.is())
3380                 {
3381                     Reference< ::com::sun::star::awt::XWindow > xBackingWin(xBackingComp, UNO_QUERY);
3382                     // Attention: You MUST(!) call setComponent() before you call attachFrame().
3383                     // Because the backing component set the property "IsBackingMode" of the frame
3384                     // to true inside attachFrame(). But setComponent() reset this state everytimes ...
3385                     xBackingFrame->setComponent(xBackingWin, xBackingComp);
3386                     xBackingComp->attachFrame(xBackingFrame);
3387                     xContainerWindow->setVisible(sal_True);
3388 
3389                     Window* pCompWindow = VCLUnoHelper::GetWindow(xBackingFrame->getComponentWindow());
3390                     if (pCompWindow)
3391                         pCompWindow->Update();
3392                 }
3393             }
3394         }
3395     }
3396     else if ( rAppEvent.GetEvent() == "QUICKSTART" && !GetCommandLineArgs()->IsInvisible()  )
3397     {
3398         // If the office has been started the second time its command line arguments are sent through a pipe
3399         // connection to the first office. We want to reuse the quickstart option for the first office.
3400         // NOTICE: The quickstart service must be initialized inside the "main thread", so we use the
3401         // application events to do this (they are executed inside main thread)!!!
3402         // Don't start quickstart service if the user specified "-invisible" on the command line!
3403         sal_Bool bQuickstart( sal_True );
3404         Sequence< Any > aSeq( 1 );
3405         aSeq[0] <<= bQuickstart;
3406 
3407         Reference < XInitialization > xQuickstart( ::comphelper::getProcessServiceFactory()->createInstance(
3408                                             DEFINE_CONST_UNICODE( "com.sun.star.office.Quickstart" )),
3409                                             UNO_QUERY );
3410         if ( xQuickstart.is() )
3411             xQuickstart->initialize( aSeq );
3412     }
3413     else if ( rAppEvent.GetEvent() == "ACCEPT" )
3414     {
3415         // every time an accept parameter is used we create an acceptor
3416         // with the corresponding accept-string
3417         OUString aAcceptString(rAppEvent.GetData().GetBuffer());
3418         createAcceptor(aAcceptString);
3419     }
3420     else if ( rAppEvent.GetEvent() == "UNACCEPT" )
3421     {
3422         // try to remove corresponding acceptor
3423         OUString aUnAcceptString(rAppEvent.GetData().GetBuffer());
3424         destroyAcceptor(aUnAcceptString);
3425     }
3426     else if ( rAppEvent.GetEvent() == "SaveDocuments" )
3427     {
3428         Desktop::_bTasksSaved = sal_False;
3429         Desktop::_bTasksSaved = SaveTasks();
3430     }
3431     else if ( rAppEvent.GetEvent() == "OPENHELPURL" )
3432     {
3433         // start help for a specific URL
3434         OUString aHelpURL(rAppEvent.GetData().GetBuffer());
3435         Help *pHelp = Application::GetHelp();
3436         pHelp->Start(aHelpURL, NULL);
3437     }
3438     else if ( rAppEvent.GetEvent() == APPEVENT_OPEN_STRING )
3439     {
3440         OUString aOpenURL(rAppEvent.GetData().GetBuffer());
3441 
3442         CommandLineArgs* pCmdLine = GetCommandLineArgs();
3443         if ( !pCmdLine->IsInvisible() && !pCmdLine->IsTerminateAfterInit() )
3444         {
3445             ProcessDocumentsRequest* pDocsRequest = new ProcessDocumentsRequest(
3446                 pCmdLine->getCwdUrl());
3447             pDocsRequest->aOpenList = aOpenURL;
3448             pDocsRequest->pcProcessed = NULL;
3449 
3450             OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest );
3451             delete pDocsRequest;
3452         }
3453     }
3454     else if ( rAppEvent.GetEvent() == APPEVENT_PRINT_STRING )
3455     {
3456         OUString aPrintURL(rAppEvent.GetData().GetBuffer());
3457 
3458         CommandLineArgs* pCmdLine = GetCommandLineArgs();
3459         if ( !pCmdLine->IsInvisible() && !pCmdLine->IsTerminateAfterInit() )
3460         {
3461             ProcessDocumentsRequest* pDocsRequest = new ProcessDocumentsRequest(
3462                 pCmdLine->getCwdUrl());
3463             pDocsRequest->aPrintList = aPrintURL;
3464             pDocsRequest->pcProcessed = NULL;
3465 
3466             OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest );
3467             delete pDocsRequest;
3468         }
3469     }
3470 #ifndef UNX
3471     else if ( rAppEvent.GetEvent() == "HELP" )
3472     {
3473         // in non unix version allow showing of cmdline help window
3474         displayCmdlineHelp();
3475     }
3476 #endif
3477     else if ( rAppEvent.GetEvent() == "SHOWDIALOG" )
3478     {
3479         // ignore all errors here. It's clicking a menu entry only ...
3480         // The user will try it again, in case nothing happens .-)
3481         try
3482         {
3483             css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory();
3484 
3485             com::sun::star::uno::Reference< ::com::sun::star::frame::XDispatchProvider >
3486                 xDesktop( xSMGR->createInstance( OUSTRING(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")) ),
3487                 ::com::sun::star::uno::UNO_QUERY );
3488 
3489             // check provider ... we know it's weak reference only
3490             if ( ! xDesktop.is())
3491                 return;
3492 
3493             css::uno::Reference< css::util::XURLTransformer > xParser(xSMGR->createInstance(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer"))), css::uno::UNO_QUERY_THROW);
3494             css::util::URL aCommand;
3495             if( rAppEvent.GetData().EqualsAscii( "PREFERENCES" ) )
3496                 aCommand.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:OptionsTreeDialog" ) );
3497             else if( rAppEvent.GetData().EqualsAscii( "ABOUT" ) )
3498                 aCommand.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:About" ) );
3499             if( aCommand.Complete.getLength() )
3500             {
3501                 xParser->parseStrict(aCommand);
3502 
3503                 css::uno::Reference< css::frame::XDispatch > xDispatch = xDesktop->queryDispatch(aCommand, rtl::OUString(), 0);
3504                 if (xDispatch.is())
3505                     xDispatch->dispatch(aCommand, css::uno::Sequence< css::beans::PropertyValue >());
3506             }
3507         }
3508         catch(const css::uno::Exception&)
3509         {}
3510     }
3511     else if( rAppEvent.GetEvent() == "PRIVATE:DOSHUTDOWN" )
3512     {
3513         Desktop* pD = dynamic_cast<Desktop*>(GetpApp());
3514         OSL_ENSURE( pD, "no desktop ?!?" );
3515         if( pD )
3516             pD->doShutdown();
3517     }
3518 }
3519 
OpenSplashScreen()3520 void Desktop::OpenSplashScreen()
3521 {
3522     ::rtl::OUString     aTmpString;
3523     CommandLineArgs*    pCmdLine = GetCommandLineArgs();
3524     sal_Bool bVisible = sal_False;
3525     // Show intro only if this is normal start (e.g. no server, no quickstart, no printing )
3526     if ( !pCmdLine->IsInvisible() &&
3527          !pCmdLine->IsHeadless() &&
3528          !pCmdLine->IsQuickstart() &&
3529          !pCmdLine->IsMinimized() &&
3530          !pCmdLine->IsNoLogo() &&
3531          !pCmdLine->IsTerminateAfterInit() &&
3532          !pCmdLine->GetPrintList( aTmpString ) &&
3533          !pCmdLine->GetPrintToList( aTmpString ) )
3534     {
3535         // Determine application name from command line parameters
3536         OUString aAppName;
3537         if ( pCmdLine->IsWriter() )
3538             aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "writer" ));
3539         else if ( pCmdLine->IsCalc() )
3540             aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "calc" ));
3541         else if ( pCmdLine->IsDraw() )
3542             aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "draw" ));
3543         else if ( pCmdLine->IsImpress() )
3544             aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "impress" ));
3545         else if ( pCmdLine->IsBase() )
3546             aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "base" ));
3547         else if ( pCmdLine->IsGlobal() )
3548             aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "global" ));
3549         else if ( pCmdLine->IsMath() )
3550             aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "math" ));
3551         else if ( pCmdLine->IsWeb() )
3552             aAppName = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "web" ));
3553 
3554         bVisible = sal_True;
3555         Sequence< Any > aSeq( 2 );
3556         aSeq[0] <<= bVisible;
3557         aSeq[1] <<= aAppName;
3558         m_rSplashScreen = Reference<XStatusIndicator>(
3559             comphelper::getProcessServiceFactory()->createInstanceWithArguments(
3560             OUString::createFromAscii("com.sun.star.office.SplashScreen"),
3561             aSeq), UNO_QUERY);
3562 
3563         if(m_rSplashScreen.is())
3564                 m_rSplashScreen->start(OUString::createFromAscii("SplashScreen"), 100);
3565     }
3566 
3567 }
3568 
SetSplashScreenProgress(sal_Int32 iProgress)3569 void Desktop::SetSplashScreenProgress(sal_Int32 iProgress)
3570 {
3571     if(m_rSplashScreen.is())
3572     {
3573         m_rSplashScreen->setValue(iProgress);
3574     }
3575 }
3576 
SetSplashScreenText(const::rtl::OUString & rText)3577 void Desktop::SetSplashScreenText( const ::rtl::OUString& rText )
3578 {
3579     if( m_rSplashScreen.is() )
3580     {
3581         m_rSplashScreen->setText( rText );
3582     }
3583 }
3584 
CloseSplashScreen()3585 void Desktop::CloseSplashScreen()
3586 {
3587     if(m_rSplashScreen.is())
3588     {
3589         m_rSplashScreen->end();
3590         m_rSplashScreen = NULL;
3591     }
3592 }
3593 
3594 // ========================================================================
DoFirstRunInitializations()3595 void Desktop::DoFirstRunInitializations()
3596 {
3597     try
3598     {
3599         Reference< XJobExecutor > xExecutor( ::comphelper::getProcessServiceFactory()->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.task.JobExecutor" ) ), UNO_QUERY );
3600         if( xExecutor.is() )
3601             xExecutor->trigger( ::rtl::OUString::createFromAscii("onFirstRunInitialization") );
3602     }
3603     catch(const ::com::sun::star::uno::Exception&)
3604     {
3605         OSL_ENSURE( sal_False, "Desktop::DoFirstRunInitializations: caught an exception while trigger job executor ..." );
3606     }
3607 }
3608 
3609 // ========================================================================
CheckFirstRun()3610 void Desktop::CheckFirstRun( )
3611 {
3612     const ::rtl::OUString sCommonMiscNodeName = ::rtl::OUString::createFromAscii( "/org.openoffice.Office.Common/Misc" );
3613     const ::rtl::OUString sFirstRunNodeName = ::rtl::OUString::createFromAscii( "FirstRun" );
3614 
3615     // --------------------------------------------------------------------
3616     // check if this is the first office start
3617 
3618     // for this, open the Common/Misc node where this info is stored
3619     ::utl::OConfigurationTreeRoot aCommonMisc = ::utl::OConfigurationTreeRoot::createWithServiceFactory(
3620         ::comphelper::getProcessServiceFactory( ),
3621         sCommonMiscNodeName,
3622         2,
3623         ::utl::OConfigurationTreeRoot::CM_UPDATABLE
3624     );
3625 
3626     // read the flag
3627     OSL_ENSURE( aCommonMisc.isValid(), "Desktop::CheckFirstRun: could not open the config node needed!" );
3628     sal_Bool bIsFirstRun = sal_False;
3629     aCommonMisc.getNodeValue( sFirstRunNodeName ) >>= bIsFirstRun;
3630 
3631     if ( !bIsFirstRun )
3632         // nothing to do ....
3633         return;
3634 
3635     // --------------------------------------------------------------------
3636     // it is the first run
3637     // this has once been done using a vos timer. this could lead to problems when
3638     // the timer would trigger when the app is already going down again, since VCL would
3639     // no longer be available. Since the old handler would do a postUserEvent to the main
3640     // thread anyway, we can use a vcl timer here to prevent the race contition (#107197#)
3641     m_firstRunTimer.SetTimeout(3000); // 3 sec.
3642     m_firstRunTimer.SetTimeoutHdl(LINK(this, Desktop, AsyncInitFirstRun));
3643     m_firstRunTimer.Start();
3644 
3645     // --------------------------------------------------------------------
3646     // reset the config flag
3647 
3648     // set the value
3649     aCommonMisc.setNodeValue( sFirstRunNodeName, makeAny( (sal_Bool)sal_False ) );
3650     // commit the changes
3651     aCommonMisc.commit();
3652 }
3653 
3654 }
3655