--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/installationservices/swi/source/swis/server/installmachine.cpp Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,1984 @@
+/*
+* Copyright (c) 2004-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:
+*
+*/
+
+
+#define __INCLUDE_CAPABILITY_NAMES__
+#include <s32mem.h>
+#include "installmachine.h"
+#include "plan.h"
+#include "dessisdataprovider.h"
+#include "siscontroller.h"
+#include "siscertificatechain.h"
+#include "sisinstallerrors.h"
+#include "siscontentprovider.h"
+#include "sisinstallblock.h"
+#include "prerequisiteschecker.h"
+#include "postrequisiteschecker.h"
+#include "installationplanner.h"
+#include "log.h"
+#include "cleanuputils.h"
+#include "sisfiledescription.h"
+#include "sisinfo.h"
+#include "sisuid.h"
+#include "siscapabilities.h"
+#include "securitypolicy.h"
+#include "swispubsubdefs.h"
+#include "installationprocessor.h"
+#include "swi/launcher.h"
+#include "certchainconstraints.h"
+#include "swi/sistruststatus.h"
+#include <pkixcertchain.h>
+#include <swicertstore.h>
+#include <sacls.h>
+#include <f32file.h>
+#include "securitycheckutil.h"
+#include "sisptrprovider.h"
+#include <e32capability.h>
+#include <ocsp.h>
+#include "secutils.h"
+#include "sislauncherclient.h"
+
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+#include "swi/sisversion.h"
+#include "swi/nativecomponentinfo.h"
+#include <usif/usifcommon.h>
+#include "scrdbconstants.h"
+#endif
+
+using namespace Swi;
+using namespace Swi::Sis;
+
+
+//
+// TInstallState
+//
+
+CInstallMachine::TInstallState::TInstallState(CInstallMachine& aInstallMachine)
+: iInstallMachine(aInstallMachine)
+ {
+ }
+
+//
+// TRegistrationState
+//
+
+CInstallMachine::TRegistrationState::TRegistrationState(
+ CInstallMachine& aInstallMachine)
+/**
+ Constructor.
+ */
+: CInstallMachine::TInstallState(aInstallMachine)
+ {
+ }
+
+void CInstallMachine::TRegistrationState::EnterL()
+/**
+ Send registration request to the SWI Observer and then activate the
+ installation machine.
+ */
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Entering Registration State"));
+ //connect to the SWI Observer
+ User::LeaveIfError(iInstallMachine.Observer().Connect());
+
+ //Register to the SWI Observer; which completes this request
+ //when the SWI Observer Processor is idle.
+ iInstallMachine.Observer().Register(iInstallMachine.iStatus);
+ iInstallMachine.SetActive();
+ }
+
+CInstallMachine::TState* CInstallMachine::TRegistrationState::CompleteL()
+/**
+ Obtains the log file handle and its name from the SWI Observer.
+ Adds the log file to the transaction.
+ */
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Registration State complete"));
+ RBuf logFileName;
+ logFileName.CreateL(KMaxFileName);
+ logFileName.CleanupClosePushL();
+
+ //Get created a log file and obtains its full name.
+ iInstallMachine.Observer().GetFileHandleL(logFileName);
+
+ //Add the log file the transaction
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ iInstallMachine.TransactionSession().RegisterNewL(logFileName);
+#else
+ iInstallMachine.IntegrityServicesL().AddL(logFileName);
+#endif
+
+ CleanupStack::PopAndDestroy(&logFileName);
+ // Get Controllers.
+ return static_cast<TState*>(&iInstallMachine.iGetControllerState);
+ }
+
+CInstallMachine::TState* CInstallMachine::TRegistrationState::ErrorL(TInt aCode)
+/**
+ If there is any error, closes the SWI Observer connection.
+ */
+ {
+ DEBUG_PRINTF2(_L8("Install Machine - Registration State failed with code '%d'"), aCode);
+ User::Leave(aCode);
+ return NULL;
+ }
+
+void CInstallMachine::TRegistrationState::Cancel()
+/**
+ Cancels the registration request.
+ */
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Registration State cancelled!"));
+ iInstallMachine.Observer().CancelRegistration();
+ }
+
+
+//
+// TGetControllerState
+//
+
+CInstallMachine::TGetControllerState::TGetControllerState(
+ CInstallMachine& aInstallMachine)
+: CInstallMachine::TInstallState(aInstallMachine)
+ {
+ }
+
+void CInstallMachine::TGetControllerState::EnterL()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Entering Get Controller state"));
+
+ if (iInstallMachine.iSecurityManager->SecurityPolicy().DrmEnabled())
+ {
+ iInstallMachine.iSisHelper.OpenDrmContentL(static_cast<ContentAccess::TIntent>(iInstallMachine.iSecurityManager->SecurityPolicy().DrmIntent()));
+ }
+
+ iInstallMachine.iControllerData=
+ iInstallMachine.iSisHelper.SisControllerLC();
+ CleanupStack::Pop();
+ DEBUG_PRINTF2(_L8("Retrieved controller size %d"), iInstallMachine.iControllerData->Size());
+
+ TPtrProvider provider(iInstallMachine.iControllerData->Des());
+
+ // Create controller
+ iInstallMachine.iController=Sis::CController::NewL(provider);
+
+ if(!iInstallMachine.iSecurityManager->SecurityPolicy().AllowPackagePropagate()
+ && iInstallMachine.iSisHelper.IsStubL())
+ {
+ // If it's a stub and our SWIPolicy AllowPackagePropagate
+ // flag is false we can only install if it's a
+ // preinstalled stub not a removable media stub
+ if(iInstallMachine.iController->Info().InstallType() != EInstPreInstalledApp
+ && iInstallMachine.iController->Info().InstallType() != EInstPreInstalledPatch)
+ {
+ // It is a removable media stub but our SWI policy forbids
+ // installation
+ User::Leave(KErrSecurityError);
+ }
+
+ }
+
+ // Create content provider which will be used everywhere for things like
+ // TAppInfo etc.
+ iInstallMachine.iContentProvider=
+ CContentProvider::NewL(*iInstallMachine.iController);
+
+ iInstallMachine.iCurrentContentProvider = iInstallMachine.iContentProvider;
+
+ // Create stuff for the installation planner to use later
+ iInstallMachine.iResult=CInstallationResult::NewL();
+ iInstallMachine.iPlanner=CInstallationPlanner::NewL(iInstallMachine.iSisHelper,iInstallMachine.UiHandler(),
+ *iInstallMachine.iCurrentContentProvider, *iInstallMachine.iResult);
+
+ iInstallMachine.iPlanner->SetDeviceSupportedLanguages(iInstallMachine.iDeviceSupportedLanguages);
+
+
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ // Check if the machine runs in info collection mode. If so, set the planner too in the same mode.
+ if (iInstallMachine.IsInInfoMode())
+ {
+ iInstallMachine.iPlanner->SetInInfoCollectionMode(ETrue);
+ }
+ #endif
+
+ iInstallMachine.CompleteSelf();
+ iInstallMachine.SetActive();
+ }
+
+CInstallMachine::TState* CInstallMachine::TGetControllerState::CompleteL()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Get Controller State complete"));
+ // Confirm installation with the user.
+ return static_cast<TState*>(&iInstallMachine.iConfirmationState);
+ }
+
+CInstallMachine::TState* CInstallMachine::TGetControllerState::ErrorL(
+ TInt aCode)
+ {
+ DEBUG_PRINTF2(_L8("Install Machine - Get Controller State failed with code '%d'"), aCode);
+ User::Leave(aCode);
+ return NULL;
+ }
+
+void CInstallMachine::TGetControllerState::Cancel()
+ {
+ }
+
+//
+// TConfirmationState
+//
+
+CInstallMachine::TConfirmationState::TConfirmationState(
+ CInstallMachine& aInstallMachine)
+: CInstallMachine::TInstallState(aInstallMachine)
+ {
+ }
+
+void CInstallMachine::TConfirmationState::EnterL()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Entering Confirmation State"));
+
+ TBool retval;
+
+ TAppInfo appInfo(
+ iInstallMachine.iCurrentContentProvider->DefaultLanguageAppInfoL());
+
+ RPointerArray<CX509Certificate> x509certs;
+ CleanupResetAndDestroyPushL(x509certs);
+ iInstallMachine.iSecurityManager->GetCertificatesFromControllerL(
+ *iInstallMachine.iController,x509certs);
+
+ RPointerArray<CCertificateInfo> certs;
+ CleanupResetAndDestroyPushL(certs);
+ CSecurityManager::FillCertInfoArrayL(x509certs,certs);
+
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ if (iInstallMachine.IsInInfoMode())
+ {
+ // If we operate in info mode, we just need the certs, no UI confirmation or logo will be displayed
+ CleanupStack::PopAndDestroy(2, &x509certs); // certs, x509certs
+
+ iInstallMachine.CompleteSelf();
+ iInstallMachine.SetActive();
+
+ iInstallMachine.iOperationConfirmed = ETrue;
+ return;
+ }
+ #endif
+
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+ CleanupClosePushL(fs);
+ User::LeaveIfError(fs.ShareProtected());
+
+ // Retrieve logo data which may not be present.
+ const CLogo* logo=iInstallMachine.iController->Logo();
+ if (logo)
+ {
+ const CFileDescription& fdesc(logo->FileDescription());
+
+ // Create a temporary file for the logo.
+
+ // Construct temporary file name for the logo.
+ TUint driveCh(RFs::GetSystemDriveChar());
+
+ TFileName logoFileName;
+ _LIT(KLogoFileNameFmt, "%c:\\sys\\install\\temp\\%08X-logo");
+ logoFileName.Format(KLogoFileNameFmt, driveCh,
+ iInstallMachine.iController->Info().Uid().Uid().iUid);
+
+ TInt err = fs.MkDirAll(logoFileName);
+ if (err!= KErrNone && err != KErrAlreadyExists)
+ User::LeaveIfError(err);
+
+ RFile logoFile;
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ iInstallMachine.TransactionSession().RegisterTemporaryL(logoFileName);
+#else
+ iInstallMachine.IntegrityServicesL().TemporaryL(logoFileName);
+#endif
+
+ User::LeaveIfError(logoFile.Replace(fs, logoFileName,
+ EFileStream|EFileWrite|EFileRead|EFileShareExclusive));
+ CleanupClosePushL(logoFile);
+
+ // Extract logo to a temporary file.
+ err=iInstallMachine.iSisHelper.ExtractFileL(fs, logoFile,
+ fdesc.Index(), iInstallMachine.iController->DataIndex(),
+ iInstallMachine.UiHandler());
+ User::LeaveIfError(err);
+ CleanupStack::PopAndDestroy(&logoFile);
+
+ // Reopen file for reading (the handle will have been closed
+ // by SISHelper).
+ User::LeaveIfError(logoFile.Open(fs, logoFileName,
+ EFileStream|EFileRead|EFileShareExclusive));
+ CleanupClosePushL(logoFile);
+ CDisplayInstall* cmd=CDisplayInstall::NewLC(appInfo, fs, &logoFile,
+ certs);
+ iInstallMachine.UiHandler().ExecuteL(*cmd);
+ retval=cmd->ReturnResult();
+ CleanupStack::PopAndDestroy(2, &logoFile); // logoFile, cmd
+
+ RLoader loader;
+ User::LeaveIfError(loader.Connect());
+ CleanupClosePushL(loader);
+
+ // Delete temporary logo file.
+ User::LeaveIfError(loader.Delete(logoFileName));
+
+ CleanupStack::PopAndDestroy(&loader);
+ }
+ else
+ {
+ CDisplayInstall* cmd=CDisplayInstall::NewLC(appInfo, fs, NULL, certs);
+ iInstallMachine.UiHandler().ExecuteL(*cmd);
+ retval=cmd->ReturnResult();
+ CleanupStack::PopAndDestroy(cmd);
+ }
+
+ CleanupStack::PopAndDestroy(3, &x509certs); // fs, certs, x509certs
+
+ // Check if the user cancelled installation.
+ if (!retval)
+ {
+ DEBUG_PRINTF(_L8("User canceled install at install dialog"));
+ User::Leave(KErrCancel);
+ }
+ iInstallMachine.CompleteSelf();
+ iInstallMachine.SetActive();
+
+ // user hasn't cancelled so mark the installation as confirmed. This
+ // will allow the registry cache to be regenerated further on during the
+ // installation process.
+ iInstallMachine.iOperationConfirmed = ETrue;
+ }
+
+CInstallMachine::TState* CInstallMachine::TConfirmationState::CompleteL()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Confirmation State complete"));
+ // Verify signature(s) if any.
+ return static_cast<TState*>(&iInstallMachine.iVerifyControllerState);
+ }
+
+CInstallMachine::TState* CInstallMachine::TConfirmationState::ErrorL(
+ TInt aCode)
+ {
+ DEBUG_PRINTF2(_L8("Install Machine - Confirmation State failed with code '%d'"), aCode);
+ User::Leave(aCode);
+ return NULL;
+ }
+
+void CInstallMachine::TConfirmationState::Cancel()
+ {
+ }
+
+//
+// TVerifyControllerState
+//
+
+CInstallMachine::TVerifyControllerState::TVerifyControllerState(
+ CInstallMachine& aInstallMachine)
+: CInstallMachine::TInstallState(aInstallMachine)
+ {
+ }
+
+// Verify signatures and cert chains using security manager
+void CInstallMachine::TVerifyControllerState::EnterL()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Entering Verify Controller State"));
+
+ // Clear any results from previous controllers
+ iInstallMachine.iSigValidationResult=EValidationSucceeded;
+ iInstallMachine.iPkixResults.ResetAndDestroy();
+ iInstallMachine.iCertificates.ResetAndDestroy();
+ iInstallMachine.iGrantableCapabilitySet.SetEmpty();
+ iInstallMachine.iSecurityManager->ResetValidCertChains();
+ iInstallMachine.iOcspOutcomes.ResetAndDestroy();
+ iInstallMachine.iCertInfos.ResetAndDestroy();
+
+ TInt64 dataOffset = iInstallMachine.CurrentController().DataOffset()-iInstallMachine.iController->DataOffset();
+
+ // Get current controller data.
+ TPtrC8 data(iInstallMachine.iControllerData->Mid(dataOffset));
+
+ // Verify certificate chains and prepare for OCSP.
+ iInstallMachine.iSecurityManager->VerifyControllerL(
+ data,
+ iInstallMachine.CurrentController(),
+ &iInstallMachine.iSigValidationResult,
+ iInstallMachine.iPkixResults,
+ iInstallMachine.iCertificates,
+ &iInstallMachine.iGrantableCapabilitySet,
+ iInstallMachine.iAllowUnsigned,
+ iInstallMachine.iEmbedded,
+ iInstallMachine.iStatus);
+
+ iInstallMachine.SetActive();
+ }
+
+// Handle signature and certificate validation errors
+CInstallMachine::TState* CInstallMachine::TVerifyControllerState::CompleteL()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Verify Controller State Complete"));
+
+ // Populate the cert info array in preparation for any
+ // dialogs we have to launch
+
+ CSecurityManager::FillCertInfoArrayL(iInstallMachine.iCertificates,
+ iInstallMachine.iCertInfos);
+
+ DEBUG_PRINTF2(_L8("Signature Validation Result is set to code %d"), iInstallMachine.iSigValidationResult);
+
+ // check what was the result of validation
+ switch (iInstallMachine.iSigValidationResult)
+ {
+ default:
+ // BC break, unknown validation code, abort
+ User::Leave(KErrNotSupported);
+ break;
+
+ case EValidationSucceeded:
+ // Chain was validated
+ // Increase the trust status of this install process
+ iInstallMachine.SetTrust(ESisPackageCertificateChainValidatedToTrustAnchor);
+ iInstallMachine.SetValidationStatus(EValidatedToAnchor);
+
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ // Alert only when machine not runs in info collection mode
+ if(iInstallMachine.IsInInfoMode())
+ break;
+ #endif
+ // Continue normally, display security warning dialog so that the
+ // UI gets certificate information.
+ // If the package is embedded, then skip notification to hide the embedding details from the user
+ if (!iInstallMachine.iEmbedded && !SecurityAlertL(ETrue))
+ User::Leave(KErrCancel); // User or UI cancelled installation.
+ break;
+
+ case ESignatureNotPresent:
+ // This is a special case because we need to look at the policy
+ // setting to determine if unsigned SIS files are allowed at all.
+ // Display security warning dialog.
+ {
+
+ iInstallMachine.SetTrust(ESisPackageUnsignedOrSelfSigned);
+ iInstallMachine.SetValidationStatus(EUnsigned);
+
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ // Alert only when machine not runs in info collection mode
+ if(iInstallMachine.IsInInfoMode())
+ break;
+ #endif
+
+ TBool cont = SecurityAlertL(iInstallMachine.iAllowUnsigned);
+ if (!cont || !iInstallMachine.iAllowUnsigned)
+ User::Leave(KErrSecurityError);
+
+ break;
+ }
+
+ case ESignatureSelfSigned:
+ iInstallMachine.SetTrust(ESisPackageCertificateChainNoTrustAnchor);
+ iInstallMachine.SetValidationStatus(EValidated);
+
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ // Alert only when machine not runs in info collection mode
+ if(iInstallMachine.IsInInfoMode())
+ break;
+ #endif
+ if (!SecurityAlertL(ETrue))
+ User::Leave(KErrCancel);
+ break;
+
+
+ case ECertificateValidationError:
+ case ENoCertificate:
+ case ENoCodeSigningExtension:
+ case ENoSupportedPolicyExtension:
+ {
+ // Unable to validate the chain
+ // We apply the same policy as per unsigned SIS files
+ iInstallMachine.SetTrust(ESisPackageValidationFailed);
+ iInstallMachine.SetValidationStatus(EInvalid);
+
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ // Alert only when machine not runs in info collection mode
+ if(iInstallMachine.IsInInfoMode())
+ break;
+ #endif
+
+ // uh-oh, not good, ask the user because these are not fatal
+ TBool cont = SecurityAlertL(iInstallMachine.iAllowUnsigned);
+ if (!cont || !iInstallMachine.iAllowUnsigned)
+ User::Leave(KErrSecurityError);
+
+ break;
+ }
+
+ case ESignatureCouldNotBeValidated:
+ case EMandatorySignatureMissing:
+ iInstallMachine.SetValidationStatus(EInvalid);
+ // we're in trouble, because these are fatal errors
+
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ // Alert only when machine not runs in info collection mode
+ if(iInstallMachine.IsInInfoMode())
+ break;
+ #endif
+
+ // coverity[unchecked_value]
+ SecurityAlertL(EFalse); // user cannot override the error
+ User::Leave(KErrSecurityError);
+
+ break;
+ }
+
+ // All subsequent controllers will be embedded controllers
+ iInstallMachine.iEmbedded = ETrue;
+
+
+ // Devcert warning
+ if (iInstallMachine.iSecurityManager->GetDevCertWarningState()==EFoundDevCerts
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ && !iInstallMachine.IsInInfoMode()
+ #endif
+ )
+ {
+ // Warn only when machine runs in normal mode.
+ TAppInfo appInfo(
+ iInstallMachine.iContentProvider->DefaultLanguageAppInfoL());
+
+ CHandleInstallEvent* cmd = CHandleInstallEvent::NewLC(appInfo, EEventDevCert, 0, KNullDesC);
+ iInstallMachine.UiHandler().ExecuteL(*cmd);
+ if (!cmd->ReturnResult())
+ {
+ User::Leave(KErrSecurityError);
+ }
+ CleanupStack::PopAndDestroy(cmd);
+
+ //Only warn once
+ iInstallMachine.iSecurityManager->SetDevCertWarningState(EDevCertsWarned);
+ }
+
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ // Forcibly skip the OCSP check and directly go to the prerequisites checking state when the
+ // machine runs in component information collection mode. OCSP would introduce latency which is not expected when retrieving component info
+ if(iInstallMachine.IsInInfoMode())
+ {
+ return static_cast<TState*>(&iInstallMachine.iCheckPrerequisitesState);
+ }
+ #endif
+
+ return static_cast<TState*>(&iInstallMachine.iOcspState);
+ }
+
+CInstallMachine::TState* CInstallMachine::TVerifyControllerState::ErrorL(
+ TInt aCode)
+ {
+ DEBUG_PRINTF2(_L8("Install Machine - Verify Controller State failed with code '%d'"), aCode);
+ User::Leave(aCode);
+ return NULL;
+ }
+
+void CInstallMachine::TVerifyControllerState::Cancel()
+ {
+ }
+
+TBool CInstallMachine::TVerifyControllerState::SecurityAlertL(
+ TBool aCanOverride)
+ {
+ TAppInfo appInfo(
+ iInstallMachine.iCurrentContentProvider->DefaultLanguageAppInfoL());
+
+ CDisplaySecurityWarning* cmd=CDisplaySecurityWarning::NewLC(appInfo,
+ iInstallMachine.iSigValidationResult, iInstallMachine.iPkixResults,
+ iInstallMachine.iCertInfos, aCanOverride);
+
+ iInstallMachine.UiHandler().ExecuteL(*cmd);
+ TBool retval=cmd->ReturnResult();
+ CleanupStack::PopAndDestroy(cmd);
+ return retval;
+ }
+
+//
+// TOcspState
+//
+
+CInstallMachine::TOcspState::TOcspState(
+ CInstallMachine& aInstallMachine)
+: CInstallMachine::TInstallState(aInstallMachine)
+, iNeedOcsp(ETrue)
+ {
+ }
+
+// Verify signatures and cert chains using security manager
+void CInstallMachine::TOcspState::EnterL()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Entering OCSP State"));
+
+ // Determine is the check is necessary.
+ iNeedOcsp = iInstallMachine.iInstallPrefs->PerformRevocationCheck() && iInstallMachine.iSecurityManager->SecurityPolicy().OcspEnabled();
+
+ if ((iInstallMachine.iCertificates.Count()) && iNeedOcsp)
+ {
+ // We haven't done the planning phase so we need to use the default
+ TAppInfo appInfo(iInstallMachine.iCurrentContentProvider->DefaultLanguageAppInfoL());
+
+ // Signal OCSP check starting
+ CHandleCancellableInstallEvent* cmd = CHandleCancellableInstallEvent::NewLC(appInfo, EEventOcspCheckStart, 0, KNullDesC);
+ iInstallMachine.UiHandler().ExecuteL(*cmd);
+ CleanupStack::PopAndDestroy(cmd);
+
+ // Start OCSP check.
+ TBuf8<256> ocspUri(iInstallMachine.iInstallPrefs->RevocationServerUri());
+ iInstallMachine.iSecurityManager->PerformOcspL(ocspUri, iInstallMachine.iIap,
+ &iInstallMachine.iOcspMsg,iInstallMachine.iOcspOutcomes,
+ iInstallMachine.iCertificates,iInstallMachine.iStatus);
+
+ TTime time;
+ time.UniversalTime();
+ TSisTrustStatus& trustStatus = iInstallMachine.iController->TrustStatus();
+ trustStatus.SetLastCheckDate(time);
+ }
+ else
+ {
+ iNeedOcsp = EFalse;
+ iInstallMachine.CompleteSelf();
+ }
+
+ iInstallMachine.SetActive();
+ }
+
+// Handle signature and certificate validation errors
+CInstallMachine::TState* CInstallMachine::TOcspState::CompleteL()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Completed OCSP State"));
+ DEBUG_PRINTF2(_L8("OCSP Overall Message: %d"), iInstallMachine.iOcspMsg);
+
+ TBool ocspError = EFalse;
+ for (TInt i = iInstallMachine.iOcspOutcomes.Count() - 1; i >= 0; i--)
+ {
+ DEBUG_PRINTF3(_L8("OCSP Result for chain %d - %d"), i, iInstallMachine.iOcspOutcomes[i]->iResult);
+
+ if (iInstallMachine.iOcspOutcomes[i]->iResult != OCSP::EGood)
+ {
+ ocspError = ETrue;
+ break;
+ }
+ }
+
+ TSisTrustStatus& trustStatus = iInstallMachine.iController->TrustStatus();
+
+ if (iNeedOcsp && !ocspError)
+ {
+ if (iInstallMachine.Trust() == ESisPackageCertificateChainValidatedToTrustAnchor)
+ {
+ iInstallMachine.SetTrust(ESisPackageChainValidatedToTrustAnchorAndOCSPValid);
+ }
+ iInstallMachine.SetRevocationStatus(EOcspGood);
+ trustStatus.SetResultDate(trustStatus.LastCheckDate());
+ }
+ else if (iNeedOcsp && ocspError)
+ {
+
+ // Regenerate cert info array since cert list may have been pruned before
+ // OCSP check.
+ iInstallMachine.iCertInfos.ResetAndDestroy();
+ CSecurityManager::FillCertInfoArrayL(iInstallMachine.iCertificates,
+ iInstallMachine.iCertInfos);
+
+
+ // If OcspMandatory() is ETrue, then all OCSP errors are fatal.
+ TBool fatalError=iInstallMachine.iSecurityManager->SecurityPolicy().OcspMandatory() ? ETrue : EFalse;
+ switch (iInstallMachine.iOcspMsg)
+ {
+ default:
+ // Unknown value, must be a BC break!
+ User::Leave(KErrNotSupported);
+ break;
+
+ case EResponseSignatureValidationFailure:
+ case EInvalidRevocationServerResponse:
+ case EInvalidCertificateStatusInformation:
+ iInstallMachine.SetRevocationStatus(EOcspTransient);
+ break;
+
+ case EInvalidRevocationServerUrl:
+ case EUnableToObtainCertificateStatus:
+ // Possibly transient error, may retry.
+ if (iInstallMachine.Trust() == ESisPackageCertificateChainValidatedToTrustAnchor)
+ {
+ iInstallMachine.SetTrust(ESisPackageChainValidatedToTrustAnchorOCSPTransientError);
+ }
+ iInstallMachine.SetRevocationStatus(EOcspTransient);
+ break;
+
+ case ECertificateStatusIsUnknown:
+ // Non-fatal permanent error, ask the user.
+ if (iInstallMachine.iSigValidationResult == ESignatureSelfSigned)
+ {
+ iInstallMachine.iOcspMsg = ECertificateStatusIsUnknownSelfSigned;
+ }
+ iInstallMachine.SetRevocationStatus(EOcspUnknown);
+ trustStatus.SetResultDate(trustStatus.LastCheckDate());
+ break;
+
+ case ECertificateStatusIsRevoked:
+ // Fatal security error, don't allow installation to proceed.
+ fatalError=ETrue;
+
+ // Install attempted with revoked certificate, reset trust
+ iInstallMachine.SetTrust(ESisPackageValidationFailed);
+ iInstallMachine.SetRevocationStatus(EOcspRevoked);
+ trustStatus.SetResultDate(trustStatus.LastCheckDate());
+ break;
+ }
+
+ // We haven't done the planning phase so we need to use the default
+ TAppInfo appInfo(iInstallMachine.iCurrentContentProvider->DefaultLanguageAppInfoL());
+
+
+ // Signal OCSP check complete
+ CHandleInstallEvent* cmd = CHandleInstallEvent::NewLC(appInfo, EEventOcspCheckEnd, 0, KNullDesC);
+ iInstallMachine.UiHandler().ExecuteL(*cmd);
+
+
+ if (!cmd->ReturnResult())
+ {
+ User::Leave(KErrCancel);
+ }
+ CleanupStack::PopAndDestroy(cmd);
+
+ // Display OCSP result dialog.
+ CDisplayOcspResult* dialogCmd=CDisplayOcspResult::NewLC(appInfo,
+ iInstallMachine.iOcspMsg,iInstallMachine.iOcspOutcomes,
+ iInstallMachine.iCertInfos,fatalError ? EFalse : ETrue);
+ iInstallMachine.UiHandler().ExecuteL(*dialogCmd);
+
+ if (fatalError || dialogCmd->ReturnResult()==EFalse)
+ {
+ User::Leave(KErrCancel);
+ }
+
+ CleanupStack::PopAndDestroy(dialogCmd);
+ } // else if (iNeedOcsp && ocspError)
+ else
+ {
+ iInstallMachine.SetRevocationStatus(EOcspNotPerformed);
+ }
+ // finished verifying the controller
+ return static_cast<TState*>(&iInstallMachine.iCheckPrerequisitesState);
+ }
+
+CInstallMachine::TState* CInstallMachine::TOcspState::ErrorL(
+ TInt aCode)
+ {
+ DEBUG_PRINTF2(_L8("Install Machine - OCSP State failed with code %d"), aCode);
+
+
+ //If the error code is -7603 (KErrNoCertificates), handle it by popping up a warning and asking the user whether
+ //he or she wants to continue. For any other error code leave the function.
+ if ((OCSP::KErrNoCertificates == aCode) && !iInstallMachine.iSecurityManager->SecurityPolicy().OcspMandatory())
+ {
+ TAppInfo appInfo(iInstallMachine.iCurrentContentProvider->DefaultLanguageAppInfoL());
+ CDisplayOcspResult* cmd=CDisplayOcspResult::NewLC(appInfo,
+ iInstallMachine.iOcspMsg, iInstallMachine.iOcspOutcomes,
+ iInstallMachine.iCertInfos, ETrue);
+
+ iInstallMachine.UiHandler().ExecuteL(*cmd);
+ TBool retval=cmd->ReturnResult();
+ CleanupStack::PopAndDestroy(cmd);
+ if (retval)
+ {
+ iInstallMachine.SetRevocationStatus(EOcspNotPerformed);
+ return static_cast<TState*>(&iInstallMachine.iCheckPrerequisitesState);
+ }
+ else
+ {
+ User::Leave(aCode);
+ return NULL;
+ }
+ }
+ else
+ {
+ User::Leave(aCode);
+ return NULL;
+ }
+ }
+
+void CInstallMachine::TOcspState::Cancel()
+ {
+ DEBUG_PRINTF(_L8("Cancelling OCSP check"));
+ iInstallMachine.iSecurityManager->Cancel();
+ }
+
+//
+// TCheckPrerequisitesState
+//
+
+CInstallMachine::TCheckPrerequisitesState::TCheckPrerequisitesState(
+ CInstallMachine& aInstallMachine)
+: CInstallMachine::TInstallState(aInstallMachine)
+ {
+ }
+
+void CInstallMachine::TCheckPrerequisitesState::EnterL()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Entering Prerequisites Check State"));
+
+ CPrerequisitesChecker* checker = CPrerequisitesChecker::NewLC(
+ iInstallMachine.UiHandler(), iInstallMachine.CurrentController(),
+ *iInstallMachine.iResult, *iInstallMachine.iCurrentContentProvider,
+ iInstallMachine.MainController());
+
+ checker->CheckPrerequisitesL();
+
+ CleanupStack::PopAndDestroy(checker);
+ iInstallMachine.CompleteSelf();
+ iInstallMachine.SetActive();
+ }
+
+CInstallMachine::TState* CInstallMachine::TCheckPrerequisitesState::CompleteL()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Completed Prerequisites Check State"));
+ return static_cast<TState*>(&iInstallMachine.iPlanInstallationState);
+ }
+
+CInstallMachine::TState* CInstallMachine::TCheckPrerequisitesState::ErrorL(
+ TInt aCode)
+ {
+ DEBUG_PRINTF2(_L8("Install Machine - Prerequisites Check State failed with code %d"), aCode);
+ User::Leave(aCode);
+ return NULL;
+ }
+
+void CInstallMachine::TCheckPrerequisitesState::Cancel()
+ {
+ }
+
+//
+// TPlanInstallationState
+//
+
+CInstallMachine::TPlanInstallationState::TPlanInstallationState(
+ CInstallMachine& aInstallMachine)
+: CInstallMachine::TInstallState(aInstallMachine)
+ {
+ }
+
+void CInstallMachine::TPlanInstallationState::EnterL()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Entering Installation Planning State"));
+
+ // The following function may leave either because of an error or because
+ // the user cancelled installation (a dialog), in which case it notifies
+ // the UI so that we don't need to display anything (cancellation is not an
+ // error). See RunError() for more details.
+
+ // used to store an array of file descriptions of the files that
+ // require capability checking
+ // This array does not OWN any of the pointers
+ RPointerArray<CFileDescription> filesToCapabilityCheck;
+ CleanupClosePushL(filesToCapabilityCheck);
+
+ // Do the planning for the controller we just validated
+ iInstallMachine.iPlanner->PlanCurrentControllerL(filesToCapabilityCheck);
+
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ // Get the Capabilities required by the executables in the given component and set it in current controller.
+ //Setting the HasExecutable flag in the current contoller if it
+ //contains any executable(.exe or .dll).
+ if (iInstallMachine.IsInInfoMode())
+ {
+ TCapabilitySet userGrantableCaps;
+ userGrantableCaps.SetEmpty();
+ iInstallMachine.GetRequestedCapabilities(userGrantableCaps, filesToCapabilityCheck);
+ iInstallMachine.SetUserGrantableCapabilities(userGrantableCaps);
+
+ Sis::CController& controller = const_cast <Sis::CController&>(iInstallMachine.iPlanner->CurrentController());
+ controller.SetHasExecutable(EFalse);
+ TInt noOfFiles = filesToCapabilityCheck.Count();
+ for(TInt i = 0 ; i < noOfFiles ; i++)
+ {
+ Swi::Sis::CFileDescription* fileDesc = filesToCapabilityCheck[i];
+ const Swi::Sis::CString& filePath = fileDesc->Target();
+ const TDesC& path = filePath.Data();
+ TInt pathLength = path.Length();
+ if(pathLength < 4)
+ continue;
+ const TPtrC& extension = path.Mid(pathLength-4,4);
+ TBuf16<5> extnInLowerCase = extension;
+ extnInLowerCase.LowerCase();
+ if(extnInLowerCase == _L(".exe") || extnInLowerCase == _L(".dll"))
+ {
+ controller.SetHasExecutable(ETrue);
+ break;
+ }
+ }
+ }
+
+ #endif
+
+ // Check capabilities and ask the user to grant them if some of the user
+ // capabilities are not signed for.
+ iInstallMachine.CheckAndGrantCapabilitiesL(filesToCapabilityCheck);
+
+ // Check if the Device ID is in the constraints.
+ iInstallMachine.CheckDeviceIdConstraintsL();
+
+ iInstallMachine.CompleteSelf();
+ iInstallMachine.SetActive();
+ CleanupStack::PopAndDestroy(&filesToCapabilityCheck);
+ }
+
+// The next state will be interfacing with STS
+CInstallMachine::TState* CInstallMachine::TPlanInstallationState::CompleteL()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Completed Installation Planning State"));
+ // find the next controller to validate, otherwise go on to next stage
+ if(!iInstallMachine.iPlanner->GetNextController())
+ {
+ DEBUG_PRINTF(_L8("Finished planning final controller"));
+
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ // If the machine runs in component information extraction mode,
+ // All the needed info would have been available by this point.
+ // So, directly go to the final state and write the collected information back to the client.
+ if(iInstallMachine.IsInInfoMode())
+ {
+ return static_cast<TState*>(&iInstallMachine.iFinalState);
+ }
+ #endif
+
+ iInstallMachine.iPlanner->FinalisePlanL();
+
+ iInstallMachine.iPlan=iInstallMachine.iPlanner->TransferPlanOwnership(); // pass on ownership!
+ delete iInstallMachine.iPlanner;
+ iInstallMachine.iPlanner = NULL;
+ iInstallMachine.iSecurityManager->SetDevCertWarningState(ENoDevCerts);
+
+ if (iInstallMachine.iContentProvider != iInstallMachine.iCurrentContentProvider)
+ {
+ delete iInstallMachine.iCurrentContentProvider;
+ iInstallMachine.iCurrentContentProvider = iInstallMachine.iContentProvider;
+ }
+ return static_cast<TState*>(&iInstallMachine.iCheckPostrequisitesState);
+ }
+ else
+ {
+ if (iInstallMachine.iContentProvider != iInstallMachine.iCurrentContentProvider)
+ {
+ delete iInstallMachine.iCurrentContentProvider;
+
+ // In case NewL() in the following line leaves.
+ iInstallMachine.iCurrentContentProvider = NULL;
+ }
+
+ iInstallMachine.iCurrentContentProvider = CContentProvider::NewL(iInstallMachine.CurrentController());
+
+ return static_cast<TState*>(&iInstallMachine.iVerifyControllerState);
+ }
+ }
+
+CInstallMachine::TState* CInstallMachine::TPlanInstallationState::ErrorL(
+ TInt aCode)
+ {
+ DEBUG_PRINTF2(_L8("Install Machine - Planning Installation State failed with code %d"), aCode);
+ User::Leave(aCode);
+ return NULL;
+ }
+
+void CInstallMachine::TPlanInstallationState::Cancel()
+ {
+ }
+
+//
+// TCheckPostrequisitesState
+//
+
+CInstallMachine::TCheckPostrequisitesState::TCheckPostrequisitesState(CInstallMachine& aInstallMachine)
+: CInstallMachine::TInstallState(aInstallMachine)
+ {
+ }
+
+void CInstallMachine::TCheckPostrequisitesState::EnterL()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Entering Postrequisites Check State"));
+
+ CPostrequisitesChecker* checker =
+ CPostrequisitesChecker::NewLC(iInstallMachine.UiHandler(),
+ *iInstallMachine.iPlan,
+ *iInstallMachine.iResult,
+ *iInstallMachine.iCurrentContentProvider);
+
+ checker->CheckPostrequisitesL();
+
+ CleanupStack::PopAndDestroy(checker);
+ iInstallMachine.CompleteSelf();
+ iInstallMachine.SetActive();
+ }
+
+CInstallMachine::TState* CInstallMachine::TCheckPostrequisitesState::CompleteL()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Completed Postrequisites Check State"));
+ // Inform UI of final progress bar value.
+ iInstallMachine.SetProgressBarFinalValueL();
+ return static_cast<TState*>(&iInstallMachine.iIntegritySupportState);
+ }
+
+CInstallMachine::TState* CInstallMachine::TCheckPostrequisitesState::ErrorL(
+ TInt aCode)
+ {
+ DEBUG_PRINTF2(_L8("Install Machine - Postrequisites Check State failed with code %d"), aCode);
+ User::Leave(aCode);
+ return NULL;
+ }
+
+void CInstallMachine::TCheckPostrequisitesState::Cancel()
+ {
+ }
+
+//
+// TIntegritySupportState
+//
+
+CInstallMachine::TIntegritySupportState::TIntegritySupportState(
+ CInstallMachine& aInstallMachine)
+: CInstallMachine::TInstallState(aInstallMachine)
+ {
+ }
+
+void CInstallMachine::TIntegritySupportState::EnterL()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Entering Integrity Support State"));
+
+ // delete some data that we don't need while doing this memory
+ // intensive operation.
+ delete iInstallMachine.iPlanner;
+ iInstallMachine.iPlanner = NULL;
+
+ // create an application processor
+ iInstallMachine.iProcessor = CInstallationProcessor::NewL(
+ *iInstallMachine.iPlan, *iInstallMachine.iSecurityManager,
+ iInstallMachine.iSisHelper, iInstallMachine.UiHandler(),
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ iInstallMachine.TransactionSession(), iInstallMachine.RegistryWrapper(),
+#else
+ iInstallMachine.IntegrityServicesL(),
+#endif
+ *iInstallMachine.iControllerData, iInstallMachine.Observer());
+
+ // execute the plan, install files, update registry, all in one step
+ iInstallMachine.iProcessor->ProcessPlanL(iInstallMachine.iStatus);
+ iInstallMachine.SetActive();
+ }
+
+CInstallMachine::TState* CInstallMachine::TIntegritySupportState::CompleteL()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Completed Integrity Support State"));
+ return static_cast<TState*>(&iInstallMachine.iFinalState);
+ }
+
+CInstallMachine::TState* CInstallMachine::TIntegritySupportState::ErrorL(
+ TInt aCode)
+ {
+ DEBUG_PRINTF2(_L8("Install Machine - Integrity Support State failed with code %d"), aCode);
+ User::Leave(aCode);
+ return NULL;
+ }
+
+void CInstallMachine::TIntegritySupportState::Cancel()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Cancelling Integrity Support State"));
+ if (iInstallMachine.iProcessor)
+ {
+ iInstallMachine.iProcessor->Cancel();
+ }
+ }
+
+//
+// TFinalState
+//
+
+CInstallMachine::TFinalState::TFinalState(
+ CInstallMachine& aInstallMachine)
+: CInstallMachine::TInstallState(aInstallMachine)
+ {
+ }
+
+void CInstallMachine::RunFileL(RSisLauncherSession& aLauncher, const TDesC& aFileName, const TDesC& aMimeType, Sis::TSISFileOperationOptions aFileOperationOption)
+ {
+ TBool wait = EFalse;
+ if (aFileOperationOption & Sis::EInstFileRunOptionWaitEnd)
+ {
+ // always wait for completion or timeout when uninstalling since
+ // cannot remove the file when it is in use!
+ wait = ETrue;
+ }
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+ CleanupClosePushL(fs);
+ User::LeaveIfError(fs.ShareProtected());
+
+ // Is the file an executable ?
+ TEntry entry;
+ User::LeaveIfError(fs.Entry(aFileName, entry));
+ if (entry.IsTypeValid() && SecUtils::IsExe(entry))
+ {
+ DEBUG_PRINTF2(_L("Install Machine - Running %S"),&aFileName);
+ aLauncher.RunExecutableL(aFileName, wait);
+ }
+ else
+ {
+ RFile file;
+ CleanupClosePushL(file);
+ if (aFileOperationOption & Sis::EInstFileRunOptionByMimeType)
+ {
+ DEBUG_PRINTF2(_L("Install Machine - Running via Mime %S"),&aFileName);
+ HBufC8* mimeType = HBufC8::NewLC(aMimeType.Length());
+ TPtr8 ptr = mimeType->Des();
+ ptr.Copy(aMimeType);
+ TRAPD(err, aLauncher.StartByMimeL(aFileName, *mimeType, wait));
+ if (err!=KErrNone)
+ {
+ User::LeaveIfError(file.Open(fs, aFileName, EFileShareExclusive|EFileWrite));
+ TRAP_IGNORE(aLauncher.StartByMimeL(file, *mimeType, wait));
+ }
+ CleanupStack::PopAndDestroy(mimeType);
+ }
+ else
+ {
+ DEBUG_PRINTF2(_L("Install Machine - Launching doc %S"),&aFileName);
+ TRAPD(err, aLauncher.StartDocumentL(aFileName, wait));
+ if (err!=KErrNone)
+ {
+ User::LeaveIfError(file.Open(fs, aFileName, EFileShareExclusive|EFileWrite));
+ TRAP_IGNORE(aLauncher.StartDocumentL(file, wait));
+ }
+ }
+ CleanupStack::PopAndDestroy(&file);
+ }
+ CleanupStack::PopAndDestroy(&fs);
+ }
+
+void CInstallMachine::PublishPropertiesL()
+ {
+ User::LeaveIfError(RProperty::Set(KUidSystemCategory, KUidSoftwareInstallKey, ESwisStatusSuccess | ESwisInstall));
+
+ // Store the top level controller's UID as the most recent successful installation
+ User::LeaveIfError(RProperty::Set(KUidSystemCategory, KUidSwiLatestInstallation, iController->Info().Uid().Uid().iUid));
+ }
+
+void CInstallMachine::PostJournalFinalizationL(TInt aError)
+ {
+ DEBUG_PRINTF(_L8("Install Machine - PostJournalFinalization"));
+
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ // Do nothing in info mode
+ if(IsInInfoMode())
+ {
+ return;
+ }
+#endif
+ if (!iPlan)
+ {
+ return;
+ }
+ const RPointerArray<CSisRegistryFileDescription>& filesToRun = iPlan->FilesToRunAfterInstall();
+
+ TInt numFiles = filesToRun.Count();
+
+ if (aError != KErrNone || numFiles <= 0)
+ {
+ return;
+ }
+
+ // Check the top level application, if it's not trusted and the policy says no
+ // then don't run anything.
+ CSecurityPolicy* secPolicy = CSecurityPolicy::GetSecurityPolicyL();
+ if (!secPolicy->AllowRunOnInstallUninstall() &&
+ iPlan->ApplicationL().ControllerL().TrustStatus().ValidationStatus() < EValidatedToAnchor)
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Toplevel controller is untrusted, not running files after install"));
+ return;
+ }
+
+ DEBUG_PRINTF(_L8("Install Machine - Processing files to run after install"));
+ RSisLauncherSession launcher;
+
+ if (launcher.Connect() != KErrNone)
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Failed to connect to SisLauncher, continuing..."));
+ return;
+ }
+ CleanupClosePushL(launcher);
+ launcher.NotifyNewAppsL(iPlan->AppArcRegFiles());
+
+ if (iPlan->ContainsPlugins())
+
+ {
+ // set the "I'm done" propererty AFTER running ECOM reliant files.
+ launcher.RunAfterEcomNotificationL(filesToRun);
+ RProperty::Set(KUidSystemCategory, KUidSoftwareInstallKey, ESwisNone);
+ }
+ else
+ {
+ // set the "I'm done" propererty before running non-ECOM reliant files.
+ RProperty::Set(KUidSystemCategory, KUidSoftwareInstallKey, ESwisNone);
+ for (int i = 0; i < numFiles; ++i)
+ {
+ CSisRegistryFileDescription* file = filesToRun[i];
+ RunFileL(launcher,file->Target(),file->MimeType(),file->OperationOptions());
+ }
+ }
+ CleanupStack::PopAndDestroy(&launcher);
+ }
+
+ void CInstallMachine::TFinalState::EnterL()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Entering Final State"));
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ // If the machine runs in component information extraction mode,
+ // All the needed info would have been available by this point.
+ // So, call the method to populate the details back to the given structure
+ // and go to the final state of the machine.
+ if(iInstallMachine.IsInInfoMode())
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Returning component info"));
+ // Call in to populate the native component info in to the given structure.
+ PopulateNativeComponentInfoL(iInstallMachine.MainController(), iInstallMachine.iNativeComponentInfo);
+
+ // Write the component information collected back in to the buffer passed in.
+ SendBackComponentInfoL();
+ }
+ else
+ #endif
+ {
+ iInstallMachine.PublishPropertiesL();
+
+ if (iInstallMachine.iSecurityManager->SecurityPolicy().DrmEnabled())
+ {
+ DEBUG_PRINTF(_L8("Attempting to access (possibly) DRM'd SIS file via CAF"));
+ iInstallMachine.iSisHelper.ExecuteDrmIntentL(static_cast<ContentAccess::TIntent>(iInstallMachine.iSecurityManager->SecurityPolicy().DrmIntent()));
+ }
+ }
+
+ iInstallMachine.CompleteSelf();
+ iInstallMachine.SetActive();
+ }
+
+CInstallMachine::TState* CInstallMachine::TFinalState::CompleteL()
+ {
+ DEBUG_PRINTF(_L8("Install Machine - Completed Final State"));
+ return NULL;
+ }
+
+CInstallMachine::TState* CInstallMachine::TFinalState::ErrorL(
+ TInt aCode)
+ {
+ DEBUG_PRINTF2(_L8("Install Machine - Final State failed with code %d"), aCode);
+ User::Leave(aCode);
+ return NULL;
+ }
+
+void CInstallMachine::TFinalState::Cancel()
+ {
+ }
+
+//
+// TControllerInfo
+//
+
+CInstallMachine::TControllerInfo::TControllerInfo(
+ const CController& aController, TInt64 aDataOffset)
+ : iController(aController), iDataOffset(aDataOffset)
+ {
+ }
+
+const CController& CInstallMachine::TControllerInfo::Controller() const
+ {
+ return iController;
+ }
+
+TInt64 CInstallMachine::TControllerInfo::DataOffset() const
+ {
+ return iDataOffset;
+ }
+
+//
+// CInstallMachine
+//
+
+CInstallMachine* CInstallMachine::NewLC(const RMessage2& aMessage)
+ {
+ CInstallMachine* self=new(ELeave) CInstallMachine(aMessage);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+CInstallMachine* CInstallMachine::NewLC(const RMessage2& aMessage, const TBool aInInfoMode)
+ {
+ CInstallMachine* self=new(ELeave) CInstallMachine(aMessage, aInInfoMode);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+#endif
+
+CInstallMachine* CInstallMachine::NewL(const RMessage2& aMessage)
+ {
+ CInstallMachine* self=NewLC(aMessage);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+CInstallMachine* CInstallMachine::NewL(const RMessage2& aMessage,const TBool aInInfoMode)
+ {
+ CInstallMachine* self=NewLC(aMessage, aInInfoMode);
+ CleanupStack::Pop(self);
+ return self;
+ }
+#endif
+
+void CInstallMachine::ConstructL()
+ {
+ DEBUG_PRINTF(_L8("Constructing new Install Machine"));
+
+ // connect to SIS helper before we start a transaction with transaction server
+ // so that long running rollbacks don't cause install to fail
+ User::LeaveIfError(iSisHelper.Connect());
+
+ // Construct base class ( transaction)
+ CSwisStateMachine::ConstructL();
+
+ // Read install preferences from the stream (they are passed in the
+ // message's parameter 0)
+ TInt len=Message().GetDesLengthL(0);
+ HBufC8* buf=HBufC8::NewMaxLC(len);
+ TPtr8 p=buf->Des();
+ Message().ReadL(0,p);
+ RMemReadStream is;
+ is.Open(p.Ptr(),len);
+ CleanupClosePushL(is);
+ iInstallPrefs=CInstallPrefs::NewL(is);
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ if(!IsInInfoMode())
+ {
+ #endif
+ TInt deviceLanguageCount = is.ReadInt32L();
+ for(TInt i=0;i<deviceLanguageCount;i++)
+ {
+ iDeviceSupportedLanguages.AppendL(is.ReadInt32L());
+ DEBUG_PRINTF2(_L8("Language id that device supports = %d"), iDeviceSupportedLanguages[i]);
+ }
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ }
+ iNativeComponentInfo = CNativeComponentInfo::NewL();
+ #endif
+
+ CleanupStack::PopAndDestroy(2,buf); // is, buf
+
+ // Create security manager here because we'll need its functionality very
+ // early to display certificates to the user in the Install dialog (see
+ // TConfirmationState::EnterL()).
+ iSecurityManager=CSecurityManager::NewL();
+ }
+
+// Constructor, sets this pointer into the state objects
+CInstallMachine::CInstallMachine(const RMessage2& aMessage)
+: CSwisStateMachine(aMessage),
+ iRegistrationState(*this),
+ iGetControllerState(*this),
+ iConfirmationState(*this),
+ iVerifyControllerState(*this),
+ iOcspState(*this),
+ iCheckPrerequisitesState(*this),
+ iPlanInstallationState(*this),
+ iCheckPostrequisitesState(*this),
+ iIntegritySupportState(*this),
+ iFinalState(*this),
+ iSigValidationResult(EValidationSucceeded),
+ iEmbedded(EFalse)
+ {
+ }
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+CInstallMachine::CInstallMachine(const RMessage2& aMessage,const TBool aInInfoMode)
+: CSwisStateMachine(aMessage, aInInfoMode),
+ iRegistrationState(*this),
+ iGetControllerState(*this),
+ iConfirmationState(*this),
+ iVerifyControllerState(*this),
+ iOcspState(*this),
+ iCheckPrerequisitesState(*this),
+ iPlanInstallationState(*this),
+ iCheckPostrequisitesState(*this),
+ iIntegritySupportState(*this),
+ iFinalState(*this),
+ iSigValidationResult(EValidationSucceeded),
+ iEmbedded(EFalse)
+ {
+
+ }
+#endif
+// Connects to UISS and SISHelper server
+TInt CInstallMachine::Start()
+ {
+ DEBUG_PRINTF(_L8("Starting Install"));
+ return CSwisStateMachine::Start();
+ }
+
+// Delete objects, close connection to the servers
+CInstallMachine::~CInstallMachine()
+ {
+ DEBUG_PRINTF(_L8("Destroying Install Machine"));
+
+ if (iCurrentContentProvider != iContentProvider)
+ {
+ delete iCurrentContentProvider;
+ }
+
+ delete iInstallPrefs;
+ delete iControllerData;
+ delete iController;
+ delete iContentProvider;
+ delete iPlan;
+ delete iResult;
+ delete iProcessor;
+ delete iSecurityManager;
+ iPkixResults.ResetAndDestroy();
+ iCertificates.ResetAndDestroy();
+ iCertInfos.ResetAndDestroy();
+ iOcspOutcomes.ResetAndDestroy();
+ iSisHelper.Close();
+ iDeviceSupportedLanguages.Close();
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ delete iNativeComponentInfo;
+ #endif
+ delete iPlanner;
+ }
+
+CInstallMachine::TState* CInstallMachine::FirstState()
+ {
+ return &iRegistrationState;
+ }
+
+// This is called from RunL() whenever a state leaves
+CInstallMachine::TState* CInstallMachine::ErrorOnStateEntryL(TInt aError)
+ {
+ return CurrentState()->ErrorL(aError);
+ }
+
+void CInstallMachine::GetRequestedCapabilities(TCapabilitySet& aRequestedCaps, RPointerArray<CFileDescription>& aFilesToCapabilityCheck)
+ {
+ // UserPromptService private directory
+ _LIT(KUpsPrivateDir, ":\\private\\10283558\\");
+
+ TInt numFiles = aFilesToCapabilityCheck.Count();
+ for (TInt i=0; i<numFiles; i++)
+ {
+ const CFileDescription* fd = aFilesToCapabilityCheck[i];
+ const CCapabilities* caps = fd->Capabilities();
+
+ // Prevent un-authorised modification to User Prompt Service Policy Files
+ if (fd->Target().Data().FindF(KUpsPrivateDir) != KErrNotFound)
+ {
+ DEBUG_PRINTF2(_L("Install Machine - Found %S: Appending AllFiles capability"), &fd->Target().Data());
+ aRequestedCaps.AddCapability(ECapabilityAllFiles);
+ }
+
+ if (!caps)
+ continue;
+
+ const TInt KCapSetSize=sizeof(TUint32); // size of a capability bit set
+ const TInt KCapSetSizeBits=8*KCapSetSize;
+ const TDesC8& rawCaps=caps->Data();
+ const TInt KNumCapSets=rawCaps.Size()/KCapSetSize;
+ for (TInt set=0; set<KNumCapSets; set++)
+ {
+ TUint32 capsValue=*(reinterpret_cast<const TUint32*>(rawCaps.Ptr())+set);
+ for (TInt capIndex=0; capIndex<KCapSetSizeBits; capIndex++)
+ {
+ if (capsValue & (0x1<<capIndex))
+ {
+ TCapability cap=static_cast<TCapability>(capIndex+set*KCapSetSizeBits);
+ aRequestedCaps.AddCapability(cap);
+ }
+ }
+ }
+ }
+ }
+
+// This is called from TVerifyControllerState::CompleteL()
+void CInstallMachine::CheckAndGrantCapabilitiesL(RPointerArray<CFileDescription>& aFilesToCapabilityCheck)
+ {
+ // The controller contains capabilities requested by all
+ // executables in it. Let's make a union of them all.
+ TCapabilitySet requestedCaps;
+ requestedCaps.SetEmpty();
+
+ // Get the set of capabilities required by the package.
+ GetRequestedCapabilities(requestedCaps, aFilesToCapabilityCheck);
+
+ //Get the CertChainConstraint instance built by the SecurityManager.
+ const CCertChainConstraints* certChainConstraints = CurrentController().CertChainConstraints();
+
+ //Get the capbibilies contrained from the CertChainConstraints
+ TCapabilitySet initCapConstraints=certChainConstraints->ValidCapabilities();
+ TCapabilitySet supportedCapabilitiesByBoth=initCapConstraints;
+
+ //build the capability constraints from the constrained capabilities and root capbilities
+ supportedCapabilitiesByBoth.Intersection(iGrantableCapabilitySet);
+
+ // We have a set of granted capabilities, which is the intersection of iCapabilitySet and
+ // Capbilities constraints(filled in the security manager).
+ // Let's see if that's enough for the files to be installed.
+ requestedCaps.Remove(supportedCapabilitiesByBoth);
+
+ // Remove capabilities granted by the loader i.e disabled capabilities
+ TCapabilitySet loaderGrantedCaps;
+ loaderGrantedCaps.SetDisabled();
+ requestedCaps.Remove(loaderGrantedCaps);
+
+ // Any capabilities left in requestedCaps after this are not signed for and not in the certs constraints.
+ // Check if any of them are system capabilities. If so, bail out.
+ TCapabilitySet requiredExtraSysCaps(requestedCaps);
+ SecurityCheckUtil::RemoveUserCaps(requiredExtraSysCaps, *iSecurityManager);
+ TAppInfo appInfo(iCurrentContentProvider->DefaultLanguageAppInfoL());
+
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ // Report the error to the user only when machine not runs in info collection mode
+ if(IsInInfoMode())
+ {
+ SetUserGrantableCapabilities(requestedCaps);
+ return;
+ }
+ #endif
+
+ if (SecurityCheckUtil::NotEmpty(requiredExtraSysCaps)||(SecurityCheckUtil::NotEmpty(requestedCaps) && EFalse==iSecurityManager->SecurityPolicy().AllowGrantUserCaps()))
+ {
+ // Report error to the user. Include the list of capabilities that are left in requestedCaps.
+ // Among these will be at least one cap that is not allowed. This is because
+ // - it is a system cap which hasn't been granted or
+ // - a user cap where granting of user caps during install is not allowed.
+
+ // Build requested capabilities string.
+ const TInt KMaxCapNameLength=32; // should be enough for one capability name and
+ // a space before the next capability name
+
+ HBufC* capsDisplayBuf=HBufC::NewLC(ECapability_Limit*KMaxCapNameLength);
+ TPtr p=capsDisplayBuf->Des();
+ _LIT(KSpace," ");
+
+ // Loop through the set of all possible capabilities. Check if each
+ // is in the requestedCaps set. If it is add the name of the
+ // capability to the string in the capsDisplayBuf
+ for (TInt cap=ECapabilityTCB; cap<ECapability_Limit; cap++)
+ {
+ if (requestedCaps.HasCapability(static_cast<TCapability>(cap)))
+ {
+ // Get the string name for the capability
+ const char* capName = CapabilityNames[cap];
+ while (*capName)
+ {
+ p.Append(*capName++);
+ }
+
+ // Add a space following each capability name in string
+ p.Append(KSpace);
+ }
+ }
+
+ // Report error to the user.
+ // Include the list of capability names
+ CDisplayError* cmd=
+ CDisplayError::NewLC(appInfo,EUiCapabilitiesCannotBeGranted,
+ *capsDisplayBuf);
+
+ UiHandler().ExecuteL(*cmd);
+ CleanupStack::PopAndDestroy(cmd);
+ CleanupStack::PopAndDestroy(capsDisplayBuf);
+ User::Leave(KErrSecurityError);
+ }
+ else if (SecurityCheckUtil::NotEmpty(requestedCaps)) //Required more user capabilities then
+ {
+ // User capabilities are supported by the CertChainConstraints, but not by root certificates.
+ if (initCapConstraints.HasCapabilities(requestedCaps))
+ {
+ // User capabilities only, ask the user to grant them
+ CDisplayGrantCapabilities* cmd=
+ CDisplayGrantCapabilities::NewLC(appInfo,requestedCaps);
+ UiHandler().ExecuteL(*cmd);
+ TBool result=cmd->ReturnResult();
+ CleanupStack::PopAndDestroy(cmd);
+ if (!result)
+ User::Leave(KErrSecurityError);
+ }
+ else
+ {
+ // User capabilities are not all supported by the CertChainConstraints.
+ CDisplayError* cmd=
+ CDisplayError::NewLC(appInfo,EUiConstraintsExceeded,
+ KNullDesC);
+ UiHandler().ExecuteL(*cmd);
+ CleanupStack::PopAndDestroy(cmd);
+ User::Leave(KErrSecurityError);
+ }
+ }
+ }
+
+void CInstallMachine::SignalCompletedL()
+ {
+ HandleInstallationEventL(iPlan, EEventCompletedInstall);
+ }
+
+void CInstallMachine::SetTrust(TSisPackageTrust aTrust)
+ {
+ DEBUG_PRINTF2(_L8("Package Trust Status set to %d"), aTrust);
+
+ // create a modifyable reference to the current controller
+ CController& controller = const_cast <CController&>
+ (CurrentController());
+
+ // set the trust
+ controller.SetTrust(aTrust);
+ }
+
+TSisPackageTrust CInstallMachine::Trust()
+ {
+
+ CController& controller = const_cast <CController&>
+ (CurrentController());
+ return controller.Trust();
+
+ }
+
+void CInstallMachine::SetValidationStatus(TValidationStatus status)
+ {
+ // set the validation status
+ CurrentController().TrustStatus().SetValidationStatus(status);
+ }
+
+void CInstallMachine::SetRevocationStatus(TRevocationStatus status)
+ {
+ // set the revocation status
+ CurrentController().TrustStatus().SetRevocationStatus(status);
+ }
+
+void CInstallMachine::CheckDeviceIdConstraintsL()
+ {
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ // Report the error to the user only when machine not runs in info collection mode
+ if(IsInInfoMode())
+ return;
+ #endif
+
+ const CCertChainConstraints* certChainConstraints = CurrentController().CertChainConstraints();
+
+ const RPointerArray<HBufC>& deviceIDs=iSecurityManager->DeviceIDsInfo();
+ TRAPD(err, SecurityCheckUtil::CheckDeviceIdConstraintsL(certChainConstraints, deviceIDs));
+
+ if (err)
+ {
+ TAppInfo appInfo(iCurrentContentProvider->DefaultLanguageAppInfoL());
+ CDisplayError* cmd=
+ CDisplayError::NewLC(appInfo,EUiConstraintsExceeded,
+ KNullDesC);
+ UiHandler().ExecuteL(*cmd);
+ CleanupStack::PopAndDestroy(cmd);
+ User::Leave(KErrSecurityError);
+ }
+ }
+
+const Sis::CController& CInstallMachine::CurrentController()
+ {
+ return iPlanner->CurrentController();
+ }
+
+const Sis::CController& CInstallMachine::MainController()
+ {
+ return iPlanner->MainController();
+ }
+
+void CInstallMachine::SetProgressBarFinalValueL()
+ {
+ HandleInstallationEventL(iPlan, EEventSetProgressBarFinalValue, iPlan->FinalProgressBarValue());
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ SetFinalProgressBarValue(iPlan->FinalProgressBarValue());
+ #endif
+ }
+
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+// Populate the native component information.
+void CInstallMachine::TFinalState::PopulateNativeComponentInfoL(const CController& aController, CNativeComponentInfo* aNativeComponentInfo)
+ {
+ const Sis::CController& controller(aController);
+ const Sis::CInfo& controllerInfo(controller.Info());
+ const TDesC& componentName((controllerInfo.Names()[0])->Data());
+ // Set the Component Name attribute.
+ aNativeComponentInfo->iComponentName = HBufC::NewL(componentName.Length());
+ TPtr bufPtr(aNativeComponentInfo->iComponentName->Des());
+ bufPtr.Copy(componentName);
+
+ // Set the Component Version details.
+ TVersion version(controllerInfo.Version().Major(),
+ controllerInfo.Version().Minor(),
+ controllerInfo.Version().Build());
+ TBuf<KSmlBufferSize> versionBuf;
+ versionBuf.AppendFormat(KVersionFormat, version.iMajor, version.iMinor, version.iBuild);
+ aNativeComponentInfo->iVersion = HBufC::NewL(versionBuf.Length());
+ bufPtr.Set(aNativeComponentInfo->iVersion->Des());
+ bufPtr.Copy(versionBuf);
+
+ // Set the Vendor Name attribute
+ const TDesC& vendorName(controllerInfo.VendorNames()[0]->Data());
+ aNativeComponentInfo->iVendor = HBufC::NewL(vendorName.Length());
+ bufPtr.Set(aNativeComponentInfo->iVendor->Des());
+ bufPtr.Copy(vendorName);
+
+ // Set the gloabl component Id
+ aNativeComponentInfo->iGlobalComponentId = FormatGlobalIdLC(controllerInfo.Uid().Uid(), componentName, controllerInfo.InstallType());
+ // It's already a member of the class. So, don't keep it in the cleanup stack, pop it out.
+ CleanupStack::Pop(aNativeComponentInfo->iGlobalComponentId);
+
+ // Initially assume component is not installed (so, id is 0) and the scomo state to be deactivated
+ aNativeComponentInfo->iComponentId = 0;
+ aNativeComponentInfo->iScomoState = Usif::EDeactivated;
+
+ // Connect to the SCR.
+ Usif::RSoftwareComponentRegistry scrSession;
+ User::LeaveIfError(scrSession.Connect());
+ CleanupClosePushL(scrSession);
+
+ // Find and set the install status.
+ PopulateInstallStatusL(aController, scrSession, aNativeComponentInfo);
+
+ // Get the actual component ID and the SCOMO state if the component entry is found in the SCR
+ if ((aNativeComponentInfo->iInstallStatus == Usif::EUpgrade) ||
+ (aNativeComponentInfo->iInstallStatus == Usif::EAlreadyInstalled) ||
+ (aNativeComponentInfo->iInstallStatus == Usif::ENewerVersionAlreadyInstalled))
+ {
+ Usif::CComponentEntry* componentEntry = NULL;
+ // Get the component entry using the global Id and the software type.
+ TRAPD(err, componentEntry = scrSession.GetComponentL(*(aNativeComponentInfo->iGlobalComponentId), Usif::KSoftwareTypeNative));
+ if (err == KErrNone)
+ {
+ aNativeComponentInfo->iComponentId = componentEntry->ComponentId();
+ aNativeComponentInfo->iScomoState = static_cast<Usif::TScomoState>(componentEntry->ScomoState());
+ delete componentEntry;
+ }
+ }
+
+ CleanupStack::PopAndDestroy(&scrSession);
+
+ // Set the authenticity info based on the validation status.
+ if (controller.TrustStatus().ValidationStatus() >= EValidatedToAnchor)
+ {
+ aNativeComponentInfo->iAuthenticity = Usif::EAuthenticated;
+ }
+ else
+ {
+ aNativeComponentInfo->iAuthenticity = Usif::ENotAuthenticated;
+ }
+
+ // Set the user grantable capabilities
+ aNativeComponentInfo->iUserGrantableCaps = const_cast<CController&>(aController).UserGrantableCapabilities();
+
+ // Calculate the component size from the sontroller's file descriptions.
+ const RPointerArray<CFileDescription>& fileDescriptions = controller.InstallBlock().FileDescriptions();
+ for(TInt i = 0; i < fileDescriptions.Count(); i++)
+ {
+ aNativeComponentInfo->iMaxInstalledSize += fileDescriptions[i]->UncompressedLength();
+ }
+
+ //Setting the HasExecutable flag
+ aNativeComponentInfo->iHasExe = controller.HasExecutable();
+
+ const RPointerArray<CController>& embeddedControllers = aController.InstallBlock().EmbeddedControllers();
+ TInt totalEmbeddedControllers = embeddedControllers.Count();
+ for (TInt controller = 0; controller < totalEmbeddedControllers; controller++)
+ {
+ CNativeComponentInfo* infoNode = CNativeComponentInfo::NewLC();
+ PopulateNativeComponentInfoL(*embeddedControllers[controller], infoNode);
+ aNativeComponentInfo->iChildren.AppendL(infoNode);
+ CleanupStack::Pop(infoNode);
+ }
+ }
+
+// Populate the install state based on its earlier installation on the device.
+void CInstallMachine::TFinalState::PopulateInstallStatusL(const CController& aController, Usif::RSoftwareComponentRegistry& aScrSession, CNativeComponentInfo* aNativeComponentInfo)
+ {
+ const Sis::CInfo& controllerInfo(aController.Info());
+ const TDesC& componentName((controllerInfo.Names()[0])->Data());
+ const TDesC& uniqueVendorName(controllerInfo.UniqueVendorName().Data());
+ TInstallType installType = controllerInfo.InstallType();
+
+ // As PA and PP packages are not support for getting component info, we check for them here
+ __ASSERT_ALWAYS(installType != EInstPreInstalledApp && installType != EInstPreInstalledPatch, User::Leave(KErrNotSupported));
+
+ // Check to see if there is a package installed with this UID.
+ RSisRegistryWritableSession registrySession;
+ User::LeaveIfError(registrySession.Connect());
+ CleanupClosePushL(registrySession);
+
+ RSisRegistryWritableEntry registryEntry;
+ // Open the registry entry using the package name and vendor name.
+ TInt error = registryEntry.Open(registrySession, componentName, uniqueVendorName);
+ if (error != KErrNone && error != KErrNotFound)
+ User::Leave(error);
+ CleanupClosePushL(registryEntry);
+
+ TInt versionComparision = 0;
+
+ // Registry entry found
+ if (error == KErrNone)
+ {
+ // Take the versions of the installed package and the new package
+ TVersion regVer = registryEntry.VersionL();
+ TVersion newVer(controllerInfo.Version().Major(),
+ controllerInfo.Version().Minor(),
+ controllerInfo.Version().Build());
+
+ TBuf<KSmlBufferSize> regVersion;
+ TBuf<KSmlBufferSize> newVersion;
+ regVersion.AppendFormat(KVersionFormat, regVer.iMajor, regVer.iMinor, regVer.iBuild);
+ newVersion.AppendFormat(KVersionFormat, newVer.iMajor, newVer.iMinor, newVer.iBuild);
+
+ // Compare versions of the already installed package and the current package.
+ versionComparision = aScrSession.CompareVersionsL(regVersion, newVersion);
+
+ // If both the versions are equal, say that, the same package is installed already
+ if (versionComparision == 0)
+ {
+ aNativeComponentInfo->iInstallStatus = Usif::EAlreadyInstalled;
+ }
+ // If the version installed is higher than the current version, say that, higher version is already installed.
+ else if (versionComparision > 0)
+ {
+ aNativeComponentInfo->iInstallStatus = Usif::ENewerVersionAlreadyInstalled;
+ }
+ // If the version installed is lower than the current version, say that, this is an upgrade.
+ else // versionComparision < 0
+ {
+ aNativeComponentInfo->iInstallStatus = Usif::EUpgrade;
+ }
+ }
+ // If the registry entry is not found and the current package is a type
+ // of base (SA or PA) package, say that, it's a new installation.
+ else if (installType == EInstInstallation)
+ {
+ aNativeComponentInfo->iInstallStatus = Usif::ENewComponent;
+ }
+ // If the registry entry is not found and the current package is a type
+ // of partial upgrade (PU) package, say that, it's invalid because of the missing base.
+ else if (installType == EInstPartialUpgrade)
+ {
+ aNativeComponentInfo->iInstallStatus = Usif::EInvalid;
+ }
+ else if (installType == EInstAugmentation)
+ {
+ // Get the component entry from SCR using the base package's globalId (UID). If the entry exists, the base package is installed.
+ // So, say the current component will become a new component. If the entry is not found in SCR, the base package is not installed.
+ // So, say the current component will become invalid (as the base is missing).
+ Usif::CComponentEntry* componentEntry = NULL;
+ HBufC* globalId = FormatGlobalIdLC(controllerInfo.Uid().Uid(), componentName, EInstInstallation);
+ componentEntry = aScrSession.GetComponentL(*globalId, Usif::KSoftwareTypeNative);
+ if (componentEntry != NULL)
+ {
+ aNativeComponentInfo->iInstallStatus = Usif::ENewComponent;
+ }
+ else
+ {
+ aNativeComponentInfo->iInstallStatus = Usif::EInvalid;
+ }
+ CleanupStack::PopAndDestroy(globalId);
+ delete componentEntry;
+ }
+ CleanupStack::PopAndDestroy(2, ®istrySession);
+ }
+
+void CInstallMachine::TFinalState::SendBackComponentInfoL()
+ {
+ const static TInt KDefaultBufferSize = 2048;
+
+ TInt err = KErrNone;
+ TInt streamBufSize = KDefaultBufferSize;
+ CBufFlat* tempBuffer = NULL;
+ RBufWriteStream stream;
+ do
+ {
+ tempBuffer = CBufFlat::NewL(streamBufSize);
+ CleanupStack::PushL(tempBuffer);
+
+ stream.Open(*tempBuffer);
+ CleanupClosePushL(stream);
+
+ // Externalise the component info in to the stream
+ TRAP(err, iInstallMachine.iNativeComponentInfo->ExternalizeL(stream));
+ if (err == KErrOverflow)
+ {
+ // Release the last allocation and re allocate with one more fold
+ CleanupStack::PopAndDestroy(2, tempBuffer); // tempBuffer, stream
+ streamBufSize += KDefaultBufferSize;
+ }
+ } while(err == KErrOverflow);
+
+ stream.CommitL();
+
+ // Create an HBufC8 from the stream buf's length, and copy
+ // the stream buffer into this descriptor
+ HBufC8* buffer = HBufC8::NewLC(tempBuffer->Size());
+ TPtr8 ptr(buffer->Des());
+ tempBuffer->Read(0, ptr, tempBuffer->Size());
+
+ // Comp info buffer in the IPC args is in 2nd position. So, the index will be 1 (starts at 0).
+ TInt compInfoBufIndex = 1;
+ TInt argBufMaxLength = iInstallMachine.Message().GetDesMaxLengthL(compInfoBufIndex);
+ TInt localBufSize = buffer->Size();
+
+ // If the allocation is insufficient for sending back the data, send the Over-Flow message to the client.
+ // client will re-allocate the required amount of memory and will issue the request again.
+ if ( argBufMaxLength < localBufSize)
+ {
+ DEBUG_PRINTF3(_L8("Discovered overflow in component info buffer - needed %d but only %d was available"),
+ localBufSize, argBufMaxLength);
+ TPckgC<TInt> bufferSizePackage(localBufSize);
+ iInstallMachine.Message().WriteL(compInfoBufIndex, bufferSizePackage);
+ User::Leave(KErrOverflow);
+ }
+ // If the memory is sufficient, write the details back in to the client allocated memory.
+ else
+ {
+ iInstallMachine.Message().WriteL(compInfoBufIndex, *buffer);
+ }
+ CleanupStack::PopAndDestroy(3, tempBuffer); // tempBuffer, stream, buffer
+ }
+
+void CInstallMachine::SetUserGrantableCapabilities(TCapabilitySet aCapabilitySet)
+ {
+ DEBUG_PRINTF(_L8("Setting Package's User Granted Capabilities"));
+
+ // create a modifyable reference to the current controller
+ CController& controller = const_cast<CController&>(CurrentController());
+
+ // set the capabilities
+ controller.SetUserGrantableCapabilities(aCapabilitySet);
+ }
+#endif