LCOV - code coverage report
Current view: top level - libreoffice/desktop/source/app - officeipcthread.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 479 0.0 %
Date: 2012-12-27 Functions: 0 36 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10