secureswitools/swisistools/source/interpretsislib/installer.cpp
changeset 0 ba25891c3a9e
child 12 7ca52d38f8c3
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #pragma warning (disable: 4786)
       
    20 
       
    21 #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
       
    22 
       
    23 #include "dbhelper.h" 
       
    24 
       
    25 #endif //SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
       
    26 #include <exception>
       
    27 #include <sstream>
       
    28 #include <algorithm>
       
    29 #include <functional>
       
    30 #include <fstream>
       
    31 #include <stdio.h>
       
    32 #include <sys/stat.h>
       
    33 
       
    34 // SisX Library
       
    35 #include "sisdependency.h"
       
    36 #include "sisversionrange.h"
       
    37 #include "sisversion.h"
       
    38 #include "sisprerequisites.h"
       
    39 #include "sisfiledescription.h"
       
    40 #include "sisstring.h"
       
    41 #include "sishash.h"
       
    42 
       
    43 // User includes
       
    44 #include "stringutils.h"
       
    45 #include "parameterlist.h"
       
    46 #include "rommanager.h"
       
    47 #include "configmanager.h"
       
    48 #include "errors.h"
       
    49 #include "is_utils.h"
       
    50 #include "installer.h"
       
    51 #include "sisregistryobject.h"
       
    52 #include "adornedutilities.h"
       
    53 
       
    54 // Constants
       
    55 const char KRomDriveLetter = 'z';
       
    56 const TUint32 KSwiDaemonUid = 0x10202DCE;
       
    57 const std::wstring KSysBinPath = L"\\sys\\bin\\";
       
    58 
       
    59 TInt CheckWildCard(TInt aVal, TInt aReplace)
       
    60 {
       
    61 	return
       
    62 		aVal == -1
       
    63 		? aReplace
       
    64 		: aVal;
       
    65 }
       
    66 
       
    67 bool InRange(const Version& aVersion, const CSISVersionRange& aRange)
       
    68 {
       
    69 	Version from(
       
    70 		CheckWildCard(aRange.FromVersion().Major(), aVersion.GetMajor()),
       
    71 		CheckWildCard(aRange.FromVersion().Minor(), aVersion.GetMinor()),
       
    72 		CheckWildCard(aRange.FromVersion().Build(), aVersion.GetBuild()));
       
    73 
       
    74 	if(!aRange.ToVersion().WasteOfSpace())
       
    75 	{
       
    76 		Version to(
       
    77 			CheckWildCard(aRange.ToVersion().Major(), aVersion.GetMajor()),
       
    78 			CheckWildCard(aRange.ToVersion().Minor(), aVersion.GetMinor()),
       
    79 			CheckWildCard(aRange.ToVersion().Build(), aVersion.GetBuild()));
       
    80 
       
    81 		if (aVersion == from ||
       
    82 			aVersion == to)
       
    83 		{
       
    84 			return true;
       
    85 		}
       
    86 
       
    87 		return (aVersion > from && aVersion < to);
       
    88 	}
       
    89 	else
       
    90 	{
       
    91 		return (aVersion >= from);
       
    92 	}
       
    93 }
       
    94 
       
    95 
       
    96 Installer::Installer( SisRegistry& aReg, const CParameterList& aParamList, RomManager& aRomManager, ConfigManager& aConfigManager )
       
    97 :   iParamList(aParamList), iRegistry(aReg), iRomManager( aRomManager ), iConfigManager( aConfigManager ),
       
    98     iExpressionEnvironment( NULL ), iExpressionEvaluator( NULL )
       
    99 {
       
   100 }
       
   101 
       
   102 TInt Installer::Install(const CParameterList::SISFileList& aList)
       
   103 {
       
   104 	TInt result = 0;
       
   105 	CParameterList::SISFileList sisFiles;
       
   106 
       
   107 	// Get the SIS files
       
   108 	for (CParameterList::SISFileList::const_iterator curr = aList.begin(); curr != aList.end(); ++curr)
       
   109 	{
       
   110 		std::wstring shortName(curr->iFileName);
       
   111 
       
   112 		// Ensure formatting is correct
       
   113 		if ( StringUtils::IsLastCharacter( shortName, KDirectorySeparator[ 0 ] ) ||
       
   114              StringUtils::IsLastCharacter( shortName, L'/' ) )
       
   115 		{
       
   116 			shortName.erase(shortName.length()-1,1);
       
   117 		}
       
   118 
       
   119 		if ( IsDirectory(shortName) )
       
   120 		{
       
   121 			std::list<std::wstring> contents;
       
   122 			GetDirContents(shortName, contents);
       
   123 
       
   124 			for (std::list<std::wstring>::iterator currStr = contents.begin(); currStr != contents.end(); ++currStr)
       
   125 			{
       
   126 				if ((currStr->find(L".SIS",0) != std::wstring::npos)
       
   127 					|| (currStr->find(L".sis",0) != std::wstring::npos))
       
   128 				{
       
   129 					InstallSISFile sisFileName(shortName + KDirectorySeparator + *currStr, 
       
   130 												curr->iTargetDrive, curr->iGenerateStub, 
       
   131 												curr->iNonRemovable, curr->iNotRegister, curr->iSUFlag);
       
   132 
       
   133 					sisFiles.push_back(sisFileName);
       
   134 				}
       
   135 			}
       
   136 
       
   137 			if (sisFiles.empty())
       
   138 			{
       
   139 				LWARN(L"No .SIS files found in directory" << shortName);
       
   140 			}
       
   141 		}
       
   142 		else if ((shortName.find(L".SIS",0) != std::wstring::npos)
       
   143 				|| (shortName.find(L".sis",0) != std::wstring::npos))
       
   144 		{
       
   145 			InstallSISFile sisFileName(shortName, curr->iTargetDrive, curr->iGenerateStub, 
       
   146 										curr->iNonRemovable, curr->iNotRegister, curr->iSUFlag);
       
   147 
       
   148 			sisFiles.push_back(sisFileName);
       
   149 		}
       
   150 		else
       
   151 		{
       
   152 			LWARN(L"Invalid SIS file: " << shortName);
       
   153 		}
       
   154 	}
       
   155 
       
   156 	bool installed = false;
       
   157 
       
   158 	do
       
   159 		{
       
   160 		installed = false;
       
   161 		iMissing.clear();
       
   162 		CParameterList::SISFileList::iterator curr = sisFiles.begin();
       
   163 
       
   164 		while (curr != sisFiles.end())
       
   165 			{
       
   166 			// install it
       
   167 			try 
       
   168 				{
       
   169 				LINFO(L"*** Installing " << (curr->iFileName) << L" ***");
       
   170 
       
   171 				SanitiseSISFileAttributes(*curr);
       
   172 
       
   173 				result = Install(*curr);
       
   174 
       
   175 				if ( result == SUCCESS)
       
   176 					{
       
   177                     LINFO(L"");
       
   178 					LINFO(L"*** Installed " << (curr->iFileName) << L" ***");
       
   179 
       
   180 					installed =  true;
       
   181 					curr = sisFiles.erase(curr);
       
   182 					}
       
   183 				else
       
   184 					{
       
   185 					LERROR(L"Failed to install " << (curr->iFileName));
       
   186 					++curr;
       
   187 					}
       
   188 				}
       
   189 			catch(CSISException e)
       
   190 				{
       
   191 				// catch problems with individual sis files
       
   192 				LERROR(L"Unable to install " << (curr->iFileName));
       
   193 				LINFO(e.widewhat());
       
   194 				curr = sisFiles.erase(curr);
       
   195 				if (result == 0)
       
   196 					result =  FILE_ERROR;
       
   197 				}
       
   198 			catch  (InterpretSisError& e)
       
   199 				{
       
   200 				LERROR(L"Failed installing " << (curr->iFileName));
       
   201 				LERROR(L"\t" << Utf8ToUcs2(e.what()));
       
   202 				curr = sisFiles.erase(curr);
       
   203 				
       
   204 				if (result == 0)
       
   205 					result =  e.GetErrorCode();
       
   206 				}
       
   207 			}
       
   208 		}
       
   209 	while (installed);
       
   210 
       
   211 	if (result == 0 && !iMissing.empty())
       
   212 		result = MISSING_DEPENDENCY;
       
   213 
       
   214 	if(iParamList.RegistryVersionExists())
       
   215 		{
       
   216 	// Backup.lst regenerated at SisRegistry startup
       
   217 	iRegistry.RemoveBackupLst();
       
   218 		}
       
   219 	return result;
       
   220 
       
   221 }
       
   222 
       
   223 
       
   224 void Installer::SanitiseSISFileAttributes(const InstallSISFile& aInstallSISFile)
       
   225 {
       
   226 	SisFile file(aInstallSISFile.iFileName);
       
   227 
       
   228 	int targetDrive = aInstallSISFile.iTargetDrive;
       
   229 
       
   230 	if (!iConfigManager.IsTargetDrivePresent(targetDrive))
       
   231 	{
       
   232 		std::wstring shortName(aInstallSISFile.iFileName);
       
   233 
       
   234 		throw InterpretSisError(L"The installing target drive for " + shortName +
       
   235 				L" is not defined", CMDLINE_ERROR);
       
   236 	}
       
   237 
       
   238 	if (aInstallSISFile.iGenerateStub && !iConfigManager.IsTargetDriveExt(targetDrive))
       
   239 	{
       
   240 		std::wstring shortName(aInstallSISFile.iFileName);
       
   241 
       
   242 		throw InterpretSisError(L"The stub SIS file for " + shortName +
       
   243 				L" cannot be created to an internal drive", CMDLINE_ERROR);
       
   244 	}
       
   245 
       
   246 	if (aInstallSISFile.iGenerateStub && file.GetInstallType() == CSISInfo::EInstPartialUpgrade)
       
   247 	{
       
   248 	std::wstring shortName(aInstallSISFile.iFileName);
       
   249 
       
   250 	throw InterpretSisError(L"Generating stub SIS file for " + shortName +
       
   251 				L" (PU type) is not supported", SIS_NOT_SUPPORTED);
       
   252 	}
       
   253 }
       
   254 
       
   255 
       
   256 TInt Installer::Install(const InstallSISFile& aInstallSISFile)
       
   257 {
       
   258 	SisFile file(aInstallSISFile.iFileName);
       
   259 
       
   260 	// Setup the expression evaluator
       
   261 	SetupExpressionEnvironment( file, GetSisRegistry(), iRomManager );
       
   262 
       
   263 	// check presence of embedded sis files and 
       
   264 	// display a warning if they are not installed before
       
   265 	if (file.HasEmbedded())
       
   266 		{
       
   267 		CheckEmbedded(file);
       
   268 		}
       
   269 
       
   270 	// check file is acceptable
       
   271 	file.CheckValid();
       
   272 
       
   273 	if (!DependenciesOk(file))
       
   274 	{
       
   275 		return MISSING_DEPENDENCY;
       
   276 	}
       
   277 
       
   278 	if (!IsValidUpgrade(file, aInstallSISFile.iSUFlag))
       
   279 	{
       
   280 		return INVALID_UPGRADE;
       
   281 	}
       
   282 
       
   283 	InstallableFiles installable;
       
   284 	GetInstallableFiles(file, installable, *iExpressionEvaluator, aInstallSISFile.iTargetDrive);
       
   285 
       
   286 	// Uninstall the same package (if found) prior to any installation
       
   287 	UninstallPkg(file);
       
   288 
       
   289 	CheckDestinations(file, installable, aInstallSISFile);
       
   290 
       
   291 	InstallFiles(installable, iParamList.SystemDriveLetter());
       
   292 
       
   293 	UpdateRegistry(file, installable, aInstallSISFile, aInstallSISFile.iSUFlag);
       
   294 	
       
   295 	if (aInstallSISFile.iGenerateStub)
       
   296 	{
       
   297 		CreateStubSisFile(aInstallSISFile, file);
       
   298 	}
       
   299 
       
   300 	FreeInstallableFiles(installable);
       
   301 
       
   302 	return SUCCESS;
       
   303 }
       
   304 
       
   305 /** 
       
   306  Prepares a list of ROM files which are allowed to be eclipsed from the right 
       
   307  source according to the SIS file upgrade type.
       
   308 
       
   309  If a SIS file wants to eclipse a file in ROM, it will fail unless there is an 
       
   310  associated stub SIS file present in the ROM that can be used by the Installer to 
       
   311  identify the replacement file as a valid upgrade of the original.  
       
   312  */
       
   313 void Installer::PrepareEclipsableFilesList(const SisFile& aSis)
       
   314 {
       
   315 	iEclipsableRomFiles.clear();
       
   316 	iEclipsableOverwriteFiles.clear();
       
   317 
       
   318 	TUint32 pkgUid = aSis.GetPackageUid();
       
   319 
       
   320 	// upgrade SIS file attributes
       
   321 	bool puInstallation = aSis.GetInstallType() == CSISInfo::EInstPartialUpgrade;
       
   322 	bool spInstallation = aSis.GetInstallType() == CSISInfo::EInstAugmentation;
       
   323 	
       
   324 	// base package
       
   325 	const SisRegistryObject& registryEntry = iRegistry.GetRegistryObject(pkgUid);
       
   326 	bool currentPkgIsInRom = registryEntry.GetInRom();
       
   327 	bool stubExistsInRom = iRegistry.IsRomStubPackage(pkgUid); 
       
   328 
       
   329 	// SA+RU, PU and SP are all allowed to eclipse ROM files. There must
       
   330 	// exist a valid ROM stub in order to populate the eclipsable files list.
       
   331 	if (IsValidEclipsingUpgrade(aSis, registryEntry))
       
   332 	{
       
   333 		// when an upgrade happens over an upgrade which has already upgraded the 
       
   334 		// ROM based pacakge (i.e. ROM Stub -> SA+RU -> PU), don't populate the
       
   335 		// eclipsable files from the SIS registry entry which may be in-complete.
       
   336 		// Directly populate the eclipsable files list from the corresponding stub
       
   337 		// SIS file.
       
   338 		if (!currentPkgIsInRom && stubExistsInRom && (puInstallation || spInstallation))
       
   339 		{
       
   340 			iRegistry.GetStubFileEntries(pkgUid, iEclipsableRomFiles);
       
   341 		}
       
   342 		else
       
   343 		{
       
   344 			const FileDescriptions& files = registryEntry.GetFileDescriptions();
       
   345 			FileDescriptions::const_iterator curr = files.begin();
       
   346 			FileDescriptions::const_iterator end  = files.end();
       
   347 
       
   348 			for ( ; curr != end ; ++curr)
       
   349 			{
       
   350 				std::wstring target((*curr)->GetTarget());
       
   351 				iEclipsableRomFiles.push_back(target);
       
   352 			}
       
   353 		}
       
   354 	}
       
   355 }
       
   356 
       
   357 /**
       
   358  Non-SU packages can Eclipse iff:
       
   359  a) The package uids match and 
       
   360  b) The package to be installed is immediate Upgrade to ROM (SP or PU over ROM)
       
   361       (SA is allowed based on next condition)
       
   362  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
       
   363  are allowed to eclipse files.    
       
   364  */
       
   365 bool Installer::IsValidEclipsingUpgrade(const SisFile& aSis, const SisRegistryObject& registryEntry)
       
   366 {
       
   367 	TUint32 pkgUid = aSis.GetPackageUid();
       
   368 
       
   369 	// case a)
       
   370 	if (pkgUid != registryEntry.GetUid())
       
   371 		return false;
       
   372 
       
   373 	bool stubExistsInRom = iRegistry.IsRomStubPackage(pkgUid);
       
   374 	bool isBaseInRom = registryEntry.GetInRom();
       
   375 	bool saInstall = aSis.GetInstallType() == CSISInfo::EInstInstallation;
       
   376 	bool reg51 = true;
       
   377 	if(iParamList.RegistryVersionExists())
       
   378 		{
       
   379 	int regMajor = iParamList.RegistryMajorVersion();
       
   380 	int regMinor = iParamList.RegistryMinorVersion();
       
   381 	bool reg51 = (regMajor >= SisRegistry::KSisRegistryMajorVersion) &&  
       
   382 					(regMinor >= SisRegistry::KSisRegistryMinorVersion);
       
   383 		}
       
   384 	// RU flag was introduce when the SISRegistry was 5.1, otherwise, treat it as normal SA file
       
   385 	bool romUpgradeFlag = (aSis.GetInstallFlags() & CSISInfo::EInstFlagROMUpgrade) && reg51;
       
   386 	bool romUpgradableSA = saInstall && romUpgradeFlag;
       
   387 	bool puInstall = aSis.GetInstallType() == CSISInfo::EInstPartialUpgrade;
       
   388 	bool spInstall = aSis.GetInstallType() == CSISInfo::EInstAugmentation;
       
   389 	
       
   390 	// case b)
       
   391 	if (isBaseInRom && !saInstall)
       
   392 		return true;
       
   393 
       
   394 	// case c)
       
   395 	return (stubExistsInRom && (romUpgradableSA || puInstall || spInstall));    	
       
   396 }
       
   397 
       
   398 void Installer::UninstallPkg(const SisFile& aSis)
       
   399 {
       
   400 	TUint32 uid = aSis.GetPackageUid();
       
   401 	TUint32 installType = aSis.GetInstallType();
       
   402 
       
   403 	// Check to see the SA is installed, otherwise, RemovePkg() will throw an exception
       
   404 	if (iRegistry.IsInstalled(uid) && (installType == CSISInfo::EInstInstallation))
       
   405 	{
       
   406 		LINFO(L"Removing package \"" << aSis.GetPackageName() << L"\" prior to re-installation");
       
   407 
       
   408 		// Remove all installed files for this Uid's packages and all the SisRegistry Entries
       
   409 		iRegistry.RemovePkg(uid, true);
       
   410 	}
       
   411 
       
   412 	if (installType == CSISInfo::EInstAugmentation)
       
   413 	{
       
   414 		// Clean up the installed files from the specified SP package and the SisRegistry Entry
       
   415 		iRegistry.RemoveEntry(uid, aSis.GetPackageName(), aSis.GetVendorName());
       
   416 	}
       
   417 
       
   418 	// Regenerate the ROM stub registry entries for eclipsing check later.
       
   419 	iRegistry.GenerateStubRegistry();
       
   420 }
       
   421 
       
   422 
       
   423 struct CheckDependencyMet
       
   424 {
       
   425 	CheckDependencyMet(
       
   426 		Installer& aInstaller,
       
   427 		std::vector<SisRegistryDependency>& aMissing)
       
   428 		: iInstaller(aInstaller),
       
   429 		iMissingDependencies(aMissing)
       
   430 	{}
       
   431 
       
   432 	void operator()(const CSISDependency* dep)
       
   433 	{
       
   434 		if (!iInstaller.CheckDependency(dep))
       
   435 		{
       
   436 			iMissingDependencies.push_back(SisRegistryDependency(*dep));
       
   437 		}
       
   438 	}
       
   439 	Installer& iInstaller;
       
   440 	std::vector<SisRegistryDependency>& iMissingDependencies;
       
   441 };
       
   442 
       
   443 bool Installer::CheckDependency(const CSISDependency* aDep)
       
   444 {
       
   445 	bool result = false;
       
   446 
       
   447 	try
       
   448 	{
       
   449 		const SisRegistryObject& pkg =
       
   450 			iRegistry.GetRegistryObject(aDep->SisUID().UID1());
       
   451 
       
   452 		const CSISVersionRange& range = aDep->VersionRange();
       
   453 		if (!range.WasteOfSpace() && InRange(pkg.GetVersion(), range))
       
   454 			{
       
   455 			result = true;
       
   456 			}
       
   457 		else
       
   458 			{
       
   459 			result = false;
       
   460 			}
       
   461 	}
       
   462 
       
   463 	catch(...)
       
   464 	{
       
   465 		result = false;
       
   466 	}
       
   467 	return result ;
       
   468 }
       
   469 
       
   470 bool Installer::DependenciesOk(const SisFile& aFile)
       
   471 	{
       
   472 	const CSISPrerequisites* reqs = aFile.GetDependencies();
       
   473 	const CSISPrerequisites::TDependencyList& deps = reqs->DependencyList();
       
   474 
       
   475 	CheckDependencyMet checkDependencyMet(*this, iMissing[aFile.GetPackageName()]);
       
   476 	for(int i = 0; i < deps.size(); ++i)
       
   477 		{
       
   478 		checkDependencyMet(&deps[i]);
       
   479 		}
       
   480 
       
   481 	return iMissing[aFile.GetPackageName()].size() == 0;
       
   482 	}
       
   483 
       
   484 
       
   485 bool Installer::IsValidUpgrade(const SisFile& aFile, bool aSUFlag)
       
   486 {
       
   487 	TUint32 pkg = aFile.GetPackageUid();
       
   488 	TUint32 installFlags = aFile.GetInstallFlags();
       
   489 	bool RUFlag = ((installFlags & CSISInfo::EInstFlagROMUpgrade) &&  CSISInfo::EInstFlagROMUpgrade);
       
   490 
       
   491 	if(iParamList.RegistryVersionExists())
       
   492 		{
       
   493 	int regMajor = iParamList.RegistryMajorVersion();
       
   494 	int regMinor = iParamList.RegistryMinorVersion();
       
   495 	bool reg51 = (regMajor >= SisRegistry::KSisRegistryMajorVersion) &&  
       
   496 					(regMinor >= SisRegistry::KSisRegistryMinorVersion);
       
   497 	// RU flag was introduce when the SISRegistry was 5.1, otherwise, treat it as normal SA file
       
   498 		RUFlag = RUFlag && reg51;
       
   499 		}
       
   500 	if ( aSUFlag && !RUFlag)
       
   501 	{
       
   502 		std::stringstream err;
       
   503 		err << "Illegal system upgrade (SU) of ROM package 0x" << std::hex << pkg << " without setting the RU flag";
       
   504 		throw InterpretSisError(err.str(), ATTEMPT_TO_UPGRADE_ROM_PKG);
       
   505 	}
       
   506 
       
   507 	// Check is this package has been installed before
       
   508 
       
   509 	TUint32 installType = aFile.GetInstallType();
       
   510 
       
   511 	if (iRegistry.IsInstalled(pkg))
       
   512 		{
       
   513 		ValidateRegistry(aFile,pkg,installFlags,RUFlag);	
       
   514 		}
       
   515 	else if (installType == CSISInfo::EInstAugmentation || installType == CSISInfo::EInstPartialUpgrade)
       
   516 		{
       
   517 		// Installing SP and PU without the base package
       
   518 		std::stringstream err;
       
   519 		err << "Could not perform upgrade - the base package 0x" << std::hex 
       
   520 			<< pkg << " is missing";
       
   521 
       
   522 		throw InterpretSisError(err.str(), MISSING_BASE_PACKAGE);
       
   523 		}
       
   524 
       
   525 	return true;
       
   526 	}
       
   527 
       
   528 void Installer::ValidateRegistry(const SisFile& aFile, TUint32 aPckgUid, TUint32 aInstallFlags, bool aRUFlag)
       
   529 	{
       
   530 	bool isSisNonRemovable = aInstallFlags & CSISInfo::EInstFlagNonRemovable;
       
   531 	bool isBaseRemovable = false;
       
   532 	bool inRom = false;
       
   533 	bool isPreInstalled = false;
       
   534 	TUint32 uid = 0;
       
   535 	std::wstring packageName;
       
   536 	
       
   537 	InitializeRegistryDetails(aPckgUid, isBaseRemovable, inRom, isPreInstalled, uid, packageName );
       
   538 	
       
   539 	// Check is this package has been installed before
       
   540 	TUint32 installType = aFile.GetInstallType();
       
   541 
       
   542 	if (installType == CSISInfo::EInstInstallation)
       
   543 		{
       
   544 		if (inRom && !aRUFlag)
       
   545 			{
       
   546 			std::stringstream err;
       
   547 			err << "Illegal SA upgrade to ROM package 0x" << std::hex << aPckgUid;
       
   548 			throw InterpretSisError(err.str(), ATTEMPT_TO_UPGRADE_ROM_PKG);
       
   549 			}
       
   550 		// This is not a ROM base package, check is there a SIS stub base package present
       
   551 		else if (iRegistry.IsRomStubPackage(aPckgUid) && !aRUFlag)
       
   552 			{			
       
   553 			std::stringstream err;
       
   554 			err << "Indirect SA upgrade to ROM package 0x" << std::hex << aPckgUid
       
   555 				<< " missing RU flag";
       
   556 			throw InterpretSisError(err.str(), ATTEMPT_TO_UPGRADE_ROM_PKG);
       
   557 			}
       
   558 		}
       
   559 	else if (installType == CSISInfo::EInstAugmentation)
       
   560 		{
       
   561 		if (isBaseRemovable && isSisNonRemovable)
       
   562 			{
       
   563 			std::stringstream err;
       
   564 			err << "Not allowed to install SP + NR to the removable base package 0x" << std::hex << aPckgUid;
       
   565 
       
   566 			throw InterpretSisError(err.str(), INVALID_UPGRADE);
       
   567 			}
       
   568 
       
   569 		if (packageName == aFile.GetPackageName() && uid == aFile.GetPackageUid())
       
   570 			{
       
   571 			std::stringstream err;
       
   572 			err << "Cannot augment package 0x" << std::hex << aFile.GetPackageUid() << " - package names match";
       
   573 
       
   574 			throw InterpretSisError(err.str(), MISSING_BASE_PACKAGE);
       
   575 			}
       
   576 		}
       
   577 	else if (installType == CSISInfo::EInstPartialUpgrade)
       
   578 		{
       
   579 		// Do not allow partial upgrades to preinstalled applications
       
   580 		if (isPreInstalled)
       
   581 			{
       
   582 			std::stringstream err;
       
   583 			err << "Cannot install PU (0x" << std::hex << aPckgUid << ") to a PA";
       
   584 
       
   585 			throw InterpretSisError(err.str(), INVALID_UPGRADE);
       
   586 			}
       
   587 
       
   588 		// Partial Upgrade can only be installed to a base package of the same install flag type.
       
   589 		// The only exception is a ROM stub which is upgradable and non-removable by definition.
       
   590 		if ((isBaseRemovable == isSisNonRemovable) && !inRom )
       
   591 			{
       
   592 			std::stringstream err;
       
   593 			err << "Cannot install PU (0x" << std::hex << aPckgUid << ") to a base package with a different removable flag type";
       
   594 
       
   595 			throw InterpretSisError(err.str(), INVALID_UPGRADE);
       
   596 			}
       
   597 		}
       
   598 	else if (installType == CSISInfo::EInstPreInstalledApp)
       
   599 		{
       
   600 		std::stringstream err;
       
   601 		err << "Cannot install PA (0x" << std::hex << aPckgUid << ") over top of another package";
       
   602 
       
   603 		throw InterpretSisError(err.str(), INVALID_UPGRADE);
       
   604 		}
       
   605 	}
       
   606 
       
   607 void Installer::InitializeRegistryDetails(  const TUint32 aPckgUid, bool& aIsBaseRemovable, 
       
   608 											bool& aInRom, bool& aIsPreInstalled, 
       
   609 											TUint32& aUid, std::wstring& aPackageName 
       
   610 										)
       
   611 	{
       
   612 	if(iParamList.RegistryVersionExists() )
       
   613 		{
       
   614 		const SisRegistryObject& obj = iRegistry.GetRegistryObject(aPckgUid);
       
   615 		aIsBaseRemovable = obj.GetIsRemovable();
       
   616 		aInRom = obj.GetInRom();
       
   617 		aIsPreInstalled = obj.IsPreInstalled();
       
   618 		aUid = obj.GetUid();
       
   619 		aPackageName = obj.GetPackageName();
       
   620 		}
       
   621 	#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
       
   622 	else
       
   623 		{
       
   624 		const DbHelper* dbHelper( iRegistry.GetDbHelper());
       
   625 		TInt32 componentId = dbHelper->GetComponentId(aPckgUid);
       
   626 		aIsBaseRemovable = dbHelper->GetIsRemovable(componentId);
       
   627 		aInRom = dbHelper->GetInRom(componentId);
       
   628 		if(dbHelper->GetInstallType(componentId) == CSISInfo::EInstPreInstalledApp )
       
   629 			{
       
   630 			aIsPreInstalled = true;
       
   631 			}
       
   632 		aUid = dbHelper->GetUid(componentId);
       
   633 		aPackageName = dbHelper->GetPackageName(componentId);
       
   634 		}
       
   635 	#endif // SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK	
       
   636 	}
       
   637 
       
   638 bool Installer::GetInstallableFiles(const SisFile& aFile, InstallableFiles& aList, ExpressionEvaluator& aEvaluator, 
       
   639 									int aInstallingDrive)
       
   640 {
       
   641 	return aFile.GetInstallableFiles(aList, aEvaluator, 
       
   642 		iConfigManager.GetLocalDrivePath(aInstallingDrive), aInstallingDrive);
       
   643 }
       
   644 
       
   645 
       
   646 struct InstallFile
       
   647 {
       
   648 	InstallFile(const std::wstring& aCDrive, const int aSystemDrive)
       
   649 		: iSystemDrivePath(aCDrive), iSystemDrive(aSystemDrive) {}
       
   650 
       
   651 	const std::wstring& iSystemDrivePath;
       
   652 	const int iSystemDrive;
       
   653 
       
   654 	void operator()(const InstallableFile* aFile)
       
   655 	{
       
   656 		std::fstream output;
       
   657 		std::wstring target(aFile->GetTarget());
       
   658 		std::wstring localTarget(aFile->GetLocalTarget());
       
   659 
       
   660 		bool fileNullOption = (aFile->FileDescription()->Operation() == CSISFileDescription::EOpNull);
       
   661 				
       
   662         if (!target.length())
       
   663             {
       
   664 			LINFO(L"Skipping file with empty destination filename");
       
   665             }
       
   666         else
       
   667             {
       
   668 			// Unicode characters can not be displayed on DOS prompt
       
   669  			std::string temporary = Ucs2ToUtf8(target);
       
   670 			std::wstring targetDisplay = Utf8ToUcs2( temporary );
       
   671 		    LINFO(L"Installing file: " << targetDisplay);
       
   672 
       
   673             std::wstring targetDirectory = localTarget.substr( 0, localTarget.rfind( KDirectorySeparator ) );    		
       
   674 			const unsigned char* buffer = NULL;
       
   675 			TUint32 len;
       
   676 
       
   677 			if (aFile->IsStub()) // PA
       
   678 			{
       
   679 				// check the presence of file at target location 
       
   680 				if (!FileExists(localTarget))
       
   681 				{
       
   682 					throw InterpretSisError(L"PA Install error - No target file- "+target, PA_NO_TARGET_FILE);
       
   683 				}
       
   684 			}
       
   685 			else // SA 
       
   686 			{
       
   687 				// if the FN option specified, leave the file creation
       
   688 				if (fileNullOption)
       
   689 				{
       
   690 					LINFO(L"File " << target << L" contains \"Delete-File-On-Uninstall\" option." );
       
   691 				}
       
   692 				else 
       
   693 				{
       
   694 					if ( !MakeDir( targetDirectory ) )
       
   695 					{
       
   696 						throw InterpretSisError(L"Directory Creation Error - "+targetDirectory,
       
   697 													DIRECTORY_CREATION_ERROR);
       
   698 					}
       
   699 
       
   700 					HANDLE hFile = MakeSISOpenFile(localTarget.c_str(), GENERIC_WRITE, CREATE_ALWAYS);
       
   701 					if( INVALID_HANDLE_VALUE == hFile )
       
   702 					{
       
   703 						throw InterpretSisError(L"FileOpenError - "+target, FILE_ERROR);
       
   704 					}
       
   705 					buffer = aFile->FileData()->Data();
       
   706 					len = aFile->FileData()->UncompressedSize();
       
   707 					DWORD bytesWritten;
       
   708 					BOOL error = WriteFile(hFile, buffer, len, &bytesWritten, NULL);
       
   709 					if( error != TRUE )
       
   710 					{
       
   711 						throw InterpretSisError(L"FileWriteError - "+target, FILE_ERROR);
       
   712 					}
       
   713 					CloseHandle(hFile);
       
   714 				}
       
   715 			}
       
   716 
       
   717 			if (aFile->IsExecutable() && !fileNullOption)
       
   718 			{
       
   719 				// register the hash
       
   720 				std::wstring basename = localTarget.substr( localTarget.rfind( KDirectorySeparator ) + 1 );
       
   721 				std::wstring hashdir = iSystemDrivePath + L"\\sys\\hash\\";
       
   722 				std::wstring reghashdir = L"$:\\sys\\hash\\";
       
   723 
       
   724 				if ( !MakeDir( hashdir ) )
       
   725 				{
       
   726 					throw InterpretSisError(L"Directory Creation Error - "+hashdir,
       
   727 													DIRECTORY_CREATION_ERROR);
       
   728 				}
       
   729 
       
   730 				// hash file is always created on the system drive
       
   731 				reghashdir[0] = iSystemDrive;
       
   732 
       
   733 				LINFO(L"\tCreating hash: " << reghashdir << basename);
       
   734 
       
   735 				std::wstring hash = hashdir + basename;
       
   736 				HANDLE hFile = MakeSISOpenFile(hash.c_str(), GENERIC_WRITE, CREATE_ALWAYS);		
       
   737 				if( INVALID_HANDLE_VALUE == hFile )
       
   738 				{
       
   739 					throw InterpretSisError(L"FileOpenError - " + hashdir + basename, FILE_ERROR);
       
   740 				}
       
   741 
       
   742 				buffer = aFile->FileDescription()->Hash().Blob().Data();
       
   743 				len = aFile->FileDescription()->Hash().Blob().Size();
       
   744 				DWORD bytesWritten;
       
   745 				BOOL error = WriteFile(hFile, buffer, len, &bytesWritten, NULL);
       
   746 				if( error != TRUE )
       
   747 				{
       
   748 					throw InterpretSisError(L"FileWriteError - " + hashdir + basename, FILE_ERROR);
       
   749 				}
       
   750 				CloseHandle(hFile);
       
   751 			}
       
   752         }
       
   753 	}
       
   754 };
       
   755 
       
   756 
       
   757 void Installer::InstallFiles(const InstallableFiles& aList, const int aInstallDrive)
       
   758 {
       
   759 	std::wstring localTargetPath = iConfigManager.GetLocalDrivePath(aInstallDrive);
       
   760 
       
   761 	std::for_each(aList.begin(), aList.end(), InstallFile(localTargetPath, aInstallDrive));
       
   762 }
       
   763 
       
   764 
       
   765 void Installer::UpdateRegistry(const SisFile& aFile, const InstallableFiles& aList, 
       
   766 												   const InstallSISFile& aInstallSISFile, const bool aSUFlag)
       
   767 {
       
   768 	if (aFile.GetInstallType() == CSISInfo::EInstPartialUpgrade)
       
   769 	{
       
   770 		iRegistry.UpdateRegistryEntry(aFile, aList, aInstallSISFile);
       
   771 	}
       
   772 	else if (!aInstallSISFile.iNotRegister)
       
   773 	{
       
   774 		iRegistry.AddRegistryEntry(aFile, aList, aInstallSISFile);
       
   775 	}
       
   776 }
       
   777 
       
   778 /** This function takes a fully qualified name and searches the filesystem through for all possible adorned filename matches.
       
   779  Besides that it calculates the unadorned version of the input filename as well and return it through the corresponding given 
       
   780  input reference variable.
       
   781  @param aTarget the fully qualified filename (full path and name)
       
   782  @param aUnadornedName the calulated unadorned name is returned through this variable(full path and unadorned name calculated from aTarget)
       
   783  @param aAdornedFileNamesFound all the found adorned name matches are returned through this list
       
   784 */
       
   785 void Installer::AdornedProcessingOfFile(const std::wstring& aTarget, std::wstring& aUnadornedName, 
       
   786 										std::list<std::wstring>& aAdornedFileNamesFound)
       
   787 {
       
   788 	std::wstring targetNameAndExt(StringUtils::NameAndExt(aTarget));
       
   789 	std::wstring targetDriveAndPath(StringUtils::DriveAndPath(aTarget));
       
   790 
       
   791 	std::wstring unadornedName;
       
   792 	std::wstring searchNameWild;
       
   793 
       
   794 	// create the unadorned version of the target file e.g. c:\sys\bin\a.dll
       
   795 	GetUnadornedFileName(targetNameAndExt, unadornedName);
       
   796 	aUnadornedName = targetDriveAndPath;
       
   797 	aUnadornedName.append(unadornedName);
       
   798 
       
   799 	// create a wildcard version of the target file e.g. c:\sys\bin\a{????????}.dll
       
   800 	GenerateSearchNameWild(targetNameAndExt, searchNameWild);
       
   801 
       
   802 	const DrivesMap& driveMap = iConfigManager.GetDrivesMap();
       
   803 	FindAllAdornedVariants(searchNameWild, KSysBinPath, aAdornedFileNamesFound, driveMap);
       
   804 
       
   805 	// find all adorned variants in the ROM/ROFS logs
       
   806 	if (iParamList.IsFlagSet(CParameterList::EFlagsRomRofsLogFilesSet))
       
   807 	{
       
   808 		std::wstring romSearchNameWild = L"z:\\sys\\bin\\";
       
   809 		romSearchNameWild.append(searchNameWild);
       
   810 		iRomManager.FindAllAdornedVariants(romSearchNameWild, aAdornedFileNamesFound);
       
   811 	}
       
   812 }
       
   813 
       
   814 /**
       
   815  This function ensures the SIS file to be installed does not illegally
       
   816  eclipse a file already installed in the ROM.
       
   817  @param aFile the SIS file to be installed
       
   818  @param aTarget the fully qualified filename (full path and name)
       
   819  @param aInstallableFile the current installing files properties
       
   820  @param aSUFlag specifies if the installing SIS file has been signed by a SU certificate
       
   821 */
       
   822 bool Installer::ValidEclipse(const SisFile& aFile, const std::wstring& aTarget, const InstallableFile& aInstallableFile, bool aSUFlag)
       
   823 {
       
   824 	bool result = true;
       
   825 	std::wstring searchNameUnadorned = L"";
       
   826 	std::wstring localDir = L"";
       
   827 	std::list<std::wstring> adornedFileNamesFound;
       
   828 
       
   829 	int targetDisk = tolower(aTarget[0]);
       
   830 	const DrivesMap& driveMap = iConfigManager.GetDrivesMap();
       
   831 
       
   832 	int count = driveMap.size();
       
   833 
       
   834 	// check for adorned (versioned) files e.g. dummy{12345678}.dll
       
   835 	if (aTarget.find(KSysBinPath) != std::wstring::npos)
       
   836 	{
       
   837 		AdornedProcessingOfFile(aTarget, searchNameUnadorned, adornedFileNamesFound);
       
   838 	}
       
   839 	else
       
   840 	{
       
   841 		searchNameUnadorned = aTarget;
       
   842 	}
       
   843 
       
   844 	DrivesMap::const_iterator it = driveMap.begin();
       
   845 	DrivesMap::const_iterator end = driveMap.end();
       
   846 
       
   847 	// search on all of defined drives (including the ROM and system drive) for
       
   848 	// the target file
       
   849 	for ( ; it != end ; ++it)
       
   850 	{
       
   851 		// drive letter
       
   852 		int disk = tolower(it->first);
       
   853 		searchNameUnadorned[0] = disk;
       
   854 		std::wstring unadornedLocalPath(searchNameUnadorned);
       
   855 
       
   856 		// check if adorned file version is found on this disk
       
   857 		bool adornedFound = false;
       
   858 
       
   859 		std::list<std::wstring>::iterator index = adornedFileNamesFound.begin();
       
   860 		std::list<std::wstring>::iterator adornedEnd = adornedFileNamesFound.end();
       
   861 		int nrOfAdornedFilenamesFound = adornedFileNamesFound.size();
       
   862 
       
   863 		for ( ; index != adornedEnd ; ++index)
       
   864 		{
       
   865 			std::wstring adornedFile = *index;
       
   866 			int drive = tolower(adornedFile[0]);
       
   867 			if (drive == disk)
       
   868 			{
       
   869 				adornedFound = true;
       
   870 				break;
       
   871 			}
       
   872 		}
       
   873 		
       
   874 		// the actual directory
       
   875 		localDir = it->second->iDir;
       
   876 		bool unadornedFound;
       
   877 
       
   878 		// check to see if we are using ROM/ROFS files to represent the z drive.
       
   879 		// If so, check to see if the ROM file exists in the logs.
       
   880 		if (disk == 'z' && localDir.empty())
       
   881 		{
       
   882 			unadornedFound = iRomManager.RomFileExists(searchNameUnadorned);
       
   883 		}
       
   884 		else
       
   885 		{
       
   886 			// convert to the local path and see if the file exists on the current drive
       
   887 			ConvertToLocalPath( unadornedLocalPath, localDir );
       
   888 			unadornedFound = FileExists(unadornedLocalPath);
       
   889 		}
       
   890 
       
   891 		bool matchFound = unadornedFound || adornedFound;
       
   892 		if (!matchFound)
       
   893 			continue;
       
   894 
       
   895 		bool processEclipsingSuspectsFoundOnThisDrive = false;
       
   896 		
       
   897 		// The logic varies whether we find an eclipsable/overwritable file on: (1) The same disk as the one we are installing to
       
   898 		// (2) The Z drive (ROM), (3) Any other drive
       
   899 		if (disk == targetDisk)  // case (1)
       
   900 		{
       
   901 			bool isOverwrite = FileExists(aInstallableFile.GetLocalTarget());
       
   902 			
       
   903 			// there are 3 possible cases: (1.1) We are correctly overwriting the already present file (a PU), 
       
   904 			// (1.2) We are incorrectly overwriting the file present, (1.3) We are eclipsing the file (if one of the file names is adorned)
       
   905 			if (isOverwrite)
       
   906 			{
       
   907 				// case 1.1 and 1.2 are handled here - overwrite the file if we have the right to do so.
       
   908 				HandleFileOverwriting(aFile, aTarget, aSUFlag);
       
   909 			}
       
   910 			else
       
   911 			{
       
   912 				// case 1.3 is handled here: 
       
   913 				// we have found a matching filename (either unadorned or adorned); add it to the eclipsing suspects
       
   914 				processEclipsingSuspectsFoundOnThisDrive = true;
       
   915 			}
       
   916 		}
       
   917 		else if (disk == 'z') // case (2)
       
   918 		{
       
   919 			// we are eclipsing a ROM file, check if this is authorised:
       
   920 			// see implementation of IsEclipsable()
       
   921 			if (!IsEclipsable(searchNameUnadorned, aSUFlag))
       
   922 			{
       
   923 				result = false;
       
   924 				break;
       
   925 			}
       
   926 		}
       
   927 		else // case (3)
       
   928 		{
       
   929 			processEclipsingSuspectsFoundOnThisDrive = true;
       
   930 		}
       
   931 
       
   932 		// now check to see whether the unadorned or the adorned filename found on 
       
   933 		// this drive should be added to iEclipsableOverwriteFiles.
       
   934 		if (processEclipsingSuspectsFoundOnThisDrive && unadornedFound)
       
   935 		{
       
   936 			iEclipsableOverwriteFiles.push_back(searchNameUnadorned);
       
   937 		}
       
   938 
       
   939 		if (processEclipsingSuspectsFoundOnThisDrive && adornedFound)
       
   940 		{
       
   941 			nrOfAdornedFilenamesFound = adornedFileNamesFound.size();
       
   942 			std::list<std::wstring>::iterator index = adornedFileNamesFound.begin();
       
   943 			std::list<std::wstring>::iterator adornedEnd = adornedFileNamesFound.end();
       
   944 
       
   945 			// add the adorned filenames found to the list of eclipsable/overwrite candidates
       
   946 			for ( ; index != adornedEnd ; ++index)
       
   947 			{
       
   948 				std::wstring adornedFile = *index;
       
   949 				int drive = tolower(adornedFile[0]);
       
   950 				if (drive == disk)
       
   951 				{
       
   952 					iEclipsableOverwriteFiles.push_back(adornedFile);
       
   953 				}
       
   954 			}
       
   955 		}
       
   956 	}
       
   957 	// end of loop
       
   958 
       
   959 	// the final step is to try and remove all the files from iEclipsableOverwriteFiles that
       
   960 	// will prevent this SIS file from installing.
       
   961 	if (result && (iEclipsableOverwriteFiles.size() > 0))
       
   962 	{
       
   963 		FilterNonBlockingFilesOfFilename(aFile, aTarget);
       
   964 	}
       
   965 
       
   966 	return result;
       
   967 }
       
   968 
       
   969 /** Checks the list of eclipsable candidate files against those that are owned by the 
       
   970  installing package (if any). Blocking files are removed if a match is found.
       
   971  @param aFile the SIS file to be installed
       
   972  @param aTarget the fully qualified filename (full path and name)
       
   973 */
       
   974 void Installer::FilterNonBlockingFilesOfFilename(const SisFile& aFile, const std::wstring& aTarget)
       
   975 {
       
   976 	// if the package aleady exists
       
   977 	TUint32 pkgUid = aFile.GetPackageUid();
       
   978 	if (iRegistry.IsInstalled(pkgUid))
       
   979 	{
       
   980 		const SisRegistryObject& registryEntry = iRegistry.GetRegistryObject(pkgUid);
       
   981 		const FileDescriptions& installedFiles = registryEntry.GetFileDescriptions();			
       
   982 	
       
   983 		FileDescriptions::const_iterator inCurr = installedFiles.begin();
       
   984 		FileDescriptions::const_iterator inEnd  = installedFiles.end();
       
   985 
       
   986 		for ( ; inCurr != inEnd ; ++inCurr)
       
   987 		{
       
   988 			std::wstring baseFile((*inCurr)->GetTarget());
       
   989 
       
   990 			std::list<std::wstring>::iterator eCurr = iEclipsableOverwriteFiles.begin();
       
   991 			std::list<std::wstring>::iterator eEnd = iEclipsableOverwriteFiles.end();
       
   992 
       
   993 			for ( ; eCurr != eEnd; ++eCurr)
       
   994 			{
       
   995 				std::wstring eclipseFile(*eCurr);
       
   996 				
       
   997 				// the installed base package owns the eclipse/overwrite candidate
       
   998 				if (FoldedCompare(baseFile, eclipseFile) == 0)
       
   999 				{
       
  1000 					// we are installing a new adorned variant of a file, so remove the blocking
       
  1001 					// file from the list
       
  1002 					if (StringUtils::NameAndExt(baseFile) != StringUtils::NameAndExt(aTarget))
       
  1003 					{
       
  1004 						eCurr = iEclipsableOverwriteFiles.erase(eCurr);
       
  1005 					}
       
  1006 				}
       
  1007 			}
       
  1008 		}
       
  1009 	}
       
  1010 }
       
  1011 
       
  1012 /** This function examines the list of ROM files we may eclipse to see if the supplied name is among them.
       
  1013  Here we have 2 options:
       
  1014  1)   file is not to be installed to \sys\bin\
       
  1015       in this case we don't invoke special handling of adorned filenames so we are only
       
  1016       interested in if that particular file is allowed to be eclipsed
       
  1017  2)   file is to be installed to \sys\bin therefore we have to handle adorned filenames.
       
  1018       Eclipsing is allowed if the filename that we are trying to install is a variant of any ROM filename 
       
  1019       marked as eclipsable i.e: if we are trying to install c:\sys\bin\A{000A0001}.dll
       
  1020       and we have z:\sys\bin\A.dll as an eclipsable file or any z:\sys\bin\A{????????}.dll
       
  1021       then we are allowed to eclipse.
       
  1022  @param aRomFile fully qualified filename in ROM that is to be checked for eclipising (i.e: z:\sys\bin\some.dll)
       
  1023  @param aSUFlag specifies if the installing SIS file has been signed by a SU certificate
       
  1024 */
       
  1025 bool Installer::IsEclipsable(std::wstring& aRomFile, bool aSUFlag)
       
  1026 {
       
  1027 	// SA/SP/PU sis + RU flag + signed by SU root cert is allowed
       
  1028 	if (aSUFlag)
       
  1029 		return true;
       
  1030 
       
  1031 	bool isEclipsable = false;
       
  1032 	bool goesToSysBin = (aRomFile.compare(KSysBinPath) != std::wstring::npos);
       
  1033 
       
  1034 	// go through the list of ROM files which are allowed to be eclipsed
       
  1035 	std::list<std::wstring>::const_iterator end = iEclipsableRomFiles.end();
       
  1036 	for (std::list<std::wstring>::const_iterator curr = iEclipsableRomFiles.begin() ;
       
  1037 		 curr != end; ++curr)
       
  1038 	{
       
  1039 		std::wstring eclipsableRomFile = *curr;
       
  1040 		
       
  1041 		// support wildcard characters in ROM stub files
       
  1042 		if (StringUtils::WildcardCompare(eclipsableRomFile,aRomFile)) // case 1
       
  1043 		{
       
  1044 			isEclipsable = true;
       
  1045 			break;
       
  1046 		}
       
  1047 		else if (goesToSysBin) // case 2
       
  1048 		{
       
  1049 			if (IsAdornedVariationOf(eclipsableRomFile,aRomFile))
       
  1050 			{
       
  1051 				isEclipsable = true;
       
  1052 				break;
       
  1053 			}
       
  1054 		}
       
  1055 	}
       
  1056 
       
  1057 	return isEclipsable;
       
  1058 }
       
  1059 
       
  1060 /** This function handles overwriting scenarios (i.e: we are trying to install c:\somedir\somename.ext however it already exists)
       
  1061  In this case we have 2 possibilities:
       
  1062  1) We are correctly overwriting the already present file (a PU)
       
  1063  2) We are incorrectly overwriting the file present
       
  1064  @param aFile the SIS file to be installed
       
  1065  @param aTarget The fully qualified filename (full path and name)
       
  1066  @param aSUFlag specifies if the installing SIS file has been signed by a SU certificate
       
  1067 */
       
  1068 void Installer::HandleFileOverwriting(const SisFile& aFile, const std::wstring& aTarget, bool aSUFlag)
       
  1069 {
       
  1070 	// find out which package this file belongs to
       
  1071 	TUint32 owningUid = 0;
       
  1072 	const SisRegistryObject* owningObj = iRegistry.OwningPackage(aTarget,owningUid);
       
  1073 	bool isSp = aFile.GetInstallType() == CSISInfo::EInstAugmentation;
       
  1074 	bool isPu = aFile.GetInstallType() == CSISInfo::EInstPartialUpgrade;
       
  1075 	bool isSa = aFile.GetInstallType() == CSISInfo::EInstInstallation;
       
  1076 
       
  1077 	// no package owns this file. Always allow orphaned file overwriting!
       
  1078 	if (owningUid == 0)
       
  1079 	{
       
  1080 		// do not display a warning if the installing file is a PA. The user
       
  1081 		// needs to copy the installing files to the installing directory
       
  1082 		// prior to installing the SIS file.
       
  1083 		std::string tempTarget = Ucs2ToUtf8(aTarget);
       
  1084   	  	std::wstring targetDisplay = Utf8ToUcs2( tempTarget );
       
  1085 		if (aFile.GetInstallType() == CSISInfo::EInstPreInstalledApp)
       
  1086 		{
       
  1087 			LINFO(targetDisplay << L" found for PA installation");
       
  1088 		}
       
  1089 		else
       
  1090 		{
       
  1091 			LWARN(targetDisplay << L" overwrites orphaned file");
       
  1092 		}
       
  1093 	}
       
  1094 	else if (aFile.GetPackageUid() == owningUid)
       
  1095 	{
       
  1096 		// SP can not overwrite a file in the base pkg
       
  1097 		if (isSp)
       
  1098 		{
       
  1099 			std::wostringstream os;
       
  1100 			os << aTarget << L" overwrites file from base package 0x" << std::hex << owningUid << L" \"" << owningObj->GetPackageName() << L"\"" << std::endl;
       
  1101 			iProblemFiles.append(os.str());
       
  1102 			iError = ECLIPSING_VIOLATION;
       
  1103 		}
       
  1104 	}
       
  1105 	else
       
  1106 	{
       
  1107 		// SP can not overwrite a file belonging to a different base pkg
       
  1108 		// PU/SA can not overwrite a file belonging to a different base pkg unless it has been signed by
       
  1109 		// a SU cert
       
  1110 		if (isSp || (!aSUFlag && (isPu || isSa)))
       
  1111 		{
       
  1112 			std::wostringstream os;
       
  1113 			os << aTarget << L" overwrites file from base package 0x" << std::hex << owningUid << L" \"" << owningObj->GetPackageName() << L"\"" << std::endl;
       
  1114 			iProblemFiles.append(os.str());
       
  1115 			iError = ECLIPSING_VIOLATION;
       
  1116 		}
       
  1117 		else
       
  1118 		{
       
  1119 			LWARN(aTarget << L" overwrites file from base package 0x" << std::hex << owningUid << L" \"" << owningObj->GetPackageName() << L"\"");
       
  1120 		}
       
  1121 	}
       
  1122 }
       
  1123 
       
  1124 void Installer::WarnEclipseOverWrite(const SisFile& aFile)
       
  1125 {
       
  1126 	// we still have some blocking files left after we have checked the destination
       
  1127 	// of the installing file.
       
  1128 	if (iEclipsableOverwriteFiles.size()>0)
       
  1129 	{
       
  1130 		// InterpretSIS allows orphan file eclipsing/overwriting
       
  1131 		std::list<std::wstring>::const_iterator curr = iEclipsableOverwriteFiles.begin();
       
  1132 		std::list<std::wstring>::const_iterator end = iEclipsableOverwriteFiles.end();
       
  1133 		
       
  1134 		for ( ; curr != end; ++curr)
       
  1135 		{
       
  1136 			std::wstring eclipseFile(*curr);
       
  1137 
       
  1138 			TUint32 owningUid = 0;
       
  1139 			const SisRegistryObject* owningObj = iRegistry.OwningPackage(eclipseFile, owningUid);
       
  1140 			
       
  1141 			// always allow orphaned file overwriting
       
  1142 			if (owningUid == 0)
       
  1143 			{
       
  1144 				LWARN(eclipseFile << L" eclipses orphaned file.");
       
  1145 			}
       
  1146 			else
       
  1147 			{
       
  1148 				// SP/PU can not overwrite a file belonging to a different base pkg or
       
  1149 				// SP/PU can not eclipse a base package which is not in the ROM.
       
  1150 				std::wostringstream os;
       
  1151 				os << eclipseFile << L" eclipses file from package 0x" << std::hex << owningUid << L" \"" << owningObj->GetPackageName() << L"\"" << std::endl;
       
  1152 				iProblemFiles.append(os.str());
       
  1153 				iError = ECLIPSING_VIOLATION;
       
  1154 				continue;
       
  1155 			}
       
  1156 		}		
       
  1157 	}
       
  1158 }
       
  1159 
       
  1160 void Installer::CheckDestinations(const SisFile& aFile, InstallableFiles& aFiles, 
       
  1161 								  const InstallSISFile& aInstallSISFile)
       
  1162 {
       
  1163 	bool suFlag = aInstallSISFile.iSUFlag;
       
  1164 	
       
  1165 	// if the -e option or InstallSISFile::iNotRegister is set, disable the eclipsing checks
       
  1166 	bool isEclipseAllowed = (iParamList.IsFlagSet(CParameterList::EFlagsDisableZDriveChecksSet)) || aInstallSISFile.iNotRegister;
       
  1167 
       
  1168 	iError = SUCCESS;
       
  1169 
       
  1170 	Sids sids;
       
  1171 	GetSidsFromInstallable(aFiles, sids);
       
  1172 
       
  1173 	const std::wstring privatePath = L":\\private\\";
       
  1174 	const std::wstring sysPath = L":\\sys\\";
       
  1175 	const std::wstring sysBinPath = L":\\sys\\bin\\";
       
  1176 	const std::wstring resourcePath = L":\\resource\\";
       
  1177 	const std::wstring exeType = L".exe";
       
  1178 
       
  1179     int num_of_files = aFiles.size();
       
  1180 	TUint32 pkgUid = aFile.GetPackageUid();
       
  1181 	TUint32 installType = aFile.GetInstallType();
       
  1182 	std::list<std::wstring> stubFileEntries;
       
  1183 
       
  1184 	iRegistry.GetStubFileEntries(pkgUid, stubFileEntries);
       
  1185 
       
  1186 	// if a base package exists, check to see if it chains back to a ROM stub. If so, populate
       
  1187 	// iEclipsableRomFiles with the files owned by the ROM stub. Only ROM files can be eclipsed.
       
  1188 	//
       
  1189 	// if the package has been signed by a SU cert, then there is no need to generate the eclipsable
       
  1190 	// file list - it is allowed to eclipse any file in the ROM.
       
  1191 	if (iRegistry.IsInstalled(pkgUid) && !suFlag)
       
  1192 		{
       
  1193 		PrepareEclipsableFilesList(aFile);
       
  1194 		}
       
  1195 
       
  1196 	// loop through the files to be installed
       
  1197 	for( int ii=num_of_files-1; ii>=0; ii-- )
       
  1198 	{   
       
  1199 		const InstallableFile* file = aFiles[ ii ];
       
  1200         const CSISFileDescription* sisDescription = file->FileDescription();
       
  1201 
       
  1202 		// file to be installed
       
  1203 		std::wstring target( file->GetTarget() );
       
  1204 
       
  1205 		if (sisDescription->Operation() == CSISFileDescription::EOpText)
       
  1206 			break;
       
  1207 		if (sisDescription->Operation() == CSISFileDescription::EOpNull)
       
  1208 			{
       
  1209 			// a FN file can not remove a file from \sys or \resource
       
  1210 			if ((target.find(sysPath,0) != std::wstring::npos) || (target.find(resourcePath,0) != std::wstring::npos))
       
  1211 				{
       
  1212 				// eclipsing problem
       
  1213 				std::wostringstream os;
       
  1214 				os << L"FN file \"" << target << L"\" can not remove a file from \\sys or \\resource" << std::endl;
       
  1215 				iProblemFiles.append(os.str());
       
  1216 				iError = DATA_CAGE_VIOLATION;
       
  1217 				continue;
       
  1218 				}
       
  1219 			}
       
  1220         else 
       
  1221             {
       
  1222 			std::wstring realTarget(file->GetLocalTarget());
       
  1223 
       
  1224 		    std::wstring romTarget(target);
       
  1225 			romTarget[0] = KRomDriveLetter;
       
  1226 
       
  1227 			// check to see if we are legally allowed to eclipse a ROM file 
       
  1228 			if (!isEclipseAllowed)
       
  1229 			{
       
  1230 				if (!ValidEclipse(aFile, target, *file, suFlag))
       
  1231 				{
       
  1232 					// eclipsing problem
       
  1233 					std::wostringstream os;
       
  1234 					os << target << L" eclipses file from ROM" << std::endl;
       
  1235 					iProblemFiles.append(os.str());
       
  1236 					iError = ECLIPSING_VIOLATION;
       
  1237 					continue;
       
  1238 				}
       
  1239 			}
       
  1240 			
       
  1241 			// additional platsec checks
       
  1242 			if (target.find(privatePath) != std::wstring::npos)
       
  1243 		    {
       
  1244 				// add an extra one for the drive letter
       
  1245 			    TInt start = privatePath.size()+1;
       
  1246 			    TInt end   = target.find( KDirectorySeparator[ 0 ], start);
       
  1247 
       
  1248 			    std::wistringstream uidStr(target.substr(start,end-start));
       
  1249 
       
  1250 			    TUint32 sid = 0;
       
  1251 			    uidStr >> std::hex >> sid;
       
  1252 				
       
  1253 				if (sid == 0)
       
  1254 					break;
       
  1255 
       
  1256 				// if a file in a private directory is registered, check to see if
       
  1257 				// it belongs to this package
       
  1258 			    if (std::find(sids.begin(), sids.end(), sid) == sids.end())
       
  1259 			    {
       
  1260 					TUint32 sidOwnerPkgUId = KNullUid;
       
  1261 
       
  1262 					if (iRegistry.SidExists(sid))
       
  1263 					{
       
  1264 						if(iParamList.RegistryVersionExists())
       
  1265 							{
       
  1266 						// SID belongs to some package, lets find out its UID
       
  1267 						const SisRegistryPackage& sisRegistryPkg = iRegistry.SidToPackage(sid);
       
  1268 
       
  1269 						sidOwnerPkgUId = sisRegistryPkg.GetUid();
       
  1270 							}
       
  1271 						else
       
  1272 							{
       
  1273 #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
       
  1274 							sidOwnerPkgUId = iRegistry.GetUid(sid);
       
  1275 #endif //SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
       
  1276 							}
       
  1277 					}
       
  1278 
       
  1279 					if (sidOwnerPkgUId != pkgUid)
       
  1280 					{
       
  1281 						// this package is trying to write to a SID's private directory 
       
  1282 						// which does not belong to this package
       
  1283 
       
  1284 						const int KUidStringLength = 8;
       
  1285 						std::wstring importPath = privatePath;
       
  1286 
       
  1287 						importPath.append( uidStr.str() + L"\\import" );
       
  1288 
       
  1289 						if ((target.find(importPath,0) == std::wstring::npos) && !suFlag)
       
  1290 						{
       
  1291 							// only SA with RU + SU and PU with RU + SU flag can override other private directory
       
  1292 							std::wostringstream os;
       
  1293 							os << target << L" cannot be written to a private directory which "
       
  1294 								<< L"does not belong to any exe in this package" << std::endl;
       
  1295 							iProblemFiles.append(os.str());
       
  1296 							iError = DATA_CAGE_VIOLATION;
       
  1297 							continue;
       
  1298 						}
       
  1299 					}
       
  1300 			    }
       
  1301 		    }
       
  1302 		    else if (file->IsExecutable())
       
  1303 		    {
       
  1304 				TUint32 sid = file->Sid();
       
  1305 
       
  1306 				std::wstring romFileWithDuplicateSid(L"");
       
  1307 				bool sidExistsInRom = iRomManager.SidExistsInRom(romFileWithDuplicateSid, sid);
       
  1308 				bool sidExistsInRegistry = iRegistry.SidExists(sid);
       
  1309 
       
  1310 				if (sidExistsInRegistry && file->IsExe())
       
  1311 				{
       
  1312 					// the .EXE which owns the SID
       
  1313 					std::wstring owningSidFile;
       
  1314 					iRegistry.SidToFileName(sid,owningSidFile);
       
  1315 
       
  1316 					bool owningPkgInRom = false;
       
  1317 					bool samePkgUid = false;
       
  1318 					TUint32 owningPkg = 0;
       
  1319 					if(iParamList.RegistryVersionExists())
       
  1320 						{
       
  1321 						// the SisRegistryObject which owns the .EXE
       
  1322 						
       
  1323 						const SisRegistryObject* owningObj = iRegistry.OwningPackage(owningSidFile,owningPkg);
       
  1324 
       
  1325 						owningPkgInRom = owningObj->GetInRom();
       
  1326 						samePkgUid = (owningPkg == pkgUid);
       
  1327 						}
       
  1328 					else
       
  1329 						{
       
  1330 						#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
       
  1331 							owningPkg = iRegistry.GetUid(owningSidFile);
       
  1332 							owningPkgInRom = iRegistry.GetInRom(owningPkg);
       
  1333 							samePkgUid = (owningPkg == pkgUid);
       
  1334 						#endif //SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
       
  1335 						}
       
  1336 					std::wstring targetName = StringUtils::NameAndExt(file->GetTarget());
       
  1337 					std::wstring owningSidFileName = StringUtils::NameAndExt(owningSidFile);
       
  1338 
       
  1339 					bool sameTargetName = (FoldedCompare(targetName,owningSidFileName) == 0);
       
  1340 					bool romStubExists = iRegistry.IsRomStubPackage(pkgUid);
       
  1341 					bool validInstallType = (installType == CSISInfo::EInstInstallation || installType == CSISInfo::EInstPartialUpgrade || installType == CSISInfo::EInstAugmentation);
       
  1342 
       
  1343 					// allow SID eclipsing in the following scenarios:
       
  1344 					// 1) SIS file has been signed by a SU cert
       
  1345 					// 2) eclipsing checks have been disabled by the user (using -e)
       
  1346 					// 3) SP/PU/SA+RU eclipsing of a ROM stub
       
  1347 					bool allowSidEclipse = false;
       
  1348 
       
  1349 					// case 1 and 2
       
  1350 					if (suFlag || isEclipseAllowed)
       
  1351 						allowSidEclipse = true;
       
  1352 
       
  1353 					// case 3
       
  1354 					if (validInstallType && sameTargetName && samePkgUid && (owningPkgInRom || romStubExists))
       
  1355 					{
       
  1356 						allowSidEclipse = true;
       
  1357 					}
       
  1358 					
       
  1359 					if (!allowSidEclipse)
       
  1360 					{
       
  1361 						std::wostringstream os;
       
  1362 										
       
  1363 						os << L"The existing file " << owningSidFile << L" already has the SID 0x" << std::hex << sid
       
  1364 						   << std::dec << L", cannot install " << target << std::endl;
       
  1365 						iProblemFiles.append(os.str());
       
  1366 						iError = DUPLICATE_SID;
       
  1367 						continue;
       
  1368 					}
       
  1369 				}
       
  1370 				// .EXE exists in the ROM, but no ROM stub has ownership of it
       
  1371 				else if (sidExistsInRom)
       
  1372 				{
       
  1373 					// A ROM stub could have referenced this .EXE using wildcards - in this case the SID will not
       
  1374 					// be registered in the SIS registry.
       
  1375 					bool isInstalled = iRegistry.IsInstalled(pkgUid);
       
  1376 					bool ownedByRomStub = false;
       
  1377 					if (isInstalled)
       
  1378 					{
       
  1379 						if (iRegistry.IsRomStubPackage(pkgUid))
       
  1380 						{
       
  1381 							CSISController* sisController = iRegistry.GetStubController(pkgUid);
       
  1382 							TFileDescList fileDesList;
       
  1383 							sisController->InstallBlock().GetFileList(fileDesList);
       
  1384 							for(TFileDescListConstIter iter = fileDesList.begin(); iter != fileDesList.end(); ++iter)
       
  1385 							{
       
  1386 								const CSISFileDescription* fD = *iter;
       
  1387 
       
  1388 								std::wstring romStubTarget(fD->Target().GetString());
       
  1389 
       
  1390 								if (StringUtils::WildcardCompare(romStubTarget,romFileWithDuplicateSid))
       
  1391 								{
       
  1392 									ownedByRomStub = true;
       
  1393 									break;
       
  1394 								}
       
  1395 							}
       
  1396 						}
       
  1397 					}
       
  1398 
       
  1399 					bool allowSidEclipse = false;
       
  1400 
       
  1401 					if (suFlag || isEclipseAllowed)
       
  1402 						allowSidEclipse = true;
       
  1403 
       
  1404 					if (!allowSidEclipse && !ownedByRomStub)
       
  1405 					{
       
  1406 						std::wostringstream os;
       
  1407 											
       
  1408 						os << L"A ROM file already has the SID 0x" << std::hex << file->Sid()
       
  1409 						   << std::dec << L", cannot install " << target << std::endl;
       
  1410 						iProblemFiles.append(os.str());
       
  1411 						iError = DUPLICATE_SID;
       
  1412 						continue;
       
  1413 					}
       
  1414 				}
       
  1415 		    }
       
  1416 		    else if (realTarget.find(sysBinPath) != std::wstring::npos)
       
  1417 		    {
       
  1418 				std::wostringstream os;
       
  1419 				os << target << L" cannot be installed to a data caged area" << std::endl;
       
  1420 				iProblemFiles.append(os.str());
       
  1421 				iError = DATA_CAGE_VIOLATION;
       
  1422 				continue;
       
  1423 		    }
       
  1424         }
       
  1425 	}
       
  1426 
       
  1427 	// we still may have blocking files left. Handle them here.
       
  1428 	WarnEclipseOverWrite(aFile);
       
  1429 
       
  1430 	iEclipsableOverwriteFiles.clear();
       
  1431 	iEclipsableRomFiles.clear();
       
  1432 
       
  1433 	if (!iProblemFiles.empty())
       
  1434 	{
       
  1435 		std::string x;
       
  1436 		throw InvalidSis("", Ucs2ToUtf8(iProblemFiles,x), iError);
       
  1437 	}
       
  1438 }
       
  1439 
       
  1440 void Installer::SetupExpressionEnvironment(const SisFile& aFile, const SisRegistry& aSisRegistry, RomManager& aRomManager )
       
  1441 {
       
  1442 	delete iExpressionEnvironment;
       
  1443 	iExpressionEnvironment = new ExpressionEnvironment( aFile,
       
  1444                                                         aSisRegistry,
       
  1445                                                         iRomManager,
       
  1446                                                         iConfigManager,
       
  1447                                                         iParamList.SystemDrivePath() );
       
  1448     
       
  1449     delete iExpressionEvaluator;
       
  1450     iExpressionEvaluator = new ExpressionEvaluator( *iExpressionEnvironment );
       
  1451 }
       
  1452 
       
  1453 void Installer::CheckEmbedded(const SisFile& aFile)
       
  1454 {
       
  1455 	PackageUids pkgs = aFile.GetEmbeddedPackageUids();
       
  1456 
       
  1457 	for (PackageUids::const_iterator curr = pkgs.begin() ;
       
  1458 		 curr != pkgs.end() ;
       
  1459 		 ++curr)
       
  1460 	{
       
  1461 		 if (!iRegistry.IsInstalled(*curr))
       
  1462 		 {
       
  1463 			 
       
  1464 			 LWARN(L" Embedded Package not installed: UID " << std::hex << *curr );
       
  1465 		 }
       
  1466 	}
       
  1467 }
       
  1468 
       
  1469 
       
  1470 void Installer::CreateStubSisFile(const InstallSISFile& aInstallSISFile, SisFile& aSis)
       
  1471 {
       
  1472 	int targetDrive = aInstallSISFile.iTargetDrive;
       
  1473 	std::wstring drivePath = iConfigManager.GetLocalDrivePath(targetDrive);
       
  1474 	
       
  1475 	drivePath.append(L"\\private\\");
       
  1476 
       
  1477 	// build SwiDaemon Pathname
       
  1478 	std::wstring ctrl = StringUtils::MakePathFromSID(drivePath, KSwiDaemonUid);
       
  1479 
       
  1480 	if ( !MakeDir( ctrl ) )
       
  1481 	{
       
  1482 		throw InterpretSisError(L"Directory Creation Error - "+ctrl, DIRECTORY_CREATION_ERROR);
       
  1483 	}
       
  1484 
       
  1485 	std::wstringstream s;
       
  1486 	s << std::hex << aSis.GetPackageUid();
       
  1487 
       
  1488 	ctrl.append(s.str());
       
  1489 
       
  1490 
       
  1491 	switch(aSis.GetInstallType())
       
  1492     {
       
  1493 	case CSISInfo::EInstInstallation:
       
  1494 	case CSISInfo::EInstPreInstalledApp:
       
  1495 		{
       
  1496 			// If an Installation type is SA/PA then append _0 after the stub UID.
       
  1497 			ctrl.append(L"_0");
       
  1498 			break;
       
  1499 		}
       
  1500 
       
  1501 	case CSISInfo::EInstAugmentation:
       
  1502 		{
       
  1503 			// If an Installation type is SP then append an index after the stub UID.
       
  1504 
       
  1505 			int num = 0;
       
  1506 
       
  1507 			ctrl.append( L"_");
       
  1508 			
       
  1509 			if (aInstallSISFile.iNotRegister)
       
  1510 			{
       
  1511 				// In this case, we can only assume all the previous SP installations 
       
  1512 				// (of a particular package) are consistently installed to the same target 
       
  1513 				// drive and all of the SP installation's attribute are set to either 
       
  1514 				// +mcardalone OR +mcardalonenr. Otherwise, the generated index will be wrong.
       
  1515 
       
  1516 				// Get the index from the daemon folder
       
  1517 				num = GetAugmentationsNumber(ctrl);
       
  1518 			}
       
  1519 			else
       
  1520 			{
       
  1521 				// In this case, we can only assume all the previous SP installations 
       
  1522 				// (of a particular package) is consistent with attributes set to either 
       
  1523 				// +mcard OR +mcardnr. Otherwise, the generated index will be wrong.
       
  1524 
       
  1525 				// Get the index from the sisregistry entries
       
  1526 				num = iRegistry.GetAugmentationsNumber(aSis.GetPackageUid());
       
  1527 			}
       
  1528 
       
  1529 			std::wstringstream s2;
       
  1530 			s2 << std::hex << num;
       
  1531 			ctrl.append( s2.str() );
       
  1532 			break;
       
  1533 		}
       
  1534 
       
  1535 	default:
       
  1536 		{
       
  1537 			std::wstring err(L"SIS file cannot be propagated: ");
       
  1538 			err.append(aInstallSISFile.iFileName);
       
  1539 			throw InterpretSisError(err, SIS_NOT_SUPPORTED);
       
  1540 		}
       
  1541 	}
       
  1542 
       
  1543 	ctrl.append(L".sis");
       
  1544 
       
  1545 	// Display the target SIS file. Format the stub SIS file string so it displays correctly.
       
  1546 	std::wstring ctrlDrive(L"$:");
       
  1547 	ctrlDrive[0] = targetDrive;
       
  1548 	std::wstring ctrlTarget = ctrl.substr(iConfigManager.GetLocalDrivePath(targetDrive).length(),ctrl.length());
       
  1549 	ctrlDrive.append(ctrlTarget);
       
  1550 
       
  1551 	LINFO(L"\tCreating stub: " << ctrlDrive);
       
  1552 
       
  1553 	aSis.MakeSISStub(ctrl);
       
  1554 	// If the NR flag is set, change the file attribute to RO
       
  1555 	if (aInstallSISFile.iNonRemovable)
       
  1556 	{
       
  1557 		_wchmod(ctrl.c_str(),_S_IREAD);
       
  1558 	}
       
  1559 }