diff -r 5cc91383ab1e -r 7333d7932ef7 appinstaller/AppinstUi/startuplistupdater/src/startuplistupdater.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/appinstaller/AppinstUi/startuplistupdater/src/startuplistupdater.cpp Tue Aug 31 15:21:33 2010 +0300 @@ -0,0 +1,544 @@ +/* +* Copyright (c) 2010 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: Startup list updater implementation. +* +*/ + +#include "startuplistupdater.h" // CStartupListUpdater +#include "cleanupresetanddestroy.h" // CleanupResetAndDestroyPushL +#include // FeatureManager +#include // DriveInfo +#include // RResourceFile +#include // TResourceReader +#include // EStartupItemExPolicyNone +#include // CDscItem +#include // Swi::RSisRegistrySession +#include // Swi::CSisRegistryPackage +#include // Swi::RSisRegistryEntry +#include // Swi::TSisTrustStatus::IsTrusted + +_LIT( KImport, "import\\" ); +_LIT( KDriveAndPathFormat, "%c:%S" ); +_LIT( KResourceFileSpec, "c:*.rsc" ); +_LIT( KExecutableExtension, ".exe" ); +_LIT( KAsterisk, "*" ); + +const TInt KDriveSpecLength = 2; +const TInt KFirstStartupItemInfo = 1; + + +// ======== LOCAL FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// FileNamesEqual() +// --------------------------------------------------------------------------- +// +TBool FileNamesEqual( const HBufC& aFile1, const HBufC& aFile2 ) + { + return ( aFile1.CompareF( aFile2 ) == 0 ); + } + + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// CStartupListUpdater::NewL() +// --------------------------------------------------------------------------- +// +CStartupListUpdater* CStartupListUpdater::NewL() + { + CStartupListUpdater* self = new( ELeave ) CStartupListUpdater; + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::~CStartupListUpdater() +// --------------------------------------------------------------------------- +// +CStartupListUpdater::~CStartupListUpdater() + { + delete iPrivateImportPath; + iFs.Close(); + + FeatureManager::UnInitializeLib(); + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::UpdateStartupListL() +// --------------------------------------------------------------------------- +// +void CStartupListUpdater::UpdateStartupListL() + { + if ( FeatureManager::FeatureSupported( KFeatureIdExtendedStartup ) ) + { + ProcessImportsAndUninstallsL(); + } + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::CStartupListUpdater() +// --------------------------------------------------------------------------- +// +CStartupListUpdater::CStartupListUpdater() + { + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::ConstructL() +// --------------------------------------------------------------------------- +// +void CStartupListUpdater::ConstructL() + { + FeatureManager::InitializeLibL(); + User::LeaveIfError( iFs.Connect() ); + + TInt err = iFs.MkDirAll( PrivateImportPathL() ); + if( err != KErrNone && err != KErrAlreadyExists ) + { + User::Leave( err ); + } + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::PrivateImportPathL() +// --------------------------------------------------------------------------- +// +const TDesC& CStartupListUpdater::PrivateImportPathL() + { + if( !iPrivateImportPath ) + { + TFileName privateImportPath; + User::LeaveIfError( iFs.PrivatePath( privateImportPath ) ); + privateImportPath.Append( KImport ); + + TInt driveNumber; + TInt err = DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber ); + User::LeaveIfError( err ); + TChar driveLetter; + User::LeaveIfError( RFs::DriveToChar( driveNumber, driveLetter ) ); + + iPrivateImportPath = HBufC::NewL( KDriveSpecLength + privateImportPath.Length() ); + TPtr ptr( iPrivateImportPath->Des() ); + ptr.Format( KDriveAndPathFormat, static_cast< TUint >( driveLetter ), &privateImportPath ); + } + return *iPrivateImportPath; + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::ProcessImportsAndUninstallsL() +// --------------------------------------------------------------------------- +// +void CStartupListUpdater::ProcessImportsAndUninstallsL() + { + RDscStore dscStore; + OpenDscStoreLC( dscStore ); + + ImportNewResourceFilesL( dscStore ); + DeregisterUninstalledAppsL( dscStore ); + + CleanupStack::PopAndDestroy( &dscStore ); + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::OpenDscStoreLC() +// --------------------------------------------------------------------------- +// +void CStartupListUpdater::OpenDscStoreLC( RDscStore& aDscStore ) + { + if( !aDscStore.IsOpened() ) + { + aDscStore.OpenL(); + CleanupClosePushL( aDscStore ); + if( !aDscStore.DscExistsL() ) + { + aDscStore.CreateDscL(); + } + } + else + { + User::Leave( KErrAlreadyExists ); + } + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::ImportNewResourceFilesL() +// --------------------------------------------------------------------------- +// +void CStartupListUpdater::ImportNewResourceFilesL( RDscStore& aDscStore ) + { + RPointerArray executableArray; + CleanupResetAndDestroyPushL( executableArray ); + RPointerArray resourceFileArray; + CleanupResetAndDestroyPushL( resourceFileArray ); + + GetDataToBeImportedL( executableArray, resourceFileArray ); + ImportExecutablesL( aDscStore, executableArray ); + RemoveImportedResourceFiles( resourceFileArray ); + + CleanupStack::PopAndDestroy( 2, &executableArray ); + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::DeregisterUninstalledAppsL() +// --------------------------------------------------------------------------- +// +void CStartupListUpdater::DeregisterUninstalledAppsL( RDscStore& aDscStore ) + { + RPointerArray startedAtBootArray; + CleanupResetAndDestroyPushL( startedAtBootArray ); + RPointerArray installedArray; + CleanupResetAndDestroyPushL( installedArray ); + RPointerArray startedNotInstalled; + CleanupResetAndDestroyPushL( startedNotInstalled ); + + GetStartupListAppsL( aDscStore, startedAtBootArray ); + GetInstalledAppsL( installedArray ); + StartedButNotInstalledAppsL( startedAtBootArray, installedArray, startedNotInstalled ); + RemoveFromStartupListL( aDscStore, startedNotInstalled ); + + CleanupStack::PopAndDestroy( 3, &startedAtBootArray ); + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::GetDataToBeImportedL() +// --------------------------------------------------------------------------- +// +void CStartupListUpdater::GetDataToBeImportedL( + RPointerArray& aExecutableArray, + RPointerArray& aResourceFileArray ) + { + TParse resourceFiles; + User::LeaveIfError( resourceFiles.Set( KResourceFileSpec, &PrivateImportPathL(), NULL ) ); + const TPtrC importDir( resourceFiles.FullName() ); + + CDir* dir; + User::LeaveIfError( iFs.GetDir( importDir, KEntryAttMaskSupported, ESortNone, dir ) ); + CleanupStack::PushL( dir ); + for( TInt index = 0; index < dir->Count(); ++index ) + { + TFileName resourceFile; + TInt lastSeparator = importDir.LocateReverse( '\\' ); + if( lastSeparator > 0 ) + { + resourceFile.Copy( importDir.Mid( 0, lastSeparator + 1 ) ); + resourceFile.Append( ( *dir )[ index ].iName ); + aResourceFileArray.AppendL( resourceFile.AllocL() ); + + AppendExecutablesFromResourceFileL( resourceFile, aExecutableArray ); + } + } + CleanupStack::PopAndDestroy( dir ); + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::ImportExecutablesL() +// --------------------------------------------------------------------------- +// +void CStartupListUpdater::ImportExecutablesL( RDscStore& aDscStore, + RPointerArray& aExecutableArray ) + { + for( TInt index = 0; index < aExecutableArray.Count(); ++index ) + { + const TDesC& executableName = *( aExecutableArray[ index ] ); + CDscItem* item = CDscItem::NewLC( executableName, KNullDesC ); + if( !aDscStore.ItemExistsL( *item ) ) + { + aDscStore.AddItemL( *item ); + } + CleanupStack::PopAndDestroy( item ); + } + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::RemoveImportedResourceFiles() +// --------------------------------------------------------------------------- +// +void CStartupListUpdater::RemoveImportedResourceFiles( + RPointerArray& aResourceFileArray ) + { + for( TInt index = 0; index < aResourceFileArray.Count(); ++index ) + { + const TDesC& fileName = *( aResourceFileArray[ index ] ); + TInt err = iFs.Delete( fileName ); + if( err ) + { +#ifdef _DEBUG + RDebug::Print( _L("CStartupListUpdater: cannot delete %S, error %d"), + &fileName, err ); +#endif + } + } + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::AppendExecutablesFromResourceFileL() +// --------------------------------------------------------------------------- +// +void CStartupListUpdater::AppendExecutablesFromResourceFileL( + const TDesC& aResourceFile, + RPointerArray& aExecutableArray ) + { + RResourceFile resource; + CleanupClosePushL( resource ); + resource.OpenL( iFs, aResourceFile ); + + for( TInt id = KFirstStartupItemInfo; resource.OwnsResourceId( id ); ++id ) + { + HBufC8* buffer = resource.AllocReadLC( id ); + + TResourceReader reader; + reader.SetBuffer( buffer ); + + // Read STARTUP_ITEM_INFO + TInt versionInfo = reader.ReadUint8(); + TFileName executableName; + executableName.Copy( reader.ReadTPtrC() ); + TInt recoveryPolicy = reader.ReadUint16(); + + CleanupStack::PopAndDestroy( buffer ); + + if( versionInfo == 0 && recoveryPolicy == EStartupItemExPolicyNone ) + { + // PKG files use '!' for drive letters that user can decide at installation time + if( executableName.Length() > 0 && executableName[ 0 ] == '!' ) + { + executableName.Replace( 0, 1, KAsterisk ); + + TFindFile fileFinder( iFs ); + CDir* executableDir; // next FindWildByDir needs AllFiles capability + TInt err = fileFinder.FindWildByDir( executableName, KNullDesC, executableDir ); + if( !err ) + { + CleanupStack::PushL( executableDir ); + executableName.Replace( 0, 1, fileFinder.File() ); + CleanupStack::PopAndDestroy( executableDir ); + } + } + + if( IsValidExecutableForStartupL( aResourceFile, executableName ) ) + { + aExecutableArray.AppendL( executableName.AllocL() ); + } + } + } + + CleanupStack::PopAndDestroy( &resource ); + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::IsValidExecutableForStartupL() +// --------------------------------------------------------------------------- +// +TBool CStartupListUpdater::IsValidExecutableForStartupL( const TDesC& aResourceFile, + const TDesC& aExecutableName ) + { + TBool isValid = EFalse; + + TEntry entry; + if( iFs.Entry( aExecutableName, entry ) == KErrNone ) // needs AllFiles capability + { + isValid = ETrue; + + // Extract package UID from the resource file name + // - allow both "[1234ABCD]" and "1234ABCD" formats + // - allow possible "0x" prefix too + TUid packageUid = KNullUid; + TParsePtrC parse( aResourceFile ); + TPtrC parseName = parse.Name(); + TInt fileNameLength = parseName.Length(); + if( !parse.IsNameWild() && fileNameLength > 0 ) + { + TPtr fileName( const_cast( parseName.Ptr() ), + fileNameLength, fileNameLength ); + + if( fileName[ 0 ] == '[' && fileName[ fileNameLength - 1 ] == ']' ) + { + const TInt KTwoCharsLength = 2; + fileNameLength -= KTwoCharsLength; + fileName = fileName.Mid( 1, fileNameLength ); + } + + _LIT( KHexPrefix, "0x" ); + const TInt KHexPrefixLength = 2; + if( fileName.Left( KHexPrefixLength ) == KHexPrefix ) + { + fileNameLength -= KHexPrefixLength; + fileName = fileName.Mid( KHexPrefixLength, fileNameLength ); + } + + TLex lex( fileName ); + TUint32 uidValue = 0; + TInt lexError = lex.Val( uidValue, EHex ); + if( !lexError ) + { + packageUid.iUid = uidValue; + } + } + + // Get package info from RSisRegistry, and check that + // - the package contains the resource file + // - the package is properly signed + if( packageUid != KNullUid ) + { + Swi::RSisRegistrySession sisRegSession; + User::LeaveIfError( sisRegSession.Connect() ); + CleanupClosePushL( sisRegSession ); + + Swi::RSisRegistryEntry package; + CleanupClosePushL( package ); + TInt openError = package.Open( sisRegSession, packageUid ); + if( !openError ) + { + TBool hasResourceFile = EFalse; + + RPointerArray files; + CleanupResetAndDestroyPushL( files ); + package.FilesL( files ); + for( TInt index = 0; index < files.Count() && !hasResourceFile; ++index ) + { + hasResourceFile = ( aResourceFile.CompareF( *files[ index ] ) == 0 ); + } + + if( hasResourceFile && package.TrustStatusL().IsTrusted() ) + { + isValid = ETrue; + } + + CleanupStack::PopAndDestroy( &files ); + } + + CleanupStack::PopAndDestroy( 2, &sisRegSession ); // package, sisRegSession + } + } + + return isValid; + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::GetInstalledAppsL() +// --------------------------------------------------------------------------- +// +void CStartupListUpdater::GetInstalledAppsL( + RPointerArray& aInstalledExecutableArray ) + { + Swi::RSisRegistrySession sisRegistrySession; + User::LeaveIfError( sisRegistrySession.Connect() ); + CleanupClosePushL( sisRegistrySession ); + + RPointerArray removablePackages; + CleanupResetAndDestroyPushL( removablePackages ); + sisRegistrySession.RemovablePackagesL( removablePackages ); + + for( TInt index = 0; index < removablePackages.Count(); ++index ) + { + Swi::RSisRegistryEntry entry; + CleanupClosePushL( entry ); + entry.OpenL( sisRegistrySession, *( removablePackages[ index ] ) ); + if( entry.RemovableL() ) + { + GetExecutablesFromEntryL( entry, aInstalledExecutableArray ); + } + CleanupStack::PopAndDestroy( &entry ); + } + + CleanupStack::PopAndDestroy( 2, &sisRegistrySession ); + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::GetStartupListAppsL() +// --------------------------------------------------------------------------- +// +void CStartupListUpdater::GetStartupListAppsL( RDscStore& aDscStore, + RPointerArray& aStartedExecutableArray ) + { + aDscStore.EnumOpenLC(); + + while( CDscItem* item = aDscStore.EnumReadNextL() ) + { + CleanupStack::PushL( item ); + aStartedExecutableArray.AppendL( item->FileName().AllocL() ); + CleanupStack::PopAndDestroy( item ); + } + + CleanupStack::PopAndDestroy(); // runs EnumClose + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::StartedButNotInstalledAppsL() +// --------------------------------------------------------------------------- +// +void CStartupListUpdater::StartedButNotInstalledAppsL( + RPointerArray& aStartedExecutableArray, // in + RPointerArray& aInstalledExecutableArray, // in + RPointerArray& aStartedButNotInstalledExecutableArray ) // out + { + aStartedButNotInstalledExecutableArray.ResetAndDestroy(); + + TIdentityRelation identityRelation( FileNamesEqual ); + for( TInt index = 0; index < aStartedExecutableArray.Count(); ++index ) + { + const HBufC* startedAppName = aStartedExecutableArray[ index ]; + if( aInstalledExecutableArray.Find( startedAppName, identityRelation ) == KErrNotFound ) + { + aStartedButNotInstalledExecutableArray.AppendL( startedAppName->AllocL() ); + } + } + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::RemoveFromStartupListL() +// --------------------------------------------------------------------------- +// +void CStartupListUpdater::RemoveFromStartupListL( RDscStore& aDscStore, + RPointerArray& aExecutableArray ) + { + for( TInt index = 0; index < aExecutableArray.Count(); ++index ) + { + const TDesC& executableName = *( aExecutableArray[ index ] ); + CDscItem* item = CDscItem::NewLC( executableName, KNullDesC ); + if( aDscStore.ItemExistsL( *item ) ) + { + aDscStore.DeleteItemL( *item ); + } + CleanupStack::PopAndDestroy( item ); + } + } + +// --------------------------------------------------------------------------- +// CStartupListUpdater::GetExecutablesFromEntryL() +// --------------------------------------------------------------------------- +// +void CStartupListUpdater::GetExecutablesFromEntryL( Swi::RSisRegistryEntry& aEntry, + RPointerArray& aExecutableArray ) + { + RPointerArray filesList; + CleanupResetAndDestroyPushL( filesList ); + aEntry.FilesL( filesList ); + + for( TInt index = 0; index < filesList.Count(); ++index ) + { + TParse parse; + TInt err = parse.SetNoWild( KNullDesC, filesList[ index ], NULL ); + if( !err && ( parse.Ext().CompareF( KExecutableExtension ) == 0 ) ) + { + aExecutableArray.AppendL( parse.FullName().AllocL() ); + } + } + + CleanupStack::PopAndDestroy( &filesList ); + } +