--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/secureswitools/swisistools/source/interpretsislib/installer.cpp Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,1559 @@
+/*
+* Copyright (c) 2006-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:
+*
+*/
+
+
+#pragma warning (disable: 4786)
+
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+
+#include "dbhelper.h"
+
+#endif //SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+#include <exception>
+#include <sstream>
+#include <algorithm>
+#include <functional>
+#include <fstream>
+#include <stdio.h>
+#include <sys/stat.h>
+
+// SisX Library
+#include "sisdependency.h"
+#include "sisversionrange.h"
+#include "sisversion.h"
+#include "sisprerequisites.h"
+#include "sisfiledescription.h"
+#include "sisstring.h"
+#include "sishash.h"
+
+// User includes
+#include "stringutils.h"
+#include "parameterlist.h"
+#include "rommanager.h"
+#include "configmanager.h"
+#include "errors.h"
+#include "is_utils.h"
+#include "installer.h"
+#include "sisregistryobject.h"
+#include "adornedutilities.h"
+
+// Constants
+const char KRomDriveLetter = 'z';
+const TUint32 KSwiDaemonUid = 0x10202DCE;
+const std::wstring KSysBinPath = L"\\sys\\bin\\";
+
+TInt CheckWildCard(TInt aVal, TInt aReplace)
+{
+ return
+ aVal == -1
+ ? aReplace
+ : aVal;
+}
+
+bool InRange(const Version& aVersion, const CSISVersionRange& aRange)
+{
+ Version from(
+ CheckWildCard(aRange.FromVersion().Major(), aVersion.GetMajor()),
+ CheckWildCard(aRange.FromVersion().Minor(), aVersion.GetMinor()),
+ CheckWildCard(aRange.FromVersion().Build(), aVersion.GetBuild()));
+
+ if(!aRange.ToVersion().WasteOfSpace())
+ {
+ Version to(
+ CheckWildCard(aRange.ToVersion().Major(), aVersion.GetMajor()),
+ CheckWildCard(aRange.ToVersion().Minor(), aVersion.GetMinor()),
+ CheckWildCard(aRange.ToVersion().Build(), aVersion.GetBuild()));
+
+ if (aVersion == from ||
+ aVersion == to)
+ {
+ return true;
+ }
+
+ return (aVersion > from && aVersion < to);
+ }
+ else
+ {
+ return (aVersion >= from);
+ }
+}
+
+
+Installer::Installer( SisRegistry& aReg, const CParameterList& aParamList, RomManager& aRomManager, ConfigManager& aConfigManager )
+: iParamList(aParamList), iRegistry(aReg), iRomManager( aRomManager ), iConfigManager( aConfigManager ),
+ iExpressionEnvironment( NULL ), iExpressionEvaluator( NULL )
+{
+}
+
+TInt Installer::Install(const CParameterList::SISFileList& aList)
+{
+ TInt result = 0;
+ CParameterList::SISFileList sisFiles;
+
+ // Get the SIS files
+ for (CParameterList::SISFileList::const_iterator curr = aList.begin(); curr != aList.end(); ++curr)
+ {
+ std::wstring shortName(curr->iFileName);
+
+ // Ensure formatting is correct
+ if ( StringUtils::IsLastCharacter( shortName, KDirectorySeparator[ 0 ] ) ||
+ StringUtils::IsLastCharacter( shortName, L'/' ) )
+ {
+ shortName.erase(shortName.length()-1,1);
+ }
+
+ if ( IsDirectory(shortName) )
+ {
+ std::list<std::wstring> contents;
+ GetDirContents(shortName, contents);
+
+ for (std::list<std::wstring>::iterator currStr = contents.begin(); currStr != contents.end(); ++currStr)
+ {
+ if ((currStr->find(L".SIS",0) != std::wstring::npos)
+ || (currStr->find(L".sis",0) != std::wstring::npos))
+ {
+ InstallSISFile sisFileName(shortName + KDirectorySeparator + *currStr,
+ curr->iTargetDrive, curr->iGenerateStub,
+ curr->iNonRemovable, curr->iNotRegister, curr->iSUFlag);
+
+ sisFiles.push_back(sisFileName);
+ }
+ }
+
+ if (sisFiles.empty())
+ {
+ LWARN(L"No .SIS files found in directory" << shortName);
+ }
+ }
+ else if ((shortName.find(L".SIS",0) != std::wstring::npos)
+ || (shortName.find(L".sis",0) != std::wstring::npos))
+ {
+ InstallSISFile sisFileName(shortName, curr->iTargetDrive, curr->iGenerateStub,
+ curr->iNonRemovable, curr->iNotRegister, curr->iSUFlag);
+
+ sisFiles.push_back(sisFileName);
+ }
+ else
+ {
+ LWARN(L"Invalid SIS file: " << shortName);
+ }
+ }
+
+ bool installed = false;
+
+ do
+ {
+ installed = false;
+ iMissing.clear();
+ CParameterList::SISFileList::iterator curr = sisFiles.begin();
+
+ while (curr != sisFiles.end())
+ {
+ // install it
+ try
+ {
+ LINFO(L"*** Installing " << (curr->iFileName) << L" ***");
+
+ SanitiseSISFileAttributes(*curr);
+
+ result = Install(*curr);
+
+ if ( result == SUCCESS)
+ {
+ LINFO(L"");
+ LINFO(L"*** Installed " << (curr->iFileName) << L" ***");
+
+ installed = true;
+ curr = sisFiles.erase(curr);
+ }
+ else
+ {
+ LERROR(L"Failed to install " << (curr->iFileName));
+ ++curr;
+ }
+ }
+ catch(CSISException e)
+ {
+ // catch problems with individual sis files
+ LERROR(L"Unable to install " << (curr->iFileName));
+ LINFO(e.widewhat());
+ curr = sisFiles.erase(curr);
+ if (result == 0)
+ result = FILE_ERROR;
+ }
+ catch (InterpretSisError& e)
+ {
+ LERROR(L"Failed installing " << (curr->iFileName));
+ LERROR(L"\t" << Utf8ToUcs2(e.what()));
+ curr = sisFiles.erase(curr);
+
+ if (result == 0)
+ result = e.GetErrorCode();
+ }
+ }
+ }
+ while (installed);
+
+ if (result == 0 && !iMissing.empty())
+ result = MISSING_DEPENDENCY;
+
+ if(iParamList.RegistryVersionExists())
+ {
+ // Backup.lst regenerated at SisRegistry startup
+ iRegistry.RemoveBackupLst();
+ }
+ return result;
+
+}
+
+
+void Installer::SanitiseSISFileAttributes(const InstallSISFile& aInstallSISFile)
+{
+ SisFile file(aInstallSISFile.iFileName);
+
+ int targetDrive = aInstallSISFile.iTargetDrive;
+
+ if (!iConfigManager.IsTargetDrivePresent(targetDrive))
+ {
+ std::wstring shortName(aInstallSISFile.iFileName);
+
+ throw InterpretSisError(L"The installing target drive for " + shortName +
+ L" is not defined", CMDLINE_ERROR);
+ }
+
+ if (aInstallSISFile.iGenerateStub && !iConfigManager.IsTargetDriveExt(targetDrive))
+ {
+ std::wstring shortName(aInstallSISFile.iFileName);
+
+ throw InterpretSisError(L"The stub SIS file for " + shortName +
+ L" cannot be created to an internal drive", CMDLINE_ERROR);
+ }
+
+ if (aInstallSISFile.iGenerateStub && file.GetInstallType() == CSISInfo::EInstPartialUpgrade)
+ {
+ std::wstring shortName(aInstallSISFile.iFileName);
+
+ throw InterpretSisError(L"Generating stub SIS file for " + shortName +
+ L" (PU type) is not supported", SIS_NOT_SUPPORTED);
+ }
+}
+
+
+TInt Installer::Install(const InstallSISFile& aInstallSISFile)
+{
+ SisFile file(aInstallSISFile.iFileName);
+
+ // Setup the expression evaluator
+ SetupExpressionEnvironment( file, GetSisRegistry(), iRomManager );
+
+ // check presence of embedded sis files and
+ // display a warning if they are not installed before
+ if (file.HasEmbedded())
+ {
+ CheckEmbedded(file);
+ }
+
+ // check file is acceptable
+ file.CheckValid();
+
+ if (!DependenciesOk(file))
+ {
+ return MISSING_DEPENDENCY;
+ }
+
+ if (!IsValidUpgrade(file, aInstallSISFile.iSUFlag))
+ {
+ return INVALID_UPGRADE;
+ }
+
+ InstallableFiles installable;
+ GetInstallableFiles(file, installable, *iExpressionEvaluator, aInstallSISFile.iTargetDrive);
+
+ // Uninstall the same package (if found) prior to any installation
+ UninstallPkg(file);
+
+ CheckDestinations(file, installable, aInstallSISFile);
+
+ InstallFiles(installable, iParamList.SystemDriveLetter());
+
+ UpdateRegistry(file, installable, aInstallSISFile, aInstallSISFile.iSUFlag);
+
+ if (aInstallSISFile.iGenerateStub)
+ {
+ CreateStubSisFile(aInstallSISFile, file);
+ }
+
+ FreeInstallableFiles(installable);
+
+ return SUCCESS;
+}
+
+/**
+ Prepares a list of ROM files which are allowed to be eclipsed from the right
+ source according to the SIS file upgrade type.
+
+ If a SIS file wants to eclipse a file in ROM, it will fail unless there is an
+ associated stub SIS file present in the ROM that can be used by the Installer to
+ identify the replacement file as a valid upgrade of the original.
+ */
+void Installer::PrepareEclipsableFilesList(const SisFile& aSis)
+{
+ iEclipsableRomFiles.clear();
+ iEclipsableOverwriteFiles.clear();
+
+ TUint32 pkgUid = aSis.GetPackageUid();
+
+ // upgrade SIS file attributes
+ bool puInstallation = aSis.GetInstallType() == CSISInfo::EInstPartialUpgrade;
+ bool spInstallation = aSis.GetInstallType() == CSISInfo::EInstAugmentation;
+
+ // base package
+ const SisRegistryObject& registryEntry = iRegistry.GetRegistryObject(pkgUid);
+ bool currentPkgIsInRom = registryEntry.GetInRom();
+ bool stubExistsInRom = iRegistry.IsRomStubPackage(pkgUid);
+
+ // SA+RU, PU and SP are all allowed to eclipse ROM files. There must
+ // exist a valid ROM stub in order to populate the eclipsable files list.
+ if (IsValidEclipsingUpgrade(aSis, registryEntry))
+ {
+ // when an upgrade happens over an upgrade which has already upgraded the
+ // ROM based pacakge (i.e. ROM Stub -> SA+RU -> PU), don't populate the
+ // eclipsable files from the SIS registry entry which may be in-complete.
+ // Directly populate the eclipsable files list from the corresponding stub
+ // SIS file.
+ if (!currentPkgIsInRom && stubExistsInRom && (puInstallation || spInstallation))
+ {
+ iRegistry.GetStubFileEntries(pkgUid, iEclipsableRomFiles);
+ }
+ else
+ {
+ const FileDescriptions& files = registryEntry.GetFileDescriptions();
+ FileDescriptions::const_iterator curr = files.begin();
+ FileDescriptions::const_iterator end = files.end();
+
+ for ( ; curr != end ; ++curr)
+ {
+ std::wstring target((*curr)->GetTarget());
+ iEclipsableRomFiles.push_back(target);
+ }
+ }
+ }
+}
+
+/**
+ Non-SU packages can Eclipse iff:
+ a) The package uids match and
+ b) The package to be installed is immediate Upgrade to ROM (SP or PU over ROM)
+ (SA is allowed based on next condition)
+ c) (or) The package to be installed is (SA+RU type or PU or SP type) and it has a matching ROM stub SIS file
+ are allowed to eclipse files.
+ */
+bool Installer::IsValidEclipsingUpgrade(const SisFile& aSis, const SisRegistryObject& registryEntry)
+{
+ TUint32 pkgUid = aSis.GetPackageUid();
+
+ // case a)
+ if (pkgUid != registryEntry.GetUid())
+ return false;
+
+ bool stubExistsInRom = iRegistry.IsRomStubPackage(pkgUid);
+ bool isBaseInRom = registryEntry.GetInRom();
+ bool saInstall = aSis.GetInstallType() == CSISInfo::EInstInstallation;
+ bool reg51 = true;
+ if(iParamList.RegistryVersionExists())
+ {
+ int regMajor = iParamList.RegistryMajorVersion();
+ int regMinor = iParamList.RegistryMinorVersion();
+ bool reg51 = (regMajor >= SisRegistry::KSisRegistryMajorVersion) &&
+ (regMinor >= SisRegistry::KSisRegistryMinorVersion);
+ }
+ // RU flag was introduce when the SISRegistry was 5.1, otherwise, treat it as normal SA file
+ bool romUpgradeFlag = (aSis.GetInstallFlags() & CSISInfo::EInstFlagROMUpgrade) && reg51;
+ bool romUpgradableSA = saInstall && romUpgradeFlag;
+ bool puInstall = aSis.GetInstallType() == CSISInfo::EInstPartialUpgrade;
+ bool spInstall = aSis.GetInstallType() == CSISInfo::EInstAugmentation;
+
+ // case b)
+ if (isBaseInRom && !saInstall)
+ return true;
+
+ // case c)
+ return (stubExistsInRom && (romUpgradableSA || puInstall || spInstall));
+}
+
+void Installer::UninstallPkg(const SisFile& aSis)
+{
+ TUint32 uid = aSis.GetPackageUid();
+ TUint32 installType = aSis.GetInstallType();
+
+ // Check to see the SA is installed, otherwise, RemovePkg() will throw an exception
+ if (iRegistry.IsInstalled(uid) && (installType == CSISInfo::EInstInstallation))
+ {
+ LINFO(L"Removing package \"" << aSis.GetPackageName() << L"\" prior to re-installation");
+
+ // Remove all installed files for this Uid's packages and all the SisRegistry Entries
+ iRegistry.RemovePkg(uid, true);
+ }
+
+ if (installType == CSISInfo::EInstAugmentation)
+ {
+ // Clean up the installed files from the specified SP package and the SisRegistry Entry
+ iRegistry.RemoveEntry(uid, aSis.GetPackageName(), aSis.GetVendorName());
+ }
+
+ // Regenerate the ROM stub registry entries for eclipsing check later.
+ iRegistry.GenerateStubRegistry();
+}
+
+
+struct CheckDependencyMet
+{
+ CheckDependencyMet(
+ Installer& aInstaller,
+ std::vector<SisRegistryDependency>& aMissing)
+ : iInstaller(aInstaller),
+ iMissingDependencies(aMissing)
+ {}
+
+ void operator()(const CSISDependency* dep)
+ {
+ if (!iInstaller.CheckDependency(dep))
+ {
+ iMissingDependencies.push_back(SisRegistryDependency(*dep));
+ }
+ }
+ Installer& iInstaller;
+ std::vector<SisRegistryDependency>& iMissingDependencies;
+};
+
+bool Installer::CheckDependency(const CSISDependency* aDep)
+{
+ bool result = false;
+
+ try
+ {
+ const SisRegistryObject& pkg =
+ iRegistry.GetRegistryObject(aDep->SisUID().UID1());
+
+ const CSISVersionRange& range = aDep->VersionRange();
+ if (!range.WasteOfSpace() && InRange(pkg.GetVersion(), range))
+ {
+ result = true;
+ }
+ else
+ {
+ result = false;
+ }
+ }
+
+ catch(...)
+ {
+ result = false;
+ }
+ return result ;
+}
+
+bool Installer::DependenciesOk(const SisFile& aFile)
+ {
+ const CSISPrerequisites* reqs = aFile.GetDependencies();
+ const CSISPrerequisites::TDependencyList& deps = reqs->DependencyList();
+
+ CheckDependencyMet checkDependencyMet(*this, iMissing[aFile.GetPackageName()]);
+ for(int i = 0; i < deps.size(); ++i)
+ {
+ checkDependencyMet(&deps[i]);
+ }
+
+ return iMissing[aFile.GetPackageName()].size() == 0;
+ }
+
+
+bool Installer::IsValidUpgrade(const SisFile& aFile, bool aSUFlag)
+{
+ TUint32 pkg = aFile.GetPackageUid();
+ TUint32 installFlags = aFile.GetInstallFlags();
+ bool RUFlag = ((installFlags & CSISInfo::EInstFlagROMUpgrade) && CSISInfo::EInstFlagROMUpgrade);
+
+ if(iParamList.RegistryVersionExists())
+ {
+ int regMajor = iParamList.RegistryMajorVersion();
+ int regMinor = iParamList.RegistryMinorVersion();
+ bool reg51 = (regMajor >= SisRegistry::KSisRegistryMajorVersion) &&
+ (regMinor >= SisRegistry::KSisRegistryMinorVersion);
+ // RU flag was introduce when the SISRegistry was 5.1, otherwise, treat it as normal SA file
+ RUFlag = RUFlag && reg51;
+ }
+ if ( aSUFlag && !RUFlag)
+ {
+ std::stringstream err;
+ err << "Illegal system upgrade (SU) of ROM package 0x" << std::hex << pkg << " without setting the RU flag";
+ throw InterpretSisError(err.str(), ATTEMPT_TO_UPGRADE_ROM_PKG);
+ }
+
+ // Check is this package has been installed before
+
+ TUint32 installType = aFile.GetInstallType();
+
+ if (iRegistry.IsInstalled(pkg))
+ {
+ ValidateRegistry(aFile,pkg,installFlags,RUFlag);
+ }
+ else if (installType == CSISInfo::EInstAugmentation || installType == CSISInfo::EInstPartialUpgrade)
+ {
+ // Installing SP and PU without the base package
+ std::stringstream err;
+ err << "Could not perform upgrade - the base package 0x" << std::hex
+ << pkg << " is missing";
+
+ throw InterpretSisError(err.str(), MISSING_BASE_PACKAGE);
+ }
+
+ return true;
+ }
+
+void Installer::ValidateRegistry(const SisFile& aFile, TUint32 aPckgUid, TUint32 aInstallFlags, bool aRUFlag)
+ {
+ bool isSisNonRemovable = aInstallFlags & CSISInfo::EInstFlagNonRemovable;
+ bool isBaseRemovable = false;
+ bool inRom = false;
+ bool isPreInstalled = false;
+ TUint32 uid = 0;
+ std::wstring packageName;
+
+ InitializeRegistryDetails(aPckgUid, isBaseRemovable, inRom, isPreInstalled, uid, packageName );
+
+ // Check is this package has been installed before
+ TUint32 installType = aFile.GetInstallType();
+
+ if (installType == CSISInfo::EInstInstallation)
+ {
+ if (inRom && !aRUFlag)
+ {
+ std::stringstream err;
+ err << "Illegal SA upgrade to ROM package 0x" << std::hex << aPckgUid;
+ throw InterpretSisError(err.str(), ATTEMPT_TO_UPGRADE_ROM_PKG);
+ }
+ // This is not a ROM base package, check is there a SIS stub base package present
+ else if (iRegistry.IsRomStubPackage(aPckgUid) && !aRUFlag)
+ {
+ std::stringstream err;
+ err << "Indirect SA upgrade to ROM package 0x" << std::hex << aPckgUid
+ << " missing RU flag";
+ throw InterpretSisError(err.str(), ATTEMPT_TO_UPGRADE_ROM_PKG);
+ }
+ }
+ else if (installType == CSISInfo::EInstAugmentation)
+ {
+ if (isBaseRemovable && isSisNonRemovable)
+ {
+ std::stringstream err;
+ err << "Not allowed to install SP + NR to the removable base package 0x" << std::hex << aPckgUid;
+
+ throw InterpretSisError(err.str(), INVALID_UPGRADE);
+ }
+
+ if (packageName == aFile.GetPackageName() && uid == aFile.GetPackageUid())
+ {
+ std::stringstream err;
+ err << "Cannot augment package 0x" << std::hex << aFile.GetPackageUid() << " - package names match";
+
+ throw InterpretSisError(err.str(), MISSING_BASE_PACKAGE);
+ }
+ }
+ else if (installType == CSISInfo::EInstPartialUpgrade)
+ {
+ // Do not allow partial upgrades to preinstalled applications
+ if (isPreInstalled)
+ {
+ std::stringstream err;
+ err << "Cannot install PU (0x" << std::hex << aPckgUid << ") to a PA";
+
+ throw InterpretSisError(err.str(), INVALID_UPGRADE);
+ }
+
+ // Partial Upgrade can only be installed to a base package of the same install flag type.
+ // The only exception is a ROM stub which is upgradable and non-removable by definition.
+ if ((isBaseRemovable == isSisNonRemovable) && !inRom )
+ {
+ std::stringstream err;
+ err << "Cannot install PU (0x" << std::hex << aPckgUid << ") to a base package with a different removable flag type";
+
+ throw InterpretSisError(err.str(), INVALID_UPGRADE);
+ }
+ }
+ else if (installType == CSISInfo::EInstPreInstalledApp)
+ {
+ std::stringstream err;
+ err << "Cannot install PA (0x" << std::hex << aPckgUid << ") over top of another package";
+
+ throw InterpretSisError(err.str(), INVALID_UPGRADE);
+ }
+ }
+
+void Installer::InitializeRegistryDetails( const TUint32 aPckgUid, bool& aIsBaseRemovable,
+ bool& aInRom, bool& aIsPreInstalled,
+ TUint32& aUid, std::wstring& aPackageName
+ )
+ {
+ if(iParamList.RegistryVersionExists() )
+ {
+ const SisRegistryObject& obj = iRegistry.GetRegistryObject(aPckgUid);
+ aIsBaseRemovable = obj.GetIsRemovable();
+ aInRom = obj.GetInRom();
+ aIsPreInstalled = obj.IsPreInstalled();
+ aUid = obj.GetUid();
+ aPackageName = obj.GetPackageName();
+ }
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ else
+ {
+ const DbHelper* dbHelper( iRegistry.GetDbHelper());
+ TInt32 componentId = dbHelper->GetComponentId(aPckgUid);
+ aIsBaseRemovable = dbHelper->GetIsRemovable(componentId);
+ aInRom = dbHelper->GetInRom(componentId);
+ if(dbHelper->GetInstallType(componentId) == CSISInfo::EInstPreInstalledApp )
+ {
+ aIsPreInstalled = true;
+ }
+ aUid = dbHelper->GetUid(componentId);
+ aPackageName = dbHelper->GetPackageName(componentId);
+ }
+ #endif // SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ }
+
+bool Installer::GetInstallableFiles(const SisFile& aFile, InstallableFiles& aList, ExpressionEvaluator& aEvaluator,
+ int aInstallingDrive)
+{
+ return aFile.GetInstallableFiles(aList, aEvaluator,
+ iConfigManager.GetLocalDrivePath(aInstallingDrive), aInstallingDrive);
+}
+
+
+struct InstallFile
+{
+ InstallFile(const std::wstring& aCDrive, const int aSystemDrive)
+ : iSystemDrivePath(aCDrive), iSystemDrive(aSystemDrive) {}
+
+ const std::wstring& iSystemDrivePath;
+ const int iSystemDrive;
+
+ void operator()(const InstallableFile* aFile)
+ {
+ std::fstream output;
+ std::wstring target(aFile->GetTarget());
+ std::wstring localTarget(aFile->GetLocalTarget());
+
+ bool fileNullOption = (aFile->FileDescription()->Operation() == CSISFileDescription::EOpNull);
+
+ if (!target.length())
+ {
+ LINFO(L"Skipping file with empty destination filename");
+ }
+ else
+ {
+ // Unicode characters can not be displayed on DOS prompt
+ std::string temporary = Ucs2ToUtf8(target);
+ std::wstring targetDisplay = Utf8ToUcs2( temporary );
+ LINFO(L"Installing file: " << targetDisplay);
+
+ std::wstring targetDirectory = localTarget.substr( 0, localTarget.rfind( KDirectorySeparator ) );
+ const unsigned char* buffer = NULL;
+ TUint32 len;
+
+ if (aFile->IsStub()) // PA
+ {
+ // check the presence of file at target location
+ if (!FileExists(localTarget))
+ {
+ throw InterpretSisError(L"PA Install error - No target file- "+target, PA_NO_TARGET_FILE);
+ }
+ }
+ else // SA
+ {
+ // if the FN option specified, leave the file creation
+ if (fileNullOption)
+ {
+ LINFO(L"File " << target << L" contains \"Delete-File-On-Uninstall\" option." );
+ }
+ else
+ {
+ if ( !MakeDir( targetDirectory ) )
+ {
+ throw InterpretSisError(L"Directory Creation Error - "+targetDirectory,
+ DIRECTORY_CREATION_ERROR);
+ }
+
+ HANDLE hFile = MakeSISOpenFile(localTarget.c_str(), GENERIC_WRITE, CREATE_ALWAYS);
+ if( INVALID_HANDLE_VALUE == hFile )
+ {
+ throw InterpretSisError(L"FileOpenError - "+target, FILE_ERROR);
+ }
+ buffer = aFile->FileData()->Data();
+ len = aFile->FileData()->UncompressedSize();
+ DWORD bytesWritten;
+ BOOL error = WriteFile(hFile, buffer, len, &bytesWritten, NULL);
+ if( error != TRUE )
+ {
+ throw InterpretSisError(L"FileWriteError - "+target, FILE_ERROR);
+ }
+ CloseHandle(hFile);
+ }
+ }
+
+ if (aFile->IsExecutable() && !fileNullOption)
+ {
+ // register the hash
+ std::wstring basename = localTarget.substr( localTarget.rfind( KDirectorySeparator ) + 1 );
+ std::wstring hashdir = iSystemDrivePath + L"\\sys\\hash\\";
+ std::wstring reghashdir = L"$:\\sys\\hash\\";
+
+ if ( !MakeDir( hashdir ) )
+ {
+ throw InterpretSisError(L"Directory Creation Error - "+hashdir,
+ DIRECTORY_CREATION_ERROR);
+ }
+
+ // hash file is always created on the system drive
+ reghashdir[0] = iSystemDrive;
+
+ LINFO(L"\tCreating hash: " << reghashdir << basename);
+
+ std::wstring hash = hashdir + basename;
+ HANDLE hFile = MakeSISOpenFile(hash.c_str(), GENERIC_WRITE, CREATE_ALWAYS);
+ if( INVALID_HANDLE_VALUE == hFile )
+ {
+ throw InterpretSisError(L"FileOpenError - " + hashdir + basename, FILE_ERROR);
+ }
+
+ buffer = aFile->FileDescription()->Hash().Blob().Data();
+ len = aFile->FileDescription()->Hash().Blob().Size();
+ DWORD bytesWritten;
+ BOOL error = WriteFile(hFile, buffer, len, &bytesWritten, NULL);
+ if( error != TRUE )
+ {
+ throw InterpretSisError(L"FileWriteError - " + hashdir + basename, FILE_ERROR);
+ }
+ CloseHandle(hFile);
+ }
+ }
+ }
+};
+
+
+void Installer::InstallFiles(const InstallableFiles& aList, const int aInstallDrive)
+{
+ std::wstring localTargetPath = iConfigManager.GetLocalDrivePath(aInstallDrive);
+
+ std::for_each(aList.begin(), aList.end(), InstallFile(localTargetPath, aInstallDrive));
+}
+
+
+void Installer::UpdateRegistry(const SisFile& aFile, const InstallableFiles& aList,
+ const InstallSISFile& aInstallSISFile, const bool aSUFlag)
+{
+ if (aFile.GetInstallType() == CSISInfo::EInstPartialUpgrade)
+ {
+ iRegistry.UpdateRegistryEntry(aFile, aList, aInstallSISFile);
+ }
+ else if (!aInstallSISFile.iNotRegister)
+ {
+ iRegistry.AddRegistryEntry(aFile, aList, aInstallSISFile);
+ }
+}
+
+/** This function takes a fully qualified name and searches the filesystem through for all possible adorned filename matches.
+ Besides that it calculates the unadorned version of the input filename as well and return it through the corresponding given
+ input reference variable.
+ @param aTarget the fully qualified filename (full path and name)
+ @param aUnadornedName the calulated unadorned name is returned through this variable(full path and unadorned name calculated from aTarget)
+ @param aAdornedFileNamesFound all the found adorned name matches are returned through this list
+*/
+void Installer::AdornedProcessingOfFile(const std::wstring& aTarget, std::wstring& aUnadornedName,
+ std::list<std::wstring>& aAdornedFileNamesFound)
+{
+ std::wstring targetNameAndExt(StringUtils::NameAndExt(aTarget));
+ std::wstring targetDriveAndPath(StringUtils::DriveAndPath(aTarget));
+
+ std::wstring unadornedName;
+ std::wstring searchNameWild;
+
+ // create the unadorned version of the target file e.g. c:\sys\bin\a.dll
+ GetUnadornedFileName(targetNameAndExt, unadornedName);
+ aUnadornedName = targetDriveAndPath;
+ aUnadornedName.append(unadornedName);
+
+ // create a wildcard version of the target file e.g. c:\sys\bin\a{????????}.dll
+ GenerateSearchNameWild(targetNameAndExt, searchNameWild);
+
+ const DrivesMap& driveMap = iConfigManager.GetDrivesMap();
+ FindAllAdornedVariants(searchNameWild, KSysBinPath, aAdornedFileNamesFound, driveMap);
+
+ // find all adorned variants in the ROM/ROFS logs
+ if (iParamList.IsFlagSet(CParameterList::EFlagsRomRofsLogFilesSet))
+ {
+ std::wstring romSearchNameWild = L"z:\\sys\\bin\\";
+ romSearchNameWild.append(searchNameWild);
+ iRomManager.FindAllAdornedVariants(romSearchNameWild, aAdornedFileNamesFound);
+ }
+}
+
+/**
+ This function ensures the SIS file to be installed does not illegally
+ eclipse a file already installed in the ROM.
+ @param aFile the SIS file to be installed
+ @param aTarget the fully qualified filename (full path and name)
+ @param aInstallableFile the current installing files properties
+ @param aSUFlag specifies if the installing SIS file has been signed by a SU certificate
+*/
+bool Installer::ValidEclipse(const SisFile& aFile, const std::wstring& aTarget, const InstallableFile& aInstallableFile, bool aSUFlag)
+{
+ bool result = true;
+ std::wstring searchNameUnadorned = L"";
+ std::wstring localDir = L"";
+ std::list<std::wstring> adornedFileNamesFound;
+
+ int targetDisk = tolower(aTarget[0]);
+ const DrivesMap& driveMap = iConfigManager.GetDrivesMap();
+
+ int count = driveMap.size();
+
+ // check for adorned (versioned) files e.g. dummy{12345678}.dll
+ if (aTarget.find(KSysBinPath) != std::wstring::npos)
+ {
+ AdornedProcessingOfFile(aTarget, searchNameUnadorned, adornedFileNamesFound);
+ }
+ else
+ {
+ searchNameUnadorned = aTarget;
+ }
+
+ DrivesMap::const_iterator it = driveMap.begin();
+ DrivesMap::const_iterator end = driveMap.end();
+
+ // search on all of defined drives (including the ROM and system drive) for
+ // the target file
+ for ( ; it != end ; ++it)
+ {
+ // drive letter
+ int disk = tolower(it->first);
+ searchNameUnadorned[0] = disk;
+ std::wstring unadornedLocalPath(searchNameUnadorned);
+
+ // check if adorned file version is found on this disk
+ bool adornedFound = false;
+
+ std::list<std::wstring>::iterator index = adornedFileNamesFound.begin();
+ std::list<std::wstring>::iterator adornedEnd = adornedFileNamesFound.end();
+ int nrOfAdornedFilenamesFound = adornedFileNamesFound.size();
+
+ for ( ; index != adornedEnd ; ++index)
+ {
+ std::wstring adornedFile = *index;
+ int drive = tolower(adornedFile[0]);
+ if (drive == disk)
+ {
+ adornedFound = true;
+ break;
+ }
+ }
+
+ // the actual directory
+ localDir = it->second->iDir;
+ bool unadornedFound;
+
+ // check to see if we are using ROM/ROFS files to represent the z drive.
+ // If so, check to see if the ROM file exists in the logs.
+ if (disk == 'z' && localDir.empty())
+ {
+ unadornedFound = iRomManager.RomFileExists(searchNameUnadorned);
+ }
+ else
+ {
+ // convert to the local path and see if the file exists on the current drive
+ ConvertToLocalPath( unadornedLocalPath, localDir );
+ unadornedFound = FileExists(unadornedLocalPath);
+ }
+
+ bool matchFound = unadornedFound || adornedFound;
+ if (!matchFound)
+ continue;
+
+ bool processEclipsingSuspectsFoundOnThisDrive = false;
+
+ // The logic varies whether we find an eclipsable/overwritable file on: (1) The same disk as the one we are installing to
+ // (2) The Z drive (ROM), (3) Any other drive
+ if (disk == targetDisk) // case (1)
+ {
+ bool isOverwrite = FileExists(aInstallableFile.GetLocalTarget());
+
+ // there are 3 possible cases: (1.1) We are correctly overwriting the already present file (a PU),
+ // (1.2) We are incorrectly overwriting the file present, (1.3) We are eclipsing the file (if one of the file names is adorned)
+ if (isOverwrite)
+ {
+ // case 1.1 and 1.2 are handled here - overwrite the file if we have the right to do so.
+ HandleFileOverwriting(aFile, aTarget, aSUFlag);
+ }
+ else
+ {
+ // case 1.3 is handled here:
+ // we have found a matching filename (either unadorned or adorned); add it to the eclipsing suspects
+ processEclipsingSuspectsFoundOnThisDrive = true;
+ }
+ }
+ else if (disk == 'z') // case (2)
+ {
+ // we are eclipsing a ROM file, check if this is authorised:
+ // see implementation of IsEclipsable()
+ if (!IsEclipsable(searchNameUnadorned, aSUFlag))
+ {
+ result = false;
+ break;
+ }
+ }
+ else // case (3)
+ {
+ processEclipsingSuspectsFoundOnThisDrive = true;
+ }
+
+ // now check to see whether the unadorned or the adorned filename found on
+ // this drive should be added to iEclipsableOverwriteFiles.
+ if (processEclipsingSuspectsFoundOnThisDrive && unadornedFound)
+ {
+ iEclipsableOverwriteFiles.push_back(searchNameUnadorned);
+ }
+
+ if (processEclipsingSuspectsFoundOnThisDrive && adornedFound)
+ {
+ nrOfAdornedFilenamesFound = adornedFileNamesFound.size();
+ std::list<std::wstring>::iterator index = adornedFileNamesFound.begin();
+ std::list<std::wstring>::iterator adornedEnd = adornedFileNamesFound.end();
+
+ // add the adorned filenames found to the list of eclipsable/overwrite candidates
+ for ( ; index != adornedEnd ; ++index)
+ {
+ std::wstring adornedFile = *index;
+ int drive = tolower(adornedFile[0]);
+ if (drive == disk)
+ {
+ iEclipsableOverwriteFiles.push_back(adornedFile);
+ }
+ }
+ }
+ }
+ // end of loop
+
+ // the final step is to try and remove all the files from iEclipsableOverwriteFiles that
+ // will prevent this SIS file from installing.
+ if (result && (iEclipsableOverwriteFiles.size() > 0))
+ {
+ FilterNonBlockingFilesOfFilename(aFile, aTarget);
+ }
+
+ return result;
+}
+
+/** Checks the list of eclipsable candidate files against those that are owned by the
+ installing package (if any). Blocking files are removed if a match is found.
+ @param aFile the SIS file to be installed
+ @param aTarget the fully qualified filename (full path and name)
+*/
+void Installer::FilterNonBlockingFilesOfFilename(const SisFile& aFile, const std::wstring& aTarget)
+{
+ // if the package aleady exists
+ TUint32 pkgUid = aFile.GetPackageUid();
+ if (iRegistry.IsInstalled(pkgUid))
+ {
+ const SisRegistryObject& registryEntry = iRegistry.GetRegistryObject(pkgUid);
+ const FileDescriptions& installedFiles = registryEntry.GetFileDescriptions();
+
+ FileDescriptions::const_iterator inCurr = installedFiles.begin();
+ FileDescriptions::const_iterator inEnd = installedFiles.end();
+
+ for ( ; inCurr != inEnd ; ++inCurr)
+ {
+ std::wstring baseFile((*inCurr)->GetTarget());
+
+ std::list<std::wstring>::iterator eCurr = iEclipsableOverwriteFiles.begin();
+ std::list<std::wstring>::iterator eEnd = iEclipsableOverwriteFiles.end();
+
+ for ( ; eCurr != eEnd; ++eCurr)
+ {
+ std::wstring eclipseFile(*eCurr);
+
+ // the installed base package owns the eclipse/overwrite candidate
+ if (FoldedCompare(baseFile, eclipseFile) == 0)
+ {
+ // we are installing a new adorned variant of a file, so remove the blocking
+ // file from the list
+ if (StringUtils::NameAndExt(baseFile) != StringUtils::NameAndExt(aTarget))
+ {
+ eCurr = iEclipsableOverwriteFiles.erase(eCurr);
+ }
+ }
+ }
+ }
+ }
+}
+
+/** This function examines the list of ROM files we may eclipse to see if the supplied name is among them.
+ Here we have 2 options:
+ 1) file is not to be installed to \sys\bin\
+ in this case we don't invoke special handling of adorned filenames so we are only
+ interested in if that particular file is allowed to be eclipsed
+ 2) file is to be installed to \sys\bin therefore we have to handle adorned filenames.
+ Eclipsing is allowed if the filename that we are trying to install is a variant of any ROM filename
+ marked as eclipsable i.e: if we are trying to install c:\sys\bin\A{000A0001}.dll
+ and we have z:\sys\bin\A.dll as an eclipsable file or any z:\sys\bin\A{????????}.dll
+ then we are allowed to eclipse.
+ @param aRomFile fully qualified filename in ROM that is to be checked for eclipising (i.e: z:\sys\bin\some.dll)
+ @param aSUFlag specifies if the installing SIS file has been signed by a SU certificate
+*/
+bool Installer::IsEclipsable(std::wstring& aRomFile, bool aSUFlag)
+{
+ // SA/SP/PU sis + RU flag + signed by SU root cert is allowed
+ if (aSUFlag)
+ return true;
+
+ bool isEclipsable = false;
+ bool goesToSysBin = (aRomFile.compare(KSysBinPath) != std::wstring::npos);
+
+ // go through the list of ROM files which are allowed to be eclipsed
+ std::list<std::wstring>::const_iterator end = iEclipsableRomFiles.end();
+ for (std::list<std::wstring>::const_iterator curr = iEclipsableRomFiles.begin() ;
+ curr != end; ++curr)
+ {
+ std::wstring eclipsableRomFile = *curr;
+
+ // support wildcard characters in ROM stub files
+ if (StringUtils::WildcardCompare(eclipsableRomFile,aRomFile)) // case 1
+ {
+ isEclipsable = true;
+ break;
+ }
+ else if (goesToSysBin) // case 2
+ {
+ if (IsAdornedVariationOf(eclipsableRomFile,aRomFile))
+ {
+ isEclipsable = true;
+ break;
+ }
+ }
+ }
+
+ return isEclipsable;
+}
+
+/** This function handles overwriting scenarios (i.e: we are trying to install c:\somedir\somename.ext however it already exists)
+ In this case we have 2 possibilities:
+ 1) We are correctly overwriting the already present file (a PU)
+ 2) We are incorrectly overwriting the file present
+ @param aFile the SIS file to be installed
+ @param aTarget The fully qualified filename (full path and name)
+ @param aSUFlag specifies if the installing SIS file has been signed by a SU certificate
+*/
+void Installer::HandleFileOverwriting(const SisFile& aFile, const std::wstring& aTarget, bool aSUFlag)
+{
+ // find out which package this file belongs to
+ TUint32 owningUid = 0;
+ const SisRegistryObject* owningObj = iRegistry.OwningPackage(aTarget,owningUid);
+ bool isSp = aFile.GetInstallType() == CSISInfo::EInstAugmentation;
+ bool isPu = aFile.GetInstallType() == CSISInfo::EInstPartialUpgrade;
+ bool isSa = aFile.GetInstallType() == CSISInfo::EInstInstallation;
+
+ // no package owns this file. Always allow orphaned file overwriting!
+ if (owningUid == 0)
+ {
+ // do not display a warning if the installing file is a PA. The user
+ // needs to copy the installing files to the installing directory
+ // prior to installing the SIS file.
+ std::string tempTarget = Ucs2ToUtf8(aTarget);
+ std::wstring targetDisplay = Utf8ToUcs2( tempTarget );
+ if (aFile.GetInstallType() == CSISInfo::EInstPreInstalledApp)
+ {
+ LINFO(targetDisplay << L" found for PA installation");
+ }
+ else
+ {
+ LWARN(targetDisplay << L" overwrites orphaned file");
+ }
+ }
+ else if (aFile.GetPackageUid() == owningUid)
+ {
+ // SP can not overwrite a file in the base pkg
+ if (isSp)
+ {
+ std::wostringstream os;
+ os << aTarget << L" overwrites file from base package 0x" << std::hex << owningUid << L" \"" << owningObj->GetPackageName() << L"\"" << std::endl;
+ iProblemFiles.append(os.str());
+ iError = ECLIPSING_VIOLATION;
+ }
+ }
+ else
+ {
+ // SP can not overwrite a file belonging to a different base pkg
+ // PU/SA can not overwrite a file belonging to a different base pkg unless it has been signed by
+ // a SU cert
+ if (isSp || (!aSUFlag && (isPu || isSa)))
+ {
+ std::wostringstream os;
+ os << aTarget << L" overwrites file from base package 0x" << std::hex << owningUid << L" \"" << owningObj->GetPackageName() << L"\"" << std::endl;
+ iProblemFiles.append(os.str());
+ iError = ECLIPSING_VIOLATION;
+ }
+ else
+ {
+ LWARN(aTarget << L" overwrites file from base package 0x" << std::hex << owningUid << L" \"" << owningObj->GetPackageName() << L"\"");
+ }
+ }
+}
+
+void Installer::WarnEclipseOverWrite(const SisFile& aFile)
+{
+ // we still have some blocking files left after we have checked the destination
+ // of the installing file.
+ if (iEclipsableOverwriteFiles.size()>0)
+ {
+ // InterpretSIS allows orphan file eclipsing/overwriting
+ std::list<std::wstring>::const_iterator curr = iEclipsableOverwriteFiles.begin();
+ std::list<std::wstring>::const_iterator end = iEclipsableOverwriteFiles.end();
+
+ for ( ; curr != end; ++curr)
+ {
+ std::wstring eclipseFile(*curr);
+
+ TUint32 owningUid = 0;
+ const SisRegistryObject* owningObj = iRegistry.OwningPackage(eclipseFile, owningUid);
+
+ // always allow orphaned file overwriting
+ if (owningUid == 0)
+ {
+ LWARN(eclipseFile << L" eclipses orphaned file.");
+ }
+ else
+ {
+ // SP/PU can not overwrite a file belonging to a different base pkg or
+ // SP/PU can not eclipse a base package which is not in the ROM.
+ std::wostringstream os;
+ os << eclipseFile << L" eclipses file from package 0x" << std::hex << owningUid << L" \"" << owningObj->GetPackageName() << L"\"" << std::endl;
+ iProblemFiles.append(os.str());
+ iError = ECLIPSING_VIOLATION;
+ continue;
+ }
+ }
+ }
+}
+
+void Installer::CheckDestinations(const SisFile& aFile, InstallableFiles& aFiles,
+ const InstallSISFile& aInstallSISFile)
+{
+ bool suFlag = aInstallSISFile.iSUFlag;
+
+ // if the -e option or InstallSISFile::iNotRegister is set, disable the eclipsing checks
+ bool isEclipseAllowed = (iParamList.IsFlagSet(CParameterList::EFlagsDisableZDriveChecksSet)) || aInstallSISFile.iNotRegister;
+
+ iError = SUCCESS;
+
+ Sids sids;
+ GetSidsFromInstallable(aFiles, sids);
+
+ const std::wstring privatePath = L":\\private\\";
+ const std::wstring sysPath = L":\\sys\\";
+ const std::wstring sysBinPath = L":\\sys\\bin\\";
+ const std::wstring resourcePath = L":\\resource\\";
+ const std::wstring exeType = L".exe";
+
+ int num_of_files = aFiles.size();
+ TUint32 pkgUid = aFile.GetPackageUid();
+ TUint32 installType = aFile.GetInstallType();
+ std::list<std::wstring> stubFileEntries;
+
+ iRegistry.GetStubFileEntries(pkgUid, stubFileEntries);
+
+ // if a base package exists, check to see if it chains back to a ROM stub. If so, populate
+ // iEclipsableRomFiles with the files owned by the ROM stub. Only ROM files can be eclipsed.
+ //
+ // if the package has been signed by a SU cert, then there is no need to generate the eclipsable
+ // file list - it is allowed to eclipse any file in the ROM.
+ if (iRegistry.IsInstalled(pkgUid) && !suFlag)
+ {
+ PrepareEclipsableFilesList(aFile);
+ }
+
+ // loop through the files to be installed
+ for( int ii=num_of_files-1; ii>=0; ii-- )
+ {
+ const InstallableFile* file = aFiles[ ii ];
+ const CSISFileDescription* sisDescription = file->FileDescription();
+
+ // file to be installed
+ std::wstring target( file->GetTarget() );
+
+ if (sisDescription->Operation() == CSISFileDescription::EOpText)
+ break;
+ if (sisDescription->Operation() == CSISFileDescription::EOpNull)
+ {
+ // a FN file can not remove a file from \sys or \resource
+ if ((target.find(sysPath,0) != std::wstring::npos) || (target.find(resourcePath,0) != std::wstring::npos))
+ {
+ // eclipsing problem
+ std::wostringstream os;
+ os << L"FN file \"" << target << L"\" can not remove a file from \\sys or \\resource" << std::endl;
+ iProblemFiles.append(os.str());
+ iError = DATA_CAGE_VIOLATION;
+ continue;
+ }
+ }
+ else
+ {
+ std::wstring realTarget(file->GetLocalTarget());
+
+ std::wstring romTarget(target);
+ romTarget[0] = KRomDriveLetter;
+
+ // check to see if we are legally allowed to eclipse a ROM file
+ if (!isEclipseAllowed)
+ {
+ if (!ValidEclipse(aFile, target, *file, suFlag))
+ {
+ // eclipsing problem
+ std::wostringstream os;
+ os << target << L" eclipses file from ROM" << std::endl;
+ iProblemFiles.append(os.str());
+ iError = ECLIPSING_VIOLATION;
+ continue;
+ }
+ }
+
+ // additional platsec checks
+ if (target.find(privatePath) != std::wstring::npos)
+ {
+ // add an extra one for the drive letter
+ TInt start = privatePath.size()+1;
+ TInt end = target.find( KDirectorySeparator[ 0 ], start);
+
+ std::wistringstream uidStr(target.substr(start,end-start));
+
+ TUint32 sid = 0;
+ uidStr >> std::hex >> sid;
+
+ if (sid == 0)
+ break;
+
+ // if a file in a private directory is registered, check to see if
+ // it belongs to this package
+ if (std::find(sids.begin(), sids.end(), sid) == sids.end())
+ {
+ TUint32 sidOwnerPkgUId = KNullUid;
+
+ if (iRegistry.SidExists(sid))
+ {
+ if(iParamList.RegistryVersionExists())
+ {
+ // SID belongs to some package, lets find out its UID
+ const SisRegistryPackage& sisRegistryPkg = iRegistry.SidToPackage(sid);
+
+ sidOwnerPkgUId = sisRegistryPkg.GetUid();
+ }
+ else
+ {
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ sidOwnerPkgUId = iRegistry.GetUid(sid);
+#endif //SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ }
+ }
+
+ if (sidOwnerPkgUId != pkgUid)
+ {
+ // this package is trying to write to a SID's private directory
+ // which does not belong to this package
+
+ const int KUidStringLength = 8;
+ std::wstring importPath = privatePath;
+
+ importPath.append( uidStr.str() + L"\\import" );
+
+ if ((target.find(importPath,0) == std::wstring::npos) && !suFlag)
+ {
+ // only SA with RU + SU and PU with RU + SU flag can override other private directory
+ std::wostringstream os;
+ os << target << L" cannot be written to a private directory which "
+ << L"does not belong to any exe in this package" << std::endl;
+ iProblemFiles.append(os.str());
+ iError = DATA_CAGE_VIOLATION;
+ continue;
+ }
+ }
+ }
+ }
+ else if (file->IsExecutable())
+ {
+ TUint32 sid = file->Sid();
+
+ std::wstring romFileWithDuplicateSid(L"");
+ bool sidExistsInRom = iRomManager.SidExistsInRom(romFileWithDuplicateSid, sid);
+ bool sidExistsInRegistry = iRegistry.SidExists(sid);
+
+ if (sidExistsInRegistry && file->IsExe())
+ {
+ // the .EXE which owns the SID
+ std::wstring owningSidFile;
+ iRegistry.SidToFileName(sid,owningSidFile);
+
+ bool owningPkgInRom = false;
+ bool samePkgUid = false;
+ TUint32 owningPkg = 0;
+ if(iParamList.RegistryVersionExists())
+ {
+ // the SisRegistryObject which owns the .EXE
+
+ const SisRegistryObject* owningObj = iRegistry.OwningPackage(owningSidFile,owningPkg);
+
+ owningPkgInRom = owningObj->GetInRom();
+ samePkgUid = (owningPkg == pkgUid);
+ }
+ else
+ {
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ owningPkg = iRegistry.GetUid(owningSidFile);
+ owningPkgInRom = iRegistry.GetInRom(owningPkg);
+ samePkgUid = (owningPkg == pkgUid);
+ #endif //SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ }
+ std::wstring targetName = StringUtils::NameAndExt(file->GetTarget());
+ std::wstring owningSidFileName = StringUtils::NameAndExt(owningSidFile);
+
+ bool sameTargetName = (FoldedCompare(targetName,owningSidFileName) == 0);
+ bool romStubExists = iRegistry.IsRomStubPackage(pkgUid);
+ bool validInstallType = (installType == CSISInfo::EInstInstallation || installType == CSISInfo::EInstPartialUpgrade || installType == CSISInfo::EInstAugmentation);
+
+ // allow SID eclipsing in the following scenarios:
+ // 1) SIS file has been signed by a SU cert
+ // 2) eclipsing checks have been disabled by the user (using -e)
+ // 3) SP/PU/SA+RU eclipsing of a ROM stub
+ bool allowSidEclipse = false;
+
+ // case 1 and 2
+ if (suFlag || isEclipseAllowed)
+ allowSidEclipse = true;
+
+ // case 3
+ if (validInstallType && sameTargetName && samePkgUid && (owningPkgInRom || romStubExists))
+ {
+ allowSidEclipse = true;
+ }
+
+ if (!allowSidEclipse)
+ {
+ std::wostringstream os;
+
+ os << L"The existing file " << owningSidFile << L" already has the SID 0x" << std::hex << sid
+ << std::dec << L", cannot install " << target << std::endl;
+ iProblemFiles.append(os.str());
+ iError = DUPLICATE_SID;
+ continue;
+ }
+ }
+ // .EXE exists in the ROM, but no ROM stub has ownership of it
+ else if (sidExistsInRom)
+ {
+ // A ROM stub could have referenced this .EXE using wildcards - in this case the SID will not
+ // be registered in the SIS registry.
+ bool isInstalled = iRegistry.IsInstalled(pkgUid);
+ bool ownedByRomStub = false;
+ if (isInstalled)
+ {
+ if (iRegistry.IsRomStubPackage(pkgUid))
+ {
+ CSISController* sisController = iRegistry.GetStubController(pkgUid);
+ TFileDescList fileDesList;
+ sisController->InstallBlock().GetFileList(fileDesList);
+ for(TFileDescListConstIter iter = fileDesList.begin(); iter != fileDesList.end(); ++iter)
+ {
+ const CSISFileDescription* fD = *iter;
+
+ std::wstring romStubTarget(fD->Target().GetString());
+
+ if (StringUtils::WildcardCompare(romStubTarget,romFileWithDuplicateSid))
+ {
+ ownedByRomStub = true;
+ break;
+ }
+ }
+ }
+ }
+
+ bool allowSidEclipse = false;
+
+ if (suFlag || isEclipseAllowed)
+ allowSidEclipse = true;
+
+ if (!allowSidEclipse && !ownedByRomStub)
+ {
+ std::wostringstream os;
+
+ os << L"A ROM file already has the SID 0x" << std::hex << file->Sid()
+ << std::dec << L", cannot install " << target << std::endl;
+ iProblemFiles.append(os.str());
+ iError = DUPLICATE_SID;
+ continue;
+ }
+ }
+ }
+ else if (realTarget.find(sysBinPath) != std::wstring::npos)
+ {
+ std::wostringstream os;
+ os << target << L" cannot be installed to a data caged area" << std::endl;
+ iProblemFiles.append(os.str());
+ iError = DATA_CAGE_VIOLATION;
+ continue;
+ }
+ }
+ }
+
+ // we still may have blocking files left. Handle them here.
+ WarnEclipseOverWrite(aFile);
+
+ iEclipsableOverwriteFiles.clear();
+ iEclipsableRomFiles.clear();
+
+ if (!iProblemFiles.empty())
+ {
+ std::string x;
+ throw InvalidSis("", Ucs2ToUtf8(iProblemFiles,x), iError);
+ }
+}
+
+void Installer::SetupExpressionEnvironment(const SisFile& aFile, const SisRegistry& aSisRegistry, RomManager& aRomManager )
+{
+ delete iExpressionEnvironment;
+ iExpressionEnvironment = new ExpressionEnvironment( aFile,
+ aSisRegistry,
+ iRomManager,
+ iConfigManager,
+ iParamList.SystemDrivePath() );
+
+ delete iExpressionEvaluator;
+ iExpressionEvaluator = new ExpressionEvaluator( *iExpressionEnvironment );
+}
+
+void Installer::CheckEmbedded(const SisFile& aFile)
+{
+ PackageUids pkgs = aFile.GetEmbeddedPackageUids();
+
+ for (PackageUids::const_iterator curr = pkgs.begin() ;
+ curr != pkgs.end() ;
+ ++curr)
+ {
+ if (!iRegistry.IsInstalled(*curr))
+ {
+
+ LWARN(L" Embedded Package not installed: UID " << std::hex << *curr );
+ }
+ }
+}
+
+
+void Installer::CreateStubSisFile(const InstallSISFile& aInstallSISFile, SisFile& aSis)
+{
+ int targetDrive = aInstallSISFile.iTargetDrive;
+ std::wstring drivePath = iConfigManager.GetLocalDrivePath(targetDrive);
+
+ drivePath.append(L"\\private\\");
+
+ // build SwiDaemon Pathname
+ std::wstring ctrl = StringUtils::MakePathFromSID(drivePath, KSwiDaemonUid);
+
+ if ( !MakeDir( ctrl ) )
+ {
+ throw InterpretSisError(L"Directory Creation Error - "+ctrl, DIRECTORY_CREATION_ERROR);
+ }
+
+ std::wstringstream s;
+ s << std::hex << aSis.GetPackageUid();
+
+ ctrl.append(s.str());
+
+
+ switch(aSis.GetInstallType())
+ {
+ case CSISInfo::EInstInstallation:
+ case CSISInfo::EInstPreInstalledApp:
+ {
+ // If an Installation type is SA/PA then append _0 after the stub UID.
+ ctrl.append(L"_0");
+ break;
+ }
+
+ case CSISInfo::EInstAugmentation:
+ {
+ // If an Installation type is SP then append an index after the stub UID.
+
+ int num = 0;
+
+ ctrl.append( L"_");
+
+ if (aInstallSISFile.iNotRegister)
+ {
+ // In this case, we can only assume all the previous SP installations
+ // (of a particular package) are consistently installed to the same target
+ // drive and all of the SP installation's attribute are set to either
+ // +mcardalone OR +mcardalonenr. Otherwise, the generated index will be wrong.
+
+ // Get the index from the daemon folder
+ num = GetAugmentationsNumber(ctrl);
+ }
+ else
+ {
+ // In this case, we can only assume all the previous SP installations
+ // (of a particular package) is consistent with attributes set to either
+ // +mcard OR +mcardnr. Otherwise, the generated index will be wrong.
+
+ // Get the index from the sisregistry entries
+ num = iRegistry.GetAugmentationsNumber(aSis.GetPackageUid());
+ }
+
+ std::wstringstream s2;
+ s2 << std::hex << num;
+ ctrl.append( s2.str() );
+ break;
+ }
+
+ default:
+ {
+ std::wstring err(L"SIS file cannot be propagated: ");
+ err.append(aInstallSISFile.iFileName);
+ throw InterpretSisError(err, SIS_NOT_SUPPORTED);
+ }
+ }
+
+ ctrl.append(L".sis");
+
+ // Display the target SIS file. Format the stub SIS file string so it displays correctly.
+ std::wstring ctrlDrive(L"$:");
+ ctrlDrive[0] = targetDrive;
+ std::wstring ctrlTarget = ctrl.substr(iConfigManager.GetLocalDrivePath(targetDrive).length(),ctrl.length());
+ ctrlDrive.append(ctrlTarget);
+
+ LINFO(L"\tCreating stub: " << ctrlDrive);
+
+ aSis.MakeSISStub(ctrl);
+ // If the NR flag is set, change the file attribute to RO
+ if (aInstallSISFile.iNonRemovable)
+ {
+ _wchmod(ctrl.c_str(),_S_IREAD);
+ }
+}