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