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