common/tools/ats/smoketest/localisation/apparchitecture/apparc/APPARC.CPP
changeset 793 0c32c669a39d
child 872 17498133d9ad
equal deleted inserted replaced
792:893b85cda81b 793:0c32c669a39d
       
     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 <apparc.h> // stuff everyone will want ie most things
       
    17 #include <apacln.h> // CleanupStack protection for CApaDocument
       
    18 #include "APADLL.H" // CApaDll CApaExe CApaAppHolder
       
    19 #include "APASTD.H" // Panics etc.
       
    20 #include <e32uid.h> // KExecutableImageUid
       
    21 
       
    22 #include <s32stor.h>
       
    23 #include <s32file.h>
       
    24 #include <s32std.h>
       
    25 
       
    26 #ifdef USING_ECOM_RECOGS
       
    27 #include <ecom/ecom.h>
       
    28 #include <ecom/implementationinformation.h>
       
    29 #endif
       
    30 
       
    31 #include "../apparc/TRACE.H"
       
    32 
       
    33 const TInt KAppProcessArrayGranularity(1);
       
    34 
       
    35 _LIT(KApplicationLocation,"\\sys\\bin\\");
       
    36   
       
    37 /////////////////////////////
       
    38 // Doc cleanup method
       
    39 /////////////////////////////
       
    40 
       
    41 EXPORT_C void TApaDocCleanupItem::DoCleanup(TAny* aPtr)
       
    42 	{
       
    43 	__ASSERT_ALWAYS(aPtr,Panic(EPanicNoCleanupItem));
       
    44 	TApaDocCleanupItem* cleanup = reinterpret_cast<TApaDocCleanupItem*>(aPtr);
       
    45 	__ASSERT_ALWAYS(cleanup->iApaProcess,Panic(EPanicNoCleanupItem));//lint !e613 Possible use of null pointer - Asserted above
       
    46 	cleanup->iApaProcess->DestroyDocument(cleanup->iApaDoc); //lint !e613 Possible use of null pointer - Asserted above
       
    47 	}
       
    48 
       
    49 
       
    50 /////////////////////////////
       
    51 // CApaAppHolder
       
    52 /////////////////////////////
       
    53 
       
    54 CApaAppHolder::CApaAppHolder()
       
    55 	{}
       
    56 
       
    57 
       
    58 CApaAppHolder::~CApaAppHolder()
       
    59 	{
       
    60 	}
       
    61 
       
    62 void CApaAppHolder::UpdateAppsRefToThis()
       
    63 	{
       
    64 	CApaApplication* app = Application();
       
    65 	__ASSERT_ALWAYS(app,Panic(EPanicNoApplication));
       
    66 	app->iAppHolder = this;	//lint !e613 Possible use of null pointer - Asserted above
       
    67 	}
       
    68 
       
    69 #ifdef USING_ECOM_RECOGS
       
    70 /////////////////////////////
       
    71 // CApaExe
       
    72 /////////////////////////////
       
    73 
       
    74 CApaExe::CApaExe()
       
    75 	{}
       
    76 
       
    77 CApaExe::~CApaExe()
       
    78 	{
       
    79 	delete iAppName;
       
    80 	delete iApplication;
       
    81 	}
       
    82 
       
    83 TFileName CApaExe::FileName()const
       
    84 	{
       
    85 	if (iAppName)
       
    86 		{
       
    87 		return *iAppName;
       
    88 		}
       
    89 	else
       
    90 		{
       
    91 		return KNullDesC();
       
    92 		}
       
    93 	}
       
    94 
       
    95 TUid CApaExe::Uid()const
       
    96 	{
       
    97 	return iFileUid;
       
    98 	}
       
    99 
       
   100 CApaApplication* CApaExe::Application() const
       
   101 	{
       
   102 	return iApplication;
       
   103 	}
       
   104 
       
   105 void CApaExe::CreateApplicationL(TApaApplicationFactory aApplicationFactory)
       
   106 	{
       
   107 	__ASSERT_ALWAYS(!iApplication,Panic(EPanicApplicationAlreadyExists));
       
   108 	iApplication = aApplicationFactory.CreateApplicationL();
       
   109 	iFileUid = aApplicationFactory.AppFileUid();
       
   110 	User::LeaveIfNull(iApplication);
       
   111 	iAppName = aApplicationFactory.AppFileNameL();
       
   112 	UpdateAppsRefToThis();
       
   113 	}
       
   114 
       
   115 #endif // USING_ECOM_RECOGS
       
   116 
       
   117 EXPORT_C void CApaDocument::OpenFileL(CFileStore*&, RFile&)
       
   118 	{
       
   119 	}
       
   120 
       
   121 EXPORT_C void CApaDocument::Reserved_2()
       
   122 	{}
       
   123 
       
   124 
       
   125 /////////////////////
       
   126 // CApaApplication
       
   127 /////////////////////
       
   128 
       
   129 /** Constructor for CApaApplication */
       
   130 EXPORT_C CApaApplication::CApaApplication()
       
   131 	{
       
   132 	}
       
   133 
       
   134 EXPORT_C TFileName CApaApplication::AppFullName()const
       
   135 /** Returns the full name and path of the application.
       
   136 
       
   137 The default implementation returns the full path name of the application DLL.
       
   138 
       
   139 An application can provide its own implementation. 
       
   140 
       
   141 @return Full path name of the application.
       
   142 @see CApaApplication::DllName() */
       
   143 	{
       
   144 	return DllName();
       
   145 	}
       
   146 
       
   147 
       
   148 EXPORT_C TFileName CApaApplication::DllName()const
       
   149 /** Returns the full name and path of the loaded application DLL.
       
   150 
       
   151 @return Full path name of the application DLL. */
       
   152 	{
       
   153 	__ASSERT_DEBUG(iAppHolder, Panic(EDPanicNoAppHolder));
       
   154 	return iAppHolder->FileName();
       
   155 	}
       
   156 
       
   157 
       
   158 EXPORT_C TInt CApaApplication::GenerateFileName(RFs& aFs,TFileName& aRootName)
       
   159 /** Generates a unique filename based on the file name contained within the specified 
       
   160 full path name.
       
   161 
       
   162 If necessary, the function creates the directory structure that is defined 
       
   163 in the specified full path name.
       
   164 
       
   165 If the file name does not yet exist, then this is the file name chosen. If 
       
   166 this file name already exists, then a file name of the form: name(nn) is generated, 
       
   167 where nn are decimal digits. The value of nn is incremented until a name is 
       
   168 generated that is unique within the directory structure. A minimum of two 
       
   169 decimal digits is generated.
       
   170 
       
   171 The function is used by the UI framework.
       
   172 
       
   173 @param aFs Handle to a file server session. 
       
   174 @param aRootName The full path name.
       
   175 @return KErrNone if successful, otherwise one of the other system-wide error 
       
   176 codes. Specifically: KErrBadName if the file name portion of the specified 
       
   177 full path name has invalid format; KErrArgument if the drive, path or file 
       
   178 name parts are missing from the specified full path name; KErrOverflow if 
       
   179 the generated filename becomes too long; KErrNoMemory if there is insufficient 
       
   180 memory to perform the operation.
       
   181 @see CEikAppUi */
       
   182 	{
       
   183 	// check that filename is valid
       
   184 	if (!aFs.IsValidName(aRootName))
       
   185 		return KErrBadName;
       
   186 	//
       
   187 	// check that a drive, path and root filename have been specified
       
   188 	TParsePtr parsePtr(aRootName);
       
   189 	if (!parsePtr.DrivePresent() || !parsePtr.PathPresent() || !parsePtr.NamePresent())
       
   190 		return KErrArgument;
       
   191 	//
       
   192 	// create the path if necessary
       
   193 	TInt ret=aFs.MkDirAll(parsePtr.DriveAndPath());
       
   194 	if (ret!=KErrNone && ret!=KErrAlreadyExists)
       
   195 		return ret;
       
   196 	//
       
   197 	// Create the Rbuf object to hold a filename (return if no mem available)
       
   198 	RBuf newName;
       
   199 	ret = newName.Create(aRootName, KMaxFileName+8);
       
   200 	if (ret!=KErrNone)
       
   201 		return KErrNoMemory;
       
   202 	//	
       
   203 	// generate a valid filename that doesn't already exist...
       
   204 	TEntry entry;
       
   205 	TInt i=1;
       
   206 	_LIT(KFormatStringOne,"%S%S(%02d)%S");
       
   207 	TBuf<16> format;
       
   208 	format=KFormatStringOne;
       
   209 	while (aFs.Entry(newName,entry)==KErrNone)		// Continue until DoesNotExist or PathDoesNotExist, etc
       
   210 		{
       
   211 		if (i>=100)
       
   212 			{
       
   213 			_LIT(KFormatStringTwo,"%S%S(%d)%S");
       
   214 			format=KFormatStringTwo;
       
   215 			}
       
   216 		TPtrC driveAndPath=parsePtr.DriveAndPath();
       
   217 		TPtrC name=parsePtr.Name();
       
   218 		TPtrC ext=parsePtr.Ext();
       
   219 		newName.Format(format,&driveAndPath,&name,i++,&ext);
       
   220 		if (newName.Length()>KMaxFileName)
       
   221 			{
       
   222 			newName.Close();
       
   223 			return KErrOverflow;
       
   224 			}
       
   225 		}
       
   226 	//
       
   227 	// set the new filename and return
       
   228 	aRootName = newName;
       
   229 	newName.Close();
       
   230 	return KErrNone;
       
   231 	}
       
   232 
       
   233 
       
   234 EXPORT_C CDictionaryStore* CApaApplication::OpenIniFileL(RFs& aFs)const
       
   235 /** Opens the .ini file associated with the application, constructs the dictionary 
       
   236 store object and returns a pointer to it.
       
   237 
       
   238 The implementation of this function is provided by the OpenIniFileLC() function. 
       
   239 The function pops the pointer returned by OpenIniFileLC() from the cleanup 
       
   240 stack.
       
   241 
       
   242 @param aFs Handle to a file server session. 
       
   243 @return A pointer to the dictionary store object representing the application's 
       
   244 .ini file. 
       
   245 @see CApaApplication::OpenIniFileLC() */
       
   246 	{
       
   247 	CDictionaryStore* store=OpenIniFileLC(aFs);
       
   248 	CleanupStack::Pop(); // store
       
   249 	return store;
       
   250 	}
       
   251 
       
   252 EXPORT_C CApaApplication::~CApaApplication()
       
   253 	{
       
   254 #ifdef USING_ECOM_RECOGS
       
   255 	if (iDtorKey!=TUid::Null()) // only some CApaApplication objects are ECom objects (i.e. only those corresponding to embedded applications, not top-level applications)
       
   256 		{
       
   257 		REComSession::DestroyedImplementation(iDtorKey);
       
   258 		}
       
   259 #endif // USING_ECOM_RECOGS
       
   260 	iAppHolder = NULL;
       
   261 	}
       
   262 
       
   263 EXPORT_C void CApaApplication::NewAppServerL(CApaAppServer*& /*aAppServer*/)
       
   264 /** Virtual function called by the framework when the application
       
   265 has been launched as a server application.
       
   266 Applications that wish to be used as server applications must
       
   267 override this function to return their implemetation of the server.
       
   268 @param aAppServer The server pointer to be set. */
       
   269 	{
       
   270 	User::Leave(KErrNotSupported);
       
   271 	}
       
   272 
       
   273 /** Reserved for future use */
       
   274 EXPORT_C void CApaApplication::CApaApplication_Reserved1()
       
   275 	{
       
   276 	}
       
   277 
       
   278 /** Reserved for future use */
       
   279 EXPORT_C void CApaApplication::CApaApplication_Reserved2()
       
   280 	{
       
   281 	}
       
   282 
       
   283 /////////////////////////////
       
   284 // CApaDocument
       
   285 /////////////////////////////
       
   286 
       
   287 /** Constructor for CApaDocument */
       
   288 EXPORT_C CApaDocument::CApaDocument()
       
   289 	{
       
   290 	}
       
   291 
       
   292 EXPORT_C CApaDocument::CApaDocument(CApaApplication& aApp,CApaProcess& aProcess)
       
   293 	: iApplication(&aApp),
       
   294 	iApaProcess(&aProcess)
       
   295 /** Constructs the document object with the specified application and process.
       
   296 
       
   297 Derived classes must define and implement a constructor through which both 
       
   298 the associated application and process can be specified. A typical implementation 
       
   299 calls this constructor through a constructor initialization list.
       
   300 
       
   301 @param aApp The application.
       
   302 @param aProcess The process.
       
   303 @see CEikDocument */
       
   304 	{}
       
   305 
       
   306 
       
   307 EXPORT_C CApaDocument::~CApaDocument()
       
   308 /** Destructor.
       
   309 
       
   310 The implementation is empty. */
       
   311 	{
       
   312 	iContainer = NULL;
       
   313 	iApplication = NULL;
       
   314 	iApaProcess = NULL;
       
   315 	}
       
   316 
       
   317 
       
   318 EXPORT_C CApaDocument::TCapability CApaDocument::Capability() const
       
   319 /** Gets the document's capabilities.
       
   320 
       
   321 Capabilities are encapsulated by an instance of a TCapability class, a public 
       
   322 class defined inside this class.
       
   323 
       
   324 The default implementation returns a default TCapability object, indicating 
       
   325 that the document does not support any of the defined capabilities.
       
   326 
       
   327 If a document does support one or more of the capabilities, it should override 
       
   328 this function to return a suitably initialised object.
       
   329 
       
   330 @return The document's capabilities */
       
   331 	{
       
   332 	return TCapability();
       
   333 	}
       
   334 
       
   335 
       
   336 EXPORT_C void CApaDocument::ValidatePasswordL() const
       
   337 /** Checks the document password.
       
   338 
       
   339 The default implementation is empty.
       
   340 
       
   341 If a document is intended to be password protected, the UI application should 
       
   342 provide an implementation that forces the user to enter the password and validate 
       
   343 the input.
       
   344 
       
   345 If the document is protected by a password and the password entered by the 
       
   346 user is incorrect, the function should leave with KErrLocked, otherwise it 
       
   347 should just return. */
       
   348 	{}
       
   349 
       
   350 
       
   351 EXPORT_C CPicture* CApaDocument::GlassPictureL()
       
   352 // Return handle to glass picture, creating one if not already created.
       
   353 // returns NULL as glass pictures are not supported by default
       
   354 /** Gets an object that can draw a representation of the document's content.
       
   355 
       
   356 If the document supports being embedded as a glass door, then the UI application 
       
   357 must provide an implementation for this function.
       
   358 
       
   359 The default implementation raises an APPARC 8 panic.
       
   360 
       
   361 @return A pointer to a glass door. */
       
   362 	{
       
   363 	Panic(EPanicNoGlassDoorMethodSupplied);
       
   364 	//
       
   365 	return NULL;
       
   366 	}
       
   367 
       
   368 
       
   369 EXPORT_C void CApaDocument::ExternalizeL(RWriteStream& /*aStream*/)const
       
   370 	{}
       
   371 
       
   372 EXPORT_C CApaDocument::TCapability::TCapability()
       
   373 	:iCapability(0),TCapability_Reserved1(0)
       
   374 /** Constructs a default capability object.
       
   375 
       
   376 All capabilities are marked as "not supported". */
       
   377 	{}
       
   378 
       
   379 /////////////////////////////
       
   380 // TApaAppHolderInfo
       
   381 /////////////////////////////
       
   382 
       
   383 class TApaAppHolderInfo
       
   384 	{
       
   385 public:
       
   386 	TApaAppHolderInfo(CApaAppHolder* aAppHolder);
       
   387 public:
       
   388 	CApaAppHolder* iAppHolder;
       
   389 	TBool iToBeRemoved;
       
   390 	};
       
   391 
       
   392 TApaAppHolderInfo::TApaAppHolderInfo(CApaAppHolder* aAppHolder)
       
   393 	:iAppHolder(aAppHolder), iToBeRemoved(EFalse)
       
   394 	{
       
   395 	}
       
   396 
       
   397 /////////////////////////////
       
   398 // CApaParentProcessMonitor
       
   399 /////////////////////////////
       
   400 
       
   401 class CApaParentProcessMonitor : public CActive
       
   402 	{
       
   403 public: // Construction / destruction
       
   404 	static CApaParentProcessMonitor* NewL(TProcessId aProcessId);
       
   405 	~CApaParentProcessMonitor();
       
   406 	void ConstructL();
       
   407 private:
       
   408 	CApaParentProcessMonitor(TProcessId aProcessId);
       
   409 public: // From CActive
       
   410 	void RunL();
       
   411 	void DoCancel();
       
   412 private:
       
   413 	TProcessId iProcessId;
       
   414 	RProcess iProcess;
       
   415 	};
       
   416 
       
   417 CApaParentProcessMonitor* CApaParentProcessMonitor::NewL(TProcessId aProcessId)
       
   418 	{
       
   419 	CApaParentProcessMonitor* self=new (ELeave) CApaParentProcessMonitor(aProcessId);
       
   420 	CleanupStack::PushL(self);
       
   421 	self->ConstructL();
       
   422 	CleanupStack::Pop(self);
       
   423 	return self;
       
   424 	}
       
   425 
       
   426 CApaParentProcessMonitor::CApaParentProcessMonitor(TProcessId aProcessId)
       
   427 	: CActive(EPriorityLow)
       
   428 	{
       
   429 	iProcessId=aProcessId;
       
   430 	}
       
   431 
       
   432 CApaParentProcessMonitor::~CApaParentProcessMonitor()
       
   433 	{
       
   434 	Cancel();
       
   435 	}
       
   436 
       
   437 void CApaParentProcessMonitor::ConstructL()
       
   438 	{
       
   439 	User::LeaveIfError(iProcess.Open(iProcessId));
       
   440 	iProcess.Logon(iStatus);
       
   441 	if(iStatus==KErrNoMemory)
       
   442 		{
       
   443 		User::WaitForRequest(iStatus);
       
   444 		User::Leave(KErrNoMemory);
       
   445 		}
       
   446 	CActiveScheduler::Add(this);
       
   447 	SetActive();
       
   448 	}
       
   449 
       
   450 void CApaParentProcessMonitor::RunL()
       
   451 	{
       
   452 	// Do something that will kill the child when the parent process terminates
       
   453 	if(iStatus==KErrNone)
       
   454 		{
       
   455 		RProcess proc;
       
   456 		proc.Terminate(KErrNone);
       
   457 		}
       
   458 	}
       
   459 
       
   460 void CApaParentProcessMonitor::DoCancel()
       
   461 	{
       
   462 	iProcess.LogonCancel(iStatus);
       
   463 	}
       
   464 
       
   465 /////////////////////////////
       
   466 // CApaProcess
       
   467 /////////////////////////////
       
   468 
       
   469 /** Constructor for CApaProcess */
       
   470 EXPORT_C CApaProcess::CApaProcess()
       
   471 	{
       
   472 	}
       
   473 
       
   474 EXPORT_C CApaProcess* CApaProcess::NewL(const RFs& aFs)
       
   475 /** Creates and returns a pointer to a new application process.
       
   476 
       
   477 This function is not used by UI applications.
       
   478 
       
   479 @param aFs Handle to a file server session.
       
   480 @return Pointer to the new application process. */
       
   481 	{
       
   482 	CApaProcess* self=new(ELeave) CApaProcess(aFs);
       
   483 	CleanupStack::PushL(self);
       
   484 	self->ConstructL();
       
   485 	CleanupStack::Pop();
       
   486 	return self;
       
   487 	}
       
   488 
       
   489 EXPORT_C CApaProcess::CApaProcess(const RFs& aFs)
       
   490 	:iFsSession(aFs)
       
   491 /** Constructs the application process object with the specified file session handle.
       
   492 
       
   493 Derived classes must define and implement a constructor through which 
       
   494 the file session handle can be specified. A 
       
   495 typical implementation calls this constructor through a constructor initialization 
       
   496 list.
       
   497 
       
   498 This constructor is used by the UI framework.
       
   499 
       
   500 @deprecated
       
   501 @param aFs Handle to a file server session */
       
   502 	{}
       
   503 
       
   504 const TInt KPriorityGreaterThanShutter=102;
       
   505 
       
   506 EXPORT_C void CApaProcess::ConstructL()
       
   507 /** Completes construction of the application process object.
       
   508 
       
   509 Implementers of derived classes must call this function as part of the second 
       
   510 stage construction of an object. Typically, derived classes implement their 
       
   511 own NewL() function and call ConstructL() as part of that implementation. */
       
   512 	{
       
   513 	//
       
   514 	iAppList = new(ELeave) CArrayFixFlat<TApaAppHolderInfo>(KAppProcessArrayGranularity);
       
   515 	iDocList = new(ELeave) CArrayFixFlat<CApaDocument*>(KAppProcessArrayGranularity);
       
   516 	iMainDocFileName = HBufC::NewL(KMaxFileName);
       
   517 	iApplicationRemover=CIdle::NewL(KPriorityGreaterThanShutter);	// Use an idle object so that app has chance to clear its call stack
       
   518 	}
       
   519 
       
   520 EXPORT_C void CApaProcess::ConstructL(TProcessId aParentProcessId)
       
   521 /** Completes construction of the application process object, passing in a Parent Process Identifier.
       
   522 
       
   523 Implementers of derived classes must call this function as part of the second 
       
   524 stage construction of an object. Typically, derived classes implement their 
       
   525 own NewL() function and call ConstructL() as part of that implementation.
       
   526 
       
   527 @param aParentProcessId Id of the parent process. This process will terminate when the parent does. */
       
   528 	{
       
   529 	ConstructL();
       
   530 	if(KNullProcessId!=aParentProcessId)
       
   531 		{
       
   532 		iMonitor=CApaParentProcessMonitor::NewL(aParentProcessId);
       
   533 		}
       
   534 	}
       
   535 
       
   536 EXPORT_C CApaProcess::~CApaProcess()
       
   537 // If this is called without calling ResetL() or CApaDocument::SaveL() first, data may be lost
       
   538 //
       
   539 /** Frees resources prior to destruction.
       
   540 
       
   541 Documents must be saved before the application process is deleted, otherwise 
       
   542 data may be lost.
       
   543 
       
   544 In debug mode, the destructor raises an APPARC 6 panic if documents still 
       
   545 exist, and an APPARC 5 panic if applications still exist. */
       
   546 	{
       
   547 	if (iMainDoc)
       
   548 		{
       
   549 		DestroyDocument(iMainDoc);
       
   550 		iMainDoc = NULL;
       
   551 		}
       
   552 	if (iDocList)
       
   553 		{
       
   554 		__ASSERT_DEBUG(iDocList->Count()==0,Panic(EPanicDocListNotEmpty));
       
   555 		for (TInt i=iDocList->Count()-1 ; i>=0 ; i--)
       
   556 			{
       
   557 			delete (*iDocList)[i]; // delete stray doc's in release mode, just to be tidy
       
   558 			}
       
   559 		}
       
   560 	if (iAppList)
       
   561 		{
       
   562 		for (TInt i=iAppList->Count()-1 ; i>=0 ; i--)
       
   563 			{
       
   564 			delete ((*iAppList)[i]).iAppHolder;
       
   565 			}
       
   566 		}
       
   567 	delete iAppList;
       
   568 	delete iDocList;
       
   569 	delete iMainDocFileName;
       
   570 	delete iApplicationRemover;
       
   571 	delete iMonitor;
       
   572 	}
       
   573 
       
   574 
       
   575 EXPORT_C void CApaProcess::ResetL()
       
   576 /** Resets the the application process to its initial state.
       
   577 
       
   578 Specifically, it saves the main document, deletes the main and all embedded 
       
   579 documents from memory, resets the main document filename and deletes all applications 
       
   580 except the main application.
       
   581 
       
   582 The function can leave if saving the main document fails. */
       
   583 	{
       
   584 	if (iMainDoc)
       
   585 		{
       
   586 		iMainDoc->SaveL();
       
   587 		DeleteAllDocs(); // sets iMainDoc to NULL, deletes all apps except main
       
   588 		}
       
   589 	__ASSERT_DEBUG(iMainDocFileName, Panic(EPanicNoDocument));
       
   590 	*iMainDocFileName=KNullDesC;
       
   591 	}
       
   592 
       
   593 
       
   594 void CApaProcess::DeleteAllDocs()
       
   595 // deletes all docs
       
   596 // deletes all apps except main app
       
   597 // sets iMainDoc* to NULL
       
   598 //
       
   599 	{
       
   600 	CApaAppHolder* mainAppHolder=NULL;
       
   601 	if (iMainDoc)
       
   602 		{
       
   603 		__ASSERT_DEBUG(iMainDoc->Application(), Panic(EDPanicNoApp));
       
   604 		mainAppHolder = iMainDoc->Application()->iAppHolder;
       
   605 		for (TInt i=iDocList->Count()-1 ; i>=0 ; i--)
       
   606 			if ((*iDocList)[i]==iMainDoc)
       
   607 				{
       
   608 				iDocList->Delete(i); // removes from array, but doesnt destroy
       
   609 				delete iMainDoc;
       
   610 				iMainDoc = NULL;
       
   611 				}
       
   612 		}
       
   613 	__ASSERT_ALWAYS(iDocList->Count()==0,Panic(EPanicDocListNotEmpty));
       
   614 	iDocList->Reset();
       
   615 	if (iAppList)
       
   616 		{
       
   617 		for (TInt ii=iAppList->Count()-1 ; ii>=0 ; ii--) // need to iterate backwards as the array changes size during the loop
       
   618 			{
       
   619 			if ((*iAppList)[ii].iAppHolder!=mainAppHolder)
       
   620 				{
       
   621 				delete (*iAppList)[ii].iAppHolder;
       
   622 				iAppList->Delete(ii);
       
   623 				}
       
   624 			}
       
   625 		iAppList->Compress();
       
   626 		}
       
   627 	}
       
   628 
       
   629 
       
   630 EXPORT_C void CApaProcess::SetMainDocFileName(const TDesC& aMainDocFileName)
       
   631 /** Sets the filename of the main document.
       
   632 
       
   633 @param aMainDocFileName The filename to be set.
       
   634 @panic APPARC 7 If the length of aMainDocFileName is greater than KMaxFileName or the
       
   635 length of the last filename set by SetMainDocFileNameL if greater
       
   636 @see KMaxFileName */
       
   637 	{
       
   638 	__ASSERT_DEBUG( iMainDocFileName, Panic(EPanicNullPointer));
       
   639 	__ASSERT_ALWAYS( aMainDocFileName.Length()<=iMainDocFileName->Des().MaxLength() ,Panic(EPanicFileNameTooLong));
       
   640 	*iMainDocFileName = aMainDocFileName;
       
   641 	}
       
   642 
       
   643 EXPORT_C void CApaProcess::SetMainDocFileNameL(const TDesC& aMainDocFileName)
       
   644 /** Sets the filename of the main document.
       
   645 
       
   646 @param aMainDocFileName The filename to be set. There is no restriction on the
       
   647 length of this descriptor. */
       
   648 	{
       
   649 	__ASSERT_ALWAYS( iMainDocFileName, Panic(EPanicNullPointer));
       
   650 	const TInt newLength = aMainDocFileName.Length() < KMaxFileName ? KMaxFileName : aMainDocFileName.Length();
       
   651 	if (newLength != iMainDocFileName->Des().MaxLength())
       
   652 		{
       
   653 		HBufC* const newMainDocFileName = HBufC::NewL(newLength);
       
   654 		delete iMainDocFileName;
       
   655 		iMainDocFileName = newMainDocFileName;
       
   656 		}
       
   657 	SetMainDocFileName(aMainDocFileName);
       
   658 	}
       
   659 
       
   660 EXPORT_C void CApaProcess::SetMainDocument(CApaDocument* aDocument)
       
   661 /** Sets the main document.
       
   662 
       
   663 @param aDocument A pointer to the document to be set as the main document 
       
   664 of the application process. This must be a an object created by the AddNewDocumentL() 
       
   665 or OpenNewDocumentL() functions 
       
   666 @see CApaProcess::AddNewDocumentL()
       
   667 @see CApaProcess::OpenNewDocumentL() */
       
   668 	{
       
   669 	__ASSERT_ALWAYS( iDocList, Panic(EPanicNullPointer));
       
   670 	// check that the prospective main doc has actually been added to the array
       
   671 	for (TInt i=iDocList->Count()-1 ; i>=0 ; i--)
       
   672 		{
       
   673 		if ((*iDocList)[i]==aDocument)
       
   674 			break;
       
   675 		if (i==0)
       
   676 			Panic(EPanicNoDocument);
       
   677 		}
       
   678 	// assign it once it has checked out
       
   679 	iMainDoc = aDocument;
       
   680 	}
       
   681 
       
   682 EXPORT_C CApaDocument* CApaProcess::AddNewDocumentL(TApaApplicationFactory aApplicationFactory)
       
   683 /** Creates and adds a new document using the specified application factory.
       
   684 
       
   685 The document may be a main document or an embedded document.
       
   686 
       
   687 Any document created with this function must be destroyed using DestroyDocument().
       
   688 
       
   689 @param aApplicationFactory Should be created implicitly by passing a pointer to
       
   690 a factory function, an ECOM plugin UID, or a CImplementationInformation reference.
       
   691 @return A pointer to the new document.
       
   692 @see CApaProcess::DestroyDocument()
       
   693 @see CApaApplication */
       
   694 	{
       
   695 #ifdef USING_ECOM_RECOGS
       
   696 	__SHOW_TRACE(_L("Starting CApaProcess::AddNewDocumentL"));
       
   697 	__APA_PROFILE_START(0);
       
   698 
       
   699 	CApaAppHolder* appHolder = AddAppExeL(aApplicationFactory);	
       
   700 
       
   701 	// use the app to create a doc
       
   702 	CApaDocument* doc=NULL;
       
   703 	TRAPD(ret,doc=CreateDocL(appHolder->Application()));
       
   704 	if (ret!=KErrNone)
       
   705 		// remove app as it has been orphaned
       
   706 		RemoveApp(appHolder);
       
   707 	User::LeaveIfError(ret);
       
   708 	__PROFILE_END(0);
       
   709 	return doc;
       
   710 #else // USING_ECOM_RECOGS
       
   711 	(void)aApplicationFactory;
       
   712 	return NULL;
       
   713 #endif // USING_ECOM_RECOGS
       
   714 	} //lint !e1762 Member function could be made const - Not true
       
   715 
       
   716 
       
   717 
       
   718 void CApaProcess::RemoveApp(CApaAppHolder* aAppHolder)
       
   719 // removes app holder from the list if it exists, panics otherwise
       
   720 	{
       
   721 	__ASSERT_ALWAYS(iAppList, Panic(EPanicNullPointer));
       
   722 	TInt i = 0;
       
   723 	for (i=iAppList->Count()-1 ; i>=0 ; i--)
       
   724 		{
       
   725 		if ((*iAppList)[i].iAppHolder==aAppHolder) // the main app may be alive on its own if Reset() has just been called
       
   726 			{
       
   727 			delete aAppHolder; // the main app may be alive on its own if Reset() has just been called
       
   728 			iAppList->Delete(i);
       
   729 			break;
       
   730 			}
       
   731 		}
       
   732 	if (i<0)
       
   733 		Panic(EPanicAppNotInList);
       
   734 	}
       
   735 
       
   736 
       
   737 EXPORT_C CApaDocument* CApaProcess::OpenNewDocumentL(CFileStore*& aStore,CStreamDictionary*& aStreamDic,const TDesC& aDocFullFileName,TUint aFileMode)
       
   738 /** Opens the specified file and restores the content as a document.
       
   739 
       
   740 The created document can be merged into or embedded in another document.
       
   741 
       
   742 Any document created with this function must be destroyed using DestroyDocument().
       
   743 
       
   744 @param aStore On return, this contains a pointer to the store object created 
       
   745 during the restore.
       
   746 @param aStreamDic On return, this contains a pointer to the stream dictionary 
       
   747 object created during the restore. 
       
   748 @param aDocFullFileName The name of the file containing the document. 
       
   749 @param aFileMode The mode in which to open the file. 
       
   750 @return A pointer to the restored document.
       
   751 @see TFileMode
       
   752 @see CApaProcess::DestroyDocument() */
       
   753 	{
       
   754 	__SHOW_TRACE(_L("Starting CApaProcess::OpenNewDocumentL"));
       
   755 	__APA_PROFILE_START(1);
       
   756 	TParse parser;
       
   757 	User::LeaveIfError(iFsSession.Parse(aDocFullFileName,parser)); 
       
   758 	// open doc as a file store & read in the header
       
   759 	CFileStore* docStore;
       
   760 	CStreamDictionary* streamDic = ReadRootStreamLC(FsSession(),docStore,parser.FullName(),aFileMode);
       
   761 	CleanupStack::PushL(docStore);
       
   762 	// read in the app id info
       
   763 	TApaAppIdentifier appId=ReadAppIdentifierL(*docStore,*streamDic);
       
   764 	// create the doc
       
   765 	CApaDocument* importedDoc =	AddNewDocumentL(appId.iAppUid);
       
   766 	// restore the document
       
   767 	TApaDocCleanupItem cleanup(this,importedDoc);
       
   768 	CleanupStack::PushL(cleanup);
       
   769 	importedDoc->RestoreL(*docStore,*streamDic);
       
   770 	CleanupStack::Pop(3); //docStore,importedDoc,streamDic
       
   771 	aStore = docStore;
       
   772 	aStreamDic = streamDic;
       
   773 	__PROFILE_END(1);
       
   774 	return importedDoc;
       
   775 	}
       
   776 
       
   777 EXPORT_C TApaAppIdentifier CApaProcess::ReadAppIdentifierL(const CStreamStore& aStore,const CStreamDictionary& aStreamDic)
       
   778 // this is a static method
       
   779 /** Reads the application identifier from its stream in the specified store and 
       
   780 returns it.
       
   781 
       
   782 The location of the stream is found in the specified stream dictionary.
       
   783 
       
   784 @param aStore The store from which the application identifier should be read. 
       
   785 @param aStreamDic The stream dictionary containing the stream ID of the application 
       
   786 identifier stream. The stream dictionary can be found in the root stream of 
       
   787 the store.
       
   788 @return The application identifier. */
       
   789 	{
       
   790 	__SHOW_TRACE(_L("Starting CApaProcess::ReadAppIdentifierL"));
       
   791 	TStreamId infoStreamId=aStreamDic.At(KUidAppIdentifierStream);
       
   792 	TApaAppIdentifier appId;
       
   793 	// create a stream and read in the data
       
   794 	RStoreReadStream stream;
       
   795 	stream.OpenLC(aStore,infoStreamId);
       
   796 	stream>> appId;
       
   797 	stream.Close();
       
   798 	CleanupStack::PopAndDestroy(); // stream
       
   799 	return appId;	
       
   800 	}
       
   801 
       
   802 
       
   803 EXPORT_C void CApaProcess::WriteAppIdentifierL(CStreamStore& aStore,CStreamDictionary& aStreamDic,const TApaAppIdentifier& aAppId)
       
   804 // this is a static method
       
   805 /** Writes the application identifier to a new stream in the specified store and 
       
   806 records the location of this stream in the specified stream dictionary.
       
   807 
       
   808 @param aStore The store to which the application identifier should be written. 
       
   809 
       
   810 @param aStreamDic The stream dictionary. 
       
   811 @param aAppId The application identifier to be externalised to a stream. */
       
   812 	{
       
   813 	__SHOW_TRACE(_L("Starting CApaProcess::WriteAppIdentifierL"));
       
   814 	// create a stream
       
   815 	RStoreWriteStream stream;
       
   816 	TStreamId streamId=stream.CreateLC(aStore);
       
   817 	// stream the header
       
   818 	stream<< aAppId;
       
   819 	stream.CommitL();
       
   820 	CleanupStack::PopAndDestroy(); // id stream
       
   821 	// enter the stream in the dictionary
       
   822 	aStreamDic.AssignL(KUidAppIdentifierStream,streamId);
       
   823 	}
       
   824 
       
   825 
       
   826 EXPORT_C CStreamDictionary* CApaProcess::ReadRootStreamLC(RFs& aFs,CFileStore*& aStore,const TDesC& aDocFullFileName,TUint aFileMode)
       
   827 /** Reads the stream dictionary contained as the root stream in the specified document 
       
   828 file.
       
   829 
       
   830 The function constructs, and returns a pointer to the stream dictionary object 
       
   831 and puts the pointer to the stream dictionary object onto the cleanup stack. 
       
   832 It also returns a pointer to the created file store object through an argument 
       
   833 reference. 
       
   834 
       
   835 The file must be a valid document file; otherwise the function leaves with one of 
       
   836 the system-wide error codes.
       
   837 
       
   838 @param aFs Handle to a file server session.
       
   839 @param aStore On return, a pointer to the newly created file store object. 
       
   840 @param aDocFullFileName The full path name of the document file. 
       
   841 @param aFileMode The mode in which to open the file.
       
   842 @return A pointer to the stream dictionary object read from the root stream 
       
   843 of the store. 
       
   844 @see TFileMode */
       
   845 	{ // static
       
   846 	__SHOW_TRACE(_L("Starting CApaProcess::ReadRootStreamLC (file-name overload)"));
       
   847 	CStreamDictionary* const streamDictionary=CStreamDictionary::NewLC();
       
   848 	CFileStore* const store=CFileStore::OpenLC(aFs,aDocFullFileName,aFileMode);
       
   849 	DoReadRootStreamL(*streamDictionary, *store);
       
   850 	aStore=store; // delay assignment until nothing can go wrong to avoid destroying the store twice if a leave occurs
       
   851 	CleanupStack::Pop(store);
       
   852 	return streamDictionary;
       
   853 	}
       
   854 
       
   855 
       
   856 EXPORT_C CStreamDictionary* CApaProcess::ReadRootStreamLC(CFileStore*& aStore, const RFile& aFile)
       
   857 /**
       
   858 @internalTechnology
       
   859 */
       
   860 	{ // static
       
   861 	__SHOW_TRACE(_L("Starting CApaProcess::ReadRootStreamLC (file-handle overload)"));
       
   862 	CStreamDictionary* const streamDictionary=CStreamDictionary::NewLC();
       
   863 	RFile duplicateFile;
       
   864 	CleanupClosePushL(duplicateFile);
       
   865 	User::LeaveIfError(duplicateFile.Duplicate(aFile)); // this is because CFileStore::FromLC closes the file its passed (and stores its own duplicate)
       
   866 	CFileStore* const store=CFileStore::FromL(duplicateFile);
       
   867 	CleanupStack::PopAndDestroy(&duplicateFile);
       
   868 	CleanupStack::PushL(store);
       
   869 	DoReadRootStreamL(*streamDictionary, *store);
       
   870 	aStore=store; // delay assignment until nothing can go wrong to avoid destroying the store twice if a leave occurs
       
   871 	CleanupStack::Pop(store);
       
   872 	return streamDictionary;
       
   873 	}
       
   874 
       
   875 
       
   876 void CApaProcess::DoReadRootStreamL(CStreamDictionary& aStreamDictionary, const CFileStore& aStore)
       
   877 	{ // static
       
   878 	const TStreamId rootStreamId=aStore.Root();
       
   879 	if ((aStore.Type()[1]!=KUidAppDllDoc) || (rootStreamId==KNullStreamId))
       
   880 		{
       
   881 		User::Leave(KErrCorrupt);
       
   882 		}
       
   883 	RStoreReadStream rootStream;
       
   884 	rootStream.OpenLC(aStore, rootStreamId);
       
   885 	rootStream>>aStreamDictionary;
       
   886 	CleanupStack::PopAndDestroy(&rootStream);
       
   887 	}
       
   888 
       
   889 
       
   890 EXPORT_C void CApaProcess::WriteRootStreamL(CPersistentStore& aStore,CStreamDictionary& aStreamDic,const CApaApplication& aApp)
       
   891 // this is a static method
       
   892 /** Writes the application identifier (derived from the application object CApaApplication) 
       
   893 followed by the stream dictionary to the store and makes the stream dictionary the root stream of the
       
   894 store.
       
   895 
       
   896 Typically, the function is called by the application when it 
       
   897 implements a file create or file save type operation. It is called after all 
       
   898 model and UI data has been persisted. The IDs of the streams containing the 
       
   899 model and UI data should have been lodged in the stream dictionary.
       
   900 
       
   901 In effect, the function finishes off the file save or file
       
   902 create type operation, leaving the file containing the store in a valid state
       
   903 with the standard interface.
       
   904 
       
   905 @param aStore  The store to which the root stream is to be written. Before
       
   906 calling this function, a reference to the store must be saved by putting a
       
   907 pointer onto the cleanup stack or by making it member data of a class. This
       
   908 ensures that it is not orphaned in the event of this function leaving.
       
   909 @param aStreamDic The stream dictionary containing the locations and associated 
       
   910 UIDs of other streams in the store.
       
   911 @param aApp  The application used to create the main document in the file
       
   912 being written. The application identifier to be written is constructed from
       
   913 this application object. */
       
   914 	{
       
   915 	__SHOW_TRACE(_L("Starting CApaProcess::WriteRootStreamL(app)"));
       
   916 	// get the app dll name
       
   917 	TParse dllPath;
       
   918 	dllPath.SetNoWild(aApp.DllName(),NULL,NULL);
       
   919 	// set up an app identifier
       
   920 	TApaAppIdentifier appId(aApp.AppDllUid(),dllPath.NameAndExt());
       
   921 	// Write the root stream
       
   922 	WriteRootStreamL(aStore,aStreamDic,appId);
       
   923 	}
       
   924 
       
   925 
       
   926 EXPORT_C void CApaProcess::WriteRootStreamL(CPersistentStore& aStore,CStreamDictionary& aStreamDic,const TApaAppIdentifier& aAppId)
       
   927 // this is a static method
       
   928 /** Writes the application identifier followed by the stream dictionary 
       
   929 to the store and makes the stream dictionary the root stream of the store.
       
   930 
       
   931 Typically, the function is called by the application when it 
       
   932 implements a file create or file save type operation. It is called after all 
       
   933 model and UI data has been persisted. The IDs of the streams containing the 
       
   934 model and UI data should have been lodged in the stream dictionary.
       
   935 
       
   936 In effect, the function finishes off the file save or file
       
   937 create type operation, leaving the file containing the store in a valid state
       
   938 with the standard interface.
       
   939 
       
   940 @param aStore  The store to which the root stream is to be written. Before
       
   941 calling this function, a reference to the store must be saved by putting a
       
   942 pointer onto the cleanup stack or by making it member data of a class. This
       
   943 ensures that it is not orphaned in the event of this function leaving.
       
   944 @param aStreamDic The stream dictionary containing the locations and associated 
       
   945 UIDs of other streams in the store.
       
   946 @param aAppId  The application identifier to be written into the application
       
   947 identifier stream. */
       
   948 	{
       
   949 	__SHOW_TRACE(_L("Starting CApaProcess::WriteRootStreamL(id)"));
       
   950 	// create a stream
       
   951 	WriteAppIdentifierL(aStore,aStreamDic,aAppId);
       
   952 	// externalize the dictionary
       
   953 	RStoreWriteStream stream;
       
   954 	TStreamId streamId=stream.CreateLC(aStore);
       
   955 	stream<< aStreamDic;
       
   956 	stream.CommitL();
       
   957 	CleanupStack::PopAndDestroy(); // dictionary stream
       
   958 	// set the dictionary stream as the root stream
       
   959 	aStore.SetRootL(streamId);
       
   960 	}
       
   961 
       
   962 
       
   963 EXPORT_C void CApaProcess::DestroyDocument(CApaDocument* aDoc)
       
   964 /** Destroys the specified document.
       
   965 
       
   966 All references to the document are removed, and associated resources are freed. 
       
   967 Specifically, the function deletes any associated application and unloads 
       
   968 the application DLL, provided that no other documents of that application 
       
   969 type are still open.
       
   970 
       
   971 All document objects created through CApaProcess must be deleted using this 
       
   972 function.
       
   973 
       
   974 @param aDoc A pointer to the document to be destroyed. 
       
   975 @see CApaApplication
       
   976 @see CApaProcess */
       
   977 	{
       
   978 	__SHOW_TRACE(_L("Starting CApaProcess::DestroyDocument(app)"));
       
   979 	//
       
   980 	if (aDoc)
       
   981 		{
       
   982 		// delete the doc, keeping a handle to its app
       
   983 		CApaApplication* app=aDoc->Application();
       
   984 		__ASSERT_DEBUG(app!=NULL,Panic(EDPanicDocWithNoApp));
       
   985 		// remove the doc from the list, keeping a handle to the doc
       
   986 		TBool appStillRequired=EFalse;
       
   987 		__ASSERT_ALWAYS(iDocList, Panic(EPanicNullPointer));
       
   988 		for (TInt i=iDocList->Count()-1 ; i>=0 ; i--)
       
   989 			{//check through the list, remove the right doc, and see if the app is used by any other docs
       
   990 			if ((*iDocList)[i]==aDoc)
       
   991 				{
       
   992 				iDocList->Delete(i); // removes from array, but doesnt destroy
       
   993 				iDocList->Compress();
       
   994 				}
       
   995 			else if ((*iDocList)[i]->Application()==app)
       
   996 				appStillRequired = ETrue;
       
   997 			}
       
   998 		// null the main doc handle if we delete the main doc
       
   999 		if (aDoc==iMainDoc)
       
  1000 			iMainDoc = NULL;
       
  1001 		
       
  1002 		delete aDoc; // del
       
  1003 		
       
  1004 		// remove app if no other doc's use it and it's not the main app
       
  1005 		if ((!appStillRequired)&&(iMainDoc)&&(app!=iMainDoc->Application()))
       
  1006 			{
       
  1007 			MarkApplicationForRemoval(app);
       
  1008 			__ASSERT_DEBUG(iApplicationRemover, Panic(EDPanicNoAppRemover));
       
  1009 			if (!iApplicationRemover->IsActive())
       
  1010 				{
       
  1011 				iApplicationRemover->Start(TCallBack(CApaProcess::IdleRemoveApplications,this));
       
  1012 				}
       
  1013 			}
       
  1014 		}
       
  1015 	}
       
  1016 
       
  1017 
       
  1018 TInt CApaProcess::IdleRemoveApplications(TAny* aThis)
       
  1019 // Remove applications on callback of idle object. Using an idle object gives an embedded application a chance to clear
       
  1020 // its call stack before its dll is closed
       
  1021 //
       
  1022 	{
       
  1023 	CApaProcess* process=reinterpret_cast<CApaProcess*>(aThis);
       
  1024 	__ASSERT_DEBUG(process, Panic(EDPanicNoProcess));
       
  1025 	process->RemoveMarkedApplications();
       
  1026 	return 0;
       
  1027 	}
       
  1028 
       
  1029 
       
  1030 void CApaProcess::RemoveMarkedApplications()
       
  1031 // Remove any applications that have been marked for removal, closing their dlls also
       
  1032 //
       
  1033 	{
       
  1034 	__ASSERT_DEBUG(iAppList, Panic(EPanicNullPointer));
       
  1035 	for (TInt i=iAppList->Count()-1 ; i>=0 ; i--)
       
  1036 		if ((*iAppList)[i].iToBeRemoved)
       
  1037 			{
       
  1038 			delete (*iAppList)[i].iAppHolder;
       
  1039 			iAppList->Delete(i); // remove from array
       
  1040 			iAppList->Compress();
       
  1041 			}
       
  1042 	}
       
  1043 
       
  1044 
       
  1045 void CApaProcess::MarkApplicationForRemoval(const CApaApplication* aApp)
       
  1046 // Mark the application in the app list for removal by idle object
       
  1047 //
       
  1048 	{
       
  1049 	__ASSERT_DEBUG(aApp!=NULL,Panic(EDPanicRemovingNullApp));
       
  1050 	__ASSERT_DEBUG(iAppList, Panic(EPanicNullPointer));
       
  1051 	// remove the app from the list, keeping a handle to it
       
  1052 	for (TInt i=iAppList->Count()-1 ; i>=0 ; i--)
       
  1053 		{
       
  1054 		__ASSERT_DEBUG((*iAppList)[i].iAppHolder, Panic(EDPanicNoAppHolder));
       
  1055 		if ((*iAppList)[i].iAppHolder->Application()==aApp)
       
  1056 			{
       
  1057 			(*iAppList)[i].iToBeRemoved=ETrue;
       
  1058 			}
       
  1059 	}
       
  1060 
       
  1061 	}
       
  1062 
       
  1063 
       
  1064 CApaDocument* CApaProcess::CreateDocL(CApaApplication* aApp)
       
  1065 // creates a new doc with aApp and adds it to the list before returning a handle to it
       
  1066 //
       
  1067 	{
       
  1068 	__SHOW_TRACE(_L("Starting CApaProcess::CreateDocL"));
       
  1069 	__ASSERT_DEBUG(aApp,Panic(EDPanicNoApp));
       
  1070 	//
       
  1071 	// create a new doc with the app
       
  1072 	CApaDocument* doc=aApp->CreateDocumentL(this); //lint !e613 Possible use of null pointer - Asserted above
       
  1073 	__ASSERT_ALWAYS(doc!=NULL,Panic(EPanicDocumentNotCreated));
       
  1074 	// add the doc to the list
       
  1075 	CleanupStack::PushL(doc);
       
  1076 	iDocList->AppendL(doc);
       
  1077 	CleanupStack::Pop(); // doc
       
  1078 	// return a	handle to the doc
       
  1079 	return doc;
       
  1080 	}
       
  1081 
       
  1082 
       
  1083 CApaAppHolder* CApaProcess::FindAppInListL(const TDesC& aAppFileName,TUid aUid)const
       
  1084 // returns pointer to a matching app, or NULL if not in list
       
  1085 //
       
  1086 	{
       
  1087 	__ASSERT_DEBUG(iAppList, Panic(EPanicNullPointer));
       
  1088 	TInt index=iAppList->Count();
       
  1089 	if (aUid!=KNullUid)
       
  1090 		{// search by UID
       
  1091 		while (--index>=0)
       
  1092 			{
       
  1093 			__ASSERT_DEBUG((*iAppList)[index].iAppHolder, Panic(EDPanicNoAppHolder));
       
  1094 			if ((*iAppList)[index].iAppHolder->Uid()==aUid)
       
  1095 				{
       
  1096 				(*iAppList)[index].iToBeRemoved = FALSE;
       
  1097 				return (*iAppList)[index].iAppHolder; // match found
       
  1098 				}
       
  1099 			}
       
  1100 		}
       
  1101 	else
       
  1102 		{// search by name as no UID has been supplied
       
  1103 		TParse app; TParse suspect;
       
  1104 		User::LeaveIfError(app.Set(aAppFileName,NULL,NULL));
       
  1105 		while (--index>=0)
       
  1106 			{
       
  1107 			__ASSERT_DEBUG((*iAppList)[index].iAppHolder, Panic(EDPanicNoAppHolder));
       
  1108 			suspect.SetNoWild((*iAppList)[index].iAppHolder->FileName(),NULL,NULL);
       
  1109 			if (!app.Name().CompareF(suspect.Name()))
       
  1110 				{
       
  1111 				(*iAppList)[index].iToBeRemoved = FALSE;
       
  1112 				return (*iAppList)[index].iAppHolder; // match found
       
  1113 				}
       
  1114 			}
       
  1115 		}
       
  1116 	return NULL; // no match found
       
  1117 	}
       
  1118 
       
  1119 #ifdef USING_ECOM_RECOGS
       
  1120 CApaExe* CApaProcess::AddAppExeL(TApaApplicationFactory aApplicationFactory)
       
  1121 	{
       
  1122 	CApaExe* exe = new(ELeave) CApaExe();
       
  1123 	CleanupStack::PushL(exe);
       
  1124 	
       
  1125 	// create the app
       
  1126 	exe->CreateApplicationL(aApplicationFactory);
       
  1127 	__ASSERT_DEBUG(exe->Application(), Panic(EPanicNullPointer));
       
  1128 	exe->Application()->PreDocConstructL();
       
  1129 	
       
  1130 	// add the application to the list and return a pointer to it
       
  1131 	TApaAppHolderInfo info(exe);
       
  1132 	__ASSERT_DEBUG(iAppList, Panic(EPanicNullPointer));
       
  1133 	iAppList->AppendL(info);
       
  1134 	CleanupStack::Pop(exe);
       
  1135 
       
  1136 	return exe;
       
  1137 	}
       
  1138 #endif // USING_ECOM_RECOGS
       
  1139 
       
  1140 
       
  1141 EXPORT_C TPtrC CApaProcess::MainDocFileName()const
       
  1142 /** Returns the filename of the main document.
       
  1143 
       
  1144 @return A non-modifiable pointer descriptor to the main document filename. 
       
  1145 For non file-based applications, the length of this descriptor is zero. */
       
  1146 	{
       
  1147 	if (iMainDocFileName!=NULL)
       
  1148 		{
       
  1149 		return *iMainDocFileName;
       
  1150 		}
       
  1151 	return KNullDesC();
       
  1152 	}
       
  1153 
       
  1154 /** Reserved for future use */
       
  1155 EXPORT_C void CApaProcess::CApaProcess_Reserved1()
       
  1156 	{
       
  1157 	}
       
  1158 
       
  1159 /** Reserved for future use */
       
  1160 EXPORT_C void CApaProcess::CApaProcess_Reserved2()
       
  1161 	{
       
  1162 	}
       
  1163 
       
  1164 /////////////////////////////
       
  1165 // TApaApplicationFactory
       
  1166 /////////////////////////////
       
  1167 
       
  1168 /**
       
  1169 Default constructor
       
  1170 */
       
  1171 
       
  1172 /** Constructor for TApaApplicationFactory */
       
  1173 EXPORT_C TApaApplicationFactory::TApaApplicationFactory()
       
  1174 	:iType(ETypeFunction),
       
  1175 	 iData(0),
       
  1176 	 iApplication(NULL)
       
  1177 	{
       
  1178 	}
       
  1179 
       
  1180 /** 
       
  1181 Constructor.
       
  1182 @publishedAll
       
  1183 @released
       
  1184 @param aFunction The function from which the application is to be created.
       
  1185 */
       
  1186 EXPORT_C TApaApplicationFactory::TApaApplicationFactory(TFunction aFunction)
       
  1187 	:iType(ETypeFunction),
       
  1188 	 iData(reinterpret_cast<TUint>(aFunction)),
       
  1189 	 iApplication(NULL)
       
  1190 	{
       
  1191 	}
       
  1192 
       
  1193 /** 
       
  1194 Constructor. Use this constructor in preference to the constructor taking a "TUid" parameter 
       
  1195 if at all possible as it is much more efficient.
       
  1196 @publishedAll
       
  1197 @released
       
  1198 @param aEmbeddedApplicationInformation The ECOM implementation-information of the embedded application to be created.
       
  1199 */
       
  1200 EXPORT_C TApaApplicationFactory::TApaApplicationFactory(const CImplementationInformation& aEmbeddedApplicationInformation)
       
  1201 	:iType(ETypeEmbeddedApplicationInformation),
       
  1202 	 iData(reinterpret_cast<TUint>(&aEmbeddedApplicationInformation)),
       
  1203 	 iApplication(NULL)
       
  1204 	{
       
  1205 	}
       
  1206 
       
  1207 /** 
       
  1208 Constructor. Use the constructor taking a "const CImplementationInformation&" parameter in preference 
       
  1209 to this constructor if at all possible as it is much more efficient.
       
  1210 @publishedAll
       
  1211 @released
       
  1212 @param aEmbeddedApplicationUid The ECOM implementation-UID of the embedded application to be created.
       
  1213 */
       
  1214 EXPORT_C TApaApplicationFactory::TApaApplicationFactory(TUid aEmbeddedApplicationUid)
       
  1215 	:iType(ETypeEmbeddedApplicationUid),
       
  1216 	 iData(aEmbeddedApplicationUid.iUid),
       
  1217 	 iApplication(NULL)
       
  1218 	{
       
  1219 	}
       
  1220 
       
  1221 #ifdef USING_ECOM_RECOGS
       
  1222 CApaApplication* TApaApplicationFactory::CreateApplicationL() const
       
  1223 	{
       
  1224 	CApaApplication* application = NULL;
       
  1225 
       
  1226 	switch (iType)
       
  1227 		{
       
  1228 		case ETypeFunction:
       
  1229 			{
       
  1230 			__ASSERT_DEBUG(iData, Panic(EPanicNullPointer));
       
  1231 			application=(*reinterpret_cast<TFunction>(iData))();
       
  1232 			break;
       
  1233 			}
       
  1234 		case ETypeEmbeddedApplicationInformation:
       
  1235 			{
       
  1236 			__ASSERT_DEBUG(iData, Panic(EPanicNullPointer));
       
  1237 			const CImplementationInformation& embeddedApplicationInformation=*reinterpret_cast<const CImplementationInformation*>(iData);
       
  1238 			TUid uid = embeddedApplicationInformation.ImplementationUid();
       
  1239 			application=CreateEmbeddedApplicationL(uid);
       
  1240 			break;
       
  1241 			}
       
  1242 		case ETypeEmbeddedApplicationUid:
       
  1243 			{
       
  1244 			TUid uid = TUid::Uid(iData);
       
  1245 			application=CreateEmbeddedApplicationL(uid);
       
  1246 			break;
       
  1247 			}
       
  1248 		default:
       
  1249 			Panic(EPanicBadApplicationFactoryType);
       
  1250 		}
       
  1251 
       
  1252 	return application;
       
  1253 	}
       
  1254 
       
  1255 HBufC* TApaApplicationFactory::AppFileNameL() const
       
  1256 	{
       
  1257 	HBufC* appFileName = NULL;
       
  1258 	switch (iType)
       
  1259 		{
       
  1260 		case ETypeFunction:
       
  1261 			{
       
  1262 			// Assume that if the type is a function pointer then the app is not embedded (so
       
  1263 			// the filename is the filename of this process).
       
  1264 			appFileName = RProcess().FileName().AllocL();
       
  1265 			break;
       
  1266 			}
       
  1267 		case ETypeEmbeddedApplicationInformation:
       
  1268 			{
       
  1269 			const CImplementationInformation& embeddedApplicationInformation=*REINTERPRET_CAST(const CImplementationInformation*,iData);
       
  1270 			appFileName = FullAppFileNameL(embeddedApplicationInformation.DisplayName());
       
  1271 			break;
       
  1272 			}
       
  1273 		case ETypeEmbeddedApplicationUid:
       
  1274 			{
       
  1275 			TUid uid = TUid::Uid(iData);
       
  1276 			HBufC* displayName = EmbeddedApplicationDisplayNameLC(uid);
       
  1277 			appFileName = FullAppFileNameL(*displayName);
       
  1278 			CleanupStack::PopAndDestroy(displayName);
       
  1279 			break;
       
  1280 			}
       
  1281 		default:
       
  1282 			Panic(EPanicBadApplicationFactoryType);
       
  1283 		}
       
  1284 
       
  1285 	return appFileName;
       
  1286 	}
       
  1287 
       
  1288 TUid TApaApplicationFactory::AppFileUid() const
       
  1289 	{
       
  1290 	TUid uid=KNullUid;
       
  1291 	switch (iType)
       
  1292 		{
       
  1293 		case ETypeFunction:
       
  1294 			{
       
  1295 			uid = RProcess().Type()[2];
       
  1296 			break;
       
  1297 			}
       
  1298 		case ETypeEmbeddedApplicationInformation:
       
  1299 			{
       
  1300 			const CImplementationInformation& embeddedApplicationInformation=*REINTERPRET_CAST(const CImplementationInformation*,iData);
       
  1301 			uid = embeddedApplicationInformation.ImplementationUid();
       
  1302 			break;
       
  1303 			}
       
  1304 		case ETypeEmbeddedApplicationUid:
       
  1305 			{
       
  1306 			uid = TUid::Uid(iData);
       
  1307 			break;
       
  1308 			}
       
  1309 		default:
       
  1310 			Panic(EPanicBadApplicationFactoryType);
       
  1311 		}
       
  1312 	return uid;
       
  1313 	}
       
  1314 
       
  1315 HBufC* TApaApplicationFactory::FullAppFileNameL(const TDesC& aAppName)
       
  1316 	{
       
  1317 	// This was appropriately changed for data caging (binaries placed in \sys\bin\)
       
  1318 	TFileName fileName;
       
  1319 	Dll::FileName(fileName);
       
  1320 
       
  1321 	TParse parse;
       
  1322 	parse.SetNoWild(aAppName, &KApplicationLocation, &fileName);
       
  1323 	return parse.FullName().AllocL();
       
  1324 	}
       
  1325 
       
  1326 CApaApplication* TApaApplicationFactory::CreateEmbeddedApplicationL(TUid aUid)
       
  1327 	{ // static
       
  1328 	CApaApplication* const application=static_cast<CApaApplication*>(REComSession::CreateImplementationL(aUid,_FOFF(CApaApplication,iDtorKey)));
       
  1329 	const TUid appUid = application->AppDllUid();
       
  1330 	__ASSERT_ALWAYS(appUid==aUid, Panic(EPanicUidsDoNotMatch));
       
  1331 	return application;
       
  1332 	}
       
  1333 
       
  1334 
       
  1335 HBufC* TApaApplicationFactory::EmbeddedApplicationDisplayNameLC(TUid aUid)
       
  1336 	{ // static
       
  1337 	HBufC* displayName=NULL;
       
  1338 
       
  1339 	RImplInfoPtrArray implementationArray;
       
  1340 	CleanupStack::PushL(TCleanupItem(CleanupImplementationArray,&implementationArray));
       
  1341 	REComSession::ListImplementationsL(KUidFileEmbeddedApplicationInterfaceUid,implementationArray);
       
  1342 	for (TInt i=implementationArray.Count()-1; i>=0; --i)
       
  1343 		{
       
  1344 		const CImplementationInformation& implementationInformation=*implementationArray[i];
       
  1345 		if (implementationInformation.ImplementationUid().iUid==aUid.iUid)
       
  1346 			{
       
  1347 			displayName=implementationInformation.DisplayName().AllocL();
       
  1348 			break;
       
  1349 			}
       
  1350 		}
       
  1351 	CleanupStack::PopAndDestroy(&implementationArray);
       
  1352 	if (displayName==NULL)
       
  1353 		{
       
  1354 		User::Leave(KErrNotFound);
       
  1355 		}
       
  1356 	CleanupStack::PushL(displayName);
       
  1357 
       
  1358 	return displayName;
       
  1359 	}
       
  1360 
       
  1361 void TApaApplicationFactory::CleanupImplementationArray(TAny* aImplementationArray)
       
  1362 	{ // static
       
  1363 	__ASSERT_DEBUG(aImplementationArray, Panic(EPanicNullPointer));
       
  1364 	RImplInfoPtrArray& implementationArray=*static_cast<RImplInfoPtrArray*>(aImplementationArray);
       
  1365 	implementationArray.ResetAndDestroy();
       
  1366 	implementationArray.Close();
       
  1367 	}
       
  1368 	
       
  1369 //
       
  1370 // MApaEmbeddedDocObserver
       
  1371 //
       
  1372 
       
  1373 /** Constructor for MApaEmbeddedDocObserver */
       
  1374 EXPORT_C MApaEmbeddedDocObserver::MApaEmbeddedDocObserver()
       
  1375 	{
       
  1376 	}
       
  1377 
       
  1378 /** Reserved for future use */
       
  1379 EXPORT_C void MApaEmbeddedDocObserver::MApaEmbeddedDocObserver_Reserved1()
       
  1380 	{
       
  1381 	}
       
  1382 
       
  1383 /** Reserved for future use */
       
  1384 EXPORT_C void MApaEmbeddedDocObserver::MApaEmbeddedDocObserver_Reserved2()
       
  1385 	{
       
  1386 	}
       
  1387 #endif // USING_ECOM_RECOGS