appinstaller/AppinstUi/startuplistupdater/src/startuplistupdater.cpp
branchRCL_3
changeset 25 7333d7932ef7
--- /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 <featmgr.h>                    // FeatureManager
+#include <driveinfo.h>                  // DriveInfo
+#include <barsc.h>                      // RResourceFile
+#include <barsread.h>                   // TResourceReader
+#include <StartupItem.hrh>              // EStartupItemExPolicyNone
+#include <dscitem.h>                    // CDscItem
+#include <swi/sisregistrysession.h>     // Swi::RSisRegistrySession
+#include <swi/sisregistrypackage.h>     // Swi::CSisRegistryPackage
+#include <swi/sisregistryentry.h>       // Swi::RSisRegistryEntry
+#include <swi/sistruststatus.h>         // 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<HBufC> executableArray;
+    CleanupResetAndDestroyPushL( executableArray );
+    RPointerArray<HBufC> resourceFileArray;
+    CleanupResetAndDestroyPushL( resourceFileArray );
+
+    GetDataToBeImportedL( executableArray, resourceFileArray );
+    ImportExecutablesL( aDscStore, executableArray );
+    RemoveImportedResourceFiles( resourceFileArray );
+
+    CleanupStack::PopAndDestroy( 2, &executableArray );
+    }
+
+// ---------------------------------------------------------------------------
+// CStartupListUpdater::DeregisterUninstalledAppsL()
+// ---------------------------------------------------------------------------
+//
+void CStartupListUpdater::DeregisterUninstalledAppsL( RDscStore& aDscStore )
+    {
+    RPointerArray<HBufC> startedAtBootArray;
+    CleanupResetAndDestroyPushL( startedAtBootArray );
+    RPointerArray<HBufC> installedArray;
+    CleanupResetAndDestroyPushL( installedArray );
+    RPointerArray<HBufC> 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<HBufC>& aExecutableArray,
+        RPointerArray<HBufC>& 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<HBufC>& 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<HBufC>& 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<HBufC>& 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<TUint16*>( 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<HBufC> 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<HBufC>& aInstalledExecutableArray )
+    {
+    Swi::RSisRegistrySession sisRegistrySession;
+    User::LeaveIfError( sisRegistrySession.Connect() );
+    CleanupClosePushL( sisRegistrySession );
+
+    RPointerArray<Swi::CSisRegistryPackage> 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<HBufC>& 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<HBufC>& aStartedExecutableArray,                  // in
+        RPointerArray<HBufC>& aInstalledExecutableArray,                // in
+        RPointerArray<HBufC>& aStartedButNotInstalledExecutableArray )  // out
+    {
+    aStartedButNotInstalledExecutableArray.ResetAndDestroy();
+
+    TIdentityRelation<HBufC> 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<HBufC>& 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<HBufC>& aExecutableArray )
+    {
+    RPointerArray<HBufC> 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 );
+    }
+