diff -r 000000000000 -r dfb7c4ff071f commsfwsupport/commselements/StartServer/src/StartProcess.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commsfwsupport/commselements/StartServer/src/StartProcess.cpp Thu Dec 17 09:22:25 2009 +0200 @@ -0,0 +1,162 @@ +// Copyright (c) 2003-2009 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: +// RStartProcess Client side header +// Implements the R class to start server process +// +// + +/** + @file +*/ + +#include "startprocess.h" +#include + +/* +* Start process has to be different for EPOC32 (EKA1/EKA2 - started as a process) and emulator +* (should be started as a DLL in a separate thread) +*/ +TInt RStartProcess::StartProcess() +/** + * Starts the process and waits for a completion + * + * @return system error code + */ + { + // + // on EPOC platform. Simultaneous launching + // of two such processes should be detected when the second one attempts to + // create the process object, failing with KErrAlreadyExists. + // + TBuf serverFile; + _LIT(KExe, ".exe"); + + serverFile.Copy( iName ); + serverFile.Append(KExe); + + // Remove any "!" prefix when forming the server binary filename. This is because only + // a single string is passed into CStartServer and used to form both the server name + // and server binary filename. However, for protected servers, the string will have + // a "!" prefix - this is used for the server name but removed for the binary filename. + _LIT(KExclamationMark, "!"); + if (serverFile.Left(1).Compare(KExclamationMark()) == 0) + serverFile.Delete(0,1); + + TInt res = iProcess.Create( serverFile,KNullDesC ); + return res == KErrNone ? WaitForCompletion() : res; + } + +TInt RStartProcess::StartProcessThreadFn(TAny* aStartProcess) + {//logon completes with the return code + return static_cast(aStartProcess)->StartProcess(); + } + + +TInt RStartProcess::WaitForCompletion() + { + TRequestStatus started; + iProcess.Rendezvous(started); + + TRequestStatus died; + iProcess.Logon(died); + if (died!=KRequestPending) + { + // logon failed - process is not yet running, so cannot have terminated + User::WaitForRequest(died); // eat signal + iProcess.Kill(0); // abort startup + iProcess.Close(); + return died.Int(); + } + // + // logon OK - start the process + iProcess.Resume(); + User::WaitForRequest(started,died); // wait for start or death + if (started==KRequestPending) + { + // process has died, never made it to the startup signal + iProcess.Close(); + return died.Int(); + } + // + // process started (at last). Cancel and consume the death-notification + // before reporting success + iProcess.LogonCancel(died); + User::WaitForRequest(died); // eat the signal (from the cancel) + iProcess.Close(); + return iErrorCode; + } + +EXPORT_C void RStartProcess::Cancel() +/** +* Intended to cancel asynchronous process startup. +* +*/ + {//not sure what this can do => kill the thread maybe + //for the time being when cancel occures nothing happens and user must still wait + //for start-up to finish + //for the time being we end up blocking our thread until the startup has finished + //and than we call. + //NOTE At the minute we don't kill the process when cancel is called we just set the error code + //and wait for the process to synchronise anyway + //iProcess.Kill( KErrCancel ); + iErrorCode = KErrCancel; //indicate the error code + } + +EXPORT_C TInt RStartProcess::Start(const TDesC& aName, TRequestStatus& aStatus) +/** +* Starts the process asynchronously (using a thread) +* +* @param aName name of the process DLL/EXE +* @param aStatus +* @return TInt - An error code +*/ + { + iErrorCode = KErrNone; + iName.Des().Copy(aName); + TName name(iName); + TTime now; + now.HomeTime(); + TInt64 seed = now.Int64(); + name.AppendNum(Math::Rand(seed), EHex); + + //start the process process using a thread => asynch + RThread t; + const TUint KStackSize=0x1000; + if ((iErrorCode=t.Create(name, StartProcessThreadFn, KStackSize, NULL/*reuses our heap*/, this)) == KErrNone) + { + t.Logon(aStatus); + t.Resume(); //RStartProcess::StartProcessThreadFn completes the logon + t.Close(); + } + else + { + TRequestStatus* p=&aStatus; + User::RequestComplete( p, iErrorCode ); + } + return iErrorCode; + } + +EXPORT_C TInt RStartProcess::Start(const TDesC& aName) +/** +* Starts the process synchronously +* +* @param aName name of the process DLL/EXE +* @return TInt - An error code +*/ + { + iName.Des().Copy(aName); + iErrorCode = KErrNone; + return StartProcessThreadFn(this); + } +