/*
* Copyright (c) 1997-2010 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
TInt noOfDetletionAttempts=1;
while ((err == KErrInUse ||err==KErrAccessDenied )&& noOfDetletionAttempts <= KMaxNoOfDeletionAttempts )
{
#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
TRAP(err, TransactionSession().RemoveL(fileToRemove));
#else
TRAP(err, IntegrityServices().RemoveL(fileToRemove));
#endif
DEBUG_PRINTF2(_L8("Deletion attempt %d"), noOfDetletionAttempts);
noOfDetletionAttempts++;
User::After(KRetryInterval);
}
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
TInt noOfDetletionAttempts=1;
while ((err == KErrInUse ||err==KErrAccessDenied )&& noOfDetletionAttempts <= KMaxNoOfDeletionAttempts )
{
#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
TRAP(err, TransactionSession().RemoveL(privatePath));
#else
TRAP(err, IntegrityServices().RemoveL(privatePath));
#endif
DEBUG_PRINTF2(_L8("Deletion attempt %d"), noOfDetletionAttempts);
noOfDetletionAttempts++;
User::After(KRetryInterval);
}
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()));
}
}