installationservices/swi/source/swis/server/processor.cpp
changeset 0 ba25891c3a9e
child 12 7ca52d38f8c3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/installationservices/swi/source/swis/server/processor.cpp	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,884 @@
+/*
+* 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 the License "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: 
+* Application Processor
+*
+*/
+
+
+/**
+ @file
+ @released
+ @internalTechnology 
+*/
+
+#include <hash.h>
+#include "processor.h"
+
+#ifndef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+#include "integrityservices.h"
+#endif
+
+#include "sishelperclient.h"
+#include "sisregistryfiledescription.h"
+#include "sisregistryentry.h"
+#include "sisstring.h"
+#include "hashcontainer.h"
+#include "siscontroller.h"
+#include "application.h"
+#include "log.h"
+#include "secutils.h"
+#include "sisuihandler.h"
+#include "filesisdataprovider.h"
+#include "securitymanager.h"
+#include "sislauncherclient.h"
+#include "sisinfo.h"
+#include "sisuid.h"
+#include "plan.h"
+#include "securitycheckutil.h"
+#include "progressbar.h"
+#include "sidcache.h"
+#include "planner.h"
+#include "sisregistrypackage.h"
+#include <f32file.h>
+#include <e32property.h>
+#include <swi/swispubsubdefs.h>
+
+using namespace Swi;
+
+const TChar KRomDrive = 'z';
+
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+CProcessor::CProcessor(const CPlan& aPlan, RUiHandler& aUiHandler,
+		Usif::RStsSession& aStsSession, CRegistryWrapper& aRegistryWrapper, 
+		RSwiObserverSession& aObserver)
+	: CActive(EPriorityStandard), 
+	iSystemDriveChar(RFs::GetSystemDriveChar()),
+	iRegistryWrapper(aRegistryWrapper),
+	iPlan(aPlan),	
+	iUiHandler(aUiHandler),
+	iStsSession(aStsSession),
+	iObserver(aObserver)
+	{
+	CActiveScheduler::Add(this);
+	}
+#else
+CProcessor::CProcessor(const CPlan& aPlan, RUiHandler& aUiHandler, CIntegrityServices& aIntegrityServices, RSwiObserverSession& aObserver)
+	: CActive(EPriorityStandard),
+	iSystemDriveChar(RFs::GetSystemDriveChar()),
+	iPlan(aPlan),	
+	iUiHandler(aUiHandler),
+	iIntegrityServices(aIntegrityServices),
+	iObserver(aObserver)
+	{
+	CActiveScheduler::Add(this);
+	}
+#endif
+
+CProcessor::~CProcessor()
+	{
+	Cancel();
+	iFs.Close();
+	iSidsAdded.Close();
+	iSidsRemoved.Close();
+	iSidsToShutdown.Close();
+	}
+
+void CProcessor::ConstructL()
+	{
+	User::LeaveIfError(iFs.Connect());
+	User::LeaveIfError(iFs.ShareProtected());	
+	}
+
+void CProcessor::ProcessApplicationL(const CApplication& aApplication, TRequestStatus& aClientStatus)
+	{
+	iApplication = &aApplication;
+	 
+	iClientStatus = &aClientStatus;
+	aClientStatus = KRequestPending;
+	iErrorCode = 0;
+	
+	// We only get the validation status of the package for uninstallation here 	
+	if (ApplicationL().IsUninstall())
+		{
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+		RSisRegistryEntry entry;		
+		User::LeaveIfError(entry.OpenL(iRegistryWrapper.RegistrySession(), ApplicationL().PackageL()));			
+		CleanupClosePushL(entry);
+		iValidationStatus=entry.TrustStatusL().ValidationStatus();
+		CleanupStack::PopAndDestroy(&entry);
+#else
+		RSisRegistrySession session;
+		User::LeaveIfError(session.Connect());
+		CleanupClosePushL(session);		
+		RSisRegistryEntry entry;		
+		User::LeaveIfError(entry.OpenL(session, ApplicationL().PackageL()));			
+		CleanupClosePushL(entry);
+		iValidationStatus=entry.TrustStatusL().ValidationStatus();
+		CleanupStack::PopAndDestroy(&entry);
+		CleanupStack::PopAndDestroy(&session);
+#endif
+		}
+	else
+		{
+		iValidationStatus =	ApplicationL().ControllerL().TrustStatus().ValidationStatus();
+		}
+		
+	iSidsAdded.Reset();
+	iSidsRemoved.Reset();
+	iSidsToShutdown.Reset();
+		
+	SwitchState(EInitialize);
+	}
+
+void CProcessor::ProcessPlanL(TRequestStatus& aClientStatus)
+	{
+	ProcessApplicationL(iPlan.ApplicationL(), aClientStatus);
+	}
+
+void CProcessor::Reset()
+	{
+	}
+
+void CProcessor::DoCancel()
+	{
+	iCancelled=ETrue;
+	User::RequestComplete(iClientStatus, KErrCancel);
+	}
+
+void CProcessor::RunL()
+	{
+	DEBUG_PRINTF3(_L8("Install Server - Processor State Machine, State: %d, Status: %d"),
+		iState, iStatus.Int());
+	
+	// Leave if there has been an error
+	User::LeaveIfError(iStatus.Int());
+	
+	if (iCancelled)
+		{
+		User::Leave(KErrCancel);
+		}
+		
+	switch(iState)
+		{
+	case EInitialize:
+		if (DoStateInitializeL())
+			{
+			SwitchState(EProcessEmbedded);
+			}
+		break;
+		
+	case EProcessEmbedded:
+		if (DoStateProcessEmbeddedL())
+			{
+			SwitchState(EShutdownAllApps);
+			}
+		break;
+	
+	case EShutdownAllApps:
+		if (DoStateShutdownAllAppsL())
+			{
+			SwitchState(ECheckApplicationInUse);
+			}
+		break;
+
+	case ECheckApplicationInUse:
+		if (DoStateCheckApplicationInUseL())
+			{
+			SwitchState(EShutdownExe);
+			}
+		break;
+	
+	case EShutdownExe:
+		if (DoStateShutdownExeL())
+			{
+			SwitchState(EDisplayFiles);
+			}
+		break;
+	
+	case EDisplayFiles:
+		if (DoStateDisplayFilesL())
+			{
+			SwitchState(EProcessSkipFiles);
+			}
+		break;
+
+	case EProcessSkipFiles:
+		if (DoStateProcessSkipFilesL())
+			{
+			SwitchState(EExtractFiles);
+			}
+		break;
+
+	case EExtractFiles:
+		if (DoStateExtractFilesL())
+			{
+			SwitchState(EProcessFiles);
+			}
+		break;
+
+	case EProcessFiles:
+		if (DoStateProcessFilesL())
+			{
+			SwitchState(EVerifyPaths);
+			}
+		break;
+
+	case EVerifyPaths:
+		if (DoStateVerifyPathsL())
+			{
+			SwitchState(ERemoveFiles);
+			}
+		break;
+
+	case ERemoveFiles:
+		if (DoStateRemoveFilesL())
+			{
+			SwitchState(ERemovePrivateDirectories);
+			}
+		break;
+
+	case ERemovePrivateDirectories:
+		if (DoStateRemovePrivateDirectoriesL())
+			{
+			SwitchState(EInstallFiles);
+			}
+		break;
+	
+	case EInstallFiles:
+		if (DoStateInstallFilesL())
+			{
+			SwitchState(EUpdateRegistry);
+			}
+		break;
+
+	case EUpdateRegistry:
+		if (DoStateUpdateRegistryL())
+			{
+			SwitchState(EFinished);
+			}
+		break;
+	
+	case EFinished:
+		DoStateFinishedL();
+		break;
+		
+	default:
+		User::Leave(KErrGeneral);
+		break;
+		}
+	}
+
+void CProcessor::SwitchState(TProcessingState aNextState)
+	{
+	if (aNextState!=ECurrentState)
+		{
+		iState=aNextState;
+		}
+	TRequestStatus* status = &iStatus;
+	User::RequestComplete(status, KErrNone);
+	SetActive();
+	}
+
+void CProcessor::WaitState(TProcessingState aNextState)
+	{
+	if (aNextState!=ECurrentState)
+		{
+		iState=aNextState;
+		}
+	SetActive();
+	}
+
+TInt CProcessor::RunError(TInt aError)
+	{
+	DEBUG_PRINTF2(_L8("Install Server - Processor State Machine RunError, Error code %d"), aError);
+	
+	User::RequestComplete(iClientStatus, aError);
+	return KErrNone;
+	}
+
+// implementations of the states provided
+
+void CProcessor::DoStateFinishedL()
+	{
+	User::RequestComplete(iClientStatus, iErrorCode);
+	}
+
+// common state functions
+
+TBool CProcessor::DoStateShutdownAllAppsL()
+	{
+	if(ApplicationL().ShutdownAllApps())
+		{
+		iUiState = EShutdownAllApps;
+		// Signal to UI apps are being shut down
+		CHandleCancellableInstallEvent* cmd = CHandleCancellableInstallEvent::NewLC(Plan().AppInfoL(), EEventShuttingDownApps, 0, KNullDesC);
+		UiHandler().ExecuteL(*cmd);
+		CleanupStack::PopAndDestroy(cmd);
+		
+		RSisLauncherSession launcher;
+		CleanupClosePushL(launcher);
+		User::LeaveIfError(launcher.Connect());
+		launcher.ShutdownAllL();
+		CleanupStack::PopAndDestroy(&launcher);
+		}
+	//Here is the first point where a package is actually being started to install.
+	//Hence, the package header is logged at that point.
+	TUid pkgUid;
+	TPackageType pkgType;
+	TOperationType opType;
+	
+	if(ApplicationL().IsUninstall())
+		{
+		pkgUid = ApplicationL().PackageL().Uid();
+		//It is assumed that we don not need pkg type during uninstallation
+		pkgType = EUnknownPackage; 
+		opType = EOpUninstall;
+		}
+	else
+		{
+		pkgUid = ApplicationL().ControllerL().Info().Uid().Uid();
+		pkgType = static_cast<TPackageType>(ApplicationL().ControllerL().Info().InstallType());
+		opType = EOpInstall;
+		}
+		
+	CObservationHeader *header = CObservationHeader::NewLC(pkgUid, pkgType, opType);
+	
+	Observer().AddHeaderL(*header);
+	CleanupStack::PopAndDestroy(header);
+	return ETrue;
+	}
+
+TBool CProcessor::DoStateCheckApplicationInUseL()
+	{
+	const RPointerArray<CSisRegistryFileDescription>& filesToRemove = ApplicationL().FilesToRemove();
+	TInt fileCount = filesToRemove.Count();
+
+	if (fileCount > 0)
+		{		
+		// Find Sids corresponding to Exes we are removing.			
+		RArray<TAppInUse> sidsArray;
+		CleanupClosePushL(sidsArray);
+		
+		for (TInt i = 0; i < fileCount; i++)
+			{
+			TEntry entry;
+			TInt err = Fs().Entry(filesToRemove[i]->Target(), entry);
+			// if this is an EXE.
+			if (err == KErrNone && entry.IsTypeValid() &&
+				SecUtils::IsExe(entry))
+				{
+				//Add it the check array
+				TAppInUse temp;
+				temp.iAppUid=filesToRemove[i]->Sid();
+				temp.iInUse=EFalse;
+				sidsArray.AppendL(temp);				
+				}
+			}			
+			
+		// If there are any executables, check if they are in use.
+		TInt exeCount=sidsArray.Count();
+		if (exeCount>0)
+			{
+			RSisLauncherSession launcher;
+			CleanupClosePushL(launcher);
+			User::LeaveIfError(launcher.Connect());
+			
+			//check if they are running	
+			TRAPD(err,launcher.CheckApplicationInUseL(sidsArray));
+			if(err == KErrNone)
+				{
+				for (TInt i=0;i<exeCount;i++)
+					{
+					if (sidsArray[i].iInUse)
+						{
+						iSidsToShutdown.AppendL(sidsArray[i].iAppUid);												
+						}
+					}
+				}
+			else
+				{
+				User::LeaveIfError(err);
+				}
+			CleanupStack::PopAndDestroy(&launcher);				
+			}
+		CleanupStack::PopAndDestroy(&sidsArray);
+		}
+
+	// If any Sids are in use, display dialog for applications in use
+	// which offers the chance to cancel.
+	if(iSidsToShutdown.Count() > 0)
+		{
+		if(!DisplayApplicationInUseL())
+			{
+			User::Leave(KErrCancel);	
+			}
+		else 
+			{
+			// User has chosen to shut down apps.  Set shutdown timeout from
+			// software install security policy.
+			CSecurityPolicy* secPolicy = CSecurityPolicy::GetSecurityPolicyL();
+			iShutdownTimeout = secPolicy->ApplicationShutdownTimeout();
+			}
+		}
+
+	return ETrue;
+	}
+	
+TBool CProcessor::DoStateShutdownExeL()
+	{
+	if (iSidsToShutdown.Count()>0)
+		{
+		// If this is the first app to shut down, signal to UI apps are
+		// being shut down.
+		if(iUiState != EShutdownExe)
+			{
+			iUiState = EShutdownExe;
+			CHandleCancellableInstallEvent* cmd = CHandleCancellableInstallEvent::NewLC(Plan().AppInfoL(), EEventShuttingDownApps, 0, KNullDesC);
+			UiHandler().ExecuteL(*cmd);
+			CleanupStack::PopAndDestroy(cmd);
+			}
+				
+		RSisLauncherSession launcher;
+		CleanupClosePushL(launcher);
+		User::LeaveIfError(launcher.Connect());
+		
+		launcher.ShutdownL(iSidsToShutdown, iShutdownTimeout);
+			
+		CleanupStack::PopAndDestroy(&launcher);		
+		}	
+	return ETrue;
+	}
+
+TBool CProcessor::DoStateRemoveFilesL()
+	{
+	if (iCurrent < ApplicationL().FilesToRemove().Count())
+		{
+		if (iUiState != ERemoveFiles)
+			{
+			iUiState = ERemoveFiles;
+			// Signal to UI we are removing files
+			CHandleCancellableInstallEvent* cmd = CHandleCancellableInstallEvent::NewLC(Plan().AppInfoL(), EEventRemovingFiles, 0, KNullDesC);
+			UiHandler().ExecuteL(*cmd);
+			CleanupStack::PopAndDestroy(cmd);
+			}
+		RemoveFileL(*ApplicationL().FilesToRemove()[iCurrent++]);					
+		SwitchState(ECurrentState);
+		return EFalse;		
+		}
+	else
+		{
+		iCurrent = 0;
+		return ETrue;
+		}
+	}
+
+TBool CProcessor::DoStateRemovePrivateDirectoriesL()
+	{
+	if (iCurrent < iSidsRemoved.Count())
+		{
+		// Remove the private directory if the sid is not being replaced
+		// and it is not in ROM too (we could be removing an exe which
+		// eclipsed one in ROM.)
+		if(iSidsAdded.Find(iSidsRemoved[iCurrent]) == KErrNotFound)
+			{
+			CSidCache* sidCache;
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+			sidCache = CSidCache::NewLC(iStsSession);
+#else
+			sidCache = CSidCache::NewLC(iIntegrityServices);
+#endif
+			if (!sidCache->IsCachedL(iSidsRemoved[iCurrent]))
+				{
+				RemovePrivateDirectoryL(iSidsRemoved[iCurrent]);
+				}
+			CleanupStack::PopAndDestroy(sidCache);
+			}
+		iCurrent++;
+		SwitchState(ECurrentState);
+		return EFalse;
+		}
+	else
+		{
+		iCurrent = 0;
+		return ETrue;
+		}
+	}
+	
+TBool CProcessor::DoStateProcessFilesL()
+	{
+	return ETrue;
+	}
+	
+// utility functions
+
+void CProcessor::RunFileL(const TDesC& aFileName, const TDesC& aMimeType, Sis::TSISFileOperationOptions aFileOperationOption)
+	{
+	CSecurityPolicy* secPolicy = CSecurityPolicy::GetSecurityPolicyL();
+	if (!secPolicy->AllowRunOnInstallUninstall() && iValidationStatus < EValidatedToAnchor )
+		{
+		return;			
+		}
+		
+	TBool wait = EFalse;
+	if((aFileOperationOption & Sis::EInstFileRunOptionWaitEnd) 
+	   || ApplicationL().IsUninstall() || iState == ERemoveFiles)
+		{
+		// always wait for completion or timeout when uninstalling since 
+		// cannot remove the file when it is in use!
+		wait = ETrue;
+		}
+	
+	RSisLauncherSession launcher;
+	CleanupClosePushL(launcher);
+	User::LeaveIfError(launcher.Connect());
+	
+	// Is the file an executable ?
+	TEntry entry;
+	User::LeaveIfError(Fs().Entry(aFileName, entry));
+	if (entry.IsTypeValid() && SecUtils::IsExe(entry))
+		{
+		launcher.RunExecutableL(aFileName, wait);
+		}	
+	else 
+		{
+		RFile file;
+		CleanupClosePushL(file);				
+		if (aFileOperationOption & Sis::EInstFileRunOptionByMimeType)
+			{
+			HBufC8* mimeType = HBufC8::NewLC(aMimeType.Length());
+			TPtr8 ptr = mimeType->Des();
+			ptr.Copy(aMimeType);
+			TRAPD(err, launcher.StartByMimeL(aFileName, *mimeType, wait));
+			if (err!=KErrNone) 
+				{
+				User::LeaveIfError(file.Open(iFs, aFileName, EFileShareExclusive|EFileWrite));
+				TRAP_IGNORE(launcher.StartByMimeL(file, *mimeType, wait));
+				}
+			CleanupStack::PopAndDestroy(mimeType);		
+			}
+		else
+			{
+			TRAPD(err, launcher.StartDocumentL(aFileName, wait));		
+			if (err!=KErrNone)
+				{
+				User::LeaveIfError(file.Open(iFs, aFileName, EFileShareExclusive|EFileWrite));
+				TRAP_IGNORE(launcher.StartDocumentL(file, wait));	
+				}
+			}
+		CleanupStack::PopAndDestroy(&file);		
+		}
+	CleanupStack::PopAndDestroy(&launcher);
+	}
+	
+TBool CProcessor::IsSafeUninstallModeSetL()
+	{
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+	TInt safeModeValue(0);
+	TInt res = RProperty::Get(KUidInstallServerCategory, KUidSafeModeUninstallKey, safeModeValue);
+	if (res != KErrNone && res != KErrNotFound)
+		User::Leave(res);
+	return (res == KErrNone && safeModeValue == KSwisSafeModeUninstallEnabled);
+#else
+	return EFalse;
+#endif
+	}
+	
+void CProcessor::RemoveFileL(const CSisRegistryFileDescription& aFileDescription)
+	{
+	DEBUG_PRINTF2(_L("Install Server - Processor State Machine, Removing File '%S'"),
+		&aFileDescription.Target());
+	
+	TInt err;
+	//Explicitly set boolean to keep armv5 compiler happy.
+	TBool skipRemove(EFalse);
+	TBool romBasedExe(EFalse);
+	TInt driveNo;
+	
+	err = Fs().CharToDrive(aFileDescription.Target()[0], driveNo);
+
+	if (err == KErrArgument)
+		{
+		skipRemove = ETrue;
+		}
+	else
+		{
+		// Should leave if RFs::CharToDrive returned anything other than
+		// KErrNone or KErrArgument, since the problem is more serious than an
+		// invalid path.
+		User::LeaveIfError(err);
+		}
+
+	TBool isPreInstalled = ApplicationL().IsPreInstalledApp() ||
+							ApplicationL().IsPreInstalledPatch();
+
+	// Run files only if not pre-installed
+	if (!isPreInstalled)
+		{
+		if (aFileDescription.Operation() == Sis::EOpRun &&
+			 aFileDescription.OperationOptions() & Sis::EInstFileRunOptionUninstall)
+			{		
+			// Check whether safe mode is enabled - don't run the executable in this case
+
+			if (!IsSafeUninstallModeSetL())
+				{
+				// ignore failure to run on uninstall, so a failing executable does
+				// not block a removal.
+				TRAP_IGNORE(RunFileL(aFileDescription.Target(), aFileDescription.MimeType(), aFileDescription.OperationOptions()));
+				}
+			}	
+		}
+	else if (!skipRemove)
+		{
+		// For preinstalled packages, we will delete files if permitted by
+		// the swipolicy and if the application is tagged as deletable preinstalled
+		// (based on whether the stub sis file was writable at install time.)
+		// The swipolicy check is paranoid, since the application should only
+		// be marked as deletable preinstalled if the swipolicy allowed it at
+		// install time.
+		CSecurityPolicy* secPolicy = CSecurityPolicy::GetSecurityPolicyL();
+		skipRemove = !(ApplicationL().IsDeletablePreinstalled() && secPolicy->DeletePreinstalledFilesOnUninstall());
+		}
+
+	// If we're not already skipping from previous checks, skip if it's
+	// preinstalled and ROM or write-protected or read-only, or filenull on
+	// ROM.
+	if (!skipRemove)
+		{
+		if ((isPreInstalled || aFileDescription.Operation() == Sis::EOpNull))
+			{
+			TDriveInfo driveInfo;
+			err = Fs().Drive(driveInfo, driveNo);
+			if ((err != KErrNone) || (driveInfo.iDriveAtt & KDriveAttRom) ||
+			(isPreInstalled && (driveInfo.iMediaAtt & KMediaAttWriteProtected)))
+				{
+				skipRemove = ETrue;
+				}
+			else if (isPreInstalled)
+				{
+				TEntry entry;
+				err = Fs().Entry(aFileDescription.Target(), entry);
+				skipRemove = ((err != KErrNone) || entry.IsReadOnly());
+				}
+			}
+		}
+	//Flag for observation log
+	TUint8 fileFlag(EFileDeleted);	
+	
+	// for the files in sys\bin directory, related hash values need to be removed
+	TParsePtrC targetPath(aFileDescription.Target());
+	if (targetPath.Path().CompareF(KBinPath) == 0)
+		{
+		
+		// Check wheather the file is referenced by one of the ROM stub files.
+		CSidCache* sidCache;
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+		sidCache = CSidCache::NewLC(iStsSession);
+#else
+		sidCache = CSidCache::NewLC(iIntegrityServices);
+#endif
+		TUid fileSid = aFileDescription.Sid();
+		romBasedExe = sidCache->IsCachedL(fileSid);
+		CleanupStack::PopAndDestroy(sidCache);
+		
+		// Backup and later delete the hash	
+		TBuf<32> hashPath;	
+		TUint driveCh(iSystemDriveChar); // can't pass TChar to Format
+		hashPath.Format(KHashPathFormat, driveCh, &KHashPath);	
+		
+		TParse hashFileName;
+		hashFileName.Set(hashPath, &aFileDescription.Target(), NULL);
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+		TRAP(err, TransactionSession().RemoveL(hashFileName.FullName()));
+#else
+		TRAP(err, IntegrityServices().RemoveL(hashFileName.FullName()));
+#endif
+		// Display error dialog if the file cannot be removed.
+		if(err == KErrInUse)
+			{
+			CDisplayError* displayCannotDelete=CDisplayError::NewLC(iPlan.AppInfoL(), EUiCannotDelete, hashFileName.FullName());
+			iUiHandler.ExecuteL(*displayCannotDelete);
+			CleanupStack::PopAndDestroy(displayCannotDelete);
+			}
+		if(err != KErrNotFound && err != KErrPathNotFound && err != KErrNotReady && err != KErrCorrupt)
+			{
+			User::LeaveIfError(err);
+			}
+		//Create an SWI event for the hash file					
+		CObservationData *event = CObservationData::NewLC(hashFileName.FullName(),TUid::Null(),fileFlag);
+		//Write the event into the observation log file
+		Observer().AddEventL(*event);
+		CleanupStack::PopAndDestroy(event);
+
+		// If we're skipping removal of an exe we also don't want to remove
+		// associated private directories, so we only need to track the SIDs
+		// for exes being removed.
+		if (!skipRemove)
+			{
+			TEntry entry;
+			err = Fs().Entry(aFileDescription.Target(), entry);
+
+			// When an executable file is removed from the system drive, it may have a counterpart 
+			// in ROM storage. This may happen if the ROM file was upgraded with an SU package.			TFileName target(aFileDescription.Target());
+			TFileName target(aFileDescription.Target());
+			target[0] = KRomDrive;
+			TEntry romEntry;
+			TInt error = Fs().Entry(target, romEntry);
+			TBool existInRom = (error == KErrNone);
+	
+			// if this is an EXE, add to list of SIDS removed for later
+			// cleanup of private directories.
+			if (err == KErrNone && entry.IsTypeValid() && !romBasedExe && !existInRom)
+				{
+				if(SecUtils::IsExe(entry))
+					{
+					TUid sid = aFileDescription.Sid();
+					User::LeaveIfError(iSidsRemoved.Append(sid));
+					//Set file exe flag.
+					fileFlag |= Swi::EFileExe;	
+					}
+				else if(SecUtils::IsDll(entry))
+					{
+					//Set file dll flag
+					fileFlag |= Swi::EFileDll;
+					}
+				}
+			}
+		}
+		
+	if (!skipRemove)
+		{
+		TInt err = KErrNone;
+		// use transaction support to backup and later delete the file
+		// ignore missing files, media cards not present or corrupt media
+
+		TPtrC fileToRemove;
+		if(targetPath.IsWild() || targetPath.NameAndExt().Length() == 0)
+			{
+			fileToRemove.Set(targetPath.DriveAndPath());
+			}
+		else
+			{
+			fileToRemove.Set(aFileDescription.Target());
+			}
+		
+		// Skip targets less than 4 characters, since this won't be a valid path
+		// for transaction service RemoveL().
+		if (fileToRemove.Length() > 3)
+			{
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+			TRAP(err, TransactionSession().RemoveL(fileToRemove));
+#else
+			TRAP(err, IntegrityServices().RemoveL(fileToRemove));
+#endif
+			// Display error dialog and leave if the file cannot be removed,
+			// ignoring missing files, media cards not present or corrupt media
+			if(err !=KErrNone && err != KErrNotFound && err != KErrPathNotFound	&& err != KErrNotReady && err != KErrCorrupt)
+				{
+				CDisplayError* displayCannotDelete=CDisplayError::NewLC(iPlan.AppInfoL(), EUiCannotDelete, fileToRemove);
+				iUiHandler.ExecuteL(*displayCannotDelete);
+				CleanupStack::PopAndDestroy(displayCannotDelete);
+				User::Leave(err);
+				}
+			//Create an SWI event					
+			CObservationData *event = CObservationData::NewLC(fileToRemove,aFileDescription.Sid(),fileFlag);
+			//Write the event into the observation log file
+			Observer().AddEventL(*event);
+			CleanupStack::PopAndDestroy(event);
+			}
+		}
+	// Update progress bar by one for uninstall of file
+	iUiHandler.UpdateProgressBarL(iPlan.AppInfoL(), KProgressBarUninstallAmount);
+	}
+
+void CProcessor::RemovePrivateDirectoryL(TUid aSid)
+	{
+	DEBUG_PRINTF2(_L8("Removing private directories \\private\\%08x\\"), aSid.iUid);
+	
+	_LIT(KPrivatePath, "?:\\private\\");
+	const TInt KPathLength = 8;
+	TFileName privatePath = KPrivatePath();
+	privatePath.AppendNumFixedWidthUC(aSid.iUid, EHex, KPathLength);
+	privatePath.Append(KPathDelimiter);
+	
+	TDriveList driveList;
+	User::LeaveIfError(iFs.DriveList(driveList));
+	for(TInt drive = EDriveA; drive <= EDriveZ; drive++)
+		{
+		// only attempt removal on writeable drives that are present
+		if (driveList[drive])
+			{
+			TDriveInfo info;
+			TInt err = iFs.Drive(info, drive);
+			if(err == KErrNone)
+				{
+				if (!(info.iMediaAtt & KMediaAttWriteProtected) && info.iType!=EMediaNotPresent)
+					{
+					TChar driveLetter;
+					User::LeaveIfError(iFs.DriveToChar(drive, driveLetter));
+					privatePath[0] =  static_cast<TText> (driveLetter);
+					// try to remove the private directory, ignore if it can't be found
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+					TRAP(err, TransactionSession().RemoveL(privatePath));
+#else
+					TRAP(err, IntegrityServices().RemoveL(privatePath));
+#endif
+					if (err != KErrNone && err != KErrNotReady &&
+						err != KErrNotFound && err != KErrPathNotFound && err != KErrCorrupt)
+						{
+						User::Leave(err);
+						}
+					}
+				}
+			}
+		}
+	}
+
+TBool CProcessor::DisplayApplicationInUseL()
+	{
+	RPointerArray<TDesC> appName;
+		
+	User::LeaveIfError(appName.Append(&Plan().AppInfoL().AppName()));
+	CleanupClosePushL(appName);
+
+	CDisplayApplicationsInUse* displayApplicationInUse=CDisplayApplicationsInUse::NewLC(Plan().AppInfoL(),appName);
+	UiHandler().ExecuteL(*displayApplicationInUse);
+	TBool result = displayApplicationInUse->ReturnResult();
+	
+	CleanupStack::PopAndDestroy(2,&appName);
+	return (result);
+	}
+	
+void CProcessor::RunBeforeShutdown()
+	{
+	// If safe mode is set, we should not run any executables
+	TBool isSafeUninstallModeSet(EFalse);
+	TRAP_IGNORE(isSafeUninstallModeSet = IsSafeUninstallModeSetL());
+	if (isSafeUninstallModeSet)	
+		return;
+		
+	const RPointerArray<CSisRegistryFileDescription>& descriptions = Plan().FilesToRunBeforeShutdown();	
+	TInt count(descriptions.Count());
+	for (TInt i = 0; i < count; i++)
+		{
+		CSisRegistryFileDescription* fileName = descriptions[i];
+		DEBUG_PRINTF2(_L("Install Server - Processor State Machine, Running the RBS executable '%S'"),
+				&fileName->Target());
+		
+		// ignore failure to run before shutdown during uninstall, so a failing executable does
+		// not block uninstallation.Retaining the RunRemove behaviour. 
+		TRAP_IGNORE(RunFileL(fileName->Target(), fileName->MimeType(), fileName->OperationOptions()));
+		}	
+	}
+