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