--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ximpfw/core/srcclient/ximpprocessstarter.cpp Thu Dec 17 08:54:49 2009 +0200
@@ -0,0 +1,396 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: XIMP Framework process starter implementation.
+*
+*/
+
+
+// INCLUDE FILES
+#include "ximpprocessstarter.h"
+#include <e32std.h>
+#include <f32file.h>
+
+
+// CONSTANTS
+_LIT( KEka2ExeDir,"\\sys\\bin\\");
+_LIT( KEka2LaunchMutexExt, "[lMtx]" );
+const TInt KEka2SrvConnTries = 7; // Try to start 7 times
+ // before giving up
+const TInt KEka2SrvConnInitialRetryWait = 500; // MicroSeconds => 0.0005s
+
+
+
+// ==============================================================
+// ====================== HELPER CLASS ==========================
+// ==============================================================
+
+/**
+ * RSessionBase accessor to give to the XIMPProcessStarter
+ * access to RSessionBase::CreateSession().
+ */
+class REka2SessionBaseAccessor : public RSessionBase
+ {
+ public: // Constructor
+ inline REka2SessionBaseAccessor()
+ {
+ }
+
+ public: // New functions
+
+ /**
+ * Public access to RSessionBase::CreateSession().
+ */
+ inline TInt CreateSession( const TDesC& aServer,
+ const TVersion& aVersion,
+ TInt aAsyncMessageSlots )
+ {
+ return RSessionBase::CreateSession( aServer,
+ aVersion,
+ aAsyncMessageSlots );
+ }
+ };
+
+
+// ==============================================================
+// ====================== PROCESSSTARTER ========================
+// ==============================================================
+
+
+// --------------------------------------------------------------
+// XIMPProcessStarter::FullExePathForClienLocation()
+// --------------------------------------------------------------
+//
+EXPORT_C void XIMPProcessStarter::FullExePathForClienLocation(
+ const TDesC& aExeName,
+ TFileName& aFullExePath )
+ {
+ //Get drive (C:) where this client code is installed
+ {
+ TFileName tmp;
+ Dll::FileName( tmp );
+ aFullExePath.Copy( TParsePtrC( tmp ).Drive() );
+ }
+
+ //Build the rest from the exe path
+ aFullExePath.Append( KEka2ExeDir );
+ aFullExePath.Append( aExeName );
+ }
+
+
+// --------------------------------------------------------------
+// XIMPProcessStarter::StartInstance()
+// --------------------------------------------------------------
+//
+EXPORT_C TInt XIMPProcessStarter::StartInstance(
+ const TDesC& aFullExePath,
+ const TDesC& aCommand,
+ const TArray< TXIMPProcessStartupParam >* aParams )
+ {
+ RMutex launchMutex;
+ TInt error = KErrNotFound;
+
+ {
+ // Dynamic mutex name used to allow code share
+ TName launchMutexName( TParsePtrC( aFullExePath ).Name() );
+ launchMutexName.Append( KEka2LaunchMutexExt );
+
+ // Open or Create mutex to serialize to access to server startup code.
+ // (race condition safe way)
+ while( error == KErrNotFound )
+ {
+ error = launchMutex.CreateGlobal( launchMutexName );
+ if( error != KErrAlreadyExists )
+ {
+ break;
+ }
+ error = launchMutex.OpenGlobal( launchMutexName );
+ }
+
+ if( error != KErrNone )
+ {
+ return error;
+ }
+ }
+
+
+ launchMutex.Wait();
+
+ //Serialized access
+ error = XIMPProcessStarter::DoStartInstance( aFullExePath,
+ aCommand,
+ aParams );
+
+ launchMutex.Signal();
+ launchMutex.Close();
+
+ return error;
+ }
+
+
+// --------------------------------------------------------------
+// XIMPProcessStarter::ConnectToServer()
+// --------------------------------------------------------------
+//
+EXPORT_C TInt XIMPProcessStarter::ConnectToServer(
+ const TDesC& aFullExePath,
+ const TDesC& aCommand,
+ const TArray< TXIMPProcessStartupParam >* aParams,
+ RSessionBase& aSessionToConnect,
+ const TDesC& aServerName,
+ const TVersion& aClientVersion,
+ TInt aAsyncMessageSlots )
+ {
+ if( aSessionToConnect.Handle() != KNullHandle )
+ {
+ return KErrInUse;
+ }
+
+ TInt err = KErrNone;
+ TInt startupWait = KEka2SrvConnInitialRetryWait;
+
+ //Server connect and launch loop
+ for( TInt trie = 0 ; trie < KEka2SrvConnTries ; trie++ )
+ {
+ REka2SessionBaseAccessor acc;
+ err = acc.CreateSession( aServerName,
+ aClientVersion,
+ aAsyncMessageSlots );
+
+ if( err == KErrNone )
+ {
+ //session ownership is now on client
+ aSessionToConnect = acc;
+ return KErrNone;
+ }
+
+ else if( ( err == KErrNotFound ) ||
+ ( err == KErrServerTerminated ) )
+ {
+ //Server missing or died when connecting
+ //Start a new server
+ err = XIMPProcessStarter::StartInstance( aFullExePath,
+ aCommand,
+ aParams );
+
+ //If process exist already, then all is fine
+ //(some other process started it between the origical connect and launch trie)
+ if( err == KErrAlreadyExists )
+ {
+ err = KErrNone;
+ }
+
+ //If server process start failed, bail out.
+ if( err != KErrNone )
+ {
+ return err;
+ }
+
+ //If this is 2nd or subsequent try,
+ //give some time for server to startup
+ if( trie > 0 )
+ {
+ User::After( startupWait ); // CSI: 92 #
+ startupWait = 2 * startupWait;
+ }
+ }
+
+ else
+ {
+ //Server process start failed. Bail out.
+ return err;
+ }
+ }
+
+ return err;
+ }
+
+
+// --------------------------------------------------------------
+// XIMPProcessStarter::DoStartServerInstance()
+// --------------------------------------------------------------
+//
+TInt XIMPProcessStarter::DoStartInstance(
+ const TDesC& aFullExePath,
+ const TDesC& aCommand,
+ const TArray< TXIMPProcessStartupParam >* aParams )
+ {
+ TInt error = KErrNone;
+
+ //Create process
+ RProcess process;
+ error = process.Create( aFullExePath, aCommand );
+
+ if( error == KErrNone )
+ {
+ //Set process startup parameters
+ error = ApplyParameters( aParams, process );
+
+ //And execute the process and wait it's startup
+ if( error == KErrNone )
+ {
+ TRequestStatus rendezvousStatus;
+ process.Rendezvous( rendezvousStatus );
+
+ process.Resume();
+ User::WaitForRequest( rendezvousStatus ); // CSI: 94 #
+ error = rendezvousStatus.Int();
+
+ if( process.ExitType() != EExitPending )
+ {
+ //Something failed in server startup
+ //Force the error code to be always something
+ //else than KErrNone
+ if( error == KErrNone )
+ {
+ error = KErrServerTerminated;
+ }
+ }
+ }
+ }
+
+ process.Close();
+
+ return error;
+ }
+
+
+// --------------------------------------------------------------
+// XIMPProcessStarter::ApplyParameters()
+// --------------------------------------------------------------
+//
+TInt XIMPProcessStarter::ApplyParameters(
+ const TArray< TXIMPProcessStartupParam >* aParams,
+ RProcess& aProcess )
+ {
+ TInt error = KErrNone;
+ if( aParams )
+ {
+ const TInt paramCount = aParams->Count();
+ for( TInt ix = 0; ix < paramCount; ix++ )
+ {
+ error = (*aParams)[ ix ].ApplyParam( aProcess );
+ if( error != KErrNone )
+ {
+ break;
+ }
+ }
+ }
+
+ return error;
+ }
+
+
+// ==============================================================
+// ================== TPROCESSSTARTUPPARAM ======================
+// ==============================================================
+
+// --------------------------------------------------------------
+// TXIMPProcessStartupParam::TXIMPProcessStartupParam()
+// --------------------------------------------------------------
+//
+EXPORT_C TXIMPProcessStartupParam::TXIMPProcessStartupParam()
+ : iType( EUnknown ),
+ iSlot( KErrNotFound )
+ {
+ }
+
+
+// --------------------------------------------------------------
+// TXIMPProcessStartupParam::Set()
+// --------------------------------------------------------------
+//
+void TXIMPProcessStartupParam::Set( TInt aSlot,
+ const RHandleBase& aHandle )
+ {
+ iType = EHandle;
+ iSlot = aSlot;
+ iHandle = &aHandle;
+ }
+
+
+// --------------------------------------------------------------
+// TXIMPProcessStartupParam::Set()
+// --------------------------------------------------------------
+//
+void TXIMPProcessStartupParam::Set( TInt aSlot,
+ const RSubSessionBase& aSubSession )
+ {
+ iType = ESubSession;
+ iSlot = aSlot;
+ iSubSession = &aSubSession;
+ }
+
+
+// --------------------------------------------------------------
+// TXIMPProcessStartupParam::Set()
+// --------------------------------------------------------------
+//
+void TXIMPProcessStartupParam::Set( TInt aSlot,
+ const TDesC16& aDes )
+ {
+ iType = EDes16;
+ iSlot = aSlot;
+ iDes16.Set( aDes );
+ }
+
+
+// --------------------------------------------------------------
+// TXIMPProcessStartupParam::Set()
+// --------------------------------------------------------------
+//
+void TXIMPProcessStartupParam::Set( TInt aSlot,
+ const TDesC8& aDes )
+ {
+ iType = EDes8;
+ iSlot = aSlot;
+ iDes8.Set( aDes );
+ }
+
+
+// --------------------------------------------------------------
+// TXIMPProcessStartupParam::Set()
+// --------------------------------------------------------------
+//
+EXPORT_C void TXIMPProcessStartupParam::Set( TInt aSlot,
+ TInt aInt )
+ {
+ iType = EInt;
+ iSlot = aSlot;
+ iInt = aInt;
+ }
+
+
+// --------------------------------------------------------------
+// TXIMPProcessStartupParam::ApplyParam()
+// --------------------------------------------------------------
+//
+TInt TXIMPProcessStartupParam::ApplyParam( RProcess& aProcess ) const
+ {
+ switch( iType )
+ {
+ case EHandle: return aProcess.SetParameter( iSlot, *iHandle );
+ case ESubSession: return aProcess.SetParameter( iSlot, *iSubSession );
+ case EDes16: return aProcess.SetParameter( iSlot, iDes16 );
+ case EDes8: return aProcess.SetParameter( iSlot, iDes8 );
+ case EInt: return aProcess.SetParameter( iSlot, iInt );
+ }
+
+ return KErrUnknown;
+ }
+
+
+// END OF FILE
+
+
+