/*
* Copyright (c) 2004-2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/


#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();
	
	}

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();
	// 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;	
	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());
	SetFinalProgressBarValue(iPlan->FinalProgressBarValue());
	}

#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, &registrySession);
	}

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
