commsfwsupport/commselements/StartServer/src/StartProcess.cpp
changeset 0 dfb7c4ff071f
--- /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 <e32math.h>
+
+/*
+* 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<KMaxFileNameLength> 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<RStartProcess*>(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);		
+	}
+