installationservices/swi/source/swis/server/restorecontroller.cpp
changeset 0 ba25891c3a9e
child 25 7333d7932ef7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/installationservices/swi/source/swis/server/restorecontroller.cpp	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,892 @@
+/*
+* 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: 
+*
+*/
+
+
+#include <s32mem.h>
+
+
+#include "restorecontroller.h"
+
+#include "arrayutils.h"
+#include "sisinfo.h"
+#include "sisuid.h"
+#include "sisversion.h"
+#include "sissupportedlanguages.h"
+#include "sisinstallblock.h"
+#include "sishash.h"
+#include "userselections.h"
+#include "siselseif.h"
+#include "log.h"
+#include "securitycheckutil.h"
+#include "siscapabilities.h"
+#include "certchainconstraints.h"
+#include "sisregistryfiledescription.h"
+#include "sistruststatus.h"
+#include "secutils.h"
+
+#include <f32file.h>
+
+using namespace Swi;
+using namespace Swi::Sis;
+
+//
+// TRestoreFileInformation
+//
+
+TRestoreFileInformation::TRestoreFileInformation(CFileDescription& aFileDescription, CApplication& aParentApplication)
+	: iFileDescription(aFileDescription), 
+	iParentApplication(aParentApplication)	
+	{
+	}
+  
+
+//
+// CRestoreController
+// 
+   
+void CRestoreController::ConstructL(TDesC8& aController)
+	{				
+	iSystemDriveChar = RFs::GetSystemDriveChar();
+	
+	// Read the controllers from the buffer		
+	InternalizeControllersL(aController);
+	
+	//We also create a dummy plan for use when writing the 
+	//registry entries
+	TInt augmentationIndex(0);
+	TInt noOfMatchingLanguages = iMatchingSupportedLanguagesArray.Count();
+	TInt matchingLanguageCount = 0;
+	for (TInt i = 0; i < iControllers.Count(); i++)
+		{
+		
+		CPlan* plan = CPlan::NewL();
+		CleanupStack::PushL(plan);
+		User::LeaveIfError(iInstallPlans.Append(plan));
+		CleanupStack::Pop(plan);
+		
+		CApplication* application = CApplication::NewLC();
+		
+		CController* controller = iControllers[i];
+		
+		DEBUG_PRINTF3(_L8("Restore - Metadata controller %d is of type %d"),
+			i, controller->Info().InstallType());
+		
+ 		// Set the install type 		
+ 		switch (controller->Info().InstallType())
+ 			{
+ 		case EInstInstallation:
+ 			application->SetInstall(*controller);
+			application->UserSelections().SetDrive(iInstallDrive);		
+			
+			//if there are macthing languages then populate iMatchingDeviceLanguages array of application object
+			if ( noOfMatchingLanguages )
+				{
+				while( iMatchingSupportedLanguagesArray[matchingLanguageCount] != ELangNone)
+					{
+					application->PopulateMatchingDeviceLanguagesL(iMatchingSupportedLanguagesArray[matchingLanguageCount++]);
+					}
+				}
+ 			break;
+ 		
+ 		case EInstPartialUpgrade:
+ 			application->SetPartialUpgrade(*controller);
+			application->UserSelections().SetDrive(iInstallDrive);	
+			// Carry forwards the in-rom flag
+			if (i == 0 || iTopLevelApplications[0]->IsInROM()) 				
+				{
+				// If the first controller is a parial upgrade then 
+				// it must be a partial upgrade to a ROM stub.
+				// If there are multiple PUs then they must also be in-rom
+				application->SetInROM();
+				}
+	         if ( noOfMatchingLanguages )
+	                {
+	                TInt i = 0;
+	                while( iMatchingSupportedLanguagesArray[i] != ELangNone)
+	                    {
+	                    application->PopulateMatchingDeviceLanguagesL(iMatchingSupportedLanguagesArray[i++]);
+	                    }
+	                }
+ 			break;
+ 			
+		case EInstAugmentation:	
+			application->SetAugmentation(*controller);
+			application->UserSelections().SetDrive(iAugmentationDrives[augmentationIndex++]);
+			
+			//if there are macthing languages then populate iMatchingDeviceLanguages array of application object
+			if ( noOfMatchingLanguages )
+				{
+				while( iMatchingSupportedLanguagesArray[matchingLanguageCount] != ELangNone)
+					  {
+					   application->PopulateMatchingDeviceLanguagesL(iMatchingSupportedLanguagesArray[matchingLanguageCount++]);
+					  }
+				}
+			break;
+ 			
+ 		default:
+ 			User::Leave(KErrNotSupported);
+ 			break;
+ 			
+ 			}
+ 					
+		TPtrC8* buf = iControllerBinaries[i];
+		
+		application->SetController(*controller);
+		
+		CSisCertificateVerifier* verifier = CSisCertificateVerifier::NewLC(controller, *buf, iSecurityManager, application);
+		User::LeaveIfError(iVerifiers.Append(verifier));
+		CleanupStack::Pop(verifier);
+		
+		TInt languageIndex = SetApplicationLanguageL(*application);
+	
+		//This is the first controller, add it to the plan
+		User::LeaveIfError(iTopLevelApplications.Append(application));
+		plan->SetApplication(application); // ownership transferred.
+			
+		const CVersion& version = controller->Info().Version();
+		TVersion appVersion(version.Major(), version.Minor(), version.Build());
+			
+		plan->SetApplicationInformationL(controller->Info().Names()[languageIndex]->Data(),
+			controller->Info().VendorNames()[languageIndex]->Data(),
+			appVersion);	
+		
+		CleanupStack::Pop(application);			
+		}	
+	}
+	
+/**
+ Locates the relevant file description in the controller and adds the file
+ to be restored to the list of files for the new SIS registry object.
+ 
+ This also checks the hash of the file if needed and generates an appropriate temporary
+ filename to be used by integrity services.
+ 
+ @param		aFile				file handle to temporary restore file.
+ @param		aTempFileName		temporary filename to use with integrity services.
+ @param		aHashCheckRequried	whether the restore files hash must be checked against the controllers
+ */
+void CRestoreController::AddFileDescriptionL(RFile& aFile, TDesC& aTarget, TDes& aTempFilename, TBool aHashCheckRequired)
+  	{
+  	// Lookup file information and check the hash if needed  	
+  	TRestoreFileInformation info = LookupFileInformationL(aFile, aTarget, aHashCheckRequired);
+  	
+  	// Add the file description to the plan
+  	CApplication& application = info.ParentApplication();
+  	application.AddFileL(info.FileDescription(), application.UserSelections().Drive());
+  	
+  	// Construct the temporary file name for this file
+  	TParsePtrC parse(aTarget);  	
+  	_LIT(KTemporaryFileFormat, "%c:%Stfile-%d-%d-%d-");
+  	TUint driveCh(iSystemDriveChar);
+  	aTempFilename.Format(KTemporaryFileFormat, driveCh, &KSysInstallTempPath, 
+  		application.ControllerL().Info().Uid().Uid().iUid, application.AbsoluteDataIndex(), info.FileDescription().Index());
+  	 
+  	// Append a hex representation of a hash of the filename. We need the
+  	// temporary filename to be effectively unique, but the filename itself
+  	// may be too long.
+  	
+  	// Use the real target path (after path subsitution) minus the drive letter.
+  	HBufC* hashBuf = SecUtils::HexHashL(aTarget.Right(aTarget.Length() - 1));
+  	aTempFilename.Append(*hashBuf);
+  	delete hashBuf;
+  	
+  	// finally, remove this file from the list of files to add entries for
+  	for (TInt i = 0; i < iInstalledFiles.Count(); ++i)
+  		{  		
+  		HBufC* filename = iInstalledFiles[i];	
+  		if (aTarget.CompareF(*filename) == 0)
+  			{
+  			delete filename;
+  			iInstalledFiles.Remove(i);
+  			break;
+  			}  		
+  		}  	
+  	}
+  
+void CRestoreController::AddEmbeddedAppsAndFilesL()
+  	{
+	//for each application/controller pair, add fake file and embedded package descriptions
+	for (TInt i = 0; i < iTopLevelApplications.Count(); ++i)
+		{
+		DoAddEmbeddedAppsAndFilesL(iTopLevelApplications[i]->ControllerL().InstallBlock(), *iTopLevelApplications[i]); 
+		}
+	}
+
+// Preserves the links between embedded applications in the registry, so uninstalling the 
+// top level package will attempt to uninstall the packages below it in the tree
+// However, these applications are not processed as part of the restore 
+// hence they are entirely fake	
+
+void CRestoreController::DoAddEmbeddedAppsAndFilesL(
+	const CInstallBlock& aInstallBlock, CApplication& aApplication)
+	{
+	
+	const RPointerArray<CController>& controllers = aInstallBlock.EmbeddedControllers();
+
+  	TInt i;	
+	for (i = 0; i < controllers.Count(); ++i)
+		{
+		
+		CController* controller = controllers[i];
+		
+		CApplication* application = CApplication::NewLC();
+		application->SetController(*controller);
+		SetApplicationLanguageL(*application);
+		aApplication.AddEmbeddedApplicationL(application); // Ownership transfered
+		CleanupStack::Pop(application);
+		
+		}
+		
+  	const RPointerArray<CFileDescription>& fileDescriptions = aInstallBlock.FileDescriptions();
+  	TChar foldedDrive = aApplication.UserSelections().Drive();
+  	if (foldedDrive != 255)
+  		{
+  		foldedDrive.Fold();	// don't convert 'no drive selection' to the y drive 
+  		}
+  	
+  	for (i = 0; i < fileDescriptions.Count(); ++i)
+  		{
+  		const TDesC& description = fileDescriptions[i]->Target().Data();
+  		if (description.Length() != 0)
+  			{
+  			TChar sisDrive = description[0];
+  			if (sisDrive == '$')
+  				{
+  				sisDrive = iFs.GetSystemDriveChar();	
+  				}  			
+  			sisDrive.Fold();
+  			
+  			for (TInt j = 0; j < iInstalledFiles.Count(); j++)
+  				{
+  				HBufC* filename = iInstalledFiles[j];
+  				TChar targetDrive = (*filename)[0];
+  				targetDrive.Fold();
+  			
+				// if the file description matches this filename (taking into account drive letter)
+				// add it to the application.
+				// This may not be 100% the correct file description, but it will be close enough
+				if (description.Mid(1).CompareF(filename->Mid(1)) == 0 &&
+				    ((targetDrive == foldedDrive) || (targetDrive == sisDrive)))
+				       {
+				       aApplication.AddFileL(*fileDescriptions[i], aApplication.UserSelections().Drive());
+				       // Cut down the search space some
+				       delete filename;
+				       iInstalledFiles.Remove(j);
+				       break;
+				       }
+				}
+			}
+  		}
+  		
+	const RPointerArray<CIf>& ifBlocks = aInstallBlock.IfStatements();
+
+	for (i = 0; i < ifBlocks.Count(); ++i)
+		{
+		
+		CIf* ifBlock = ifBlocks[i];
+		DoAddEmbeddedAppsAndFilesL(ifBlock->InstallBlock(), aApplication);
+		
+		const RPointerArray<CElseIf>& elseBlocks = ifBlock->ElseIfs();
+		
+		for (TInt j = 0; j < elseBlocks.Count(); j++)
+			{
+			
+			CElseIf* elseBlock = elseBlocks[j];
+			DoAddEmbeddedAppsAndFilesL(elseBlock->InstallBlock(), aApplication);
+			
+			}
+		
+		}
+		
+	}	
+// Creates a TPtrC8* which points to the data of controllers stored in MetaData which was backedup.
+// Not using HBufC8::NewLC as it allocates memory afresh for the data.
+TPtrC8* CRestoreController::CreateRawControllerPtrLC(RDesReadStream& aStream, const TUint8* aBasePtr, TInt& aOffset )
+	{
+	TCardinality card;
+	aStream>>card;
+	TInt tmpLen = (TInt)card;
+	//Right shift TCardinality by one as its LSB is not
+	// used to represent the length of the descriptor
+	TInt len = ((TInt)card) >> 1;
+
+	//TCardinality uses 
+	// 1 Byte to store the length if it is between 0-127 
+	// 2 Bytes if length is between 128-16383
+	// 4 Bytes if length > 16383
+	
+	if ( tmpLen < 128 )
+		aOffset+=1;
+	else if ( tmpLen < 16384 )
+		aOffset+=2;
+	else
+		aOffset+=4;
+	
+	TPtrC8* controllerBuf = new (ELeave)TPtrC8(); 
+	controllerBuf->Set(aBasePtr+aOffset,len);
+	CleanupStack::PushL(controllerBuf);
+	
+	aOffset += len;
+	
+	while( len-- )
+		aStream.ReadInt8L();
+
+	return controllerBuf;
+	}
+
+void CRestoreController::InternalizeControllersL(TDesC8& aController)
+	{
+	
+	RDesReadStream stream(aController);
+	CleanupClosePushL(stream);
+	TInt offset = 0;
+	const TUint8* basePtr = aController.Ptr();
+	
+	// Drive letter to install to
+	iInstallDrive = TChar(stream.ReadUint32L());
+	offset+=4;
+	
+	// We need to count the augmentations to know how many selected drives to
+	// read after the list of files.
+	TInt augmentationsCount(0);
+
+	TInt controllerCount = stream.ReadInt32L();
+	DEBUG_PRINTF2(_L8("Restore - Metadata consists of %d seperate controllers"), 
+		controllerCount);
+	offset+=4;
+	
+	while (controllerCount--)
+		{
+		TPtrC8* controllerBuf = CreateRawControllerPtrLC(stream,basePtr,offset);
+		
+		User::LeaveIfError(iControllerBinaries.Append(controllerBuf));
+		CleanupStack::Pop(controllerBuf);
+		
+		// Create a CController object from the binary
+		
+		CDesDataProvider* provider = CDesDataProvider::NewLC(*controllerBuf);
+		CController* controller = CController::NewLC(*provider, EAssumeType);
+		User::LeaveIfError(iControllers.Append(controller));
+		CleanupStack::Pop(controller);
+		if (controller->Info().InstallType() == EInstAugmentation)
+			{
+			augmentationsCount++;
+			}
+		CleanupStack::PopAndDestroy(provider);
+		
+		}
+		
+  	// Trap this to make the metadata file format BC	
+  	TInt filesCount = 0;
+  	TRAPD(err, filesCount = stream.ReadInt32L());
+  	// If this is an old style backup metadata file, it won't include this section
+  	if (err == KErrNone)
+  		{
+  		while (filesCount--)
+  			{
+  			HBufC* filename = HBufC::NewLC(stream, KMaxTInt);
+  			User::LeaveIfError(iInstalledFiles.Append(filename));
+  			CleanupStack::Pop(filename);
+  			}
+
+ 		// Trap reading augmentations' selected drives, which appear after the
+ 		// file list in metadata files created after the fix for DEF087124.
+ 		// Leave if the read fails beyond the first augmentation, since we should
+ 		// have all or none.
+  		for (TInt i = 0; i < augmentationsCount; i++)
+			{
+			if (err == KErrNone)
+				{
+  				TChar selectedDrive(iInstallDrive);
+  				TRAP(err, selectedDrive = stream.ReadInt32L());
+  				if (i != 0)
+  					{
+  					User::LeaveIfError(err);
+  					}
+				iAugmentationDrives.AppendL(selectedDrive);
+				}
+			else
+				{
+				// If we failed on reading the first drive, fill the rest of
+				// the array with the selected drive for the base package.
+				iAugmentationDrives.AppendL(iInstallDrive);			
+				}
+			}
+  		}
+  		
+  		// Reading the array of matching device supported languages
+  		TRAP(err, InternalizeArrayL(iMatchingSupportedLanguagesArray,stream));
+
+	CleanupStack::PopAndDestroy(&stream);
+	}
+	
+		
+CRestoreController* CRestoreController::NewL(TDesC8& aController, CSecurityManager& aSecurityManager, RFs& aFs)
+	{
+	
+	CRestoreController* self = CRestoreController::NewLC(aController, aSecurityManager, aFs);
+	CleanupStack::Pop(self);
+	return self;
+	
+	}
+		
+CRestoreController* CRestoreController::NewLC(TDesC8& aController, CSecurityManager& aSecurityManager, RFs& aFs)
+	{
+	
+	CRestoreController* self = new (ELeave) CRestoreController(aSecurityManager, aFs);
+	CleanupStack::PushL(self);
+	self->ConstructL(aController);
+	return self;
+		
+	}
+		
+CRestoreController::CRestoreController(CSecurityManager& aSecurityManager, RFs& aFs)
+	: iFs(aFs), iSecurityManager(aSecurityManager)
+	{
+	}
+ /**
+  Finds the matching file description in the controller and checks the hash if required.
+  
+  @param		aFile				handle to the file to restore
+  @param 	aTarget				path that the file handle should be restored.
+  @param		aHashCheckRequired	if the target path is TCB protected and a hash check is required.
+  */
+ TRestoreFileInformation CRestoreController::LookupFileInformationL(RFile& aFile, TDesC& aTarget, TBool aHashCheckRequired)
+
+
+	{
+	CFileDescription* desc = NULL;
+	
+	// Search through the controllers backwards in case an executable has been ugpraded with 
+	// a partial upgrade
+	TBool foundMatch = EFalse;
+	TInt i = iControllers.Count() - 1;
+	CApplication* application = NULL;
+	while (i >= 0 && ! foundMatch)
+		{
+		CController* controller = iControllers[i];
+		application = iTopLevelApplications[i];
+		TChar drive = application->UserSelections().Drive();
+		desc = FindFileDescriptionL(controller->InstallBlock(), aFile, aTarget, aHashCheckRequired, drive);
+				
+		if (desc)
+			{
+			foundMatch = ETrue;
+			}
+		else
+			{
+			--i;	// Check the next controller
+			}
+		}
+		
+	if (aHashCheckRequired && ! foundMatch)
+		{
+		// Previously the code would return either KErrNotFound or KErrSISWouldOverWrite
+		// both of these errors are incorrect and SBE does not depend on the exact error code
+		// in this scenario.
+		// N.B. It is already possible for KErrSecurityError to be returned so the backup
+		// client MUST be able to handle this.
+		DEBUG_PRINTF2(_L("No matching hash for file %S"), &aTarget);
+		User::Leave(KErrSecurityError);
+		}
+	else if (! foundMatch)
+		{
+		// It's difficult to report VerifyOnRestore mis-matches as a security error because
+		// the file could be present in multiple controllers and in multiple install blocks
+		// with and without the VerifyOnRestore flag set
+		DEBUG_PRINTF2(_L("No match in controller for %S"), &aTarget);
+		User::Leave(KErrNotFound);
+		}
+	
+	// This is where things get really interesting ...
+	// The restore machine invokes a restore processor for each controller in turn
+	// and as well as checking the exe header the restore processor builds a list of SIDs
+	// as it goes.
+	// When the files are installed private directories are checked against the list of SIDs.
+	// BUT
+	// If the exe has been upgraded via a partial upgrade then the application pointer here will
+	// refer to the partial upgrade that hasn't been checked yet so the SID isn't known and the processor
+	// will reject the restore of files to that private dir.
+	// Reversing the order of processing the controllers doesn't help because if the exe
+	// hasn't been upgraded but the PU deploys a file to the exe's private dir then again the SID
+	// isn't known so the install will be rejected.
+	
+	// The work around is to associate all of the files supplied by SBE for PUs with
+	// the first application which will be the SA
+	// It's not safe blindly do this for all applications because this would incorrectly associate
+	// the augmenation's files with the SP
+	if (application->IsPartialUpgrade()) 
+		{
+		application = iTopLevelApplications[0];
+		}
+	TRestoreFileInformation result(*desc, *application);
+	return result;	
+	}
+	
+CFileDescription* CRestoreController::FindFileDescriptionL(
+		const CInstallBlock& aInstallBlock, RFile& aFile, TDesC& aTarget, TBool aHashCheckRequired, const TChar& aDrive)
+	{	
+	const RPointerArray<CFileDescription> descriptions = aInstallBlock.FileDescriptions();
+	CFileDescription* result = NULL;
+	
+	for (TInt j = 0; j < descriptions.Count(); j++)
+		{
+		CFileDescription* description = descriptions[j];		
+		const TDesC& descTarget = (description->Target()).Data();
+		
+		// We'll acknowledge that the file matches the description iff:
+		// a) The hashes match
+		// b) The targets match, taking into account wildcard drive letters
+		
+		// substitute the drive letter and replace any relevant paths
+		HBufC* transDest =
+			iSecurityManager.SecurityPolicy().ResolveTargetFileNameLC(descTarget, aDrive);
+		
+		// check if this file matches the file name		
+		TBool match = (transDest->Left(1).CompareF(aTarget.Left(1)) == 0)
+						&&(transDest->Mid(1) == aTarget.Mid(1));
+		
+		// if it does, do we also need to do as hash check to approve this file?						
+		if ((aHashCheckRequired || (description->OperationOptions() & EInstVerifyOnRestore)) && match)
+			{
+			// If the file is TCB protected OR the VerifyOnRestore flag is set the 
+			// a match is only valid if the hash also matches
+			const CHash& hash = description->Hash();
+			TSISHashAlgorithm algorithm = hash.Algorithm();			
+			CMessageDigest* temp = CalculateHashL(aFile, algorithm);
+			CleanupStack::PushL(temp);			
+			match = (temp->Final() == hash.Data());
+			DEBUG_PRINTF3(_L("Checking hash candiate for file %S pass = %d"), &aTarget, match);
+			CleanupStack::PopAndDestroy(temp);
+			}		
+		CleanupStack::PopAndDestroy(transDest);		
+		if (match)
+			{
+			return description;
+			}
+		}
+	
+	const RPointerArray<CIf>& ifBlocks = aInstallBlock.IfStatements();
+	for (TInt i = 0; i < ifBlocks.Count(); i++)
+		{		
+		CIf* ifBlock = ifBlocks[i];
+		if (NULL != (result = FindFileDescriptionL(ifBlock->InstallBlock(), aFile, aTarget, aHashCheckRequired, aDrive)))
+			{			
+			return result;			
+			}
+		
+		const RPointerArray<CElseIf>& elseBlocks = ifBlock->ElseIfs();		
+		for (TInt j = 0; j < elseBlocks.Count(); j++)
+			{			
+			CElseIf* elseBlock = elseBlocks[j];
+			if (NULL != (result = FindFileDescriptionL(elseBlock->InstallBlock(), aFile, aTarget, aHashCheckRequired, aDrive)))
+				{				
+				return result;			
+				}			
+			}		
+		}		
+	return result;	
+	}
+	
+		
+CMessageDigest* CRestoreController::CalculateHashL(RFile& aFile, TSISHashAlgorithm aAlgorithm)
+	{		
+	HBufC8* buf = HBufC8::NewLC(1024);
+	TPtr8 bufPtr(buf->Des());
+	TInt seekPos = 0;
+	aFile.Seek(ESeekStart, seekPos);	
+	CMessageDigest* digest = NULL;
+	
+	switch (aAlgorithm)
+		{		
+	case EHashAlgSHA1:
+		digest = CSHA1::NewL();
+		break;
+			
+	default:
+		User::Leave(KErrNotSupported);
+		break;		
+		}
+			
+	while (KErrNone == aFile.Read(bufPtr) && bufPtr.Length() != 0)
+		{			
+		digest->Update(bufPtr);		
+		}
+			
+	CleanupStack::PopAndDestroy(buf);			
+	return digest;				
+	}
+		
+TInt CRestoreController::SetApplicationLanguageL(CApplication& aApplication)
+	{
+	
+	// We set either the current locale if available, or the default
+	// language.
+	
+	TLanguage locale = User::Language();
+	const CSupportedLanguages& languages = aApplication.ControllerL().SupportedLanguages();
+	TInt langIndex = 0;
+	
+	for (TInt i = 0; i < languages.Count(); i++)
+		{
+		
+		if (locale == languages[i])
+			{
+			
+			langIndex = i;
+			break;
+			
+			}
+			
+		}
+		
+	aApplication.UserSelections().SetLanguage(languages[langIndex]);
+	return langIndex;
+	
+	}
+	
+	
+CRestoreController::~CRestoreController()
+	{
+		
+	iControllers.ResetAndDestroy();
+	iVerifiers.ResetAndDestroy();
+	iControllerBinaries.ResetAndDestroy(); 
+	iInstallPlans.ResetAndDestroy();
+	iTopLevelApplications.Reset(); // These pointers owned by the plan
+	iInstalledFiles.ResetAndDestroy();
+	iAugmentationDrives.Close();
+	iMatchingSupportedLanguagesArray.Close();
+	}
+		
+		
+//
+// CSisCertificateVerifier
+//
+
+		
+CRestoreController::CSisCertificateVerifier* CRestoreController::CSisCertificateVerifier::NewL(CController* aController, TDesC8& aControllerBinary, CSecurityManager& aSecurityManager, CApplication* aApplication)
+	{
+	
+	CSisCertificateVerifier* self = CSisCertificateVerifier::NewLC(aController, aControllerBinary, aSecurityManager, aApplication);
+	CleanupStack::Pop(self);
+	return self;
+	
+	}
+		
+CRestoreController::CSisCertificateVerifier* CRestoreController::CSisCertificateVerifier::NewLC(CController* aController, TDesC8& aControllerBinary, CSecurityManager& aSecurityManager, CApplication* aApplication)
+	{
+	
+	CSisCertificateVerifier* self = new (ELeave) CSisCertificateVerifier(aController, aSecurityManager, aApplication,aControllerBinary);
+	CleanupStack::PushL(self);
+	return self;
+		
+	}
+		
+CRestoreController::CSisCertificateVerifier::CSisCertificateVerifier(CController* aController, CSecurityManager& aSecurityManager, CApplication* aApplication, TDesC8& aControllerBinary)
+	: CActive(CActive::EPriorityStandard),
+	  iSecurityManager(aSecurityManager),
+	  iApplication(aApplication),iControllerBinary(aControllerBinary)
+	{
+	
+	iController = aController;
+	CActiveScheduler::Add(this);
+	
+	}
+		
+void CRestoreController::CSisCertificateVerifier::StartL(TRequestStatus& aStatus)
+	{
+	
+	iWatcherStatus = &aStatus;
+	aStatus = KRequestPending;
+	
+	TBool isEmbedded = ETrue;
+	
+	iSecurityManager.VerifyControllerL(
+		iControllerBinary, 
+		*iController,
+		&iResult,
+		iValidationResults, 
+		iCerts,
+		&iGrantableCapabilitySet,
+		iAllowUnsigned,
+		isEmbedded,
+		iStatus);
+	
+	SetActive();
+	
+	}
+		
+void CRestoreController::CSisCertificateVerifier::RunL()
+	{
+	DEBUG_PRINTF2(_L8("Restore - Controller verification complete, verification status was %d"),
+		iResult);
+	
+	TBool verified = EFalse;
+	switch (iResult)
+		{
+		default:
+			// BC break, unknown validation code, abort
+			User::Leave(KErrNotSupported);
+			break;
+		
+		case EValidationSucceeded:
+			// Chain was validated
+			// Increase the trust status of this install process			
+			iController->SetTrust(ESisPackageCertificateChainValidatedToTrustAnchor);
+			iController->TrustStatus().SetValidationStatus(EValidatedToAnchor);
+			verified = ETrue;
+			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.
+			iController->SetTrust(ESisPackageUnsignedOrSelfSigned);
+			iController->TrustStatus().SetValidationStatus(EUnsigned);
+ 			if (iAllowUnsigned)
+  				{
+  				verified = ETrue;
+  				}	
+			break;		
+		case ESignatureSelfSigned:	
+			iController->SetTrust(ESisPackageCertificateChainNoTrustAnchor);
+			iController->TrustStatus().SetValidationStatus(EValidated);
+			verified = ETrue;
+			break;					   
+		case ECertificateValidationError:
+		case ENoCertificate:
+		case ENoCodeSigningExtension:
+		case ENoSupportedPolicyExtension:
+			// Unable to validate the chain
+			// We apply the same policy as per unsigned SIS files
+			iController->SetTrust(ESisPackageValidationFailed);	
+			iController->TrustStatus().SetValidationStatus(EInvalid);
+			break;
+		case ESignatureCouldNotBeValidated:
+		case EMandatorySignatureMissing:
+			iController->TrustStatus().SetValidationStatus(EInvalid);
+			break;
+		}
+		
+	if (verified)
+		{
+		TRAPD(err, CheckDeviceIdConstraintsL();CheckCapabilitiesL());
+		if (err)
+			{
+			DEBUG_PRINTF(_L8("Restore - Device ID or Capability Check Failed"));
+			User::RequestComplete(iWatcherStatus, err);
+			}		
+		else
+			{
+			User::RequestComplete(iWatcherStatus, KErrNone);
+			}			
+		}
+	else
+		{
+		User::RequestComplete(iWatcherStatus, KErrCorrupt);				
+		}	
+	}
+	
+		
+void CRestoreController::CSisCertificateVerifier::DoCancel()
+	{
+	
+	iSecurityManager.Cancel();
+	
+	}
+	
+CRestoreController::CSisCertificateVerifier::~CSisCertificateVerifier()
+	{
+	
+	Cancel();
+	iValidationResults.ResetAndDestroy();
+	iCerts.ResetAndDestroy();
+			
+	}
+
+void CRestoreController::CSisCertificateVerifier::CheckDeviceIdConstraintsL()
+	{
+	const CCertChainConstraints* certChainConstraints = iController->CertChainConstraints();
+
+	const RPointerArray<HBufC>& deviceIDs=iSecurityManager.DeviceIDsInfo();
+	SecurityCheckUtil::CheckDeviceIdConstraintsL(certChainConstraints, deviceIDs);
+	}
+
+void CRestoreController::CSisCertificateVerifier::CheckCapabilitiesL()
+	{	
+	TCapabilitySet requestedCaps;
+	requestedCaps.SetEmpty();	
+	const RPointerArray<CSisRegistryFileDescription>& sidFdList=iApplication->FilesToAdd();
+	TInt count=sidFdList.Count();
+	for (TInt i=0; i<count; i++)
+		{
+		const HBufC8* rawFileHeaderCaps = sidFdList[i]->CapabilitiesData();
+		if	(rawFileHeaderCaps)
+			{
+			const TInt KCapSetSize=sizeof(TUint32); // size of a capability bit set
+			const TInt KCapSetSizeBits=8*KCapSetSize;
+			const TInt KNumCapSets=rawFileHeaderCaps->Size()/KCapSetSize;
+			for (TInt set=0; set<KNumCapSets; set++)
+				{
+				TUint32 capsValue=*(reinterpret_cast<const TUint32*>(rawFileHeaderCaps->Ptr())+set);
+				for (TInt capIndex=0; capIndex<KCapSetSizeBits; capIndex++)
+					{
+					if (capsValue & (0x1<<capIndex))
+						{
+						TCapability cap=static_cast<TCapability>(capIndex+set*KCapSetSizeBits);
+						requestedCaps.AddCapability(cap);
+						}
+					}
+				}		
+			}
+		}
+		
+	//Get the CertChainConstraint instance built by the SecurityManager.
+	const CCertChainConstraints* certChainConstraints = iController->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);
+	
+	// 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);	
+	if (SecurityCheckUtil::NotEmpty(requiredExtraSysCaps))
+		{
+		DEBUG_PRINTF(_L8("Restore - Controller requires more system capabilities than are signed for"));
+		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))
+			{
+			DEBUG_PRINTF(_L8("Restore - Controller requires user capabilities that are not supported by devcert constraints"));
+			// User capabilities are not all supported by the CertChainConstraints.
+			User::Leave(KErrSecurityError);					
+			}
+		}
+	}