LCOV - code coverage report
Current view: top level - desktop/source/app - officeipcthread.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 171 457 37.4 %
Date: 2012-08-25 Functions: 20 36 55.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 125 764 16.4 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : 
      30                 :            : #include "app.hxx"
      31                 :            : #include "officeipcthread.hxx"
      32                 :            : #include "cmdlineargs.hxx"
      33                 :            : #include "dispatchwatcher.hxx"
      34                 :            : #include <memory>
      35                 :            : #include <stdio.h>
      36                 :            : #include <osl/process.h>
      37                 :            : #include <unotools/bootstrap.hxx>
      38                 :            : #include <vcl/svapp.hxx>
      39                 :            : #include <vcl/help.hxx>
      40                 :            : #include <unotools/configmgr.hxx>
      41                 :            : #include <osl/thread.hxx>
      42                 :            : #include <rtl/digest.h>
      43                 :            : #include <rtl/ustrbuf.hxx>
      44                 :            : #include <rtl/instance.hxx>
      45                 :            : #include <osl/conditn.hxx>
      46                 :            : #include <unotools/moduleoptions.hxx>
      47                 :            : #include <rtl/bootstrap.hxx>
      48                 :            : #include <rtl/strbuf.hxx>
      49                 :            : #include <comphelper/processfactory.hxx>
      50                 :            : #include <osl/file.hxx>
      51                 :            : #include <rtl/process.h>
      52                 :            : #include "tools/getprocessworkingdir.hxx"
      53                 :            : 
      54                 :            : using namespace desktop;
      55                 :            : using namespace ::com::sun::star::uno;
      56                 :            : using namespace ::com::sun::star::lang;
      57                 :            : using namespace ::com::sun::star::frame;
      58                 :            : 
      59                 :            : using ::rtl::OString;
      60                 :            : using ::rtl::OUString;
      61                 :            : using ::rtl::OUStringBuffer;
      62                 :            : 
      63                 :            : const char  *OfficeIPCThread::sc_aTerminationSequence = "InternalIPC::TerminateThread";
      64                 :            : const int OfficeIPCThread::sc_nTSeqLength = 28;
      65                 :            : const char  *OfficeIPCThread::sc_aShowSequence = "-tofront";
      66                 :            : const int OfficeIPCThread::sc_nShSeqLength = 5;
      67                 :            : const char  *OfficeIPCThread::sc_aConfirmationSequence = "InternalIPC::ProcessingDone";
      68                 :            : const int OfficeIPCThread::sc_nCSeqLength = 27;
      69                 :            : 
      70                 :            : namespace { static char const ARGUMENT_PREFIX[] = "InternalIPC::Arguments"; }
      71                 :            : 
      72                 :            : // Type of pipe we use
      73                 :            : enum PipeMode
      74                 :            : {
      75                 :            :     PIPEMODE_DONTKNOW,
      76                 :            :     PIPEMODE_CREATED,
      77                 :            :     PIPEMODE_CONNECTED
      78                 :            : };
      79                 :            : 
      80                 :            : namespace desktop
      81                 :            : {
      82                 :            : 
      83                 :            : namespace {
      84                 :            : 
      85                 :            : class Parser: public CommandLineArgs::Supplier {
      86                 :            : public:
      87         [ #  # ]:          0 :     explicit Parser(rtl::OString const & input): m_input(input) {
      88         [ #  # ]:          0 :         if (!m_input.match(ARGUMENT_PREFIX) ||
           [ #  #  #  # ]
      89                 :          0 :             m_input.getLength() == RTL_CONSTASCII_LENGTH(ARGUMENT_PREFIX))
      90                 :            :         {
      91         [ #  # ]:          0 :             throw CommandLineArgs::Supplier::Exception();
      92                 :            :         }
      93                 :          0 :         m_index = RTL_CONSTASCII_LENGTH(ARGUMENT_PREFIX);
      94   [ #  #  #  # ]:          0 :         switch (m_input[m_index++]) {
      95                 :            :         case '0':
      96                 :          0 :             break;
      97                 :            :         case '1':
      98                 :            :             {
      99                 :          0 :                 rtl::OUString url;
     100 [ #  # ][ #  # ]:          0 :                 if (!next(&url, false)) {
     101         [ #  # ]:          0 :                     throw CommandLineArgs::Supplier::Exception();
     102                 :            :                 }
     103         [ #  # ]:          0 :                 m_cwdUrl.reset(url);
     104                 :          0 :                 break;
     105                 :            :             }
     106                 :            :         case '2':
     107                 :            :             {
     108                 :          0 :                 rtl::OUString path;
     109 [ #  # ][ #  # ]:          0 :                 if (!next(&path, false)) {
     110         [ #  # ]:          0 :                     throw CommandLineArgs::Supplier::Exception();
     111                 :            :                 }
     112                 :          0 :                 rtl::OUString url;
     113 [ #  # ][ #  # ]:          0 :                 if (osl::FileBase::getFileURLFromSystemPath(path, url) ==
     114                 :            :                     osl::FileBase::E_None)
     115                 :            :                 {
     116         [ #  # ]:          0 :                     m_cwdUrl.reset(url);
     117                 :            :                 }
     118                 :          0 :                 break;
     119                 :            :             }
     120                 :            :         default:
     121         [ #  # ]:          0 :             throw CommandLineArgs::Supplier::Exception();
     122                 :            :         }
     123                 :          0 :     }
     124                 :            : 
     125 [ #  # ][ #  # ]:          0 :     virtual ~Parser() {}
     126                 :            : 
     127                 :          0 :     virtual boost::optional< rtl::OUString > getCwdUrl() { return m_cwdUrl; }
     128                 :            : 
     129                 :          0 :     virtual bool next(rtl::OUString * argument) { return next(argument, true); }
     130                 :            : 
     131                 :            : private:
     132                 :          0 :     virtual bool next(rtl::OUString * argument, bool prefix) {
     133                 :            :         OSL_ASSERT(argument != NULL);
     134         [ #  # ]:          0 :         if (m_index < m_input.getLength()) {
     135         [ #  # ]:          0 :             if (prefix) {
     136         [ #  # ]:          0 :                 if (m_input[m_index] != ',') {
     137         [ #  # ]:          0 :                     throw CommandLineArgs::Supplier::Exception();
     138                 :            :                 }
     139                 :          0 :                 ++m_index;
     140                 :            :             }
     141                 :          0 :             rtl::OStringBuffer b;
     142         [ #  # ]:          0 :             while (m_index < m_input.getLength()) {
     143                 :          0 :                 char c = m_input[m_index];
     144         [ #  # ]:          0 :                 if (c == ',') {
     145                 :          0 :                     break;
     146                 :            :                 }
     147                 :          0 :                 ++m_index;
     148         [ #  # ]:          0 :                 if (c == '\\') {
     149         [ #  # ]:          0 :                     if (m_index < m_input.getLength()) {
     150                 :          0 :                         c = m_input[m_index++];
     151      [ #  #  # ]:          0 :                         switch (c) {
     152                 :            :                         case '0':
     153                 :          0 :                             c = '\0';
     154                 :          0 :                             break;
     155                 :            :                         case ',':
     156                 :            :                         case '\\':
     157                 :          0 :                             break;
     158                 :            :                         default:
     159         [ #  # ]:          0 :                             throw CommandLineArgs::Supplier::Exception();
     160                 :            :                         }
     161                 :            :                     } else {
     162         [ #  # ]:          0 :                         throw CommandLineArgs::Supplier::Exception();
     163                 :            :                     }
     164                 :            :                 }
     165         [ #  # ]:          0 :                 b.append(c);
     166                 :            :             }
     167                 :          0 :             rtl::OString b2(b.makeStringAndClear());
     168         [ #  # ]:          0 :             if (!rtl_convertStringToUString(
     169                 :            :                     &argument->pData, b2.getStr(), b2.getLength(),
     170                 :            :                     RTL_TEXTENCODING_UTF8,
     171                 :            :                     (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
     172                 :            :                      RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
     173                 :          0 :                      RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
     174                 :            :             {
     175         [ #  # ]:          0 :                 throw CommandLineArgs::Supplier::Exception();
     176                 :            :             }
     177                 :          0 :             return true;
     178                 :            :         } else {
     179                 :          0 :             return false;
     180                 :            :         }
     181                 :            :     }
     182                 :            : 
     183                 :            :     boost::optional< rtl::OUString > m_cwdUrl;
     184                 :            :     rtl::OString m_input;
     185                 :            :     sal_Int32 m_index;
     186                 :            : };
     187                 :            : 
     188                 :          0 : bool addArgument(rtl::OStringBuffer &rArguments, char prefix,
     189                 :            :     const rtl::OUString &rArgument)
     190                 :            : {
     191                 :          0 :     rtl::OString utf8;
     192         [ #  # ]:          0 :     if (!rArgument.convertToString(
     193                 :            :             &utf8, RTL_TEXTENCODING_UTF8,
     194                 :            :             (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
     195                 :          0 :              RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
     196                 :            :     {
     197                 :          0 :         return false;
     198                 :            :     }
     199         [ #  # ]:          0 :     rArguments.append(prefix);
     200         [ #  # ]:          0 :     for (sal_Int32 i = 0; i < utf8.getLength(); ++i) {
     201                 :          0 :         char c = utf8[i];
     202   [ #  #  #  # ]:          0 :         switch (c) {
     203                 :            :         case '\0':
     204         [ #  # ]:          0 :             rArguments.append("\\0");
     205                 :          0 :             break;
     206                 :            :         case ',':
     207         [ #  # ]:          0 :             rArguments.append("\\,");
     208                 :          0 :             break;
     209                 :            :         case '\\':
     210         [ #  # ]:          0 :             rArguments.append("\\\\");
     211                 :          0 :             break;
     212                 :            :         default:
     213         [ #  # ]:          0 :             rArguments.append(c);
     214                 :          0 :             break;
     215                 :            :         }
     216                 :            :     }
     217                 :          0 :     return true;
     218                 :            : }
     219                 :            : 
     220                 :            : }
     221                 :            : 
     222                 :        158 : rtl::Reference< OfficeIPCThread > OfficeIPCThread::pGlobalOfficeIPCThread;
     223                 :            :     namespace { struct Security : public rtl::Static<osl::Security, Security> {}; }
     224                 :            : 
     225                 :            : // Turns a string in aMsg such as file:///home/foo/.libreoffice/3
     226                 :            : // Into a hex string of well known length ff132a86...
     227                 :        158 : String CreateMD5FromString( const OUString& aMsg )
     228                 :            : {
     229                 :            : #if (OSL_DEBUG_LEVEL > 2)
     230                 :            :     fprintf( stderr, "create md5 from '%s'\n",
     231                 :            :              rtl::OUStringToOString (aMsg, RTL_TEXTENCODING_UTF8).getStr() );
     232                 :            : #endif
     233                 :            : 
     234                 :        158 :     rtlDigest handle = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
     235         [ +  - ]:        158 :     if ( handle )
     236                 :            :     {
     237                 :        158 :         const sal_uInt8* pData = (const sal_uInt8*)aMsg.getStr();
     238                 :        158 :         sal_uInt32       nSize = ( aMsg.getLength() * sizeof( sal_Unicode ));
     239                 :        158 :         sal_uInt32       nMD5KeyLen = rtl_digest_queryLength( handle );
     240         [ +  - ]:        158 :         sal_uInt8*       pMD5KeyBuffer = new sal_uInt8[ nMD5KeyLen ];
     241                 :            : 
     242                 :        158 :         rtl_digest_init( handle, pData, nSize );
     243                 :        158 :         rtl_digest_update( handle, pData, nSize );
     244                 :        158 :         rtl_digest_get( handle, pMD5KeyBuffer, nMD5KeyLen );
     245                 :        158 :         rtl_digest_destroy( handle );
     246                 :            : 
     247                 :            :         // Create hex-value string from the MD5 value to keep the string size minimal
     248                 :        158 :         OUStringBuffer aBuffer( nMD5KeyLen * 2 + 1 );
     249         [ +  + ]:       2686 :         for ( sal_uInt32 i = 0; i < nMD5KeyLen; i++ )
     250         [ +  - ]:       2528 :             aBuffer.append( (sal_Int32)pMD5KeyBuffer[i], 16 );
     251                 :            : 
     252         [ +  - ]:        158 :         delete [] pMD5KeyBuffer;
     253 [ +  - ][ +  - ]:        158 :         return aBuffer.makeStringAndClear();
     254                 :            :     }
     255                 :            : 
     256                 :        158 :     return String();
     257                 :            : }
     258                 :            : 
     259                 :            : class ProcessEventsClass_Impl
     260                 :            : {
     261                 :            : public:
     262                 :            :     DECL_STATIC_LINK( ProcessEventsClass_Impl, CallEvent, void* pEvent );
     263                 :            :     DECL_STATIC_LINK( ProcessEventsClass_Impl, ProcessDocumentsEvent, void* pEvent );
     264                 :            : };
     265                 :            : 
     266                 :          0 : IMPL_STATIC_LINK_NOINSTANCE( ProcessEventsClass_Impl, CallEvent, void*, pEvent )
     267                 :            : {
     268                 :            :     // Application events are processed by the Desktop::HandleAppEvent implementation.
     269                 :          0 :     Desktop::HandleAppEvent( *((ApplicationEvent*)pEvent) );
     270         [ #  # ]:          0 :     delete (ApplicationEvent*)pEvent;
     271                 :          0 :     return 0;
     272                 :            : }
     273                 :            : 
     274                 :          0 : IMPL_STATIC_LINK_NOINSTANCE( ProcessEventsClass_Impl, ProcessDocumentsEvent, void*, pEvent )
     275                 :            : {
     276                 :            :     // Documents requests are processed by the OfficeIPCThread implementation
     277                 :          0 :     ProcessDocumentsRequest* pDocsRequest = (ProcessDocumentsRequest*)pEvent;
     278                 :            : 
     279         [ #  # ]:          0 :     if ( pDocsRequest )
     280                 :            :     {
     281                 :          0 :         OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest );
     282         [ #  # ]:          0 :         delete pDocsRequest;
     283                 :            :     }
     284                 :          0 :     return 0;
     285                 :            : }
     286                 :            : 
     287                 :          0 : void ImplPostForeignAppEvent( ApplicationEvent* pEvent )
     288                 :            : {
     289         [ #  # ]:          0 :     Application::PostUserEvent( STATIC_LINK( NULL, ProcessEventsClass_Impl, CallEvent ), pEvent );
     290                 :          0 : }
     291                 :            : 
     292                 :          0 : void ImplPostProcessDocumentsEvent( ProcessDocumentsRequest* pEvent )
     293                 :            : {
     294         [ #  # ]:          0 :     Application::PostUserEvent( STATIC_LINK( NULL, ProcessEventsClass_Impl, ProcessDocumentsEvent ), pEvent );
     295                 :          0 : }
     296                 :            : 
     297                 :          0 : oslSignalAction SAL_CALL SalMainPipeExchangeSignal_impl(void* /*pData*/, oslSignalInfo* pInfo)
     298                 :            : {
     299         [ #  # ]:          0 :     if( pInfo->Signal == osl_Signal_Terminate )
     300                 :          0 :         OfficeIPCThread::DisableOfficeIPCThread(false);
     301                 :          0 :     return osl_Signal_ActCallNextHdl;
     302                 :            : }
     303                 :            : 
     304                 :            : // ----------------------------------------------------------------------------
     305                 :            : 
     306                 :            : // The OfficeIPCThreadController implementation is a bookkeeper for all pending requests
     307                 :            : // that were created by the OfficeIPCThread. The requests are waiting to be processed by
     308                 :            : // our framework loadComponentFromURL function (e.g. open/print request).
     309                 :            : // During shutdown the framework is asking OfficeIPCThreadController about pending requests.
     310                 :            : // If there are pending requests framework has to stop the shutdown process. It is waiting
     311                 :            : // for these requests because framework is not able to handle shutdown and open a document
     312                 :            : // concurrently.
     313                 :            : 
     314                 :            : 
     315                 :            : // XServiceInfo
     316                 :         96 : OUString SAL_CALL OfficeIPCThreadController::getImplementationName()
     317                 :            : throw ( RuntimeException )
     318                 :            : {
     319                 :         96 :     return OUString( "com.sun.star.comp.OfficeIPCThreadController" );
     320                 :            : }
     321                 :            : 
     322                 :          0 : sal_Bool SAL_CALL OfficeIPCThreadController::supportsService( const OUString& )
     323                 :            : throw ( RuntimeException )
     324                 :            : {
     325                 :          0 :     return sal_False;
     326                 :            : }
     327                 :            : 
     328                 :          0 : Sequence< OUString > SAL_CALL OfficeIPCThreadController::getSupportedServiceNames()
     329                 :            : throw ( RuntimeException )
     330                 :            : {
     331                 :          0 :     Sequence< OUString > aSeq( 0 );
     332                 :          0 :     return aSeq;
     333                 :            : }
     334                 :            : 
     335                 :            : // XEventListener
     336                 :          0 : void SAL_CALL OfficeIPCThreadController::disposing( const EventObject& )
     337                 :            : throw( RuntimeException )
     338                 :            : {
     339                 :          0 : }
     340                 :            : 
     341                 :            : // XTerminateListener
     342                 :         96 : void SAL_CALL OfficeIPCThreadController::queryTermination( const EventObject& )
     343                 :            : throw( TerminationVetoException, RuntimeException )
     344                 :            : {
     345                 :            :     // Desktop ask about pending request through our office ipc pipe. We have to
     346                 :            :     // be sure that no pending request is waiting because framework is not able to
     347                 :            :     // handle shutdown and open a document concurrently.
     348                 :            : 
     349         [ -  + ]:         96 :     if ( OfficeIPCThread::AreRequestsPending() )
     350         [ #  # ]:          0 :         throw TerminationVetoException();
     351                 :            :     else
     352                 :         96 :         OfficeIPCThread::SetDowning();
     353                 :         96 : }
     354                 :            : 
     355                 :         96 : void SAL_CALL OfficeIPCThreadController::notifyTermination( const EventObject& )
     356                 :            : throw( RuntimeException )
     357                 :            : {
     358                 :         96 : }
     359                 :            : 
     360                 :            : namespace
     361                 :            : {
     362                 :            :     class theOfficeIPCThreadMutex
     363                 :            :         : public rtl::Static<osl::Mutex, theOfficeIPCThreadMutex> {};
     364                 :            : }
     365                 :            : 
     366                 :        858 : ::osl::Mutex& OfficeIPCThread::GetMutex()
     367                 :            : {
     368                 :        858 :     return theOfficeIPCThreadMutex::get();
     369                 :            : }
     370                 :            : 
     371                 :         96 : void OfficeIPCThread::SetDowning()
     372                 :            : {
     373                 :            :     // We have the order to block all incoming requests. Framework
     374                 :            :     // wants to shutdown and we have to make sure that no loading/printing
     375                 :            :     // requests are executed anymore.
     376 [ +  - ][ +  - ]:         96 :     ::osl::MutexGuard   aGuard( GetMutex() );
     377                 :            : 
     378         [ +  - ]:         96 :     if ( pGlobalOfficeIPCThread.is() )
     379         [ +  - ]:         96 :         pGlobalOfficeIPCThread->mbDowning = true;
     380                 :         96 : }
     381                 :            : 
     382                 :            : static bool s_bInEnableRequests = false;
     383                 :            : 
     384                 :         96 : void OfficeIPCThread::EnableRequests( bool i_bEnable )
     385                 :            : {
     386                 :            :     // switch between just queueing the requests and executing them
     387 [ +  - ][ +  - ]:         96 :     ::osl::MutexGuard   aGuard( GetMutex() );
     388                 :            : 
     389         [ +  - ]:         96 :     if ( pGlobalOfficeIPCThread.is() )
     390                 :            :     {
     391                 :         96 :         s_bInEnableRequests = true;
     392                 :         96 :         pGlobalOfficeIPCThread->mbRequestsEnabled = i_bEnable;
     393         [ +  - ]:         96 :         if( i_bEnable )
     394                 :            :         {
     395                 :            :             // hit the compiler over the head
     396 [ +  - ][ +  - ]:         96 :             ProcessDocumentsRequest aEmptyReq = ProcessDocumentsRequest( boost::optional< rtl::OUString >() );
                 [ +  - ]
     397                 :            :             // trigger already queued requests
     398 [ +  - ][ +  - ]:         96 :             OfficeIPCThread::ExecuteCmdLineRequests( aEmptyReq );
     399                 :            :         }
     400                 :         96 :         s_bInEnableRequests = false;
     401         [ +  - ]:         96 :     }
     402                 :         96 : }
     403                 :            : 
     404                 :         96 : sal_Bool OfficeIPCThread::AreRequestsPending()
     405                 :            : {
     406                 :            :     // Give info about pending requests
     407 [ +  - ][ +  - ]:         96 :     ::osl::MutexGuard   aGuard( GetMutex() );
     408         [ +  - ]:         96 :     if ( pGlobalOfficeIPCThread.is() )
     409                 :         96 :         return ( pGlobalOfficeIPCThread->mnPendingRequests > 0 );
     410                 :            :     else
     411         [ +  - ]:         96 :         return sal_False;
     412                 :            : }
     413                 :            : 
     414                 :          0 : void OfficeIPCThread::RequestsCompleted( int nCount )
     415                 :            : {
     416                 :            :     // Remove nCount pending requests from our internal counter
     417 [ #  # ][ #  # ]:          0 :     ::osl::MutexGuard   aGuard( GetMutex() );
     418         [ #  # ]:          0 :     if ( pGlobalOfficeIPCThread.is() )
     419                 :            :     {
     420         [ #  # ]:          0 :         if ( pGlobalOfficeIPCThread->mnPendingRequests > 0 )
     421                 :          0 :             pGlobalOfficeIPCThread->mnPendingRequests -= nCount;
     422         [ #  # ]:          0 :     }
     423                 :          0 : }
     424                 :            : 
     425                 :        158 : OfficeIPCThread::Status OfficeIPCThread::EnableOfficeIPCThread()
     426                 :            : {
     427 [ +  - ][ +  - ]:        158 :     ::osl::MutexGuard   aGuard( GetMutex() );
     428                 :            : 
     429         [ -  + ]:        158 :     if( pGlobalOfficeIPCThread.is() )
     430                 :          0 :         return IPC_STATUS_OK;
     431                 :            : 
     432                 :        158 :     ::rtl::OUString aUserInstallPath;
     433                 :        158 :     ::rtl::OUString aDummy;
     434                 :            : 
     435 [ +  - ][ +  - ]:        158 :     rtl::Reference< OfficeIPCThread > pThread(new OfficeIPCThread);
                 [ +  - ]
     436                 :            : 
     437                 :        158 :     pThread->maPipeIdent = OUString( "SingleOfficeIPC_"  );
     438                 :            : 
     439                 :            :     // The name of the named pipe is created with the hashcode of the user installation directory (without /user). We have to retrieve
     440                 :            :     // this information from a unotools implementation.
     441         [ +  - ]:        158 :     ::utl::Bootstrap::PathStatus aLocateResult = ::utl::Bootstrap::locateUserInstallation( aUserInstallPath );
     442 [ -  + ][ #  # ]:        158 :     if ( aLocateResult == ::utl::Bootstrap::PATH_EXISTS || aLocateResult == ::utl::Bootstrap::PATH_VALID)
     443                 :        158 :         aDummy = aUserInstallPath;
     444                 :            :     else
     445                 :            :     {
     446                 :          0 :         return IPC_STATUS_BOOTSTRAP_ERROR;
     447                 :            :     }
     448                 :            : 
     449                 :            :     // Try to  determine if we are the first office or not! This should prevent multiple
     450                 :            :     // access to the user directory !
     451                 :            :     // First we try to create our pipe if this fails we try to connect. We have to do this
     452                 :            :     // in a loop because the the other office can crash or shutdown between createPipe
     453                 :            :     // and connectPipe!!
     454                 :            : 
     455                 :        158 :     OUString            aIniName;
     456                 :            : 
     457         [ +  - ]:        158 :     osl_getExecutableFile( &aIniName.pData );
     458                 :            : 
     459                 :        158 :     sal_uInt32     lastIndex = aIniName.lastIndexOf('/');
     460         [ +  - ]:        158 :     if ( lastIndex > 0 )
     461                 :            :     {
     462                 :        158 :         aIniName    = aIniName.copy( 0, lastIndex+1 );
     463                 :        158 :         aIniName    += OUString( "perftune" );
     464                 :            : #if defined(WNT)
     465                 :            :         aIniName    += OUString( ".ini" );
     466                 :            : #else
     467                 :        158 :         aIniName    += OUString( "rc" );
     468                 :            : #endif
     469                 :            :     }
     470                 :            : 
     471                 :        158 :     ::rtl::Bootstrap aPerfTuneIniFile( aIniName );
     472                 :            : 
     473                 :        158 :     OUString aDefault( "0" );
     474                 :        158 :     OUString aPreloadData;
     475                 :            : 
     476                 :        158 :     aPerfTuneIniFile.getFrom( OUString( "FastPipeCommunication" ), aPreloadData, aDefault );
     477                 :            : 
     478                 :            : 
     479                 :        158 :     OUString aUserInstallPathHashCode;
     480                 :            : 
     481         [ -  + ]:        158 :     if ( aPreloadData == "1" )
     482                 :            :     {
     483                 :            :         sal_Char    szBuffer[32];
     484                 :          0 :         sprintf( szBuffer, "%d", SUPD );
     485 [ #  # ][ #  # ]:          0 :         aUserInstallPathHashCode = OUString( szBuffer, strlen(szBuffer), osl_getThreadTextEncoding() );
     486                 :            :     }
     487                 :            :     else
     488 [ +  - ][ +  - ]:        158 :         aUserInstallPathHashCode = CreateMD5FromString( aDummy );
                 [ +  - ]
     489                 :            : 
     490                 :            : 
     491                 :            :     // Check result to create a hash code from the user install path
     492         [ -  + ]:        158 :     if ( aUserInstallPathHashCode.isEmpty() )
     493                 :          0 :         return IPC_STATUS_BOOTSTRAP_ERROR; // Something completely broken, we cannot create a valid hash code!
     494                 :            : 
     495                 :        158 :     pThread->maPipeIdent = pThread->maPipeIdent + aUserInstallPathHashCode;
     496                 :            : 
     497                 :        158 :     PipeMode nPipeMode = PIPEMODE_DONTKNOW;
     498         [ -  + ]:        158 :     do
     499                 :            :     {
     500         [ +  - ]:        158 :         osl::Security &rSecurity = Security::get();
     501                 :            :         // Try to create pipe
     502 [ +  - ][ +  - ]:        158 :         if ( pThread->maPipe.create( pThread->maPipeIdent.getStr(), osl_Pipe_CREATE, rSecurity ))
     503                 :            :         {
     504                 :            :             // Pipe created
     505                 :        158 :             nPipeMode = PIPEMODE_CREATED;
     506                 :            :         }
     507 [ #  # ][ #  # ]:          0 :         else if( pThread->maPipe.create( pThread->maPipeIdent.getStr(), osl_Pipe_OPEN, rSecurity )) // Creation not successfull, now we try to connect
     508                 :            :         {
     509                 :            :             // Pipe connected to first office
     510                 :          0 :             nPipeMode = PIPEMODE_CONNECTED;
     511                 :            :         }
     512                 :            :         else
     513                 :            :         {
     514         [ #  # ]:          0 :             oslPipeError eReason = pThread->maPipe.getError();
     515 [ #  # ][ #  # ]:          0 :             if ((eReason == osl_Pipe_E_ConnectionRefused) || (eReason == osl_Pipe_E_invalidError))
     516                 :          0 :                 return IPC_STATUS_BOOTSTRAP_ERROR;
     517                 :            : 
     518                 :            :             // Wait for second office to be ready
     519                 :            :             TimeValue aTimeValue;
     520                 :          0 :             aTimeValue.Seconds = 0;
     521                 :          0 :             aTimeValue.Nanosec = 10000000; // 10ms
     522         [ #  # ]:          0 :             salhelper::Thread::wait( aTimeValue );
     523                 :            :         }
     524                 :            : 
     525                 :            :     } while ( nPipeMode == PIPEMODE_DONTKNOW );
     526                 :            : 
     527         [ +  - ]:        158 :     if ( nPipeMode == PIPEMODE_CREATED )
     528                 :            :     {
     529                 :            :         // Seems we are the one and only, so start listening thread
     530         [ +  - ]:        158 :         pGlobalOfficeIPCThread = pThread;
     531         [ +  - ]:        158 :         pThread->launch();
     532                 :            :     }
     533                 :            :     else
     534                 :            :     {
     535                 :            :         // Seems another office is running. Pipe arguments to it and self terminate
     536         [ #  # ]:          0 :         osl::StreamPipe aStreamPipe(pThread->maPipe.getHandle());
     537                 :            : 
     538                 :            :         rtl::OStringBuffer aArguments(RTL_CONSTASCII_STRINGPARAM(
     539         [ #  # ]:          0 :             ARGUMENT_PREFIX));
     540                 :          0 :         rtl::OUString cwdUrl;
     541 [ #  # ][ #  # ]:          0 :         if (!(tools::getProcessWorkingDir(cwdUrl) &&
     542 [ #  # ][ #  # ]:          0 :               addArgument(aArguments, '1', cwdUrl)))
                 [ #  # ]
     543                 :            :         {
     544         [ #  # ]:          0 :             aArguments.append('0');
     545                 :            :         }
     546         [ #  # ]:          0 :         sal_uInt32 nCount = rtl_getAppCommandArgCount();
     547         [ #  # ]:          0 :         for( sal_uInt32 i=0; i < nCount; i++ )
     548                 :            :         {
     549         [ #  # ]:          0 :             rtl_getAppCommandArg( i, &aDummy.pData );
     550 [ #  # ][ #  # ]:          0 :             if (!addArgument(aArguments, ',', aDummy)) {
     551                 :          0 :                 return IPC_STATUS_BOOTSTRAP_ERROR;
     552                 :            :             }
     553                 :            :         }
     554                 :            :         // finally, write the string onto the pipe
     555         [ #  # ]:          0 :         aStreamPipe.write(aArguments.getStr(), aArguments.getLength());
     556         [ #  # ]:          0 :         aStreamPipe.write("\0", 1);
     557                 :            : 
     558                 :          0 :         rtl::OString aToken(sc_aConfirmationSequence);
     559         [ #  # ]:          0 :         char *pReceiveBuffer = new char[aToken.getLength()+1];
     560         [ #  # ]:          0 :         sal_Int32 n = aStreamPipe.read(pReceiveBuffer, aToken.getLength());
     561                 :          0 :         pReceiveBuffer[n]='\0';
     562                 :            : 
     563                 :          0 :         bool bIsConfirmationSequence = aToken.equals(pReceiveBuffer);
     564         [ #  # ]:          0 :         delete[] pReceiveBuffer;
     565                 :            : 
     566         [ #  # ]:          0 :         if (!bIsConfirmationSequence)
     567                 :            :         {
     568                 :            :             // something went wrong
     569                 :          0 :             return IPC_STATUS_BOOTSTRAP_ERROR;
     570                 :            :         }
     571                 :            : 
     572         [ #  # ]:          0 :         return IPC_STATUS_2ND_OFFICE;
     573                 :            :     }
     574                 :            : 
     575 [ +  - ][ +  - ]:        158 :     return IPC_STATUS_OK;
     576                 :            : }
     577                 :            : 
     578                 :        158 : void OfficeIPCThread::DisableOfficeIPCThread(bool join)
     579                 :            : {
     580 [ +  - ][ +  - ]:        158 :     osl::ClearableMutexGuard aMutex( GetMutex() );
     581                 :            : 
     582         [ +  - ]:        158 :     if( pGlobalOfficeIPCThread.is() )
     583                 :            :     {
     584                 :            :         rtl::Reference< OfficeIPCThread > pOfficeIPCThread(
     585         [ +  - ]:        158 :             pGlobalOfficeIPCThread);
     586         [ +  - ]:        158 :         pGlobalOfficeIPCThread.clear();
     587                 :            : 
     588                 :            :         // send thread a termination message
     589                 :            :         // this is done so the subsequent join will not hang
     590                 :            :         // because the thread hangs in accept of pipe
     591 [ +  - ][ +  - ]:        158 :         osl::StreamPipe aPipe ( pOfficeIPCThread->maPipeIdent, osl_Pipe_OPEN, Security::get() );
     592         [ +  - ]:        158 :         if (aPipe.is())
     593                 :            :         {
     594         [ +  - ]:        158 :             aPipe.send( sc_aTerminationSequence, sc_nTSeqLength+1 ); // also send 0-byte
     595                 :            : 
     596                 :            :             // close the pipe so that the streampipe on the other
     597                 :            :             // side produces EOF
     598         [ +  - ]:        158 :             aPipe.close();
     599                 :            :         }
     600                 :            : 
     601                 :            :         // release mutex to avoid deadlocks
     602         [ +  - ]:        158 :         aMutex.clear();
     603                 :            : 
     604         [ +  - ]:        158 :         OfficeIPCThread::SetReady(pOfficeIPCThread);
     605                 :            : 
     606                 :            :         // exit gracefully and join
     607         [ +  - ]:        158 :         if (join)
     608                 :            :         {
     609         [ +  - ]:        158 :             pOfficeIPCThread->join();
     610 [ +  - ][ +  - ]:        158 :         }
     611         [ +  - ]:        158 :     }
     612                 :        158 : }
     613                 :            : 
     614                 :        158 : OfficeIPCThread::OfficeIPCThread() :
     615                 :            :     Thread( "OfficeIPCThread" ),
     616                 :            :     mbDowning( false ),
     617                 :            :     mbRequestsEnabled( false ),
     618                 :            :     mnPendingRequests( 0 ),
     619 [ +  - ][ +  - ]:        158 :     mpDispatchWatcher( 0 )
                 [ +  - ]
     620                 :            : {
     621                 :        158 : }
     622                 :            : 
     623 [ +  - ][ +  - ]:        158 : OfficeIPCThread::~OfficeIPCThread()
         [ +  - ][ +  - ]
     624                 :            : {
     625 [ +  - ][ +  - ]:        158 :     ::osl::ClearableMutexGuard  aGuard( GetMutex() );
     626                 :            : 
     627         [ +  + ]:        158 :     if ( mpDispatchWatcher )
     628                 :         96 :         mpDispatchWatcher->release();
     629         [ +  - ]:        158 :     maPipe.close();
     630         [ +  - ]:        158 :     maStreamPipe.close();
     631 [ +  - ][ +  - ]:        158 :     pGlobalOfficeIPCThread.clear();
     632         [ -  + ]:        316 : }
     633                 :            : 
     634                 :        254 : void OfficeIPCThread::SetReady(
     635                 :            :     rtl::Reference< OfficeIPCThread > const & pThread)
     636                 :            : {
     637                 :            :     rtl::Reference< OfficeIPCThread > const & t(
     638         [ +  + ]:        254 :         pThread.is() ? pThread : pGlobalOfficeIPCThread);
     639         [ +  - ]:        254 :     if (t.is())
     640                 :            :     {
     641                 :        254 :         t->cReady.set();
     642                 :            :     }
     643                 :        254 : }
     644                 :            : 
     645                 :        158 : void OfficeIPCThread::execute()
     646                 :            : {
     647         [ #  # ]:        158 :     do
     648                 :            :     {
     649                 :        158 :         oslPipeError nError = maPipe.accept( maStreamPipe );
     650                 :            : 
     651                 :            : 
     652         [ +  - ]:        158 :         if( nError == osl_Pipe_E_None )
     653                 :            :         {
     654                 :            :             // if we receive a request while the office is displaying some dialog or error during
     655                 :            :             // bootstrap, that dialogs event loop might get events that are dispatched by this thread
     656                 :            :             // we have to wait for cReady to be set by the real main loop.
     657                 :            :             // only reqests that dont dispatch events may be processed before cReady is set.
     658         [ +  - ]:        158 :             cReady.wait();
     659                 :            : 
     660                 :            :             // we might have decided to shutdown while we were sleeping
     661         [ -  + ]:        158 :             if (!pGlobalOfficeIPCThread.is()) return;
     662                 :            : 
     663                 :            :             // only lock the mutex when processing starts, othewise we deadlock when the office goes
     664                 :            :             // down during wait
     665 [ #  # ][ #  # ]:          0 :             osl::ClearableMutexGuard aGuard( GetMutex() );
     666                 :            : 
     667                 :            :             // test byte by byte
     668                 :          0 :             const int nBufSz = 2048;
     669                 :            :             char pBuf[nBufSz];
     670                 :          0 :             int nBytes = 0;
     671                 :          0 :             int nResult = 0;
     672                 :          0 :             rtl::OStringBuffer aBuf;
     673                 :            :             // read into pBuf until '\0' is read or read-error
     674 [ #  # ][ #  # ]:          0 :             while ((nResult=maStreamPipe.recv( pBuf+nBytes, nBufSz-nBytes))>0) {
     675                 :          0 :                 nBytes += nResult;
     676         [ #  # ]:          0 :                 if (pBuf[nBytes-1]=='\0') {
     677         [ #  # ]:          0 :                     aBuf.append(pBuf);
     678                 :          0 :                     break;
     679                 :            :                 }
     680                 :            :             }
     681                 :            :             // don't close pipe ...
     682                 :            : 
     683                 :          0 :             rtl::OString aArguments = aBuf.makeStringAndClear();
     684                 :            : 
     685                 :            :             // Is this a lookup message from another application? if so, ignore
     686         [ #  # ]:          0 :             if (aArguments.isEmpty())
     687                 :          0 :                 continue;
     688                 :            : 
     689                 :            :             // is this a termination message ? if so, terminate
     690 [ #  # ][ #  # ]:          0 :             if (aArguments.equalsL(sc_aTerminationSequence, sc_nTSeqLength) || mbDowning)
                 [ #  # ]
     691                 :            :                 return;
     692                 :          0 :             std::auto_ptr< CommandLineArgs > aCmdLineArgs;
     693                 :            :             try
     694                 :            :             {
     695         [ #  # ]:          0 :                 Parser p(aArguments);
     696 [ #  # ][ #  # ]:          0 :                 aCmdLineArgs.reset( new CommandLineArgs( p ) );
           [ #  #  #  # ]
     697                 :            :             }
     698         [ #  # ]:          0 :             catch ( const CommandLineArgs::Supplier::Exception & )
     699                 :            :             {
     700                 :            : #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
     701                 :            :                 fprintf( stderr, "Error in received command line arguments\n" );
     702                 :            : #endif
     703                 :          0 :                 continue;
     704                 :            :             }
     705                 :            : 
     706                 :            : #ifdef UNX
     707 [ #  # ][ #  # ]:          0 :             if (aCmdLineArgs->HasUnknown() || aCmdLineArgs->IsVersion() || aCmdLineArgs->IsHelp())
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     708                 :          0 :                 continue;
     709                 :            : #endif
     710                 :            : 
     711         [ #  # ]:          0 :             const CommandLineArgs &rCurrentCmdLineArgs = Desktop::GetCommandLineArgs();
     712                 :            : 
     713 [ #  # ][ #  # ]:          0 :             if ( aCmdLineArgs->IsQuickstart() )
     714                 :            :             {
     715                 :            :                 // we have to use application event, because we have to start quickstart service in main thread!!
     716                 :            :                 ApplicationEvent* pAppEvent =
     717         [ #  # ]:          0 :                     new ApplicationEvent(ApplicationEvent::TYPE_QUICKSTART);
     718         [ #  # ]:          0 :                 ImplPostForeignAppEvent( pAppEvent );
     719                 :            :             }
     720                 :            : 
     721                 :            :             // handle request for acceptor
     722                 :            :             std::vector< rtl::OUString > const & accept = aCmdLineArgs->
     723         [ #  # ]:          0 :                 GetAccept();
     724 [ #  # ][ #  # ]:          0 :             for (std::vector< rtl::OUString >::const_iterator i(accept.begin());
     725                 :          0 :                  i != accept.end(); ++i)
     726                 :            :             {
     727                 :            :                 ApplicationEvent* pAppEvent = new ApplicationEvent(
     728         [ #  # ]:          0 :                     ApplicationEvent::TYPE_ACCEPT, *i);
     729         [ #  # ]:          0 :                 ImplPostForeignAppEvent( pAppEvent );
     730                 :            :             }
     731                 :            :             // handle acceptor removal
     732                 :            :             std::vector< rtl::OUString > const & unaccept = aCmdLineArgs->
     733         [ #  # ]:          0 :                 GetUnaccept();
     734 [ #  # ][ #  # ]:          0 :             for (std::vector< rtl::OUString >::const_iterator i(
     735                 :          0 :                      unaccept.begin());
     736                 :          0 :                  i != unaccept.end(); ++i)
     737                 :            :             {
     738                 :            :                 ApplicationEvent* pAppEvent = new ApplicationEvent(
     739         [ #  # ]:          0 :                     ApplicationEvent::TYPE_UNACCEPT, *i);
     740         [ #  # ]:          0 :                 ImplPostForeignAppEvent( pAppEvent );
     741                 :            :             }
     742                 :            : 
     743                 :            : #ifndef UNX
     744                 :            :             // only in non-unix version, we need to handle a -help request
     745                 :            :             // in a running instance in order to display  the command line help
     746                 :            :             if ( aCmdLineArgs->IsHelp() ) {
     747                 :            :                 ApplicationEvent* pAppEvent =
     748                 :            :                     new ApplicationEvent(ApplicationEvent::TYPE_HELP);
     749                 :            :                 ImplPostForeignAppEvent( pAppEvent );
     750                 :            :             }
     751                 :            : #endif
     752                 :            : 
     753                 :          0 :             sal_Bool bDocRequestSent = sal_False;
     754                 :            :             ProcessDocumentsRequest* pRequest = new ProcessDocumentsRequest(
     755 [ #  # ][ #  # ]:          0 :                 aCmdLineArgs->getCwdUrl());
         [ #  # ][ #  # ]
     756         [ #  # ]:          0 :             cProcessed.reset();
     757                 :          0 :             pRequest->pcProcessed = &cProcessed;
     758                 :            : 
     759                 :            :             // Print requests are not dependent on the --invisible cmdline argument as they are
     760                 :            :             // loaded with the "hidden" flag! So they are always checked.
     761         [ #  # ]:          0 :             pRequest->aPrintList = aCmdLineArgs->GetPrintList();
     762                 :          0 :             bDocRequestSent |= !pRequest->aPrintList.empty();
     763         [ #  # ]:          0 :             pRequest->aPrintToList = aCmdLineArgs->GetPrintToList();
     764         [ #  # ]:          0 :             pRequest->aPrinterName = aCmdLineArgs->GetPrinterName();
     765 [ #  # ][ #  # ]:          0 :             bDocRequestSent |= !( pRequest->aPrintToList.empty() || pRequest->aPrinterName.isEmpty() );
     766                 :            : 
     767 [ #  # ][ #  # ]:          0 :             if ( !rCurrentCmdLineArgs.IsInvisible() )
     768                 :            :             {
     769                 :            :                 // Read cmdline args that can open/create documents. As they would open a window
     770                 :            :                 // they are only allowed if the "--invisible" is currently not used!
     771         [ #  # ]:          0 :                 pRequest->aOpenList = aCmdLineArgs->GetOpenList();
     772                 :          0 :                 bDocRequestSent |= !pRequest->aOpenList.empty();
     773         [ #  # ]:          0 :                 pRequest->aViewList = aCmdLineArgs->GetViewList();
     774                 :          0 :                 bDocRequestSent |= !pRequest->aViewList.empty();
     775         [ #  # ]:          0 :                 pRequest->aStartList = aCmdLineArgs->GetStartList();
     776                 :          0 :                 bDocRequestSent |= !pRequest->aStartList.empty();
     777         [ #  # ]:          0 :                 pRequest->aForceOpenList = aCmdLineArgs->GetForceOpenList();
     778                 :          0 :                 bDocRequestSent |= !pRequest->aForceOpenList.empty();
     779         [ #  # ]:          0 :                 pRequest->aForceNewList = aCmdLineArgs->GetForceNewList();
     780                 :          0 :                 bDocRequestSent |= !pRequest->aForceNewList.empty();
     781                 :            : 
     782                 :            :                 // Special command line args to create an empty document for a given module
     783                 :            : 
     784                 :            :                 // #i18338# (lo)
     785                 :            :                 // we only do this if no document was specified on the command line,
     786                 :            :                 // since this would be inconsistent with the the behaviour of
     787                 :            :                 // the first process, see OpenClients() (call to OpenDefault()) in app.cxx
     788 [ #  # ][ #  # ]:          0 :                 if ( aCmdLineArgs->HasModuleParam() && (!bDocRequestSent) )
         [ #  # ][ #  # ]
     789                 :            :                 {
     790         [ #  # ]:          0 :                     SvtModuleOptions aOpt;
     791                 :          0 :                     SvtModuleOptions::EFactory eFactory = SvtModuleOptions::E_WRITER;
     792 [ #  # ][ #  # ]:          0 :                     if ( aCmdLineArgs->IsWriter() )
     793                 :          0 :                         eFactory = SvtModuleOptions::E_WRITER;
     794 [ #  # ][ #  # ]:          0 :                     else if ( aCmdLineArgs->IsCalc() )
     795                 :          0 :                         eFactory = SvtModuleOptions::E_CALC;
     796 [ #  # ][ #  # ]:          0 :                     else if ( aCmdLineArgs->IsDraw() )
     797                 :          0 :                         eFactory = SvtModuleOptions::E_DRAW;
     798 [ #  # ][ #  # ]:          0 :                     else if ( aCmdLineArgs->IsImpress() )
     799                 :          0 :                         eFactory = SvtModuleOptions::E_IMPRESS;
     800 [ #  # ][ #  # ]:          0 :                     else if ( aCmdLineArgs->IsBase() )
     801                 :          0 :                         eFactory = SvtModuleOptions::E_DATABASE;
     802 [ #  # ][ #  # ]:          0 :                     else if ( aCmdLineArgs->IsMath() )
     803                 :          0 :                         eFactory = SvtModuleOptions::E_MATH;
     804 [ #  # ][ #  # ]:          0 :                     else if ( aCmdLineArgs->IsGlobal() )
     805                 :          0 :                         eFactory = SvtModuleOptions::E_WRITERGLOBAL;
     806 [ #  # ][ #  # ]:          0 :                     else if ( aCmdLineArgs->IsWeb() )
     807                 :          0 :                         eFactory = SvtModuleOptions::E_WRITERWEB;
     808                 :            : 
     809         [ #  # ]:          0 :                     if ( !pRequest->aOpenList.empty() )
     810         [ #  # ]:          0 :                         pRequest->aModule = aOpt.GetFactoryName( eFactory );
     811                 :            :                     else
     812 [ #  # ][ #  # ]:          0 :                         pRequest->aOpenList.push_back( aOpt.GetFactoryEmptyDocumentURL( eFactory ) );
     813         [ #  # ]:          0 :                     bDocRequestSent = sal_True;
     814                 :            :                 }
     815                 :            :             }
     816                 :            : 
     817 [ #  # ][ #  # ]:          0 :             if ( !aCmdLineArgs->IsQuickstart() ) {
     818                 :          0 :                 sal_Bool bShowHelp = sal_False;
     819                 :          0 :                 rtl::OUStringBuffer aHelpURLBuffer;
     820 [ #  # ][ #  # ]:          0 :                 if (aCmdLineArgs->IsHelpWriter()) {
     821                 :          0 :                     bShowHelp = sal_True;
     822         [ #  # ]:          0 :                     aHelpURLBuffer.appendAscii("vnd.sun.star.help://swriter/start");
     823 [ #  # ][ #  # ]:          0 :                 } else if (aCmdLineArgs->IsHelpCalc()) {
     824                 :          0 :                     bShowHelp = sal_True;
     825         [ #  # ]:          0 :                     aHelpURLBuffer.appendAscii("vnd.sun.star.help://scalc/start");
     826 [ #  # ][ #  # ]:          0 :                 } else if (aCmdLineArgs->IsHelpDraw()) {
     827                 :          0 :                     bShowHelp = sal_True;
     828         [ #  # ]:          0 :                     aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdraw/start");
     829 [ #  # ][ #  # ]:          0 :                 } else if (aCmdLineArgs->IsHelpImpress()) {
     830                 :          0 :                     bShowHelp = sal_True;
     831         [ #  # ]:          0 :                     aHelpURLBuffer.appendAscii("vnd.sun.star.help://simpress/start");
     832 [ #  # ][ #  # ]:          0 :                 } else if (aCmdLineArgs->IsHelpBase()) {
     833                 :          0 :                     bShowHelp = sal_True;
     834         [ #  # ]:          0 :                     aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdatabase/start");
     835 [ #  # ][ #  # ]:          0 :                 } else if (aCmdLineArgs->IsHelpBasic()) {
     836                 :          0 :                     bShowHelp = sal_True;
     837         [ #  # ]:          0 :                     aHelpURLBuffer.appendAscii("vnd.sun.star.help://sbasic/start");
     838 [ #  # ][ #  # ]:          0 :                 } else if (aCmdLineArgs->IsHelpMath()) {
     839                 :          0 :                     bShowHelp = sal_True;
     840         [ #  # ]:          0 :                     aHelpURLBuffer.appendAscii("vnd.sun.star.help://smath/start");
     841                 :            :                 }
     842         [ #  # ]:          0 :                 if (bShowHelp) {
     843         [ #  # ]:          0 :                     aHelpURLBuffer.appendAscii("?Language=");
     844 [ #  # ][ #  # ]:          0 :                     aHelpURLBuffer.append(utl::ConfigManager::getLocale());
     845                 :            : #if defined UNX
     846         [ #  # ]:          0 :                     aHelpURLBuffer.appendAscii("&System=UNX");
     847                 :            : #elif defined WNT
     848                 :            :                     aHelpURLBuffer.appendAscii("&System=WIN");
     849                 :            : #endif
     850                 :            :                     ApplicationEvent* pAppEvent = new ApplicationEvent(
     851                 :            :                         ApplicationEvent::TYPE_OPENHELPURL,
     852 [ #  # ][ #  # ]:          0 :                         aHelpURLBuffer.makeStringAndClear());
     853         [ #  # ]:          0 :                     ImplPostForeignAppEvent( pAppEvent );
     854                 :          0 :                 }
     855                 :            :             }
     856                 :            : 
     857         [ #  # ]:          0 :             if ( bDocRequestSent )
     858                 :            :              {
     859                 :            :                 // Send requests to dispatch watcher if we have at least one. The receiver
     860                 :            :                 // is responsible to delete the request after processing it.
     861 [ #  # ][ #  # ]:          0 :                 if ( aCmdLineArgs->HasModuleParam() )
     862                 :            :                 {
     863         [ #  # ]:          0 :                     SvtModuleOptions    aOpt;
     864                 :            : 
     865                 :            :                     // Support command line parameters to start a module (as preselection)
     866 [ #  # ][ #  # ]:          0 :                     if ( aCmdLineArgs->IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SWRITER ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     867         [ #  # ]:          0 :                         pRequest->aModule = aOpt.GetFactoryName( SvtModuleOptions::E_WRITER );
     868 [ #  # ][ #  # ]:          0 :                     else if ( aCmdLineArgs->IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SCALC ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     869         [ #  # ]:          0 :                         pRequest->aModule = aOpt.GetFactoryName( SvtModuleOptions::E_CALC );
     870 [ #  # ][ #  # ]:          0 :                     else if ( aCmdLineArgs->IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SIMPRESS ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     871         [ #  # ]:          0 :                         pRequest->aModule= aOpt.GetFactoryName( SvtModuleOptions::E_IMPRESS );
     872 [ #  # ][ #  # ]:          0 :                     else if ( aCmdLineArgs->IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::E_SDRAW ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     873 [ #  # ][ #  # ]:          0 :                         pRequest->aModule= aOpt.GetFactoryName( SvtModuleOptions::E_DRAW );
     874                 :            :                 }
     875                 :            : 
     876                 :            : 
     877         [ #  # ]:          0 :                 ImplPostProcessDocumentsEvent( pRequest );
     878                 :            :             }
     879                 :            :             else
     880                 :            :             {
     881                 :            :                 // delete not used request again
     882 [ #  # ][ #  # ]:          0 :                 delete pRequest;
     883                 :          0 :                 pRequest = NULL;
     884                 :            :             }
     885 [ #  # ][ #  # ]:          0 :             if (aArguments.equalsL(sc_aShowSequence, sc_nShSeqLength) ||
                 [ #  # ]
     886         [ #  # ]:          0 :                 aCmdLineArgs->IsEmpty())
     887                 :            :             {
     888                 :            :                 // no document was sent, just bring Office to front
     889                 :            :                 ApplicationEvent* pAppEvent =
     890         [ #  # ]:          0 :                     new ApplicationEvent(ApplicationEvent::TYPE_APPEAR);
     891         [ #  # ]:          0 :                 ImplPostForeignAppEvent( pAppEvent );
     892                 :            :             }
     893                 :            : 
     894                 :            :             // we don't need the mutex any longer...
     895         [ #  # ]:          0 :             aGuard.clear();
     896                 :            :             // wait for processing to finish
     897         [ #  # ]:          0 :             if (bDocRequestSent)
     898         [ #  # ]:          0 :                 cProcessed.wait();
     899                 :            :             // processing finished, inform the requesting end
     900                 :          0 :             nBytes = 0;
     901 [ #  # ][ #  # ]:          0 :             while (
         [ #  # ][ #  # ]
     902                 :          0 :                    (nResult = maStreamPipe.send(sc_aConfirmationSequence+nBytes, sc_nCSeqLength-nBytes))>0 &&
     903 [ #  # ][ #  # ]:        158 :                    ((nBytes += nResult) < sc_nCSeqLength) ) ;
              [ #  #  # ]
              [ #  #  # ]
                 [ #  # ]
              [ #  #  # ]
     904                 :            :         }
     905                 :            :         else
     906                 :            :         {
     907                 :            : #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
     908                 :            :             fprintf( stderr, "Error on accept: %d\n", (int)nError );
     909                 :            : #endif
     910                 :            :             TimeValue tval;
     911                 :          0 :             tval.Seconds = 1;
     912                 :          0 :             tval.Nanosec = 0;
     913         [ #  # ]:          0 :             salhelper::Thread::wait( tval );
     914                 :            :         }
     915                 :          0 :     } while( schedule() );
     916                 :            : }
     917                 :            : 
     918                 :        768 : static void AddToDispatchList(
     919                 :            :     DispatchWatcher::DispatchList& rDispatchList,
     920                 :            :     boost::optional< rtl::OUString > const & cwdUrl,
     921                 :            :     std::vector< rtl::OUString > const & aRequestList,
     922                 :            :     DispatchWatcher::RequestType nType,
     923                 :            :     const OUString& aParam,
     924                 :            :     const OUString& aFactory )
     925                 :            : {
     926 [ +  - ][ -  + ]:       1536 :     for (std::vector< rtl::OUString >::const_iterator i(aRequestList.begin());
     927                 :        768 :          i != aRequestList.end(); ++i)
     928                 :            :     {
     929                 :            :         rDispatchList.push_back(
     930 [ #  # ][ #  # ]:          0 :             DispatchWatcher::DispatchRequest( nType, *i, cwdUrl, aParam, aFactory ));
                 [ #  # ]
     931                 :            :     }
     932                 :        768 : }
     933                 :            : 
     934                 :         96 : static void AddConversionsToDispatchList(
     935                 :            :     DispatchWatcher::DispatchList& rDispatchList,
     936                 :            :     boost::optional< rtl::OUString > const & cwdUrl,
     937                 :            :     std::vector< rtl::OUString > const & rRequestList,
     938                 :            :     const OUString& rParam,
     939                 :            :     const OUString& rPrinterName,
     940                 :            :     const OUString& rFactory,
     941                 :            :     const OUString& rParamOut )
     942                 :            : {
     943                 :            :     DispatchWatcher::RequestType nType;
     944                 :         96 :     OUString aParam( rParam );
     945                 :            : 
     946         [ -  + ]:         96 :     if( !rParam.isEmpty() )
     947                 :            :     {
     948                 :          0 :         nType = DispatchWatcher::REQUEST_CONVERSION;
     949                 :          0 :         aParam = rParam;
     950                 :            :     }
     951                 :            :     else
     952                 :            :     {
     953                 :         96 :         nType = DispatchWatcher::REQUEST_BATCHPRINT;
     954                 :         96 :         aParam = rPrinterName;
     955                 :            :     }
     956                 :            : 
     957                 :         96 :     OUString aOutDir( rParamOut.trim() );
     958                 :         96 :     ::rtl::OUString aPWD;
     959         [ +  - ]:         96 :     ::tools::getProcessWorkingDir( aPWD );
     960                 :            : 
     961 [ +  - ][ -  + ]:         96 :     if( !::osl::FileBase::getAbsoluteFileURL( aPWD, rParamOut, aOutDir ) )
     962         [ #  # ]:          0 :         ::osl::FileBase::getSystemPathFromFileURL( aOutDir, aOutDir );
     963                 :            : 
     964         [ -  + ]:         96 :     if( !rParamOut.trim().isEmpty() )
     965                 :            :     {
     966                 :          0 :         aParam += ::rtl::OUString(";");
     967                 :          0 :         aParam += aOutDir;
     968                 :            :     }
     969                 :            :     else
     970                 :            :     {
     971         [ +  - ]:         96 :         ::osl::FileBase::getSystemPathFromFileURL( aPWD, aPWD );
     972                 :         96 :         aParam += ::rtl::OUString(";" ) + aPWD;
     973                 :            :     }
     974                 :            : 
     975 [ +  - ][ -  + ]:        192 :     for (std::vector< rtl::OUString >::const_iterator i(rRequestList.begin());
     976                 :         96 :          i != rRequestList.end(); ++i)
     977                 :            :     {
     978                 :            :         rDispatchList.push_back(
     979 [ #  # ][ #  # ]:          0 :             DispatchWatcher::DispatchRequest( nType, *i, cwdUrl, aParam, rFactory ));
                 [ #  # ]
     980                 :         96 :     }
     981                 :         96 : }
     982                 :            : 
     983                 :            : 
     984                 :         96 : sal_Bool OfficeIPCThread::ExecuteCmdLineRequests( ProcessDocumentsRequest& aRequest )
     985                 :            : {
     986                 :            :     // protect the dispatch list
     987 [ +  - ][ +  - ]:         96 :     osl::ClearableMutexGuard aGuard( GetMutex() );
     988                 :            : 
     989 [ +  - ][ +  - ]:         96 :     static DispatchWatcher::DispatchList    aDispatchList;
         [ +  - ][ #  # ]
     990                 :            : 
     991                 :         96 :     rtl::OUString aEmpty;
     992                 :            :     // Create dispatch list for dispatch watcher
     993         [ +  - ]:         96 :     AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aInFilter, DispatchWatcher::REQUEST_INFILTER, aEmpty, aRequest.aModule );
     994         [ +  - ]:         96 :     AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aOpenList, DispatchWatcher::REQUEST_OPEN, aEmpty, aRequest.aModule );
     995         [ +  - ]:         96 :     AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aViewList, DispatchWatcher::REQUEST_VIEW, aEmpty, aRequest.aModule );
     996         [ +  - ]:         96 :     AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aStartList, DispatchWatcher::REQUEST_START, aEmpty, aRequest.aModule );
     997         [ +  - ]:         96 :     AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aPrintList, DispatchWatcher::REQUEST_PRINT, aEmpty, aRequest.aModule );
     998         [ +  - ]:         96 :     AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aPrintToList, DispatchWatcher::REQUEST_PRINTTO, aRequest.aPrinterName, aRequest.aModule );
     999         [ +  - ]:         96 :     AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aForceOpenList, DispatchWatcher::REQUEST_FORCEOPEN, aEmpty, aRequest.aModule );
    1000         [ +  - ]:         96 :     AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aForceNewList, DispatchWatcher::REQUEST_FORCENEW, aEmpty, aRequest.aModule );
    1001         [ +  - ]:         96 :     AddConversionsToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aConversionList, aRequest.aConversionParams, aRequest.aPrinterName, aRequest.aModule, aRequest.aConversionOut );
    1002                 :         96 :     sal_Bool bShutdown( sal_False );
    1003                 :            : 
    1004         [ +  - ]:         96 :     if ( pGlobalOfficeIPCThread.is() )
    1005                 :            :     {
    1006         [ -  + ]:         96 :         if( ! pGlobalOfficeIPCThread->AreRequestsEnabled() )
    1007                 :          0 :             return bShutdown;
    1008                 :            : 
    1009                 :         96 :         pGlobalOfficeIPCThread->mnPendingRequests += aDispatchList.size();
    1010         [ +  - ]:         96 :         if ( !pGlobalOfficeIPCThread->mpDispatchWatcher )
    1011                 :            :         {
    1012         [ +  - ]:         96 :             pGlobalOfficeIPCThread->mpDispatchWatcher = DispatchWatcher::GetDispatchWatcher();
    1013                 :         96 :             pGlobalOfficeIPCThread->mpDispatchWatcher->acquire();
    1014                 :            :         }
    1015                 :            : 
    1016                 :            :         // copy for execute
    1017         [ +  - ]:         96 :         DispatchWatcher::DispatchList aTempList( aDispatchList );
    1018                 :         96 :         aDispatchList.clear();
    1019                 :            : 
    1020         [ +  - ]:         96 :         aGuard.clear();
    1021                 :            : 
    1022                 :            :         // Execute dispatch requests
    1023         [ +  - ]:         96 :         bShutdown = pGlobalOfficeIPCThread->mpDispatchWatcher->executeDispatchRequests( aTempList, s_bInEnableRequests );
    1024                 :            : 
    1025                 :            :         // set processed flag
    1026         [ -  + ]:         96 :         if (aRequest.pcProcessed != NULL)
    1027         [ #  # ]:         96 :             aRequest.pcProcessed->set();
    1028                 :            :     }
    1029                 :            : 
    1030         [ +  - ]:         96 :     return bShutdown;
    1031                 :            : }
    1032                 :            : 
    1033 [ +  - ][ +  - ]:        474 : }
    1034                 :            : 
    1035                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10