--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/appfw/apparchitecture/apparc/apaproc.cpp Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,824 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// apaproc.cpp
+//
+
+#include <apaproc.h> // stuff everyone will want ie most things
+#include <apacln.h> // CleanupStack protection for CApaDocument
+#include "APADLL.H" // class RApaApplication
+#include "APASTD.H" // Panics etc.
+#include <s32file.h>
+#include "../apparc/TRACE.H"
+#include <e32def_private.h> // MattR addition for __PROFILE_END error
+
+const TInt KAppProcessArrayGranularity(1);
+
+
+//
+// CApaParentProcessMonitor
+//
+
+class CApaParentProcessMonitor : public CActive
+ {
+public: // Construction / destruction
+ static CApaParentProcessMonitor* NewL(TProcessId aProcessId);
+ ~CApaParentProcessMonitor();
+ void ConstructL();
+private:
+ CApaParentProcessMonitor(TProcessId aProcessId);
+public: // From CActive
+ void RunL();
+ void DoCancel();
+private:
+ TProcessId iProcessId;
+ RProcess iProcess;
+ };
+
+CApaParentProcessMonitor* CApaParentProcessMonitor::NewL(TProcessId aProcessId)
+ {
+ CApaParentProcessMonitor* self=new (ELeave) CApaParentProcessMonitor(aProcessId);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CApaParentProcessMonitor::CApaParentProcessMonitor(TProcessId aProcessId)
+ : CActive(EPriorityLow)
+ {
+ iProcessId=aProcessId;
+ }
+
+CApaParentProcessMonitor::~CApaParentProcessMonitor()
+ {
+ Cancel();
+ }
+
+void CApaParentProcessMonitor::ConstructL()
+ {
+ User::LeaveIfError(iProcess.Open(iProcessId));
+ iProcess.Logon(iStatus);
+ if(iStatus==KErrNoMemory)
+ {
+ User::WaitForRequest(iStatus);
+ User::Leave(KErrNoMemory);
+ }
+ CActiveScheduler::Add(this);
+ SetActive();
+ }
+
+void CApaParentProcessMonitor::RunL()
+ {
+ // Do something that will kill the child when the parent process terminates
+ if(iStatus==KErrNone)
+ {
+ RProcess proc;
+ proc.Terminate(KErrNone);
+ }
+ }
+
+void CApaParentProcessMonitor::DoCancel()
+ {
+ iProcess.LogonCancel(iStatus);
+ }
+
+//
+// CApaProcess
+//
+
+/** Constructor for CApaProcess */
+EXPORT_C CApaProcess::CApaProcess()
+ {
+ }
+
+EXPORT_C CApaProcess* CApaProcess::NewL(const RFs& aFs)
+/** Creates and returns a pointer to a new application process.
+
+This function is not used by UI applications.
+
+@param aFs Handle to a file server session.
+@return Pointer to the new application process. */
+ {
+ CApaProcess* self=new(ELeave) CApaProcess(aFs);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+EXPORT_C CApaProcess::CApaProcess(const RFs& aFs)
+ :iFsSession(aFs)
+/** Constructs the application process object with the specified file session handle.
+
+Derived classes must define and implement a constructor through which
+the file session handle can be specified. A
+typical implementation calls this constructor through a constructor initialization
+list.
+
+This constructor is used by the UI framework.
+
+@deprecated
+@param aFs Handle to a file server session */
+ {}
+
+const TInt KPriorityGreaterThanShutter=102;
+
+EXPORT_C void CApaProcess::ConstructL()
+/** Completes construction of the application process object.
+
+Implementers of derived classes must call this function as part of the second
+stage construction of an object. Typically, derived classes implement their
+own NewL() function and call ConstructL() as part of that implementation. */
+ {
+ //
+ iAppList = new(ELeave) CArrayPtrFlat<RApaApplication>(KAppProcessArrayGranularity);
+ iDocList = new(ELeave) CArrayPtrFlat<CApaDocument>(KAppProcessArrayGranularity);
+ iMainDocFileName = HBufC::NewL(KMaxFileName);
+ iAsyncAppRemover = CIdle::NewL(KPriorityGreaterThanShutter); // Use an idle object so that app has chance to clear its call stack
+ }
+
+EXPORT_C void CApaProcess::ConstructL(TProcessId aParentProcessId)
+/** Completes construction of the application process object, passing in a Parent Process Identifier.
+
+Implementers of derived classes must call this function as part of the second
+stage construction of an object. Typically, derived classes implement their
+own NewL() function and call ConstructL() as part of that implementation.
+
+@param aParentProcessId Id of the parent process. This process will terminate when the parent does. */
+ {
+ ConstructL();
+ if(KNullProcessId!=aParentProcessId)
+ {
+ iMonitor=CApaParentProcessMonitor::NewL(aParentProcessId);
+ }
+ }
+
+/** Frees resources prior to destruction.
+
+Documents must be saved before the application process is deleted, otherwise
+data may be lost.
+
+In debug mode, the destructor raises an APPARC 6 panic if documents still
+exist, and an APPARC 5 panic if applications still exist. */
+EXPORT_C CApaProcess::~CApaProcess()
+// If this is called without calling ResetL() or CApaDocument::SaveL() first, data may be lost
+//
+ {
+ if (iMainDoc)
+ {
+ DestroyDocument(iMainDoc);
+ iMainDoc = NULL;
+ }
+
+ if (iDocList)
+ {
+ __ASSERT_DEBUG(iDocList->Count()==0,Panic(EPanicDocListNotEmpty));
+ for (TInt i=iDocList->Count()-1 ; i>=0 ; i--)
+ delete (*iDocList)[i]; // delete stray doc's in release mode, just to be tidy
+ }
+
+ if (iAppList)
+ {
+ for (TInt i = iAppList->Count()-1 ; i >= 0 ; i--)
+ (*iAppList)[i]->Close();
+ }
+
+ delete iAppList;
+ delete iDocList;
+ delete iMainDocFileName;
+ delete iAsyncAppRemover;
+ delete iMonitor;
+ }
+
+
+/** Resets the the application process to its initial state.
+
+Specifically, it saves the main document, deletes the main and all embedded
+documents from memory, resets the main document filename and deletes all applications
+except the main application.
+
+The function can leave if saving the main document fails. */
+EXPORT_C void CApaProcess::ResetL()
+ {
+ if (iMainDoc)
+ {
+ iMainDoc->SaveL();
+ DeleteAllDocs(); // sets iMainDoc to NULL, deletes all apps except main
+ }
+
+ __ASSERT_DEBUG(iMainDocFileName, Panic(EPanicNoDocument));
+ *iMainDocFileName = KNullDesC;
+ }
+
+
+void CApaProcess::DeleteAllDocs()
+// deletes all docs
+// deletes all apps except main app
+// sets iMainDoc* to NULL
+//
+ {
+ CApaApplication* mainApp = NULL;
+
+ // If the main document has been constructed...
+ if (iMainDoc) // then iDocList must also exist
+ {
+ __ASSERT_DEBUG(iMainDoc->Application(), Panic(EDPanicNoApp));
+ mainApp = iMainDoc->Application();
+
+ // ...find the main document in the list of documents and delete it.
+ for (TInt i = iDocList->Count()-1; i >= 0; i--)
+ {
+ if ((*iDocList)[i] == iMainDoc)
+ {
+ iDocList->Delete(i); // removes from array, but doesnt destroy
+ delete iMainDoc;
+ iMainDoc = NULL;
+ break;
+ }
+ }
+ }
+
+ // Remove all documents from the list of documents, without deleting them.
+ if(iDocList)
+ {
+ __ASSERT_ALWAYS(iDocList->Count()==0, Panic(EPanicDocListNotEmpty));
+ iDocList->Reset();
+ }
+
+ // Delete all applications except the main one.
+ if(iAppList)
+ {
+ for (TInt ii = iAppList->Count()-1; ii >= 0; ii--) // need to iterate backwards as the array changes size during the loop
+ {
+ if ((*iAppList)[ii]->Application() != mainApp)
+ {
+ (*iAppList)[ii]->Close();
+ iAppList->Delete(ii);
+ }
+ }
+
+ iAppList->Compress();
+ }
+ }
+
+
+EXPORT_C void CApaProcess::SetMainDocFileName(const TDesC& aMainDocFileName)
+/** Sets the filename of the main document.
+
+@param aMainDocFileName The filename to be set.
+@panic APPARC 7 If the length of aMainDocFileName is greater than KMaxFileName or the
+length of the last filename set by SetMainDocFileNameL if greater
+@see KMaxFileName */
+ {
+ __ASSERT_DEBUG( iMainDocFileName, Panic(EPanicNullPointer));
+ __ASSERT_ALWAYS( aMainDocFileName.Length()<=iMainDocFileName->Des().MaxLength() ,Panic(EPanicFileNameTooLong));
+ *iMainDocFileName = aMainDocFileName;
+ }
+
+EXPORT_C void CApaProcess::SetMainDocFileNameL(const TDesC& aMainDocFileName)
+/** Sets the filename of the main document.
+
+@param aMainDocFileName The filename to be set. There is no restriction on the
+length of this descriptor. */
+ {
+ __ASSERT_ALWAYS( iMainDocFileName, Panic(EPanicNullPointer));
+ const TInt newLength = aMainDocFileName.Length() < KMaxFileName ? KMaxFileName : aMainDocFileName.Length();
+ if (newLength != iMainDocFileName->Des().MaxLength())
+ {
+ HBufC* const newMainDocFileName = HBufC::NewL(newLength);
+ delete iMainDocFileName;
+ iMainDocFileName = newMainDocFileName;
+ }
+ SetMainDocFileName(aMainDocFileName);
+ }
+
+/** Sets the main document.
+
+@param aDocument A pointer to the document to be set as the main document
+of the application process. This must be a an object created by the AddNewDocumentL()
+or OpenNewDocumentL() functions
+@see CApaProcess::AddNewDocumentL()
+@see CApaProcess::OpenNewDocumentL() */
+EXPORT_C void CApaProcess::SetMainDocument(CApaDocument* aDocument)
+ {
+ __ASSERT_ALWAYS( iDocList, Panic(EPanicNullPointer));
+ // check that the prospective main doc has actually been added to the array
+ for (TInt i = iDocList->Count()-1 ; i >= 0 ; i--)
+ {
+ if ((*iDocList)[i] == aDocument)
+ break;
+
+ if (i==0)
+ Panic(EPanicNoDocument);
+ }
+
+ // assign it once it has checked out
+ iMainDoc = aDocument;
+ }
+
+/** Creates and adds a new document using the specified application factory.
+
+The document may be a main document or an embedded document.
+
+Any document created with this function must be destroyed using DestroyDocument().
+
+@param aApplicationFactory Should be created implicitly by passing a pointer to
+a factory function, an ECOM plugin UID, or a CImplementationInformation reference.
+@return A pointer to the new document.
+@see CApaProcess::DestroyDocument()
+@see CApaApplication */
+EXPORT_C CApaDocument* CApaProcess::AddNewDocumentL(TApaApplicationFactory aApplicationFactory)
+ {
+ __SHOW_TRACE(_L("Starting CApaProcess::AddNewDocumentL"));
+ __APA_PROFILE_START(0);
+
+ RApaApplication* app = AddAppL(aApplicationFactory);
+
+ // use the app to create a doc
+ CApaDocument* doc = NULL;
+ TRAPD(err, doc = CreateDocL(app->Application()));
+ if (err)
+ RemoveApp(app); // remove app as it has been orphaned
+
+ User::LeaveIfError(err);
+ __PROFILE_END(0);
+ return doc;
+ } //lint !e1762 Member function could be made const - Not true
+
+
+
+void CApaProcess::RemoveApp(RApaApplication* aApp)
+// removes app exe from the list if it exists, panics otherwise
+ {
+ __ASSERT_ALWAYS(iAppList, Panic(EPanicNullPointer));
+ TInt i = 0;
+ for (i = iAppList->Count()-1; i >= 0; i--)
+ {
+ if ((*iAppList)[i] == aApp) // the main app may be alive on its own if Reset() has just been called
+ {
+ aApp->Close(); // the main app may be alive on its own if Reset() has just been called
+ iAppList->Delete(i);
+ break;
+ }
+ }
+
+ if (i < 0)
+ Panic(EPanicAppNotInList);
+ }
+
+
+/** Opens the specified file and restores the content as a document.
+
+The created document can be merged into or embedded in another document.
+
+Any document created with this function must be destroyed using DestroyDocument().
+
+@param aStore On return, this contains a pointer to the store object created
+during the restore.
+@param aStreamDic On return, this contains a pointer to the stream dictionary
+object created during the restore.
+@param aDocFullFileName The name of the file containing the document.
+@param aFileMode The mode in which to open the file.
+@return A pointer to the restored document.
+@see TFileMode
+@see CApaProcess::DestroyDocument() */
+EXPORT_C CApaDocument* CApaProcess::OpenNewDocumentL(CFileStore*& aStore,CStreamDictionary*& aStreamDic,const TDesC& aDocFullFileName,TUint aFileMode)
+ {
+ __SHOW_TRACE(_L("Starting CApaProcess::OpenNewDocumentL"));
+ __APA_PROFILE_START(1);
+ TParse parser;
+ User::LeaveIfError(iFsSession.Parse(aDocFullFileName,parser));
+ // open doc as a file store & read in the header
+ CFileStore* docStore;
+ CStreamDictionary* streamDic = ReadRootStreamLC(FsSession(),docStore,parser.FullName(),aFileMode);
+ CleanupStack::PushL(docStore);
+ // read in the app id info
+ TApaAppIdentifier appId=ReadAppIdentifierL(*docStore,*streamDic);
+ // create the doc
+ CApaDocument* importedDoc = AddNewDocumentL(appId.iAppUid);
+ // restore the document
+ TApaDocCleanupItem cleanup(this,importedDoc);
+ CleanupStack::PushL(cleanup);
+ importedDoc->RestoreL(*docStore,*streamDic);
+ CleanupStack::Pop(3); //docStore,importedDoc,streamDic
+ aStore = docStore;
+ aStreamDic = streamDic;
+ __PROFILE_END(1);
+ return importedDoc;
+ }
+
+/** Reads the application identifier from its stream in the specified store and
+returns it.
+
+The location of the stream is found in the specified stream dictionary.
+
+@param aStore The store from which the application identifier should be read.
+@param aStreamDic The stream dictionary containing the stream ID of the application
+identifier stream. The stream dictionary can be found in the root stream of
+the store.
+@return The application identifier. */
+EXPORT_C TApaAppIdentifier CApaProcess::ReadAppIdentifierL(const CStreamStore& aStore,const CStreamDictionary& aStreamDic)
+ {
+ // this is a static method
+ __SHOW_TRACE(_L("Starting CApaProcess::ReadAppIdentifierL"));
+
+ TStreamId infoStreamId = aStreamDic.At(KUidAppIdentifierStream);
+ TApaAppIdentifier appId;
+
+ // create a stream and read in the data
+ RStoreReadStream stream;
+ stream.OpenLC(aStore,infoStreamId);
+
+ stream >> appId;
+ stream.Close();
+
+ CleanupStack::PopAndDestroy(); // stream
+ return appId;
+ }
+
+
+/** Writes the application identifier to a new stream in the specified store and
+records the location of this stream in the specified stream dictionary.
+
+@param aStore The store to which the application identifier should be written.
+
+@param aStreamDic The stream dictionary.
+@param aAppId The application identifier to be externalised to a stream. */
+EXPORT_C void CApaProcess::WriteAppIdentifierL(CStreamStore& aStore,CStreamDictionary& aStreamDic,const TApaAppIdentifier& aAppId)
+ {
+ // this is a static method
+ __SHOW_TRACE(_L("Starting CApaProcess::WriteAppIdentifierL"));
+
+ // create a stream
+ RStoreWriteStream stream;
+ TStreamId streamId = stream.CreateLC(aStore);
+
+ // stream the header
+ stream << aAppId;
+ stream.CommitL();
+
+ CleanupStack::PopAndDestroy(); // id stream
+ // enter the stream in the dictionary
+ aStreamDic.AssignL(KUidAppIdentifierStream, streamId);
+ }
+
+
+/** Reads the stream dictionary contained as the root stream in the specified document
+file.
+
+The function constructs, and returns a pointer to the stream dictionary object
+and puts the pointer to the stream dictionary object onto the cleanup stack.
+It also returns a pointer to the created file store object through an argument
+reference.
+
+The file must be a valid document file; otherwise the function leaves with one of
+the system-wide error codes.
+
+@param aFs Handle to a file server session.
+@param aStore On return, a pointer to the newly created file store object.
+@param aDocFullFileName The full path name of the document file.
+@param aFileMode The mode in which to open the file.
+@return A pointer to the stream dictionary object read from the root stream
+of the store.
+@see TFileMode */
+EXPORT_C CStreamDictionary* CApaProcess::ReadRootStreamLC(RFs& aFs,CFileStore*& aStore,const TDesC& aDocFullFileName,TUint aFileMode)
+ { // static
+ __SHOW_TRACE(_L("Starting CApaProcess::ReadRootStreamLC (file-name overload)"));
+ CStreamDictionary* const streamDictionary=CStreamDictionary::NewLC();
+ CFileStore* const store=CFileStore::OpenLC(aFs,aDocFullFileName,aFileMode);
+ DoReadRootStreamL(*streamDictionary, *store);
+ aStore=store; // delay assignment until nothing can go wrong to avoid destroying the store twice if a leave occurs
+ CleanupStack::Pop(store);
+ return streamDictionary;
+ }
+
+
+/**
+@internalTechnology
+*/
+EXPORT_C CStreamDictionary* CApaProcess::ReadRootStreamLC(CFileStore*& aStore, const RFile& aFile)
+ { // static
+ __SHOW_TRACE(_L("Starting CApaProcess::ReadRootStreamLC (file-handle overload)"));
+
+ CStreamDictionary* const streamDictionary = CStreamDictionary::NewLC();
+
+ RFile duplicateFile;
+ CleanupClosePushL(duplicateFile);
+ User::LeaveIfError(duplicateFile.Duplicate(aFile)); // this is because CFileStore::FromLC closes the file its passed (and stores its own duplicate)
+
+ CFileStore* const store = CFileStore::FromL(duplicateFile);
+ CleanupStack::PopAndDestroy(&duplicateFile);
+
+ CleanupStack::PushL(store);
+ DoReadRootStreamL(*streamDictionary, *store);
+ aStore = store; // delay assignment until nothing can go wrong to avoid destroying the store twice if a leave occurs
+ CleanupStack::Pop(store);
+
+ return streamDictionary;
+ }
+
+
+void CApaProcess::DoReadRootStreamL(CStreamDictionary& aStreamDictionary, const CFileStore& aStore)
+ { // static
+ const TStreamId rootStreamId=aStore.Root();
+ if ((aStore.Type()[1] != KUidAppDllDoc) || (rootStreamId == KNullStreamId))
+ User::Leave(KErrCorrupt);
+
+ RStoreReadStream rootStream;
+ rootStream.OpenLC(aStore, rootStreamId);
+ rootStream >> aStreamDictionary;
+ CleanupStack::PopAndDestroy(&rootStream);
+ }
+
+
+/** Writes the application identifier (derived from the application object CApaApplication)
+followed by the stream dictionary to the store and makes the stream dictionary the root stream of the
+store.
+
+Typically, the function is called by the application when it
+implements a file create or file save type operation. It is called after all
+model and UI data has been persisted. The IDs of the streams containing the
+model and UI data should have been lodged in the stream dictionary.
+
+In effect, the function finishes off the file save or file
+create type operation, leaving the file containing the store in a valid state
+with the standard interface.
+
+@param aStore The store to which the root stream is to be written. Before
+calling this function, a reference to the store must be saved by putting a
+pointer onto the cleanup stack or by making it member data of a class. This
+ensures that it is not orphaned in the event of this function leaving.
+@param aStreamDic The stream dictionary containing the locations and associated
+UIDs of other streams in the store.
+@param aApp The application used to create the main document in the file
+being written. The application identifier to be written is constructed from
+this application object. */
+EXPORT_C void CApaProcess::WriteRootStreamL(CPersistentStore& aStore,CStreamDictionary& aStreamDic,const CApaApplication& aApp)
+ { // this is a static method
+ __SHOW_TRACE(_L("Starting CApaProcess::WriteRootStreamL(app)"));
+ // get the app dll name
+ TParse dllPath;
+ dllPath.SetNoWild(aApp.DllName(),NULL,NULL);
+ // set up an app identifier
+ TApaAppIdentifier appId(aApp.AppDllUid(),dllPath.NameAndExt());
+ // Write the root stream
+ WriteRootStreamL(aStore,aStreamDic,appId);
+ }
+
+
+/** Writes the application identifier followed by the stream dictionary
+to the store and makes the stream dictionary the root stream of the store.
+
+Typically, the function is called by the application when it
+implements a file create or file save type operation. It is called after all
+model and UI data has been persisted. The IDs of the streams containing the
+model and UI data should have been lodged in the stream dictionary.
+
+In effect, the function finishes off the file save or file
+create type operation, leaving the file containing the store in a valid state
+with the standard interface.
+
+@param aStore The store to which the root stream is to be written. Before
+calling this function, a reference to the store must be saved by putting a
+pointer onto the cleanup stack or by making it member data of a class. This
+ensures that it is not orphaned in the event of this function leaving.
+@param aStreamDic The stream dictionary containing the locations and associated
+UIDs of other streams in the store.
+@param aAppId The application identifier to be written into the application
+identifier stream. */
+EXPORT_C void CApaProcess::WriteRootStreamL(CPersistentStore& aStore,CStreamDictionary& aStreamDic,const TApaAppIdentifier& aAppId)
+ { // this is a static method
+ __SHOW_TRACE(_L("Starting CApaProcess::WriteRootStreamL(id)"));
+ // create a stream
+ WriteAppIdentifierL(aStore,aStreamDic,aAppId);
+
+ // externalize the dictionary
+ RStoreWriteStream stream;
+ TStreamId streamId = stream.CreateLC(aStore);
+ stream << aStreamDic;
+ stream.CommitL();
+ CleanupStack::PopAndDestroy(); // dictionary stream
+
+ // set the dictionary stream as the root stream
+ aStore.SetRootL(streamId);
+ }
+
+
+/** Destroys the specified document.
+
+All references to the document are removed, and associated resources are freed.
+Specifically, the function deletes any associated application and unloads
+the application DLL, provided that no other documents of that application
+type are still open.
+
+All document objects created through CApaProcess must be deleted using this
+function.
+
+@param aDoc A pointer to the document to be destroyed.
+@see CApaApplication
+@see CApaProcess */
+EXPORT_C void CApaProcess::DestroyDocument(CApaDocument* aDoc)
+ {
+ __SHOW_TRACE(_L("Starting CApaProcess::DestroyDocument(app)"));
+
+ if(!aDoc)
+ return;
+
+ // delete the doc, keeping a handle to its app
+ CApaApplication* const app = aDoc->Application();
+ __ASSERT_DEBUG(app, Panic(EDPanicDocWithNoApp));
+
+ // remove the doc from the list, keeping a handle to the doc
+ TBool appStillRequired = EFalse;
+ __ASSERT_ALWAYS(iDocList, Panic(EPanicNullPointer));
+ for (TInt i = iDocList->Count()-1; i >= 0; i--)
+ { // check through the list, remove the right doc, and see if the app is used by any other docs
+ if((*iDocList)[i] == aDoc)
+ {
+ iDocList->Delete(i); // removes from array, but doesnt destroy
+ iDocList->Compress();
+ }
+ else if ((*iDocList)[i]->Application() == app)
+ appStillRequired = ETrue;
+ }
+
+ // Null the main doc handle if we are deleting the main doc
+ if (aDoc == iMainDoc)
+ iMainDoc = NULL;
+
+ // Now delete the document
+ delete aDoc;
+
+ // Remove app if no other doc's use it and it's not the main app
+ if (!appStillRequired && iMainDoc && app!=iMainDoc->Application())
+ {
+ MarkApplicationForAsyncRemoval(app);
+ __ASSERT_DEBUG(iAsyncAppRemover, Panic(EDPanicNoAppRemover));
+
+ if (!iAsyncAppRemover->IsActive())
+ iAsyncAppRemover->Start(TCallBack(CApaProcess::IdleRemoveApplications, this));
+ }
+ }
+
+void CApaProcess::MarkApplicationForAsyncRemoval(const CApaApplication* aApp)
+// Mark the application in the app list for removal by idle object
+//
+ {
+ __ASSERT_DEBUG(aApp!=NULL,Panic(EDPanicRemovingNullApp));
+ __ASSERT_DEBUG(iAppList, Panic(EPanicNullPointer));
+ // remove the app from the list, keeping a handle to it
+ for (TInt i = iAppList->Count()-1 ; i >= 0 ; i--)
+ {
+ __ASSERT_DEBUG((*iAppList)[i], Panic(EDPanicNoAppHolder));
+ if ((*iAppList)[i]->Application() == aApp)
+ {
+ (*iAppList)[i]->ScheduleForAsyncDeletion();
+ return;
+ }
+ }
+ }
+
+TInt CApaProcess::IdleRemoveApplications(TAny* aApaProcess)
+// Remove applications on callback of idle object. Using an idle object gives an embedded application a chance to clear
+// its call stack before its dll is closed
+//
+ {
+ CApaProcess* process = reinterpret_cast<CApaProcess*>(aApaProcess);
+ __ASSERT_DEBUG(process, Panic(EDPanicNoProcess));
+ process->RemoveMarkedApplications();
+
+ return KErrNone;
+ }
+
+
+void CApaProcess::RemoveMarkedApplications()
+// Remove any applications that have been marked for removal, closing their dlls also
+//
+ {
+ __ASSERT_DEBUG(iAppList, Panic(EPanicNullPointer));
+ for (TInt i = iAppList->Count()-1; i >= 0; i--)
+ {
+ if ((*iAppList)[i]->IsScheduleForAsyncDeletion())
+ {
+ (*iAppList)[i]->Close();
+ iAppList->Delete(i); // remove from array
+ }
+ }
+
+ iAppList->Compress();
+ }
+
+
+CApaDocument* CApaProcess::CreateDocL(CApaApplication* aApp)
+// creates a new doc with aApp and adds it to the list before returning a handle to it
+//
+ {
+ __SHOW_TRACE(_L("Starting CApaProcess::CreateDocL"));
+ __ASSERT_DEBUG(aApp, Panic(EDPanicNoApp));
+
+ // create a new doc with the app
+ CApaDocument* doc = aApp->CreateDocumentL(this); //lint !e613 Possible use of null pointer - Asserted above
+ __ASSERT_ALWAYS(doc, Panic(EPanicDocumentNotCreated));
+
+ // add the doc to the list
+ CleanupStack::PushL(doc);
+ iDocList->AppendL(doc);
+ CleanupStack::Pop(); // doc
+
+ // return a handle to the doc
+ return doc;
+ }
+
+
+RApaApplication* CApaProcess::FindAppInListL(const TDesC& aAppFileName, TUid aUid) const
+// returns pointer to a matching app, or NULL if not in list
+//
+ {
+ __ASSERT_DEBUG(iAppList, Panic(EPanicNullPointer));
+
+ TInt index = iAppList->Count();
+ if (aUid!=KNullUid)
+ {// search by UID
+ while(--index >= 0)
+ {
+ __ASSERT_DEBUG((*iAppList)[index], Panic(EDPanicNoAppHolder));
+ if ((*iAppList)[index]->AppFileUid() == aUid)
+ {
+ (*iAppList)[index]->ScheduleForAsyncDeletion(EFalse);
+ return (*iAppList)[index]; // match found
+ }
+ }
+ }
+ else
+ {// search by name as no UID has been supplied
+ TParse app;
+ TParse suspect;
+ User::LeaveIfError(app.Set(aAppFileName,NULL,NULL));
+ while (--index>=0)
+ {
+ __ASSERT_DEBUG((*iAppList)[index], Panic(EDPanicNoAppHolder));
+ suspect.SetNoWild((*iAppList)[index]->AppFileName(), NULL, NULL);
+ if (!app.Name().CompareF(suspect.Name()))
+ {
+ (*iAppList)[index]->ScheduleForAsyncDeletion(EFalse);
+ return (*iAppList)[index]; // match found
+ }
+ }
+ }
+
+ return NULL; // no match found
+ }
+
+RApaApplication* CApaProcess::AddAppL(TApaApplicationFactory aApplicationFactory)
+ {
+ RApaApplication* app = new (ELeave) RApaApplication;
+ CleanupClosePushL(*app);
+
+ // create the app
+ app->CreateApplicationL(aApplicationFactory);
+ __ASSERT_DEBUG(app->Application(), Panic(EPanicNullPointer));
+ app->Application()->PreDocConstructL();
+
+ // add the application to the list and return a pointer to it
+ __ASSERT_DEBUG(iAppList, Panic(EPanicNullPointer));
+ iAppList->AppendL(app);
+
+ CleanupStack::Pop(app);
+ return app;
+ }
+
+EXPORT_C TPtrC CApaProcess::MainDocFileName()const
+/** Returns the filename of the main document.
+
+@return A non-modifiable pointer descriptor to the main document filename.
+For non file-based applications, the length of this descriptor is zero. */
+ {
+ if (iMainDocFileName)
+ return *iMainDocFileName;
+
+ return KNullDesC();
+ }
+
+/** Reserved for future use */
+EXPORT_C void CApaProcess::CApaProcess_Reserved1()
+ {
+ }
+
+/** Reserved for future use */
+EXPORT_C void CApaProcess::CApaProcess_Reserved2()
+ {
+ }
+
+
+