appfw/apparchitecture/apparc/APACMDLN.CPP
changeset 0 2e3d3ce01487
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // apacmdln.cpp
       
    15 //
       
    16 
       
    17 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    18 #if !defined(__APA_INTERNAL_H__)
       
    19 #include "apainternal.h"
       
    20 #endif
       
    21 #endif //SYMBIAN_ENABLE_SPLIT_HEADERS
       
    22 
       
    23 #include <apacmdln.h>
       
    24 #include "APASTD.H" // Panics etc.
       
    25 #include <s32mem.h>
       
    26 
       
    27 #include <e32svr.h>
       
    28 
       
    29 // comand line tokens
       
    30 const TUint KApaCommandLetterOpen='O';
       
    31 const TUint KApaCommandLetterCreate='C';
       
    32 const TUint KApaCommandLetterRun='R';
       
    33 const TUint KApaCommandLetterBackground='B';
       
    34 const TUint KApaCommandLetterViewActivate='V';
       
    35 const TUint KApaCommandLetterRunWithoutViews='W';
       
    36 const TUint KApaCommandLetterBackgroundAndWithoutViews='A';
       
    37 
       
    38 _LIT(KLitTokenServerDifferentiator, "-srvDfr=");
       
    39 _LIT(KLitTokenDefaultScreenNumber, "-dsc=");
       
    40 _LIT(KLitTokenParentWindowGroupID, "-prntwgid=");
       
    41 _LIT(KLitTokenDebugMemFail, "-debugMemFail:");
       
    42 _LIT(KLitTokenAppStartupInstrumentationEventIdBase, "-appStartupInstrEvIdBase=");
       
    43 _LIT(KLitTokenOpaqueData, "-opaque=");
       
    44 
       
    45 enum TProcessEnvironmentSots 
       
    46 	{
       
    47 	EEnvironmentSlotUnused = 0,
       
    48 	EEnvironmentSlotMain = 1,
       
    49 	EEnvironmentSlotFsSession = 2,
       
    50 	EEnvironmentSlotFile = 3,
       
    51 	EFirstEnvironmentSlotForPublicUse = 8,
       
    52 	ENumberOfEnvironmentSlotsForPublicUse = 4
       
    53 	};
       
    54 
       
    55 enum TIpcMessageSlots
       
    56 	{
       
    57 	EIpcSlotMain = 0,
       
    58 	EIpcSlotFsSession = 1,
       
    59 	EIpcSlotFile = 2
       
    60 	};
       
    61 
       
    62 
       
    63 // CApaCommandLine
       
    64 
       
    65 /** Private c'tor - initialize using NewLC()
       
    66 @internalTechnology */
       
    67 CApaCommandLine::CApaCommandLine() : 
       
    68 	iCommand(EApaCommandRun), iServerDifferentiator(0), iDefaultScreenNumber(KErrNotFound),
       
    69 	iParentWindowGroupID(0), iDebugMemFail(0), iAppStartupInstrumentationEventIdBase(0),
       
    70 	iFile(), iParentProcessId(KNullProcessId)
       
    71 	{
       
    72 	}
       
    73 
       
    74 /** Destructor.
       
    75 Frees resources owned by the object prior to deletion. */
       
    76 EXPORT_C CApaCommandLine::~CApaCommandLine()
       
    77 	{
       
    78 	iDocumentName.Close();
       
    79 	iExecutableName.Close();
       
    80 	iOpaqueData.Close();
       
    81 	iTailEnd.Close();
       
    82 	iFile.Close();
       
    83 	}
       
    84 
       
    85 /** Creates an empty command line object.
       
    86 @return A pointer to the new command line object. */
       
    87 EXPORT_C CApaCommandLine* CApaCommandLine::NewL()
       
    88 	{
       
    89 	CApaCommandLine* self = CApaCommandLine::NewLC();
       
    90 	CleanupStack::Pop();
       
    91 	return self;
       
    92 	}
       
    93 
       
    94 /** Creates an empty command line object, and puts a pointer to it onto the cleanup stack.
       
    95 @return A pointer to the new command line object. */
       
    96 EXPORT_C CApaCommandLine* CApaCommandLine::NewLC()
       
    97 	{
       
    98 	CApaCommandLine* self = new(ELeave) CApaCommandLine;
       
    99 	CleanupStack::PushL(self);
       
   100 	return self;
       
   101 	}
       
   102 
       
   103 EXPORT_C void CApaCommandLine::SetDocumentNameL(const TDesC& aDocName)
       
   104 /** Sets the document name from the specified descriptor.
       
   105 
       
   106 If the document name has embedded spaces, then it must be enclosed within 
       
   107 quotation marks.
       
   108 
       
   109 @param aDocName A descriptor containing the document name. */
       
   110 	{
       
   111 	RBuf documentName;
       
   112 	documentName.CreateL(aDocName);
       
   113 	
       
   114 	iDocumentName.Close();	// free any existing memory
       
   115 	iDocumentName.Assign(documentName);	
       
   116 	}
       
   117 
       
   118 /** Gets the document name from the launch information.
       
   119 @return A pointer descriptor representing the document name. The document 
       
   120 name is returned without any enclosing quotation marks. If the launch information 
       
   121 contains no document name, then the pointer descriptor has zero length. */
       
   122 EXPORT_C TPtrC CApaCommandLine::DocumentName() const
       
   123 	{
       
   124 	return iDocumentName;
       
   125 	}
       
   126 
       
   127 /** Sets the executable name from the specified descriptor.
       
   128 @param aExecutableName A descriptor containing the executable name. */
       
   129 EXPORT_C void CApaCommandLine::SetExecutableNameL(const TDesC& aExecutableName)
       
   130 	{
       
   131 	RBuf executableName;
       
   132 	executableName.CreateL(aExecutableName);
       
   133 	
       
   134 	iExecutableName.Close();	// free any existing memory
       
   135 	iExecutableName.Assign(executableName);
       
   136 	}
       
   137 
       
   138 /** Gets the executable name from the launch information.
       
   139 @return A pointer descriptor representing the executable name. */
       
   140 EXPORT_C TPtrC CApaCommandLine::ExecutableName() const
       
   141 	{
       
   142 	return iExecutableName;
       
   143 	}
       
   144 
       
   145 /** Sets the opaque-data from the specified 8-bit descriptor.
       
   146 
       
   147 This is called internally and populated from the data in the application's registration resource file, 
       
   148 i.e. from the resource indicated by the opaque_data field of the APP_REGISTRATION_INFO resource (if the 
       
   149 opaque_data field was non-zero).
       
   150 
       
   151 @param aOpaqueData An 8-bit descriptor containing the opaque-data. 
       
   152 */
       
   153 EXPORT_C void CApaCommandLine::SetOpaqueDataL(const TDesC8& aOpaqueData)
       
   154 	{
       
   155 	RBuf8 opaqueData;
       
   156 	opaqueData.CreateL(aOpaqueData);
       
   157 	
       
   158 	iOpaqueData.Close();	// free any existing memory
       
   159 	iOpaqueData.Assign(opaqueData);
       
   160 	}
       
   161 
       
   162 /** Gets the opaque-data from the launch information.
       
   163 
       
   164 See the description of SetOpaqueDataL. By default, this attribute is an empty descriptor.
       
   165 
       
   166 @see SetOpaqueDataL
       
   167 @return An 8-bit pointer descriptor representing the opaque-data. 
       
   168 */
       
   169 EXPORT_C TPtrC8 CApaCommandLine::OpaqueData() const
       
   170 	{
       
   171 	return iOpaqueData;
       
   172 	}
       
   173 
       
   174 /** Sets the command code.
       
   175 
       
   176 The command code is used to indicate how an application is to be launched.
       
   177 
       
   178 @see TApaCommand
       
   179 @param aCommand The command code. */
       
   180 EXPORT_C void CApaCommandLine::SetCommandL(TApaCommand aCommand)
       
   181 	{
       
   182 	iCommand = aCommand;
       
   183 	}
       
   184 
       
   185 /** Gets the command code from the launch information.
       
   186 
       
   187 See the description of SetCommandL.
       
   188 
       
   189 @see SetCommandL
       
   190 @see TApaCommand
       
   191 @return The command code. */
       
   192 EXPORT_C TApaCommand CApaCommandLine::Command() const
       
   193 	{
       
   194 	return iCommand;
       
   195 	}
       
   196 
       
   197 /** Sets the trailing data.
       
   198 
       
   199 The UI Framework provides a specific set of pre-defined command line 
       
   200 options. Additional user defined or pre-defined command line options, 
       
   201 may be passed to an application by setting the TailEnd.
       
   202 
       
   203 @param aTailEnd An 8 bit descriptor containing the trailing data. 
       
   204 @publishedAll */
       
   205 EXPORT_C void CApaCommandLine::SetTailEndL(const TDesC8& aTailEnd)
       
   206 	{
       
   207 	RBuf8 tailEnd;
       
   208 	tailEnd.CreateL(aTailEnd);
       
   209 	
       
   210 	iTailEnd.Close();	// free any existing memory
       
   211 	iTailEnd.Assign(tailEnd);
       
   212 	}
       
   213 
       
   214 /** Gets the trailing data from the launch information.
       
   215 
       
   216 See the description of SetTailEndL.
       
   217 
       
   218 @see SetTailEndL
       
   219 @return A pointer descriptor representing the trailing data. If the launch 
       
   220 information contains no trailing data, then the pointer descriptor has zero 
       
   221 length. 
       
   222 @publishedAll */
       
   223 EXPORT_C TPtrC8 CApaCommandLine::TailEnd() const
       
   224 	{
       
   225 	return iTailEnd;
       
   226 	}
       
   227 
       
   228 /** Sets the file to be passed into the application (by handle). 
       
   229 This will then be retrieved by that application-process calling GetFileByHandleL().
       
   230 
       
   231 @publishedPartner
       
   232 @released
       
   233 @param aFile The file object to be passed into the application. No transfer of this 
       
   234 object's ownership takes place in this function. */
       
   235 EXPORT_C void CApaCommandLine::SetFileByHandleL(const RFile& aFile)
       
   236 	{
       
   237 	__ASSERT_ALWAYS(aFile.SubSessionHandle() != KNullHandle, Panic(EPanicInvalidHandle));
       
   238 	__ASSERT_ALWAYS(iFile.SubSessionHandle() == KNullHandle, Panic(EPanicHandleAlreadySet));
       
   239 	
       
   240 	User::LeaveIfError(iFile.Duplicate(aFile));
       
   241 	}
       
   242 
       
   243 /** Opens (by handle) the file that was passed into SetFileByHandleL by the process launching the local application.
       
   244 
       
   245 On entering this function, aFile must be non-open. It is recommended that aFile is 
       
   246 pushed onto the cleanup-stack (via CleanupClosePushL()) before this function is called.
       
   247 
       
   248 @publishedPartner
       
   249 @released
       
   250 @param aFile The file object to be set up from the handle passed into the application. The 
       
   251 caller has the responsibility to Close() this object, even if this function leaves. */
       
   252 EXPORT_C void CApaCommandLine::GetFileByHandleL(RFile& aFile) const
       
   253 	{
       
   254 	__ASSERT_ALWAYS(aFile.SubSessionHandle()==KNullHandle, Panic(EPanicHandleAlreadySet));
       
   255 
       
   256 	if (iFile.SubSessionHandle() != KNullHandle)
       
   257 		User::LeaveIfError(aFile.Duplicate(iFile));
       
   258 	}
       
   259 
       
   260 /** Assigns a command line to a process (EKA2 only). 
       
   261 
       
   262 This replaces the EKA1 method which involved retrieving the full command line (using 
       
   263 CApaCommandLine::FullCommandLine()) and passing it to the process (or thread on the 
       
   264 emulator).
       
   265 
       
   266 This function is used as follows (the order of the first 2 steps is irrelevant):-
       
   267 - create the process and load the executable (RProcess::Create()),
       
   268 - create the command line object (CApaCommandLine::NewLC()), and set it up using 
       
   269 the various setter functions, for instance SetDocumentNameL(),
       
   270 - call SetProcessEnvironmentL() to assign the command line to the process,
       
   271 - call Resume() on the process.
       
   272 
       
   273 Note that this sequence of steps bypasses the application architecture, and is 
       
   274 not recommended. RApaLsSession::StartApp() is the recommended way to 
       
   275 launch an application with a command line.
       
   276 
       
   277 @param aProcess The process to which the command line is assigned.
       
   278 @leave KErrNotSupported This indicates that the function was called on EKA1.
       
   279 @see RApaLsSession::StartApp()
       
   280 */
       
   281 EXPORT_C void CApaCommandLine::SetProcessEnvironmentL(RProcess& aProcess) const
       
   282 	{
       
   283 	HBufC8* const streamableAttributes = StreamableAttributesLC();
       
   284 	User::LeaveIfError(aProcess.SetParameter(EEnvironmentSlotMain, *streamableAttributes));
       
   285 	CleanupStack::PopAndDestroy(streamableAttributes);
       
   286 
       
   287 	if (iFile.SubSessionHandle() != KNullHandle)
       
   288 		User::LeaveIfError(iFile.TransferToProcess(aProcess, EEnvironmentSlotFsSession, EEnvironmentSlotFile));
       
   289 	}
       
   290 
       
   291 /**
       
   292 @internalTechnology
       
   293 */
       
   294 EXPORT_C void CApaCommandLine::GetIpcArgsLC(TIpcArgs& aIpcArgs) const
       
   295 	{
       
   296 	aIpcArgs.Set(EIpcSlotMain, StreamableAttributesLC());
       
   297 	if (iFile.SubSessionHandle() != KNullHandle)
       
   298 		User::LeaveIfError(iFile.TransferToServer(aIpcArgs, EIpcSlotFsSession, EIpcSlotFile));
       
   299 	}
       
   300 
       
   301 /**
       
   302 @internalTechnology
       
   303 */
       
   304 HBufC8* CApaCommandLine::StreamableAttributesLC() const
       
   305 	{
       
   306 	CBufFlat* const buffer = CBufFlat::NewL(128);
       
   307 	CleanupStack::PushL(buffer);
       
   308 	
       
   309 	RBufWriteStream writeStream;
       
   310 	writeStream.Truncate(*buffer);
       
   311 	ExternalizeL(writeStream);
       
   312 	writeStream.CommitL();
       
   313 	HBufC8* const bufferAsDescriptor = buffer->Ptr(0).AllocL();
       
   314 	
       
   315 	CleanupStack::PopAndDestroy(buffer);
       
   316 	
       
   317 	CleanupStack::PushL(bufferAsDescriptor);
       
   318 	return bufferAsDescriptor;
       
   319 	}
       
   320 
       
   321 /** Acts as a second constructor and completes a commandline object from 
       
   322 the aMessage object.
       
   323 @internalTechnology */
       
   324 EXPORT_C void CApaCommandLine::ConstructCmdLineFromMessageL(const RMessage2& aMessage)
       
   325 	{
       
   326 	// Create a buffer of the right size and get the data from the RMessage2
       
   327 	RBuf8 buffer;
       
   328 	buffer.CleanupClosePushL();
       
   329 	buffer.CreateL(aMessage.GetDesLengthL(EIpcSlotMain));
       
   330 	aMessage.ReadL(EIpcSlotMain, buffer);
       
   331 	
       
   332 	// Create a stream and use it to read the data from the buffer
       
   333 	RDesReadStream stream;
       
   334 	CleanupClosePushL(stream);
       
   335 	stream.Open(buffer);
       
   336 	InternalizeL(stream);
       
   337 	CleanupStack::PopAndDestroy();	// stream
       
   338 	
       
   339 	CleanupStack::PopAndDestroy();	// buffer
       
   340 	iFile.AdoptFromClient(aMessage, EIpcSlotFsSession, EIpcSlotFile); // ignore the returned error - assume it means that no file has been passed across
       
   341 	}
       
   342 
       
   343 /** Constructs a command line object.
       
   344 
       
   345 If command line information is provided in the environment-slots it creates command line object from
       
   346 process environment-slots, else creates it from the information returned by User::CommandLine().
       
   347 
       
   348 It can be called from a context where there is no CTrapCleanup.
       
   349 
       
   350 Calling this function more than once in a process is not supported and will result in an empty command
       
   351 line being returned. If an application wants to inspect any part of its command line, it 
       
   352 should override CEikAppUi::ProcessCommandParametersL(CApaCommandLine& aCommandLine) and call the base
       
   353 class implementation if required.
       
   354 
       
   355 @see CEikAppUi::ProcessCommandParametersL(CApaCommandLine& aCommandLine).
       
   356 @param aCommandLine On return, a pointer to a newly constructed command line object.
       
   357 @return KErrNone, if successful; otherwise one of the other system-wide error codes.
       
   358 @internalTechnology */
       
   359 EXPORT_C TInt CApaCommandLine::GetCommandLineFromProcessEnvironment(CApaCommandLine*& aCommandLine)
       
   360 	{ // static
       
   361 	aCommandLine = NULL;
       
   362 	CApaCommandLine* const commandLine = new CApaCommandLine;
       
   363 	if(!commandLine)
       
   364 		return KErrNoMemory;
       
   365 	
       
   366 	CTrapCleanup* trapCleanup = NULL;
       
   367 	if (!User::TrapHandler())
       
   368 		{
       
   369 		trapCleanup = CTrapCleanup::New(); // we're being called from an environment without a cleanup-stack, so temporarily create one here
       
   370 		if(!trapCleanup)
       
   371 			{
       
   372 			delete commandLine;
       
   373 			return KErrNoMemory;
       
   374 			}
       
   375 		}
       
   376 	
       
   377 	TRAPD(error, commandLine->DoGetCommandLineFromProcessEnvironmentL());
       
   378 	aCommandLine = commandLine;
       
   379 	delete trapCleanup;
       
   380 	return error;
       
   381 	}
       
   382 
       
   383 void CApaCommandLine::DoGetCommandLineFromProcessEnvironmentL()
       
   384 	{
       
   385 	const TInt bufLen = User::ParameterLength(EEnvironmentSlotMain);
       
   386 	if (bufLen == KErrNotFound)
       
   387 		{
       
   388 		RBuf commandLineString;
       
   389 		commandLineString.CleanupClosePushL();
       
   390 		commandLineString.CreateL(User::CommandLineLength());
       
   391 		User::CommandLine(commandLineString);
       
   392 		User::LeaveIfError(DoGetParametersFromCommandLineString(commandLineString));
       
   393 		CleanupStack::PopAndDestroy();	// commandLineString
       
   394 		}
       
   395 	else
       
   396 		{
       
   397 		User::LeaveIfError(bufLen); // in case bufLen is some error other than KErrNotFound
       
   398 		RBuf8 buffer;
       
   399 		buffer.CleanupClosePushL();
       
   400 		buffer.CreateL(bufLen);
       
   401 		
       
   402 		User::LeaveIfError(User::GetDesParameter(EEnvironmentSlotMain, buffer));
       
   403 		RDesReadStream stream;
       
   404 		CleanupClosePushL(stream);
       
   405 		stream.Open(buffer);
       
   406 		InternalizeL(stream);
       
   407 		CleanupStack::PopAndDestroy();	// stream
       
   408 		
       
   409 		CleanupStack::PopAndDestroy();	// buffer
       
   410 		}
       
   411 
       
   412 	iFile.AdoptFromCreator(EEnvironmentSlotFsSession, EEnvironmentSlotFile); // ignore the returned error - assume it means that no file has been passed across
       
   413 	}
       
   414 
       
   415 /** Sets the Parent Process ID for the Child Process launched with this command line.
       
   416 
       
   417 This establishes a Parent-Child relationship which ensures that the child process is
       
   418 terminated when the parent terminates.
       
   419 
       
   420 @param aProcessId The Process ID. */
       
   421 EXPORT_C void CApaCommandLine::SetParentProcessId(TProcessId aProcessId)
       
   422 	{
       
   423 	iParentProcessId = aProcessId;
       
   424 	}
       
   425 
       
   426 /** Gets the Parent Process ID of the Child Process launched with this command line.
       
   427 
       
   428 See the description of SetParentProcessId.
       
   429 
       
   430 @see SetParentProcessId
       
   431 @return The Parent Process ID. */
       
   432 EXPORT_C TProcessId CApaCommandLine::ParentProcessId() const
       
   433 	{
       
   434 	return iParentProcessId;
       
   435 	}
       
   436 
       
   437 void CApaCommandLine::ExternalizeL(RWriteStream& aStream) const
       
   438 	{
       
   439 	// iFile is not supported via RReadStream/RWriteStream
       
   440 	aStream << DocumentName();
       
   441 	aStream << ExecutableName();
       
   442 	aStream << OpaqueData();
       
   443 	aStream << TailEnd();
       
   444 	aStream.WriteInt32L(iCommand);
       
   445 	aStream.WriteInt32L(iServerDifferentiator);
       
   446 	aStream.WriteInt32L(iDefaultScreenNumber);
       
   447 	aStream.WriteInt32L(iParentWindowGroupID);
       
   448 	aStream.WriteInt32L(iDebugMemFail);
       
   449 	aStream.WriteInt32L(iAppStartupInstrumentationEventIdBase);
       
   450 	aStream.WriteInt32L(iParentProcessId);
       
   451 	}
       
   452 
       
   453 void CApaCommandLine::InternalizeL(RReadStream& aStream)
       
   454 	{
       
   455 	// iFile is not supported via RReadStream/RWriteStream
       
   456 	const TInt KMaxBufLength = 4000;
       
   457 	iDocumentName.Close();	// free any existing memory
       
   458 	iDocumentName.CreateL(aStream, KMaxBufLength);
       
   459 	iExecutableName.Close();	// free any existing memory
       
   460 	iExecutableName.CreateL(aStream, KMaxBufLength);
       
   461 	iOpaqueData.Close();	// free any existing memory
       
   462 	iOpaqueData.CreateL(aStream, KMaxBufLength);
       
   463 	iTailEnd.Close();	// free any existing memory
       
   464 	iTailEnd.CreateL(aStream, KMaxBufLength);
       
   465 	iCommand = static_cast<TApaCommand>(aStream.ReadInt32L());
       
   466 	iServerDifferentiator = aStream.ReadInt32L();
       
   467 	iDefaultScreenNumber = aStream.ReadInt32L();
       
   468 	iParentWindowGroupID = aStream.ReadInt32L();
       
   469 	iDebugMemFail = aStream.ReadInt32L();
       
   470 	iAppStartupInstrumentationEventIdBase = aStream.ReadInt32L();
       
   471 	iParentProcessId = aStream.ReadInt32L();
       
   472 	}
       
   473 
       
   474 /** Sets that no server is required.
       
   475 
       
   476 The value of server differentiator is set to zero, to indicate that no server
       
   477 is required.
       
   478 
       
   479 See the description of SetServerRequiredL.
       
   480 @see SetServerRequiredL
       
   481 */
       
   482 EXPORT_C void CApaCommandLine::SetServerNotRequiredL()
       
   483 	{
       
   484 	SetServerDifferentiatorL(0);
       
   485 	}
       
   486 
       
   487 /** Sets the required server.
       
   488 
       
   489 The server differentiator is a number generated by the client that helps to uniquely 
       
   490 identify the server. It is used by an application to indicate whether a server should
       
   491 be created and how it should be named.
       
   492 
       
   493 @param aServerDifferentiator A differentiator for the required server.
       
   494 @see REikAppServiceBase::LaunchAppL() 
       
   495 */
       
   496 EXPORT_C void CApaCommandLine::SetServerRequiredL(TUint aServerDifferentiator)
       
   497 	{
       
   498 	SetServerDifferentiatorL(aServerDifferentiator);
       
   499 	}
       
   500 
       
   501 /**
       
   502 @see REikAppServiceBase::LaunchAppL()
       
   503 @internalTechnology
       
   504 */
       
   505 void CApaCommandLine::SetServerDifferentiatorL(TUint aServerDifferentiator)
       
   506 	{
       
   507 	iServerDifferentiator = aServerDifferentiator;
       
   508 	}
       
   509 	
       
   510 /** Gets the server differentiator.
       
   511 
       
   512 See the description of SetServerRequiredL.
       
   513 
       
   514 @see SetServerRequiredL
       
   515 @return The non-zero differentiator for the server, else zero indicating a server 
       
   516 is not required.
       
   517 @see REikAppServiceBase::LaunchAppL() */
       
   518 EXPORT_C TUint CApaCommandLine::ServerRequired() const
       
   519 	{
       
   520 	return iServerDifferentiator;
       
   521 	}
       
   522 
       
   523 /** Provides support for devices with more than one screen.  A number representing the default
       
   524 or startup screen may be passed to an application.
       
   525 Screen numbers and characteristics are defined in the window server initialisation 
       
   526 file (wsini.ini).
       
   527 
       
   528 @param aDefaultScreenNumber The number of the default (startup) screen.
       
   529 @publishedAll */
       
   530 EXPORT_C void CApaCommandLine::SetDefaultScreenL(TInt aDefaultScreenNumber)
       
   531 	{
       
   532 	__ASSERT_ALWAYS(aDefaultScreenNumber>=0, Panic(EPanicInvalidScreenNumber));
       
   533 	iDefaultScreenNumber = aDefaultScreenNumber;
       
   534 	}
       
   535 
       
   536 /** Extracts and returns the default (startup) screen that was specified in the command line.
       
   537 
       
   538 @return	A number representing the default (startup) screen.  0 (Zero) if nothing present.
       
   539 @publishedAll */
       
   540 EXPORT_C TInt CApaCommandLine::DefaultScreen() const
       
   541 	{
       
   542 	return Max(0, iDefaultScreenNumber);
       
   543 	}
       
   544 	
       
   545 /**
       
   546 @publishedAll
       
   547 */
       
   548 EXPORT_C TBool CApaCommandLine::IsDefaultScreenSet() const
       
   549 	{
       
   550 	return (iDefaultScreenNumber != KErrNotFound);
       
   551  	}
       
   552 
       
   553 /** Sets the ID of the parent window-group - the application should create its own 
       
   554 window-group as a child off this parent.
       
   555 
       
   556 @param aParentWindowGroupID The ID of the parent window-group - the application 
       
   557 should create its window-group as a child off this parent. */
       
   558 EXPORT_C void CApaCommandLine::SetParentWindowGroupID(TInt aParentWindowGroupID)
       
   559 	{
       
   560 	iParentWindowGroupID = aParentWindowGroupID;
       
   561 	}
       
   562 
       
   563 /** Returns the ID of the parent window-group - the application should create its own 
       
   564 window-group as a child of this parent.
       
   565 
       
   566 @return The ID of the parent window-group - the application should create its 
       
   567 window-group as a child off this . */
       
   568 EXPORT_C TInt CApaCommandLine::ParentWindowGroupID() const
       
   569 	{
       
   570 	return iParentWindowGroupID;
       
   571 	}
       
   572 
       
   573 /** @internalAll */
       
   574 EXPORT_C void CApaCommandLine::SetDebugMemFailL(TInt aDebugMemFail)
       
   575 	{
       
   576 	iDebugMemFail = aDebugMemFail;
       
   577 	}
       
   578 
       
   579 /** @internalAll */
       
   580 EXPORT_C TInt CApaCommandLine::DebugMemFail() const
       
   581 	{
       
   582 	return iDebugMemFail;
       
   583 	}
       
   584 
       
   585 /** @internalAll */
       
   586 EXPORT_C void CApaCommandLine::SetAppStartupInstrumentationEventIdBaseL(TInt aAppStartupInstrumentationEventIdBase)
       
   587 	{
       
   588 	iAppStartupInstrumentationEventIdBase = aAppStartupInstrumentationEventIdBase;
       
   589 	}
       
   590 
       
   591 /** @internalAll */
       
   592 EXPORT_C TInt CApaCommandLine::AppStartupInstrumentationEventIdBase() const
       
   593 	{
       
   594 	return iAppStartupInstrumentationEventIdBase;
       
   595 	}
       
   596 
       
   597 /** Returns the index of a process environment-slot for public use (in other words, 
       
   598 one that is not used internally by CApaCommandLine). The number of slots available 
       
   599 for public use is returned from NumberOfEnvironmentSlotsForPublicUse(), (this value 
       
   600 may be increased over time). The returned value can then be passed into any of the 
       
   601 Open(TInt,...) functions on RSessionBase, RMutex, RChunk, RCondVar, etc, or into 
       
   602 User::GetTIntParameter(), User::GetDesParameter(), etc, depending on the type 
       
   603 of the object in that environment slot.
       
   604 
       
   605 @param aIndex The logical index of the public environment-slot. This must be greater 
       
   606 than or equal to zero, and less than the value returned from NumberOfEnvironmentSlotsForPublicUse().
       
   607 @return The physical index of an environment-slot in the local process. 
       
   608 @publishedAll
       
   609 */
       
   610 EXPORT_C TInt CApaCommandLine::EnvironmentSlotForPublicUse(TInt aIndex)
       
   611 	{ // static
       
   612 	__ASSERT_ALWAYS((aIndex>=0) && (aIndex < ENumberOfEnvironmentSlotsForPublicUse), Panic(EPanicEnvironmentSlotNotForPublicUse));
       
   613 	return EFirstEnvironmentSlotForPublicUse + aIndex;
       
   614 	}
       
   615 
       
   616 /**
       
   617 The number of process environment-slot available for public use.
       
   618 @publishedAll
       
   619 */
       
   620 EXPORT_C TInt CApaCommandLine::NumberOfEnvironmentSlotsForPublicUse()
       
   621 	{
       
   622 	return ENumberOfEnvironmentSlotsForPublicUse;
       
   623 	}
       
   624 
       
   625 // For use in CApaCommandLine::DoGetParametersFromCommandLineString() only.
       
   626 struct SOption
       
   627 	{
       
   628 	const TDesC* iToken;
       
   629 	TInt* iResult;
       
   630 	TRadix iRadix;
       
   631 	HBufC8* iHBufC8Result;
       
   632 	};
       
   633 
       
   634 TInt CApaCommandLine::DoGetParametersFromCommandLineString(const TDesC& aCmdLine)
       
   635 // does the opposite of SetCmdLineL, i.e. sets iDocumentName, iExecutableName, iTailEnd, iCommand, iServerDifferentiator, iDefaultScreenNumber, iParentWindowGroupID , iDebugMemFail & iAppStartupInstrumentationEventIdBase from aCmdLine
       
   636 // also sets iOpaqueData
       
   637 	{
       
   638 	const TInt cmdLength = aCmdLine.Length();
       
   639 	TInt endLibNameOffset = cmdLength-1;
       
   640 	TInt endDocNameOffset = cmdLength-1;
       
   641 
       
   642 	// 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	
       
   643 	HBufC* documentName = NULL;
       
   644 	HBufC* executableName = NULL;
       
   645 	HBufC8* tailEnd = NULL;
       
   646 	HBufC8* opaqueData = NULL;
       
   647 	
       
   648 	TApaCommand command = EApaCommandRun;
       
   649 	TInt serverDifferentiator = 0;
       
   650 	TInt defaultScreenNumber = KErrNotFound;
       
   651 	TInt parentWindowGroupID = 0;
       
   652 	TInt debugMemFail = 0;
       
   653 	TInt appStartupInstrumentationEventIdBase = 0;
       
   654 	TInt notUsed = 0;
       
   655 
       
   656 	// Look for the name of the executable
       
   657 	executableName = NameOfExecutable(aCmdLine, endDocNameOffset);
       
   658 	if (!executableName)
       
   659 	{
       
   660 	delete executableName;
       
   661 	return KErrNoMemory;	
       
   662 	}
       
   663 	
       
   664 	// Work out the type of command		
       
   665 	const TInt offset = endDocNameOffset-endLibNameOffset;
       
   666 	if (offset > 1)
       
   667 		{
       
   668 		const TChar commandLetter = aCmdLine[endLibNameOffset+2];
       
   669 		switch (commandLetter)
       
   670 			{
       
   671 		case KApaCommandLetterOpen:
       
   672 			command = EApaCommandOpen;
       
   673 			break;
       
   674 		case KApaCommandLetterCreate:
       
   675 			command = EApaCommandCreate;
       
   676 			break;
       
   677 		case KApaCommandLetterViewActivate:
       
   678 			command = EApaCommandViewActivate;
       
   679 			break;
       
   680 		case KApaCommandLetterRunWithoutViews:
       
   681 			command = EApaCommandRunWithoutViews;
       
   682 			break;
       
   683 		case KApaCommandLetterBackgroundAndWithoutViews:
       
   684 			command = EApaCommandBackgroundAndWithoutViews;
       
   685 			break;
       
   686 		case KApaCommandLetterRun:
       
   687 		default:
       
   688 			break;
       
   689 		case KApaCommandLetterBackground:
       
   690 			command = EApaCommandBackground;
       
   691 			break;
       
   692 			}
       
   693 
       
   694 	// Get the name of the document file, if any.
       
   695 	if (offset > 2)
       
   696 		{
       
   697 		const TInt documentNameStartPosition = endLibNameOffset+3;
       
   698 		documentName = StripQuotes(aCmdLine.Mid(documentNameStartPosition, (endDocNameOffset+1)-documentNameStartPosition)).Alloc();
       
   699 		if (!documentName)
       
   700 			{
       
   701 			delete executableName;
       
   702 			delete documentName;
       
   703 			return KErrNoMemory;			
       
   704 			}
       
   705 		}
       
   706 	}
       
   707 	
       
   708 	// Translate the command line tokens into their corresponing options
       
   709 	const TInt KNumberOfSupportedOptions = 6;
       
   710 	TFixedArray<SOption, KNumberOfSupportedOptions> optionArray;
       
   711 	optionArray[0].iToken = &KLitTokenServerDifferentiator;
       
   712 	optionArray[0].iResult = &serverDifferentiator;
       
   713 	optionArray[0].iRadix = EDecimal;
       
   714 	optionArray[1].iToken = &KLitTokenDefaultScreenNumber;
       
   715 	optionArray[1].iResult = &defaultScreenNumber;
       
   716 	optionArray[1].iRadix = EDecimal;
       
   717 	optionArray[2].iToken = &KLitTokenParentWindowGroupID;
       
   718 	optionArray[2].iResult = &parentWindowGroupID;
       
   719 	optionArray[2].iRadix = EDecimal;
       
   720 	optionArray[3].iToken = &KLitTokenDebugMemFail;
       
   721 	optionArray[3].iResult = &debugMemFail;
       
   722 	optionArray[3].iRadix = EHex;
       
   723 	optionArray[4].iToken = &KLitTokenAppStartupInstrumentationEventIdBase;
       
   724 	optionArray[4].iResult = &appStartupInstrumentationEventIdBase;
       
   725 	optionArray[4].iRadix = EDecimal;
       
   726 	optionArray[5].iToken = &KLitTokenOpaqueData;
       
   727 	optionArray[5].iResult = &notUsed;
       
   728 	optionArray[5].iRadix = EDecimal; // should not used if the command-line is well-formed
       
   729 	
       
   730 	TLex lex(aCmdLine.Mid(endDocNameOffset+1));
       
   731 	lex.Mark();
       
   732 	for (TInt optionIndex = 0; optionIndex < KNumberOfSupportedOptions; ++optionIndex)
       
   733 		{
       
   734 		lex.SkipSpace();
       
   735 		const SOption& option = optionArray[optionIndex];
       
   736 		const TPtrC remainder(lex.Remainder());
       
   737 		__ASSERT_DEBUG(option.iToken, Panic(EDPanicInvalidToken));
       
   738 		const TInt tokenLength = option.iToken->Length();
       
   739 		if ((remainder.Length() >= tokenLength) && (remainder.Left(tokenLength).CompareF(*option.iToken) == 0))
       
   740 			{
       
   741 			if (option.iToken == &KLitTokenOpaqueData)
       
   742 				{
       
   743 				TInt endOfOpaqueDataIndex = 0;			
       
   744 				for (TInt i = tokenLength; i < remainder.Length(); ++i)
       
   745 					{
       
   746 					const TChar current = remainder[i];
       
   747 					if (current == ' ')
       
   748 						{
       
   749 						endOfOpaqueDataIndex = i;
       
   750 						break; // parse no further
       
   751 						}
       
   752 					}
       
   753 					
       
   754 				if(endOfOpaqueDataIndex > tokenLength)
       
   755 					{
       
   756 					const TInt opaqueDataLength = endOfOpaqueDataIndex - tokenLength;
       
   757 					delete opaqueData;
       
   758 					opaqueData = TPtrC8(reinterpret_cast<const TUint8*>(remainder.Mid(tokenLength, opaqueDataLength).Ptr()),opaqueDataLength*sizeof(TText)).Alloc();
       
   759 					if (!opaqueData)
       
   760 						{
       
   761 						delete executableName;
       
   762 						delete documentName;
       
   763 						delete opaqueData;
       
   764 						return KErrNoMemory;						
       
   765 						}
       
   766 					
       
   767 					lex.Inc(tokenLength + opaqueDataLength);
       
   768 					lex.Mark();
       
   769 					}
       
   770 				else
       
   771 					{
       
   772 					delete opaqueData;
       
   773 					delete documentName;
       
   774 					delete executableName;
       
   775 					delete tailEnd;
       
   776 					// invalid command line. copy TLex.Val behavior
       
   777 					return KErrGeneral;
       
   778 					}
       
   779 				}
       
   780 			else
       
   781 				{
       
   782 				ASSERT(option.iResult);
       
   783 				const TInt originalValue = *option.iResult;
       
   784 				lex.Inc(tokenLength);
       
   785 				TUint16 val = static_cast<TUint16> (*option.iResult);
       
   786 				if (lex.Val(val, option.iRadix) == KErrNone)
       
   787 					lex.Mark();
       
   788 				else
       
   789 					*option.iResult = originalValue;
       
   790 				}
       
   791 			}
       
   792 		}
       
   793 		
       
   794 	lex.UnGetToMark();
       
   795 	lex.SkipSpace();
       
   796 	
       
   797 	// Get the tail end
       
   798 	const TPtrC remainder(lex.Remainder());
       
   799 	const TInt lengthOfRemainder = remainder.Length();
       
   800 	if (lengthOfRemainder > 0)
       
   801 		{
       
   802 		tailEnd = TPtrC8(reinterpret_cast<const TUint8*>(remainder.Ptr()),lengthOfRemainder*sizeof(TText)).Alloc();
       
   803 		if (!tailEnd)
       
   804 			{
       
   805 			delete executableName;
       
   806 			delete documentName;
       
   807 			delete opaqueData;
       
   808 			delete tailEnd;
       
   809 			return KErrNoMemory;		
       
   810 			}
       
   811 		}
       
   812 
       
   813 	// Free any existing memory
       
   814 	iDocumentName.Close();
       
   815 	iExecutableName.Close();
       
   816 	iTailEnd.Close();
       
   817 	iOpaqueData.Close();
       
   818 	
       
   819 	// Set the member variables, as all memory-allocations have succeeded.
       
   820 	iDocumentName.Assign(documentName);
       
   821 	iExecutableName.Assign(executableName);
       
   822 	iTailEnd.Assign(tailEnd);
       
   823 	iOpaqueData.Assign(opaqueData);
       
   824 	iCommand = command;
       
   825 	iServerDifferentiator = serverDifferentiator;
       
   826 	iDefaultScreenNumber = defaultScreenNumber;
       
   827 	iParentWindowGroupID = parentWindowGroupID;
       
   828 	iDebugMemFail = debugMemFail;
       
   829 	iAppStartupInstrumentationEventIdBase = appStartupInstrumentationEventIdBase;
       
   830 	
       
   831 	return KErrNone;
       
   832 	}
       
   833 
       
   834 /**
       
   835 Get the name of the executable from the command line string.
       
   836 @internalTechnology
       
   837 */
       
   838 HBufC* CApaCommandLine::NameOfExecutable(const TDesC& aCmdLine, TInt& aEndDocNameOffset)
       
   839 	{
       
   840 	const TInt cmdLength = aCmdLine.Length();
       
   841 
       
   842 	TBool openQuote = EFalse;
       
   843 	TBool foundEndLibName = EFalse;
       
   844 	for (TInt i = 0; i < cmdLength; ++i)
       
   845 		{
       
   846 		const TChar current = aCmdLine[i];
       
   847 		if (current=='"')
       
   848 			{
       
   849 			openQuote = !openQuote;
       
   850 			continue;
       
   851 			};
       
   852 			
       
   853 		if ((current==' ') && !openQuote)
       
   854 			{
       
   855 			// space found outside of quotes
       
   856 			if (foundEndLibName)
       
   857 				{
       
   858 				aEndDocNameOffset = i-1;
       
   859 				break; // parse no further
       
   860 				}
       
   861 				
       
   862 			aEndDocNameOffset = i-1;
       
   863 			foundEndLibName = ETrue;
       
   864 			}
       
   865 		}
       
   866 		
       
   867 	return (aEndDocNameOffset > -1 ? StripQuotes(aCmdLine.Left(aEndDocNameOffset+1)) : KNullDesC()).Alloc();
       
   868 	}
       
   869 
       
   870 /**
       
   871 Strip all quates from the string.
       
   872 */
       
   873 TPtrC CApaCommandLine::StripQuotes(const TDesC& aDes)
       
   874 	//
       
   875 	// return aDes stripped of any enclosing quotes 
       
   876 	//
       
   877 	{
       
   878 	TInt start = 0;
       
   879 	TInt end = aDes.Length()-1;
       
   880 	TPtrC ret;
       
   881 	if (end >= 0)
       
   882 		{
       
   883 		if (aDes[0] == '"')
       
   884 			start++;
       
   885 
       
   886 		if (aDes[end] == '"')
       
   887 			end--;
       
   888 
       
   889 		const TInt length = end-start+1;
       
   890 		if (length > 0)
       
   891 			ret.Set(aDes.Mid(start, length));
       
   892 		}
       
   893 	
       
   894 	return ret;
       
   895 	}
       
   896