appfw/apparchitecture/apparc/APACMDLN.CPP
changeset 0 2e3d3ce01487
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/appfw/apparchitecture/apparc/APACMDLN.CPP	Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,896 @@
+// Copyright (c) 1997-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:
+// apacmdln.cpp
+//
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#if !defined(__APA_INTERNAL_H__)
+#include "apainternal.h"
+#endif
+#endif //SYMBIAN_ENABLE_SPLIT_HEADERS
+
+#include <apacmdln.h>
+#include "APASTD.H" // Panics etc.
+#include <s32mem.h>
+
+#include <e32svr.h>
+
+// comand line tokens
+const TUint KApaCommandLetterOpen='O';
+const TUint KApaCommandLetterCreate='C';
+const TUint KApaCommandLetterRun='R';
+const TUint KApaCommandLetterBackground='B';
+const TUint KApaCommandLetterViewActivate='V';
+const TUint KApaCommandLetterRunWithoutViews='W';
+const TUint KApaCommandLetterBackgroundAndWithoutViews='A';
+
+_LIT(KLitTokenServerDifferentiator, "-srvDfr=");
+_LIT(KLitTokenDefaultScreenNumber, "-dsc=");
+_LIT(KLitTokenParentWindowGroupID, "-prntwgid=");
+_LIT(KLitTokenDebugMemFail, "-debugMemFail:");
+_LIT(KLitTokenAppStartupInstrumentationEventIdBase, "-appStartupInstrEvIdBase=");
+_LIT(KLitTokenOpaqueData, "-opaque=");
+
+enum TProcessEnvironmentSots 
+	{
+	EEnvironmentSlotUnused = 0,
+	EEnvironmentSlotMain = 1,
+	EEnvironmentSlotFsSession = 2,
+	EEnvironmentSlotFile = 3,
+	EFirstEnvironmentSlotForPublicUse = 8,
+	ENumberOfEnvironmentSlotsForPublicUse = 4
+	};
+
+enum TIpcMessageSlots
+	{
+	EIpcSlotMain = 0,
+	EIpcSlotFsSession = 1,
+	EIpcSlotFile = 2
+	};
+
+
+// CApaCommandLine
+
+/** Private c'tor - initialize using NewLC()
+@internalTechnology */
+CApaCommandLine::CApaCommandLine() : 
+	iCommand(EApaCommandRun), iServerDifferentiator(0), iDefaultScreenNumber(KErrNotFound),
+	iParentWindowGroupID(0), iDebugMemFail(0), iAppStartupInstrumentationEventIdBase(0),
+	iFile(), iParentProcessId(KNullProcessId)
+	{
+	}
+
+/** Destructor.
+Frees resources owned by the object prior to deletion. */
+EXPORT_C CApaCommandLine::~CApaCommandLine()
+	{
+	iDocumentName.Close();
+	iExecutableName.Close();
+	iOpaqueData.Close();
+	iTailEnd.Close();
+	iFile.Close();
+	}
+
+/** Creates an empty command line object.
+@return A pointer to the new command line object. */
+EXPORT_C CApaCommandLine* CApaCommandLine::NewL()
+	{
+	CApaCommandLine* self = CApaCommandLine::NewLC();
+	CleanupStack::Pop();
+	return self;
+	}
+
+/** Creates an empty command line object, and puts a pointer to it onto the cleanup stack.
+@return A pointer to the new command line object. */
+EXPORT_C CApaCommandLine* CApaCommandLine::NewLC()
+	{
+	CApaCommandLine* self = new(ELeave) CApaCommandLine;
+	CleanupStack::PushL(self);
+	return self;
+	}
+
+EXPORT_C void CApaCommandLine::SetDocumentNameL(const TDesC& aDocName)
+/** Sets the document name from the specified descriptor.
+
+If the document name has embedded spaces, then it must be enclosed within 
+quotation marks.
+
+@param aDocName A descriptor containing the document name. */
+	{
+	RBuf documentName;
+	documentName.CreateL(aDocName);
+	
+	iDocumentName.Close();	// free any existing memory
+	iDocumentName.Assign(documentName);	
+	}
+
+/** Gets the document name from the launch information.
+@return A pointer descriptor representing the document name. The document 
+name is returned without any enclosing quotation marks. If the launch information 
+contains no document name, then the pointer descriptor has zero length. */
+EXPORT_C TPtrC CApaCommandLine::DocumentName() const
+	{
+	return iDocumentName;
+	}
+
+/** Sets the executable name from the specified descriptor.
+@param aExecutableName A descriptor containing the executable name. */
+EXPORT_C void CApaCommandLine::SetExecutableNameL(const TDesC& aExecutableName)
+	{
+	RBuf executableName;
+	executableName.CreateL(aExecutableName);
+	
+	iExecutableName.Close();	// free any existing memory
+	iExecutableName.Assign(executableName);
+	}
+
+/** Gets the executable name from the launch information.
+@return A pointer descriptor representing the executable name. */
+EXPORT_C TPtrC CApaCommandLine::ExecutableName() const
+	{
+	return iExecutableName;
+	}
+
+/** Sets the opaque-data from the specified 8-bit descriptor.
+
+This is called internally and populated from the data in the application's registration resource file, 
+i.e. from the resource indicated by the opaque_data field of the APP_REGISTRATION_INFO resource (if the 
+opaque_data field was non-zero).
+
+@param aOpaqueData An 8-bit descriptor containing the opaque-data. 
+*/
+EXPORT_C void CApaCommandLine::SetOpaqueDataL(const TDesC8& aOpaqueData)
+	{
+	RBuf8 opaqueData;
+	opaqueData.CreateL(aOpaqueData);
+	
+	iOpaqueData.Close();	// free any existing memory
+	iOpaqueData.Assign(opaqueData);
+	}
+
+/** Gets the opaque-data from the launch information.
+
+See the description of SetOpaqueDataL. By default, this attribute is an empty descriptor.
+
+@see SetOpaqueDataL
+@return An 8-bit pointer descriptor representing the opaque-data. 
+*/
+EXPORT_C TPtrC8 CApaCommandLine::OpaqueData() const
+	{
+	return iOpaqueData;
+	}
+
+/** Sets the command code.
+
+The command code is used to indicate how an application is to be launched.
+
+@see TApaCommand
+@param aCommand The command code. */
+EXPORT_C void CApaCommandLine::SetCommandL(TApaCommand aCommand)
+	{
+	iCommand = aCommand;
+	}
+
+/** Gets the command code from the launch information.
+
+See the description of SetCommandL.
+
+@see SetCommandL
+@see TApaCommand
+@return The command code. */
+EXPORT_C TApaCommand CApaCommandLine::Command() const
+	{
+	return iCommand;
+	}
+
+/** Sets the trailing data.
+
+The UI Framework provides a specific set of pre-defined command line 
+options. Additional user defined or pre-defined command line options, 
+may be passed to an application by setting the TailEnd.
+
+@param aTailEnd An 8 bit descriptor containing the trailing data. 
+@publishedAll */
+EXPORT_C void CApaCommandLine::SetTailEndL(const TDesC8& aTailEnd)
+	{
+	RBuf8 tailEnd;
+	tailEnd.CreateL(aTailEnd);
+	
+	iTailEnd.Close();	// free any existing memory
+	iTailEnd.Assign(tailEnd);
+	}
+
+/** Gets the trailing data from the launch information.
+
+See the description of SetTailEndL.
+
+@see SetTailEndL
+@return A pointer descriptor representing the trailing data. If the launch 
+information contains no trailing data, then the pointer descriptor has zero 
+length. 
+@publishedAll */
+EXPORT_C TPtrC8 CApaCommandLine::TailEnd() const
+	{
+	return iTailEnd;
+	}
+
+/** Sets the file to be passed into the application (by handle). 
+This will then be retrieved by that application-process calling GetFileByHandleL().
+
+@publishedPartner
+@released
+@param aFile The file object to be passed into the application. No transfer of this 
+object's ownership takes place in this function. */
+EXPORT_C void CApaCommandLine::SetFileByHandleL(const RFile& aFile)
+	{
+	__ASSERT_ALWAYS(aFile.SubSessionHandle() != KNullHandle, Panic(EPanicInvalidHandle));
+	__ASSERT_ALWAYS(iFile.SubSessionHandle() == KNullHandle, Panic(EPanicHandleAlreadySet));
+	
+	User::LeaveIfError(iFile.Duplicate(aFile));
+	}
+
+/** Opens (by handle) the file that was passed into SetFileByHandleL by the process launching the local application.
+
+On entering this function, aFile must be non-open. It is recommended that aFile is 
+pushed onto the cleanup-stack (via CleanupClosePushL()) before this function is called.
+
+@publishedPartner
+@released
+@param aFile The file object to be set up from the handle passed into the application. The 
+caller has the responsibility to Close() this object, even if this function leaves. */
+EXPORT_C void CApaCommandLine::GetFileByHandleL(RFile& aFile) const
+	{
+	__ASSERT_ALWAYS(aFile.SubSessionHandle()==KNullHandle, Panic(EPanicHandleAlreadySet));
+
+	if (iFile.SubSessionHandle() != KNullHandle)
+		User::LeaveIfError(aFile.Duplicate(iFile));
+	}
+
+/** Assigns a command line to a process (EKA2 only). 
+
+This replaces the EKA1 method which involved retrieving the full command line (using 
+CApaCommandLine::FullCommandLine()) and passing it to the process (or thread on the 
+emulator).
+
+This function is used as follows (the order of the first 2 steps is irrelevant):-
+- create the process and load the executable (RProcess::Create()),
+- create the command line object (CApaCommandLine::NewLC()), and set it up using 
+the various setter functions, for instance SetDocumentNameL(),
+- call SetProcessEnvironmentL() to assign the command line to the process,
+- call Resume() on the process.
+
+Note that this sequence of steps bypasses the application architecture, and is 
+not recommended. RApaLsSession::StartApp() is the recommended way to 
+launch an application with a command line.
+
+@param aProcess The process to which the command line is assigned.
+@leave KErrNotSupported This indicates that the function was called on EKA1.
+@see RApaLsSession::StartApp()
+*/
+EXPORT_C void CApaCommandLine::SetProcessEnvironmentL(RProcess& aProcess) const
+	{
+	HBufC8* const streamableAttributes = StreamableAttributesLC();
+	User::LeaveIfError(aProcess.SetParameter(EEnvironmentSlotMain, *streamableAttributes));
+	CleanupStack::PopAndDestroy(streamableAttributes);
+
+	if (iFile.SubSessionHandle() != KNullHandle)
+		User::LeaveIfError(iFile.TransferToProcess(aProcess, EEnvironmentSlotFsSession, EEnvironmentSlotFile));
+	}
+
+/**
+@internalTechnology
+*/
+EXPORT_C void CApaCommandLine::GetIpcArgsLC(TIpcArgs& aIpcArgs) const
+	{
+	aIpcArgs.Set(EIpcSlotMain, StreamableAttributesLC());
+	if (iFile.SubSessionHandle() != KNullHandle)
+		User::LeaveIfError(iFile.TransferToServer(aIpcArgs, EIpcSlotFsSession, EIpcSlotFile));
+	}
+
+/**
+@internalTechnology
+*/
+HBufC8* CApaCommandLine::StreamableAttributesLC() const
+	{
+	CBufFlat* const buffer = CBufFlat::NewL(128);
+	CleanupStack::PushL(buffer);
+	
+	RBufWriteStream writeStream;
+	writeStream.Truncate(*buffer);
+	ExternalizeL(writeStream);
+	writeStream.CommitL();
+	HBufC8* const bufferAsDescriptor = buffer->Ptr(0).AllocL();
+	
+	CleanupStack::PopAndDestroy(buffer);
+	
+	CleanupStack::PushL(bufferAsDescriptor);
+	return bufferAsDescriptor;
+	}
+
+/** Acts as a second constructor and completes a commandline object from 
+the aMessage object.
+@internalTechnology */
+EXPORT_C void CApaCommandLine::ConstructCmdLineFromMessageL(const RMessage2& aMessage)
+	{
+	// Create a buffer of the right size and get the data from the RMessage2
+	RBuf8 buffer;
+	buffer.CleanupClosePushL();
+	buffer.CreateL(aMessage.GetDesLengthL(EIpcSlotMain));
+	aMessage.ReadL(EIpcSlotMain, buffer);
+	
+	// Create a stream and use it to read the data from the buffer
+	RDesReadStream stream;
+	CleanupClosePushL(stream);
+	stream.Open(buffer);
+	InternalizeL(stream);
+	CleanupStack::PopAndDestroy();	// stream
+	
+	CleanupStack::PopAndDestroy();	// buffer
+	iFile.AdoptFromClient(aMessage, EIpcSlotFsSession, EIpcSlotFile); // ignore the returned error - assume it means that no file has been passed across
+	}
+
+/** Constructs a command line object.
+
+If command line information is provided in the environment-slots it creates command line object from
+process environment-slots, else creates it from the information returned by User::CommandLine().
+
+It can be called from a context where there is no CTrapCleanup.
+
+Calling this function more than once in a process is not supported and will result in an empty command
+line being returned. If an application wants to inspect any part of its command line, it 
+should override CEikAppUi::ProcessCommandParametersL(CApaCommandLine& aCommandLine) and call the base
+class implementation if required.
+
+@see CEikAppUi::ProcessCommandParametersL(CApaCommandLine& aCommandLine).
+@param aCommandLine On return, a pointer to a newly constructed command line object.
+@return KErrNone, if successful; otherwise one of the other system-wide error codes.
+@internalTechnology */
+EXPORT_C TInt CApaCommandLine::GetCommandLineFromProcessEnvironment(CApaCommandLine*& aCommandLine)
+	{ // static
+	aCommandLine = NULL;
+	CApaCommandLine* const commandLine = new CApaCommandLine;
+	if(!commandLine)
+		return KErrNoMemory;
+	
+	CTrapCleanup* trapCleanup = NULL;
+	if (!User::TrapHandler())
+		{
+		trapCleanup = CTrapCleanup::New(); // we're being called from an environment without a cleanup-stack, so temporarily create one here
+		if(!trapCleanup)
+			{
+			delete commandLine;
+			return KErrNoMemory;
+			}
+		}
+	
+	TRAPD(error, commandLine->DoGetCommandLineFromProcessEnvironmentL());
+	aCommandLine = commandLine;
+	delete trapCleanup;
+	return error;
+	}
+
+void CApaCommandLine::DoGetCommandLineFromProcessEnvironmentL()
+	{
+	const TInt bufLen = User::ParameterLength(EEnvironmentSlotMain);
+	if (bufLen == KErrNotFound)
+		{
+		RBuf commandLineString;
+		commandLineString.CleanupClosePushL();
+		commandLineString.CreateL(User::CommandLineLength());
+		User::CommandLine(commandLineString);
+		User::LeaveIfError(DoGetParametersFromCommandLineString(commandLineString));
+		CleanupStack::PopAndDestroy();	// commandLineString
+		}
+	else
+		{
+		User::LeaveIfError(bufLen); // in case bufLen is some error other than KErrNotFound
+		RBuf8 buffer;
+		buffer.CleanupClosePushL();
+		buffer.CreateL(bufLen);
+		
+		User::LeaveIfError(User::GetDesParameter(EEnvironmentSlotMain, buffer));
+		RDesReadStream stream;
+		CleanupClosePushL(stream);
+		stream.Open(buffer);
+		InternalizeL(stream);
+		CleanupStack::PopAndDestroy();	// stream
+		
+		CleanupStack::PopAndDestroy();	// buffer
+		}
+
+	iFile.AdoptFromCreator(EEnvironmentSlotFsSession, EEnvironmentSlotFile); // ignore the returned error - assume it means that no file has been passed across
+	}
+
+/** Sets the Parent Process ID for the Child Process launched with this command line.
+
+This establishes a Parent-Child relationship which ensures that the child process is
+terminated when the parent terminates.
+
+@param aProcessId The Process ID. */
+EXPORT_C void CApaCommandLine::SetParentProcessId(TProcessId aProcessId)
+	{
+	iParentProcessId = aProcessId;
+	}
+
+/** Gets the Parent Process ID of the Child Process launched with this command line.
+
+See the description of SetParentProcessId.
+
+@see SetParentProcessId
+@return The Parent Process ID. */
+EXPORT_C TProcessId CApaCommandLine::ParentProcessId() const
+	{
+	return iParentProcessId;
+	}
+
+void CApaCommandLine::ExternalizeL(RWriteStream& aStream) const
+	{
+	// iFile is not supported via RReadStream/RWriteStream
+	aStream << DocumentName();
+	aStream << ExecutableName();
+	aStream << OpaqueData();
+	aStream << TailEnd();
+	aStream.WriteInt32L(iCommand);
+	aStream.WriteInt32L(iServerDifferentiator);
+	aStream.WriteInt32L(iDefaultScreenNumber);
+	aStream.WriteInt32L(iParentWindowGroupID);
+	aStream.WriteInt32L(iDebugMemFail);
+	aStream.WriteInt32L(iAppStartupInstrumentationEventIdBase);
+	aStream.WriteInt32L(iParentProcessId);
+	}
+
+void CApaCommandLine::InternalizeL(RReadStream& aStream)
+	{
+	// iFile is not supported via RReadStream/RWriteStream
+	const TInt KMaxBufLength = 4000;
+	iDocumentName.Close();	// free any existing memory
+	iDocumentName.CreateL(aStream, KMaxBufLength);
+	iExecutableName.Close();	// free any existing memory
+	iExecutableName.CreateL(aStream, KMaxBufLength);
+	iOpaqueData.Close();	// free any existing memory
+	iOpaqueData.CreateL(aStream, KMaxBufLength);
+	iTailEnd.Close();	// free any existing memory
+	iTailEnd.CreateL(aStream, KMaxBufLength);
+	iCommand = static_cast<TApaCommand>(aStream.ReadInt32L());
+	iServerDifferentiator = aStream.ReadInt32L();
+	iDefaultScreenNumber = aStream.ReadInt32L();
+	iParentWindowGroupID = aStream.ReadInt32L();
+	iDebugMemFail = aStream.ReadInt32L();
+	iAppStartupInstrumentationEventIdBase = aStream.ReadInt32L();
+	iParentProcessId = aStream.ReadInt32L();
+	}
+
+/** Sets that no server is required.
+
+The value of server differentiator is set to zero, to indicate that no server
+is required.
+
+See the description of SetServerRequiredL.
+@see SetServerRequiredL
+*/
+EXPORT_C void CApaCommandLine::SetServerNotRequiredL()
+	{
+	SetServerDifferentiatorL(0);
+	}
+
+/** Sets the required server.
+
+The server differentiator is a number generated by the client that helps to uniquely 
+identify the server. It is used by an application to indicate whether a server should
+be created and how it should be named.
+
+@param aServerDifferentiator A differentiator for the required server.
+@see REikAppServiceBase::LaunchAppL() 
+*/
+EXPORT_C void CApaCommandLine::SetServerRequiredL(TUint aServerDifferentiator)
+	{
+	SetServerDifferentiatorL(aServerDifferentiator);
+	}
+
+/**
+@see REikAppServiceBase::LaunchAppL()
+@internalTechnology
+*/
+void CApaCommandLine::SetServerDifferentiatorL(TUint aServerDifferentiator)
+	{
+	iServerDifferentiator = aServerDifferentiator;
+	}
+	
+/** Gets the server differentiator.
+
+See the description of SetServerRequiredL.
+
+@see SetServerRequiredL
+@return The non-zero differentiator for the server, else zero indicating a server 
+is not required.
+@see REikAppServiceBase::LaunchAppL() */
+EXPORT_C TUint CApaCommandLine::ServerRequired() const
+	{
+	return iServerDifferentiator;
+	}
+
+/** Provides support for devices with more than one screen.  A number representing the default
+or startup screen may be passed to an application.
+Screen numbers and characteristics are defined in the window server initialisation 
+file (wsini.ini).
+
+@param aDefaultScreenNumber The number of the default (startup) screen.
+@publishedAll */
+EXPORT_C void CApaCommandLine::SetDefaultScreenL(TInt aDefaultScreenNumber)
+	{
+	__ASSERT_ALWAYS(aDefaultScreenNumber>=0, Panic(EPanicInvalidScreenNumber));
+	iDefaultScreenNumber = aDefaultScreenNumber;
+	}
+
+/** Extracts and returns the default (startup) screen that was specified in the command line.
+
+@return	A number representing the default (startup) screen.  0 (Zero) if nothing present.
+@publishedAll */
+EXPORT_C TInt CApaCommandLine::DefaultScreen() const
+	{
+	return Max(0, iDefaultScreenNumber);
+	}
+	
+/**
+@publishedAll
+*/
+EXPORT_C TBool CApaCommandLine::IsDefaultScreenSet() const
+	{
+	return (iDefaultScreenNumber != KErrNotFound);
+ 	}
+
+/** Sets the ID of the parent window-group - the application should create its own 
+window-group as a child off this parent.
+
+@param aParentWindowGroupID The ID of the parent window-group - the application 
+should create its window-group as a child off this parent. */
+EXPORT_C void CApaCommandLine::SetParentWindowGroupID(TInt aParentWindowGroupID)
+	{
+	iParentWindowGroupID = aParentWindowGroupID;
+	}
+
+/** Returns the ID of the parent window-group - the application should create its own 
+window-group as a child of this parent.
+
+@return The ID of the parent window-group - the application should create its 
+window-group as a child off this . */
+EXPORT_C TInt CApaCommandLine::ParentWindowGroupID() const
+	{
+	return iParentWindowGroupID;
+	}
+
+/** @internalAll */
+EXPORT_C void CApaCommandLine::SetDebugMemFailL(TInt aDebugMemFail)
+	{
+	iDebugMemFail = aDebugMemFail;
+	}
+
+/** @internalAll */
+EXPORT_C TInt CApaCommandLine::DebugMemFail() const
+	{
+	return iDebugMemFail;
+	}
+
+/** @internalAll */
+EXPORT_C void CApaCommandLine::SetAppStartupInstrumentationEventIdBaseL(TInt aAppStartupInstrumentationEventIdBase)
+	{
+	iAppStartupInstrumentationEventIdBase = aAppStartupInstrumentationEventIdBase;
+	}
+
+/** @internalAll */
+EXPORT_C TInt CApaCommandLine::AppStartupInstrumentationEventIdBase() const
+	{
+	return iAppStartupInstrumentationEventIdBase;
+	}
+
+/** Returns the index of a process environment-slot for public use (in other words, 
+one that is not used internally by CApaCommandLine). The number of slots available 
+for public use is returned from NumberOfEnvironmentSlotsForPublicUse(), (this value 
+may be increased over time). The returned value can then be passed into any of the 
+Open(TInt,...) functions on RSessionBase, RMutex, RChunk, RCondVar, etc, or into 
+User::GetTIntParameter(), User::GetDesParameter(), etc, depending on the type 
+of the object in that environment slot.
+
+@param aIndex The logical index of the public environment-slot. This must be greater 
+than or equal to zero, and less than the value returned from NumberOfEnvironmentSlotsForPublicUse().
+@return The physical index of an environment-slot in the local process. 
+@publishedAll
+*/
+EXPORT_C TInt CApaCommandLine::EnvironmentSlotForPublicUse(TInt aIndex)
+	{ // static
+	__ASSERT_ALWAYS((aIndex>=0) && (aIndex < ENumberOfEnvironmentSlotsForPublicUse), Panic(EPanicEnvironmentSlotNotForPublicUse));
+	return EFirstEnvironmentSlotForPublicUse + aIndex;
+	}
+
+/**
+The number of process environment-slot available for public use.
+@publishedAll
+*/
+EXPORT_C TInt CApaCommandLine::NumberOfEnvironmentSlotsForPublicUse()
+	{
+	return ENumberOfEnvironmentSlotsForPublicUse;
+	}
+
+// For use in CApaCommandLine::DoGetParametersFromCommandLineString() only.
+struct SOption
+	{
+	const TDesC* iToken;
+	TInt* iResult;
+	TRadix iRadix;
+	HBufC8* iHBufC8Result;
+	};
+
+TInt CApaCommandLine::DoGetParametersFromCommandLineString(const TDesC& aCmdLine)
+// does the opposite of SetCmdLineL, i.e. sets iDocumentName, iExecutableName, iTailEnd, iCommand, iServerDifferentiator, iDefaultScreenNumber, iParentWindowGroupID , iDebugMemFail & iAppStartupInstrumentationEventIdBase from aCmdLine
+// also sets iOpaqueData
+	{
+	const TInt cmdLength = aCmdLine.Length();
+	TInt endLibNameOffset = cmdLength-1;
+	TInt endDocNameOffset = cmdLength-1;
+
+	// these variables are all "shadows" of member variables - we'll set the member variables corresponding to these at the end of this function, once all memory-allocation has succeeded, to make this function atomic	
+	HBufC* documentName = NULL;
+	HBufC* executableName = NULL;
+	HBufC8* tailEnd = NULL;
+	HBufC8* opaqueData = NULL;
+	
+	TApaCommand command = EApaCommandRun;
+	TInt serverDifferentiator = 0;
+	TInt defaultScreenNumber = KErrNotFound;
+	TInt parentWindowGroupID = 0;
+	TInt debugMemFail = 0;
+	TInt appStartupInstrumentationEventIdBase = 0;
+	TInt notUsed = 0;
+
+	// Look for the name of the executable
+	executableName = NameOfExecutable(aCmdLine, endDocNameOffset);
+	if (!executableName)
+	{
+	delete executableName;
+	return KErrNoMemory;	
+	}
+	
+	// Work out the type of command		
+	const TInt offset = endDocNameOffset-endLibNameOffset;
+	if (offset > 1)
+		{
+		const TChar commandLetter = aCmdLine[endLibNameOffset+2];
+		switch (commandLetter)
+			{
+		case KApaCommandLetterOpen:
+			command = EApaCommandOpen;
+			break;
+		case KApaCommandLetterCreate:
+			command = EApaCommandCreate;
+			break;
+		case KApaCommandLetterViewActivate:
+			command = EApaCommandViewActivate;
+			break;
+		case KApaCommandLetterRunWithoutViews:
+			command = EApaCommandRunWithoutViews;
+			break;
+		case KApaCommandLetterBackgroundAndWithoutViews:
+			command = EApaCommandBackgroundAndWithoutViews;
+			break;
+		case KApaCommandLetterRun:
+		default:
+			break;
+		case KApaCommandLetterBackground:
+			command = EApaCommandBackground;
+			break;
+			}
+
+	// Get the name of the document file, if any.
+	if (offset > 2)
+		{
+		const TInt documentNameStartPosition = endLibNameOffset+3;
+		documentName = StripQuotes(aCmdLine.Mid(documentNameStartPosition, (endDocNameOffset+1)-documentNameStartPosition)).Alloc();
+		if (!documentName)
+			{
+			delete executableName;
+			delete documentName;
+			return KErrNoMemory;			
+			}
+		}
+	}
+	
+	// Translate the command line tokens into their corresponing options
+	const TInt KNumberOfSupportedOptions = 6;
+	TFixedArray<SOption, KNumberOfSupportedOptions> optionArray;
+	optionArray[0].iToken = &KLitTokenServerDifferentiator;
+	optionArray[0].iResult = &serverDifferentiator;
+	optionArray[0].iRadix = EDecimal;
+	optionArray[1].iToken = &KLitTokenDefaultScreenNumber;
+	optionArray[1].iResult = &defaultScreenNumber;
+	optionArray[1].iRadix = EDecimal;
+	optionArray[2].iToken = &KLitTokenParentWindowGroupID;
+	optionArray[2].iResult = &parentWindowGroupID;
+	optionArray[2].iRadix = EDecimal;
+	optionArray[3].iToken = &KLitTokenDebugMemFail;
+	optionArray[3].iResult = &debugMemFail;
+	optionArray[3].iRadix = EHex;
+	optionArray[4].iToken = &KLitTokenAppStartupInstrumentationEventIdBase;
+	optionArray[4].iResult = &appStartupInstrumentationEventIdBase;
+	optionArray[4].iRadix = EDecimal;
+	optionArray[5].iToken = &KLitTokenOpaqueData;
+	optionArray[5].iResult = &notUsed;
+	optionArray[5].iRadix = EDecimal; // should not used if the command-line is well-formed
+	
+	TLex lex(aCmdLine.Mid(endDocNameOffset+1));
+	lex.Mark();
+	for (TInt optionIndex = 0; optionIndex < KNumberOfSupportedOptions; ++optionIndex)
+		{
+		lex.SkipSpace();
+		const SOption& option = optionArray[optionIndex];
+		const TPtrC remainder(lex.Remainder());
+		__ASSERT_DEBUG(option.iToken, Panic(EDPanicInvalidToken));
+		const TInt tokenLength = option.iToken->Length();
+		if ((remainder.Length() >= tokenLength) && (remainder.Left(tokenLength).CompareF(*option.iToken) == 0))
+			{
+			if (option.iToken == &KLitTokenOpaqueData)
+				{
+				TInt endOfOpaqueDataIndex = 0;			
+				for (TInt i = tokenLength; i < remainder.Length(); ++i)
+					{
+					const TChar current = remainder[i];
+					if (current == ' ')
+						{
+						endOfOpaqueDataIndex = i;
+						break; // parse no further
+						}
+					}
+					
+				if(endOfOpaqueDataIndex > tokenLength)
+					{
+					const TInt opaqueDataLength = endOfOpaqueDataIndex - tokenLength;
+					delete opaqueData;
+					opaqueData = TPtrC8(reinterpret_cast<const TUint8*>(remainder.Mid(tokenLength, opaqueDataLength).Ptr()),opaqueDataLength*sizeof(TText)).Alloc();
+					if (!opaqueData)
+						{
+						delete executableName;
+						delete documentName;
+						delete opaqueData;
+						return KErrNoMemory;						
+						}
+					
+					lex.Inc(tokenLength + opaqueDataLength);
+					lex.Mark();
+					}
+				else
+					{
+					delete opaqueData;
+					delete documentName;
+					delete executableName;
+					delete tailEnd;
+					// invalid command line. copy TLex.Val behavior
+					return KErrGeneral;
+					}
+				}
+			else
+				{
+				ASSERT(option.iResult);
+				const TInt originalValue = *option.iResult;
+				lex.Inc(tokenLength);
+				TUint16 val = static_cast<TUint16> (*option.iResult);
+				if (lex.Val(val, option.iRadix) == KErrNone)
+					lex.Mark();
+				else
+					*option.iResult = originalValue;
+				}
+			}
+		}
+		
+	lex.UnGetToMark();
+	lex.SkipSpace();
+	
+	// Get the tail end
+	const TPtrC remainder(lex.Remainder());
+	const TInt lengthOfRemainder = remainder.Length();
+	if (lengthOfRemainder > 0)
+		{
+		tailEnd = TPtrC8(reinterpret_cast<const TUint8*>(remainder.Ptr()),lengthOfRemainder*sizeof(TText)).Alloc();
+		if (!tailEnd)
+			{
+			delete executableName;
+			delete documentName;
+			delete opaqueData;
+			delete tailEnd;
+			return KErrNoMemory;		
+			}
+		}
+
+	// Free any existing memory
+	iDocumentName.Close();
+	iExecutableName.Close();
+	iTailEnd.Close();
+	iOpaqueData.Close();
+	
+	// Set the member variables, as all memory-allocations have succeeded.
+	iDocumentName.Assign(documentName);
+	iExecutableName.Assign(executableName);
+	iTailEnd.Assign(tailEnd);
+	iOpaqueData.Assign(opaqueData);
+	iCommand = command;
+	iServerDifferentiator = serverDifferentiator;
+	iDefaultScreenNumber = defaultScreenNumber;
+	iParentWindowGroupID = parentWindowGroupID;
+	iDebugMemFail = debugMemFail;
+	iAppStartupInstrumentationEventIdBase = appStartupInstrumentationEventIdBase;
+	
+	return KErrNone;
+	}
+
+/**
+Get the name of the executable from the command line string.
+@internalTechnology
+*/
+HBufC* CApaCommandLine::NameOfExecutable(const TDesC& aCmdLine, TInt& aEndDocNameOffset)
+	{
+	const TInt cmdLength = aCmdLine.Length();
+
+	TBool openQuote = EFalse;
+	TBool foundEndLibName = EFalse;
+	for (TInt i = 0; i < cmdLength; ++i)
+		{
+		const TChar current = aCmdLine[i];
+		if (current=='"')
+			{
+			openQuote = !openQuote;
+			continue;
+			};
+			
+		if ((current==' ') && !openQuote)
+			{
+			// space found outside of quotes
+			if (foundEndLibName)
+				{
+				aEndDocNameOffset = i-1;
+				break; // parse no further
+				}
+				
+			aEndDocNameOffset = i-1;
+			foundEndLibName = ETrue;
+			}
+		}
+		
+	return (aEndDocNameOffset > -1 ? StripQuotes(aCmdLine.Left(aEndDocNameOffset+1)) : KNullDesC()).Alloc();
+	}
+
+/**
+Strip all quates from the string.
+*/
+TPtrC CApaCommandLine::StripQuotes(const TDesC& aDes)
+	//
+	// return aDes stripped of any enclosing quotes 
+	//
+	{
+	TInt start = 0;
+	TInt end = aDes.Length()-1;
+	TPtrC ret;
+	if (end >= 0)
+		{
+		if (aDes[0] == '"')
+			start++;
+
+		if (aDes[end] == '"')
+			end--;
+
+		const TInt length = end-start+1;
+		if (length > 0)
+			ret.Set(aDes.Mid(start, length));
+		}
+	
+	return ret;
+	}
+