installationservices/swi/source/swis/server/packageremover.cpp
changeset 0 ba25891c3a9e
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2007-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 
       
    20 #include <s32file.h>
       
    21 #include "pkgremovererrors.h"
       
    22 #include "siscontroller.h"
       
    23 #include "sisinstallblock.h"
       
    24 #include "sisinfo.h"
       
    25 #include "sisstring.h"
       
    26 #include "packageremover.h"
       
    27 #include "sisuid.h"
       
    28 #include "sisversion.h"
       
    29 #include "sisfieldtypes.h"
       
    30 #include "cleanuputils.h"
       
    31 #include "securitycheckutil.h"
       
    32 #include "secutils.h"
       
    33 #include "log.h"
       
    34 #include "sissupportedlanguages.h"
       
    35 #include <hash.h>
       
    36 
       
    37 using namespace Swi;
       
    38 using namespace Swi::Sis;
       
    39 
       
    40 
       
    41 // SIS registry main path
       
    42 _LIT(KRegistryPath, "\\sys\\install\\sisregistry\\");
       
    43 
       
    44 // SWI daemon private directory
       
    45 _LIT(KSwiDaemonPrivateDirectory, "\\private\\10202dce\\");
       
    46 
       
    47 // Controller and SIS file extensions
       
    48 _LIT(KControllerFileExt, ".ctl");
       
    49 _LIT(KSisFileExt, ".sis");
       
    50 _LIT(KSisXFileExt, ".sisx");
       
    51 
       
    52 // Maximum embedding depth allowed in SIS files
       
    53 const TInt KMaximumEmbeddingDepth = 8;
       
    54 
       
    55 // Length of UIDs in hex
       
    56 const TInt KUidHexLength = 8;
       
    57 
       
    58 //
       
    59 // Implementation of class CUninstalledPkgEntry
       
    60 //
       
    61 
       
    62 CUninstalledPkgEntry* CUninstalledPkgEntry::NewLC(const TUid& aUid, const TDesC& aPackageName,
       
    63 	const TDesC& aVendorName, const TVersion& aVersion, const TPackageType aPackageType,
       
    64 	const TDesC& aSisCtlFileName, const TDesC& aAssociatedStubSisName, const TDesC8& aControllerHash)
       
    65  	{
       
    66  	CUninstalledPkgEntry* self = new(ELeave) CUninstalledPkgEntry();
       
    67  	CleanupStack::PushL(self);
       
    68  	self->ConstructL(aUid, aPackageName, aVendorName, aVersion, aPackageType,
       
    69  					aSisCtlFileName, aAssociatedStubSisName, aControllerHash);
       
    70  	return self;
       
    71  	}
       
    72 
       
    73 CUninstalledPkgEntry::CUninstalledPkgEntry()
       
    74 	{
       
    75 	}
       
    76 
       
    77 CUninstalledPkgEntry::~CUninstalledPkgEntry()
       
    78 	{
       
    79 	delete iVendorName;
       
    80 	delete iPackageName;
       
    81 	delete iSisCtlFileName;
       
    82 	delete iAssociatedStubSisName;
       
    83 	delete iHashController;
       
    84 	}
       
    85 
       
    86 // Constructs the objects using the property values
       
    87 void CUninstalledPkgEntry::ConstructL(const TUid& aUid, const TDesC& aPackageName,
       
    88 	const TDesC& aVendorName, const TVersion& aVersion, const TPackageType aPackageType,
       
    89 	const TDesC& aSisCtlFileName, const TDesC& aAssociatedStubSisName, const TDesC8& aControllerHash)
       
    90 	{
       
    91 	iUid = aUid;
       
    92 	iPackageName = aPackageName.AllocL();
       
    93 	iVendorName = aVendorName.AllocL();
       
    94 	iVersion = aVersion;
       
    95 	iPackageType = aPackageType;
       
    96 	iSisCtlFileName = aSisCtlFileName.AllocL();
       
    97 	iAssociatedStubSisName = aAssociatedStubSisName.AllocL();	
       
    98 	iHashController = aControllerHash.AllocL();
       
    99 	}
       
   100 
       
   101 void CUninstalledPkgEntry::SetAssociatedStubSisNameL(const TDesC& aAssociatedStubSisName)
       
   102 	{
       
   103 	delete iAssociatedStubSisName;
       
   104 	iAssociatedStubSisName = NULL;
       
   105 	iAssociatedStubSisName = aAssociatedStubSisName.AllocL();
       
   106 	}
       
   107 
       
   108 //
       
   109 // Implementation of class CPackageRemover
       
   110 //
       
   111 
       
   112 CPackageRemover* CPackageRemover::NewLC(const RMessage2& aMessage)
       
   113 	{
       
   114 	CPackageRemover* self=new(ELeave) CPackageRemover(aMessage);
       
   115 	CleanupStack::PushL(self);
       
   116 	self->ConstructL();
       
   117 	return self;
       
   118 	}
       
   119 
       
   120 CPackageRemover* CPackageRemover::NewL(const RMessage2& aMessage)
       
   121 	{
       
   122 	CPackageRemover* self=NewLC(aMessage);
       
   123 	CleanupStack::Pop(self);
       
   124 	return self;
       
   125 	}
       
   126 
       
   127 // Constructor
       
   128 CPackageRemover::CPackageRemover(const RMessage2& aMessage) :
       
   129 	iMessage(aMessage)
       
   130 	{
       
   131 	}
       
   132 
       
   133 void CPackageRemover::ConstructL()
       
   134 	{
       
   135 	DEBUG_PRINTF(_L8("Constructing CPackageRemover"));
       
   136 
       
   137 	// connect to SIS helper 
       
   138 	User::LeaveIfError(iSisHelper.Connect());
       
   139 	User::LeaveIfError(iFs.Connect());
       
   140 	User::LeaveIfError(iFs.ShareProtected());
       
   141 	// connect to SIS registry
       
   142 	User::LeaveIfError(iSisRegistry.Connect());
       
   143 	}
       
   144 
       
   145 // Delete objects, close connection to the servers
       
   146 CPackageRemover::~CPackageRemover()
       
   147 	{	
       
   148 	iFs.Close();
       
   149 	iSisHelper.Close(); 
       
   150 	iSisRegistry.Close();
       
   151 	iUninstalledPkgEntry.ResetAndDestroy();
       
   152 
       
   153 	iFileList.ResetAndDestroy();
       
   154 	iControllerList.ResetAndDestroy();
       
   155 	delete iMainController;
       
   156 	delete iControllerData;
       
   157 	}
       
   158 
       
   159 // Logic for finding uninstalled packages:
       
   160 // FIRST : Controller file path processed and added the entries into the array
       
   161 // SECOND: Stub sis path processed and verified with already added enties, if
       
   162 // not-added, then add this as new entry. 
       
   163 // There are following possibilities:
       
   164 // 1. Autopropagation enabled then both sis file and ctl file will exist - (ctl added and sis won't added)
       
   165 // In this case ctl files added into array and also the sis file path is 
       
   166 // referened from the same array entry.
       
   167 // 2. Autopropagation disabled then only ctl file exist - ctl added.
       
   168 // 3. For PA and PP type, only stub sis file exist - sis file added
       
   169 void CPackageRemover::ListL()
       
   170 	{
       
   171 	TInt driveNumber = iMessage.Int0();
       
   172 	TDriveInfo info;
       
   173 	
       
   174 	User::LeaveIfError(iFs.Drive(info, driveNumber));
       
   175 	if (!(info.iDriveAtt & KDriveAttRemovable) || (info.iDriveAtt & KDriveAttSubsted))
       
   176 		{
       
   177 		User::Leave(KErrNotRemovable);
       
   178 		}
       
   179 
       
   180 	TPath stubSisPath;
       
   181 	TPath ControllerFilePath;
       
   182 	TChar drive;
       
   183 	CDir* dir = NULL;
       
   184 	User::LeaveIfError(RFs::DriveToChar(driveNumber, drive));
       
   185 	
       
   186 	// Construct the Controller file path
       
   187 	ControllerFilePath.Append(drive);
       
   188 	ControllerFilePath.Append(KDriveDelimiter);
       
   189 	ControllerFilePath.Append(KRegistryPath);
       
   190 
       
   191 	// Get the list of controller file
       
   192 	// List the directory contents including directories
       
   193 	TInt err = KErrNone;
       
   194 	err = iFs.GetDir(ControllerFilePath, KEntryAttDir, ESortByName, dir);
       
   195 	if (err == KErrNone)
       
   196 		{
       
   197 		CleanupStack::PushL(dir);
       
   198 
       
   199 		TInt count(dir->Count());
       
   200 		for (TInt i = 0; i < count; ++i)
       
   201 			{
       
   202 			const TDesC& directoryName = (*dir)[i].iName;
       
   203 			// we expect uid directories to be 8 characters long, ignore others
       
   204 			if (directoryName.Length() != KUidHexLength)
       
   205 				{
       
   206 				continue;
       
   207 				}
       
   208 			else if (!((*dir)[i].IsDir()))
       
   209 				{
       
   210 				continue;
       
   211 				}
       
   212 			else
       
   213 				{
       
   214 				TPath ctlPath;
       
   215 				CDir* ctlFileList = NULL;
       
   216 				ctlPath.Append(ControllerFilePath);
       
   217 				ctlPath.Append((*dir)[i].iName);
       
   218 				ctlPath.Append(KPathDelimiter);
       
   219 				// List the directory contents, excluding directories, system and hidden files.
       
   220 				// i.e. just normal files
       
   221 				err = iFs.GetDir(ctlPath, KEntryAttMatchExclude | KEntryAttDir, ESortByName, ctlFileList);
       
   222 				if (err == KErrNone)
       
   223 					{
       
   224 					CleanupStack::PushL(ctlFileList);
       
   225 					// Add the un-installed controller file into an array
       
   226 					AddIfUninstalledL(*ctlFileList, ctlPath);
       
   227 					CleanupStack::PopAndDestroy(ctlFileList);
       
   228 					}
       
   229 				}
       
   230 			}
       
   231 		CleanupStack::PopAndDestroy(dir); 
       
   232 		}
       
   233 	if (err == KErrNone || err == KErrNotFound || err == KErrPathNotFound)
       
   234 		{
       
   235 		// Construct the Stub sis file path
       
   236 		stubSisPath.Append(drive);
       
   237 		stubSisPath.Append(KDriveDelimiter);
       
   238 		stubSisPath.Append(KSwiDaemonPrivateDirectory);
       
   239 	
       
   240 		// Get the list of stub sis file 
       
   241 		CDir* stubFileList = NULL;
       
   242 		// List the directory contents, excluding directories, system and hidden files.
       
   243 		// i.e. just normal files
       
   244 		err = iFs.GetDir(stubSisPath, KEntryAttMatchExclude | KEntryAttDir, ESortByName, stubFileList);
       
   245 		if (err == KErrNone)
       
   246 			{
       
   247 			CleanupStack::PushL(stubFileList);
       
   248 			// Add the un-installed stub sis file into an array
       
   249 			AddIfUninstalledL(*stubFileList, stubSisPath);
       
   250 			CleanupStack::PopAndDestroy(stubFileList);
       
   251 			}
       
   252 		}
       
   253 	if (err == KErrNone || err == KErrNotFound || err == KErrPathNotFound)
       
   254 		{
       
   255 		// write the array entries into the buffer
       
   256 		HBufC8* buffer = WriteListToBufferLC();
       
   257 		TPtr8 pBuffer = buffer->Des();
       
   258 	
       
   259 		if (iMessage.GetDesMaxLengthL(1) < pBuffer.Length())
       
   260 			{
       
   261 			TInt bufferSize = pBuffer.Size();
       
   262 			TPckgC<TInt> bufferSizePackage(bufferSize);
       
   263 			iMessage.WriteL(1, bufferSizePackage);
       
   264 			err = KErrOverflow;
       
   265 			}
       
   266 		else
       
   267 			{
       
   268 			iMessage.WriteL(1, pBuffer);
       
   269 			err = KErrNone;
       
   270 			}
       
   271 		CleanupStack::PopAndDestroy(buffer); //buffer
       
   272 		}
       
   273 	iMessage.Complete(err);
       
   274 	}
       
   275 
       
   276 void CPackageRemover::AddIfUninstalledL(const CDir& aDirName, const TDesC& aPathName)
       
   277 	{
       
   278 	TInt fileCount = aDirName.Count();
       
   279 	if(fileCount)
       
   280 		{
       
   281 		for(TInt i = 0; i < fileCount; i++)
       
   282 			{
       
   283 			const TEntry &entry = (aDirName)[i];
       
   284 
       
   285 			HBufC* fileName = HBufC::NewLC(aPathName.Length() + entry.iName.Length());
       
   286 			TPtr localFilename = fileName->Des();
       
   287 			localFilename.Copy(aPathName);
       
   288 			localFilename.Append(entry.iName);
       
   289 
       
   290  			// Sanity check the filename
       
   291  			TParsePtrC fileParser(*fileName);
       
   292 			TBool isControllerFile = (fileParser.Ext().CompareF(KControllerFileExt)) ? EFalse : ETrue;
       
   293 			TBool isSisFile = EFalse;
       
   294 			
       
   295 			if ((fileParser.Ext().CompareF(KSisFileExt)) ||
       
   296 				(fileParser.Ext().CompareF(KSisXFileExt)))
       
   297 				{
       
   298 				isSisFile = ETrue;
       
   299 				}
       
   300 			
       
   301 			if (!isSisFile && !isControllerFile)
       
   302 				{
       
   303 				// ctl and sis file only processed other files skipped
       
   304 				CleanupStack::PopAndDestroy(fileName);
       
   305  				continue;
       
   306 				}
       
   307 				
       
   308 			// Get hold of the controller
       
   309 			HBufC8* bufController = NULL;
       
   310 			TInt err = KErrNone;
       
   311 			
       
   312 			if (isControllerFile)
       
   313    				{
       
   314 				// Get the controller data from the file
       
   315 				TRAP(err, bufController = GetControllerFromControllerFileLC(*fileName);
       
   316 							CleanupStack::Pop(bufController));
       
   317    				}
       
   318    			else 
       
   319    				{
       
   320    				// Get controller data from sishelper (may need to deflate controller)
       
   321 				TRAP(err, bufController = iSisHelper.GetControllerFromSisFileLC(*fileName);
       
   322 							CleanupStack::Pop(bufController));
       
   323    				}
       
   324 			if (err != KErrNone)
       
   325 				{
       
   326 				CleanupStack::PopAndDestroy(fileName);
       
   327  				continue;
       
   328 				}
       
   329 	
       
   330 			CleanupStack::PushL(bufController);
       
   331 			
       
   332 			// Ensure the application is not installed
       
   333 			// Discard the 4 byte type field for consistency with
       
   334 			// all other registry entries
       
   335 			TPtrC8 typeController(bufController->Mid(4));
       
   336 			
       
   337 			if (iSisRegistry.IsInstalledL(typeController))
       
   338 				{
       
   339 				CleanupStack::PopAndDestroy(2, fileName); //fileName, bufcontroller
       
   340 				continue;
       
   341 				}
       
   342 
       
   343 			HBufC8* hashController = ComputeHashL(typeController);
       
   344 			CleanupStack::PushL(hashController);
       
   345 			TPtrC8 hashControllerPtr(hashController->Des());
       
   346 			if (IsAlreadyAddedL(hashControllerPtr, *fileName))
       
   347 				{
       
   348 				CleanupStack::PopAndDestroy(3, fileName); //fileName, bufcontroller, hashController
       
   349 				continue;
       
   350 				}
       
   351 				
       
   352 			// Create controller
       
   353 			TPtrProvider provider(bufController->Des());
       
   354 			CController* currentController = NULL;
       
   355 			TRAP(err, currentController = CController::NewL(provider));
       
   356 			if (err != KErrNone)
       
   357 				{
       
   358 				CleanupStack::PopAndDestroy(3, fileName); // filename , bufController, hashController
       
   359  				continue;
       
   360 				}
       
   361 				
       
   362 			CleanupStack::PushL(currentController);
       
   363 
       
   364 			TUid pkgUid = currentController->Info().Uid().Uid();
       
   365 			if (isControllerFile)
       
   366    				{
       
   367    				// Determine the uid from the directory name
       
   368 	   			TLex lex(aPathName.Right(9).Left(8));
       
   369    				TUint uidValue;
       
   370    				User::LeaveIfError(lex.Val(uidValue, EHex));
       
   371    				TUid uuid = TUid::Uid(uidValue);
       
   372 				if (uuid != pkgUid)
       
   373 					{
       
   374 					// shouldn't add this entry as it may be malware
       
   375 					// where ctl file is placed under  a uid different from the controller'S UID
       
   376 					CleanupStack::PopAndDestroy(4, fileName); //fileName, bufcontroller, hashController, currentController
       
   377 					continue;
       
   378 					}
       
   379    				}
       
   380 
       
   381 			Sis::TInstallType installType = currentController->Info().InstallType();
       
   382 			CUninstalledPkgEntry::TPackageType pkgType = CUninstalledPkgEntry::ESaPackage; // to suppress warning
       
   383 			switch(installType)
       
   384 				{
       
   385 				case EInstInstallation:
       
   386 					pkgType = CUninstalledPkgEntry::ESaPackage;
       
   387 					break;
       
   388 				case EInstAugmentation:
       
   389 					pkgType = CUninstalledPkgEntry::ESpPackage;
       
   390 					break;
       
   391 				case EInstPartialUpgrade:
       
   392 					pkgType = CUninstalledPkgEntry::EPuPackage;
       
   393 					break;
       
   394 				case EInstPreInstalledApp:
       
   395 					pkgType = CUninstalledPkgEntry::EPaPackage;
       
   396 					break;
       
   397 				case EInstPreInstalledPatch:
       
   398 					pkgType = CUninstalledPkgEntry::EPpPackage;
       
   399 					break;
       
   400 				default:
       
   401 					// shouldn't come here
       
   402 					User::Leave(KErrNotSupported);							
       
   403 				}
       
   404 					
       
   405 			// Localise dependency name
       
   406 			TLanguage systemLanguage = User::Language();    // Language of the current locale
       
   407     		// Check whether the current locale is in the list of languages in the SIS file
       
   408     		const CSupportedLanguages& languages = currentController->SupportedLanguages();
       
   409 			TInt langIndex = 0;
       
   410 			for (TInt i = 0; i < languages.Count(); i++)
       
   411 				{
       
   412 				if (systemLanguage == languages[i])
       
   413 					{
       
   414 					langIndex = i;
       
   415 					break;
       
   416 					}
       
   417 				}
       
   418     	
       
   419 			HBufC* pkgName = currentController->Info().Names()[langIndex]->Data().AllocLC();
       
   420 			HBufC* pkgVendor = currentController->Info().VendorNames()[langIndex]->Data().AllocLC();
       
   421 			TInt major = currentController->Info().Version().Major();
       
   422 			TInt minor = currentController->Info().Version().Minor();
       
   423 			TInt build = currentController->Info().Version().Build();
       
   424 			TVersion pkgVersion(major,minor,build);
       
   425 			
       
   426 			HBufC* associateStubFile = KNullDesC().AllocLC(); // later this will be set
       
   427 			CUninstalledPkgEntry* PkgEntry = CUninstalledPkgEntry::NewLC(pkgUid, *pkgName,
       
   428 					*pkgVendor, pkgVersion, pkgType, *fileName, *associateStubFile, *hashController);
       
   429 			iUninstalledPkgEntry.AppendL(PkgEntry); // ownership is transfered to array.
       
   430 			CleanupStack::Pop(PkgEntry); 			// PkgEntry
       
   431 			// associateStubFile, pkgVendor, pkgName ,currentController, bufController, hashController and fileName
       
   432 			CleanupStack::PopAndDestroy(7, fileName); 	
       
   433 			}
       
   434 		}
       
   435 	}
       
   436 
       
   437 HBufC8* CPackageRemover::ComputeHashL(TDesC8& aController)
       
   438 	{
       
   439 	// calculate the controller hash
       
   440 	CMessageDigest* digest = CMessageDigestFactory::NewDigestLC(CMessageDigest::ESHA1);
       
   441 	digest->Update(aController);
       
   442 	TPtrC8 hash = digest->Final();	
       
   443 	HBufC8* hashBuffer = hash.AllocL();
       
   444 	CleanupStack::PopAndDestroy(digest);
       
   445 	return hashBuffer;
       
   446 	}
       
   447 
       
   448 TBool CPackageRemover::IsAlreadyAddedL(TDesC8& aHashController, const TDesC& aFileName)
       
   449 	{
       
   450 	// Ensure this entry is not already added into the array using ctl files.
       
   451 	// check with existing RArray<TUninstalledAppEntry> which contains 
       
   452 	// a list of uninstalled entries.
       
   453 	TInt count = iUninstalledPkgEntry.Count();
       
   454 	TBool same = EFalse;
       
   455 	for (TInt j = 0; j < count; ++j)
       
   456 		{
       
   457 		const TDesC8& existingHash = iUninstalledPkgEntry[j]->HashController();
       
   458 		if (aHashController.CompareF(existingHash) == 0)
       
   459 			{
       
   460 			TBool isSisFile = EFalse;
       
   461 			if ( (aFileName.Right(4).CompareF(KSisFileExt)) || 
       
   462 				 (aFileName.Right(4).CompareF(KSisXFileExt)))
       
   463 				{
       
   464 				isSisFile = ETrue;
       
   465 				}
       
   466 			if (!isSisFile)
       
   467 				{
       
   468 				// already a ctl file added in the array
       
   469 				// it may happen as copy - paste the ctl file with different name
       
   470 				// e.g copy 00000000_0000.ctl  and paste it as 00000000_1000.ctl or abc.ctl....
       
   471 				same = ETrue;
       
   472 				break;
       
   473 				}
       
   474 			if (iUninstalledPkgEntry[j]->AssociatedStubSisName() == KNullDesC)
       
   475 				{
       
   476 				iUninstalledPkgEntry[j]->SetAssociatedStubSisNameL(aFileName); 
       
   477 				}
       
   478 			same = ETrue;
       
   479 			break;
       
   480 			}
       
   481 		}
       
   482 	return same;
       
   483 	}
       
   484 
       
   485 HBufC8* CPackageRemover::WriteListToBufferLC()
       
   486 	{
       
   487 	TInt fileCount = iUninstalledPkgEntry.Count();
       
   488 	TInt length = (fileCount + 1) * sizeof (CUninstalledPkgEntry);
       
   489 	// Write the object out to a buffer, send to client
       
   490 	CBufSeg* buf = CBufSeg::NewL(length);
       
   491 	CleanupStack::PushL(buf);
       
   492 	
       
   493 	// create write stream
       
   494 	RBufWriteStream writeStream(*buf);
       
   495 	CleanupClosePushL(writeStream);
       
   496 	
       
   497 	// write the files to the stream
       
   498 	writeStream.WriteInt32L(fileCount);
       
   499 	for(TInt i = 0; i < fileCount; i++)
       
   500 		{
       
   501 		writeStream.WriteInt32L(iUninstalledPkgEntry[i]->Uid().iUid);
       
   502 		
       
   503 		const TDesC& pkgName = iUninstalledPkgEntry[i]->PackageName();
       
   504 		writeStream.WriteInt32L(pkgName.Length());
       
   505 		writeStream.WriteL(pkgName);
       
   506 		
       
   507 		const TDesC& vendorName = iUninstalledPkgEntry[i]->VendorName();
       
   508 		writeStream.WriteInt32L(vendorName.Length());
       
   509 		writeStream.WriteL(vendorName);
       
   510 		
       
   511 		writeStream.WriteInt32L(iUninstalledPkgEntry[i]->Version().iMajor);
       
   512 		writeStream.WriteInt32L(iUninstalledPkgEntry[i]->Version().iMinor);
       
   513 		writeStream.WriteInt32L(iUninstalledPkgEntry[i]->Version().iBuild);
       
   514 		writeStream.WriteInt32L(iUninstalledPkgEntry[i]->PackageType());	
       
   515 
       
   516 		const TDesC& sisCtlFileName = iUninstalledPkgEntry[i]->SisCtlFileName();
       
   517 		writeStream.WriteInt32L(sisCtlFileName.Length());
       
   518 		writeStream.WriteL(sisCtlFileName);
       
   519 		
       
   520 		const TDesC& assocatedStubName = iUninstalledPkgEntry[i]->AssociatedStubSisName();
       
   521 		writeStream.WriteInt32L(assocatedStubName.Length());
       
   522 		writeStream.WriteL(assocatedStubName);
       
   523 		}
       
   524 	
       
   525 	HBufC8* buffer = HBufC8::NewLC(buf->Size());
       
   526 	TPtr8 ptr(buffer->Des());
       
   527 	buf->Read(0, ptr, buf->Size());
       
   528 	CleanupStack::Pop(buffer);
       
   529 	CleanupStack::PopAndDestroy(2, buf); // writeStream , buf
       
   530 	CleanupStack::PushL(buffer);
       
   531 	return buffer;
       
   532 	}
       
   533 
       
   534 // Method to remove a specified uninstalled package
       
   535 void CPackageRemover::RemoveL()
       
   536 	{
       
   537 	// Get the package file
       
   538 	HBufC* packageFileName = HBufC::NewLC(iMessage.GetDesLengthL(0));
       
   539 	TPtr ptr(packageFileName->Des());
       
   540 	iMessage.ReadL(0, ptr);
       
   541 
       
   542 	// Get the associated stub file (if any)
       
   543 	HBufC* stubSisFileName = HBufC::NewLC(iMessage.GetDesLengthL(1));
       
   544 	TPtr ptrStub(stubSisFileName->Des());
       
   545 	iMessage.ReadL(1, ptrStub);
       
   546 
       
   547 	// Sanity check the filename
       
   548 	TBool isControllerFile = CheckFileL(*packageFileName);
       
   549 
       
   550 	// Get hold of the controller
       
   551 	if (isControllerFile)
       
   552 		{
       
   553 		// Get the controller data from the file
       
   554 		iControllerData = GetControllerFromControllerFileLC(*packageFileName);
       
   555 		CleanupStack::Pop(iControllerData);
       
   556 		}
       
   557 	else
       
   558 		{
       
   559 		// Get controller data from sishelper (may need to deflate controller)
       
   560 		iControllerData = iSisHelper.GetControllerFromSisFileLC(*packageFileName);
       
   561 		CleanupStack::Pop(iControllerData);
       
   562 		}
       
   563 
       
   564 
       
   565 	// Process the controller and compile a list of their referenced files
       
   566 	ProcessControllerL();
       
   567 
       
   568 	// Delete the files
       
   569 	ValidateAndDeleteFilesL();
       
   570 
       
   571 	// Delete the sis / controller file
       
   572 	// And remove the folders if they are empty
       
   573 	DeleteFile(*packageFileName);
       
   574 	DeletePathIfEmpty(*packageFileName);
       
   575 
       
   576 	// For controller files check if a corresponding stub exists
       
   577 	if (isControllerFile && (*stubSisFileName != KNullDesC))
       
   578 		{
       
   579 		// Sanity check file and ensure its a sis file
       
   580 		if (CheckFileL(*stubSisFileName) == EFalse)
       
   581 			{
       
   582 			DeleteFile(*stubSisFileName);
       
   583 			DeletePathIfEmpty(*stubSisFileName);
       
   584 			}
       
   585 		}
       
   586 
       
   587 	CleanupStack::PopAndDestroy(2, packageFileName); // stubSisFileName
       
   588 	iMessage.Complete(KErrNone);
       
   589 	}
       
   590 
       
   591 // Process the given controller (including embedded controllers) to get referenced files
       
   592 void CPackageRemover::ProcessControllerL()
       
   593 	{
       
   594 	// Create the controller
       
   595 	TPtrProvider provider(iControllerData->Des());
       
   596 	iMainController = Sis::CController::NewL(provider);
       
   597 
       
   598 	// Process the controller (including the embedded ones)
       
   599 	// Collect all the file descriptions from the install block
       
   600 	// No need to close this array!
       
   601 	Sis::CController* currentController = iMainController;
       
   602 	const RPointerArray<CFileDescription>& files = currentController->InstallBlock().FileDescriptions();
       
   603 	TInstallType installType = currentController->Info().InstallType();
       
   604 	
       
   605 	for (TInt index = 0; index < files.Count(); ++index)
       
   606 		{
       
   607 		iFileList.AppendL(new (ELeave) TFileDescAndInstallType(installType, files[index]));
       
   608 		}
       
   609 
       
   610 	TInt nestingLevel = 0;
       
   611 	iControllerList.AppendL(new (ELeave) TControllerAndLevel(nestingLevel, currentController));
       
   612 	TInt controllerIndex = -1;
       
   613 	
       
   614 	while (++controllerIndex < iControllerList.Count())
       
   615 		{
       
   616 		currentController = iControllerList[controllerIndex]->iController;
       
   617 		nestingLevel = iControllerList[controllerIndex]->iLevel;
       
   618 		
       
   619 		if (nestingLevel++ >= KMaximumEmbeddingDepth)
       
   620 			{
       
   621 			User::Leave(KErrSISTooDeeplyEmbedded);
       
   622 			}
       
   623 
       
   624 		// Get a list of embedded controllers and process them
       
   625 		const RPointerArray<Sis::CController>& subControllers = currentController->InstallBlock().EmbeddedControllers();
       
   626 		
       
   627 		for (TInt index = 0; index < subControllers.Count(); ++index)
       
   628 			{
       
   629 			currentController = subControllers[index];
       
   630 			
       
   631 			// Check if the embedded controller is installed on the device
       
   632 			// If installed do not process
       
   633 			TInt controllerDataOffset = (TInt)currentController->DataOffset();
       
   634 			TPtrC8 typeController(iControllerData->Mid(controllerDataOffset));
       
   635 			
       
   636 			// Pass on the controller plus the data after DataIndex field;
       
   637 			// otherwise CController::NewLC will crash when addition data not found.
       
   638 			if (!iSisRegistry.IsInstalledL(typeController))
       
   639 				{
       
   640 				const RPointerArray<CFileDescription>& files = currentController->InstallBlock().FileDescriptions();
       
   641 				TInstallType installType = currentController->Info().InstallType();
       
   642 				
       
   643 				for (TInt indexFiles = 0; indexFiles < files.Count(); ++indexFiles)
       
   644 					{
       
   645 					iFileList.AppendL(new (ELeave) TFileDescAndInstallType(installType, files[indexFiles]));
       
   646 					}
       
   647 				}
       
   648 
       
   649 			// Append the controller to the list
       
   650 			TControllerAndLevel* currentControllerAndLevel = new (ELeave) TControllerAndLevel(nestingLevel, currentController);
       
   651 			CleanupStack::PushL(currentControllerAndLevel);
       
   652 			iControllerList.AppendL(currentControllerAndLevel);
       
   653 			CleanupStack::Pop(currentControllerAndLevel);
       
   654 			}
       
   655 		}
       
   656 	}
       
   657 
       
   658 // Read the controller file and return the controller data
       
   659 HBufC8* CPackageRemover::GetControllerFromControllerFileLC(const TDesC& aFileName)
       
   660 	{
       
   661 	RFile file;
       
   662 	User::LeaveIfError(file.Open(iFs, aFileName, EFileRead | EFileShareReadersOnly));
       
   663 	CleanupClosePushL(file);
       
   664 	TInt fileSize;
       
   665 	User::LeaveIfError(file.Size(fileSize));
       
   666 
       
   667 	// Allocate size for controller data and controller field type (4 bytes)
       
   668 	HBufC8* bufController = HBufC8::NewLC(fileSize + 4);
       
   669 	TPtr8 ptrFileContents(bufController->Des());
       
   670 	RDesWriteStream write(ptrFileContents);
       
   671 	CleanupClosePushL(write);
       
   672 
       
   673 	RFileReadStream read(file);
       
   674 	CleanupClosePushL(read);
       
   675 
       
   676 	// Write the controller type
       
   677 	write.WriteInt32L(EFieldTypeController);
       
   678 
       
   679 	// Stream in the rest of the controller
       
   680 	write.WriteL(read);
       
   681 
       
   682 	CleanupStack::PopAndDestroy(2, &write); // read
       
   683 	CleanupStack::Pop(bufController);
       
   684 	CleanupStack::PopAndDestroy(&file);
       
   685 	CleanupStack::PushL(bufController);
       
   686 
       
   687 	return bufController;
       
   688 	}
       
   689 
       
   690 // Validate the referenced files and delete them
       
   691 // Also deletes the path if found empty
       
   692 void CPackageRemover::ValidateAndDeleteFilesL()
       
   693 	{
       
   694 	// Get the filename with full path
       
   695 	TInt driveNum;
       
   696 	User::LeaveIfError(RFs::CharToDrive(iRemovableDriveChar, driveNum));
       
   697 
       
   698 	// Validate and create final list of files to be removed
       
   699 	RPointerArray<HBufC> filesList;
       
   700 	CleanupResetAndDestroy<RPointerArray<HBufC> >::PushL(filesList);
       
   701 	TInt fileCount = iFileList.Count();
       
   702 	for (TInt index = 0; index < fileCount; ++index)
       
   703 		{
       
   704 		Sis::CFileDescription* fileDesc = iFileList[index]->iFileDesc;
       
   705 		const Sis::CString& stringTarget = iFileList[index]->iFileDesc->Target();
       
   706 		HBufC* bufFileName = stringTarget.Data().AllocLC();
       
   707 		TPtr ptr(bufFileName->Des());
       
   708 		TBool skipFile = EFalse;
       
   709 
       
   710 		// Handle special drive markers
       
   711 		if (bufFileName->Length() == 0)
       
   712 			{
       
   713 			skipFile = ETrue;
       
   714 			}
       
   715 		else if (ptr[0] == '!')
       
   716 			{
       
   717 			// For PA and PP install types replace with the removable drive
       
   718 			ptr[0] = iRemovableDriveChar;
       
   719 			// For others we have no idea what drive the user would've chosen!
       
   720 			// anyhow we will delete if the file available in removable drive and 
       
   721 			// not owned by any other package.
       
   722 			}
       
   723 		else if (ptr[0] == '$')
       
   724 			{
       
   725 			// Replace with system drive
       
   726 			// Doing this just for the heck of it (since system drive is not removable!)
       
   727 			ptr[0] = iFs.GetSystemDriveChar();
       
   728 			}
       
   729 
       
   730 		// Ensure a valid drive and path are present
       
   731 		if (!skipFile)
       
   732 			{
       
   733 			TParsePtr fileName(ptr);
       
   734 			if (!fileName.DrivePresent() || !fileName.PathPresent() || !fileName.NamePresent())
       
   735 				{
       
   736 				skipFile = ETrue;
       
   737 				}
       
   738 
       
   739 			// The file being deleted should belong to the same drive as the controller / stub sis file
       
   740 			TInt delFileDrive;
       
   741 			User::LeaveIfError(RFs::CharToDrive(ptr[0], delFileDrive));
       
   742 			if (delFileDrive != driveNum)
       
   743 				{
       
   744 				skipFile = ETrue;
       
   745 				}
       
   746 
       
   747 			// Ensure the file is not in a data-caged area
       
   748 			TFileName directory = fileName.Path();
       
   749 			if (fileDesc->Operation() == EOpNull)
       
   750 				{
       
   751 				// For FN ensure file is not in \sys or \resource
       
   752 				TPtrC sysPath(KSysPath);
       
   753 				TPtrC resourcePath(KResourcePath);
       
   754 				if ((directory.Left(sysPath.Length()).CompareF(sysPath) == 0) ||
       
   755 					(directory.Left(resourcePath.Length()).CompareF(resourcePath) == 0))
       
   756 					{
       
   757 					skipFile = ETrue;
       
   758 					}
       
   759 				}
       
   760 
       
   761 			TEntry entry;
       
   762 			TInt err = iFs.Entry(*bufFileName, entry);
       
   763 			if ((err != KErrNone) && 
       
   764 				(entry.IsTypeValid() && (!SecUtils::IsExe(entry) && !SecUtils::IsDll(entry))))
       
   765 				{
       
   766 				// Only EXE and DLL are allowed in \sys\bin
       
   767 				TPtrC binPath(KBinPath);
       
   768 				if (directory.Left(binPath.Length()).CompareF(binPath) == 0)
       
   769 					{
       
   770 					skipFile = ETrue;
       
   771 					}
       
   772 				}
       
   773 			}
       
   774 
       
   775 		if (skipFile)
       
   776 			{
       
   777 			DEBUG_PRINTF2(_L8("CPackageRemover: Skipping delete %S"), bufFileName);
       
   778 			CleanupStack::PopAndDestroy(bufFileName);
       
   779 			continue;	// Skip this file
       
   780 			}
       
   781 		else
       
   782 			{
       
   783 			// Add the file to the list of files to be removed
       
   784 			filesList.AppendL(bufFileName);
       
   785 			CleanupStack::Pop(bufFileName);		// Ownership transferred to array
       
   786 			}
       
   787 		}
       
   788  
       
   789 	// Filter out unorphaned files (is not part of another valid installation)
       
   790 	fileCount = filesList.Count();
       
   791 	if (fileCount > 0)
       
   792 		{
       
   793 		SecurityCheckUtil::FilterOrphanedFilesL(filesList);
       
   794 		}
       
   795 
       
   796 	// Delete files and remove empty directories
       
   797 	fileCount = filesList.Count();
       
   798 	for (TInt indx = 0; indx < fileCount; ++indx)
       
   799 		{
       
   800 		DEBUG_PRINTF2(_L8("CPackageRemover: Deleting "), filesList[indx]);
       
   801 		DeleteFile(*filesList[indx]);
       
   802 		DeletePathIfEmpty(*filesList[indx]);
       
   803 		}
       
   804 
       
   805 	CleanupStack::PopAndDestroy(&filesList);
       
   806 	}
       
   807 
       
   808 TInt CPackageRemover::DeleteFile(const TDesC& aName)
       
   809 	{
       
   810 	TInt err = iFs.Delete(aName);
       
   811 	if (err == KErrAccessDenied)
       
   812 		{
       
   813 		// File may be read-only. Clear the attribute and try again
       
   814 		iFs.SetAtt(aName, 0, KEntryAttReadOnly);
       
   815 		err = iFs.Delete(aName);
       
   816 		}
       
   817 
       
   818 	return err;
       
   819 	}
       
   820 
       
   821 // Recursively deletes all folders in the path (as long as they are empty)
       
   822 void CPackageRemover::DeletePathIfEmpty(const TDesC& aPath)
       
   823 	{
       
   824 	TParse path;
       
   825 	path.Set(aPath, NULL, NULL);
       
   826 
       
   827 	if (path.PathPresent())
       
   828 		{
       
   829 		while ((iFs.RmDir(path.DriveAndPath()) == KErrNone) && (path.PopDir() == KErrNone))
       
   830 			;
       
   831 		}
       
   832 	}
       
   833 
       
   834 // Sanity checks the filename and path
       
   835 // Returns ETrue if the file is a controller file
       
   836 TBool CPackageRemover::CheckFileL(TDesC& aFile)
       
   837 	{
       
   838 	// Sanity check the filename
       
   839 	HBufC* bufFileName = aFile.AllocLC();
       
   840 	TPtr ptrFileName(bufFileName->Des());
       
   841 	TParsePtr fileName(ptrFileName);
       
   842 	if (!fileName.DrivePresent() || !fileName.PathPresent() || !iFs.IsValidName(aFile))
       
   843 		{
       
   844 		User::Leave(KErrArgument);
       
   845 		}
       
   846 
       
   847 	// Ensure the drive is a removable one
       
   848 	TInt driveNum;
       
   849 	iRemovableDriveChar = fileName.Drive()[0];
       
   850 	User::LeaveIfError(RFs::CharToDrive(iRemovableDriveChar, driveNum));
       
   851 
       
   852 	TDriveInfo info;
       
   853 	User::LeaveIfError(iFs.Drive(info, driveNum));
       
   854 	if (!(info.iDriveAtt & KDriveAttRemovable) || (info.iDriveAtt & KDriveAttSubsted))
       
   855 		{
       
   856 		User::Leave(KErrNotRemovable);
       
   857 		}
       
   858 
       
   859 	// Check if volume is present
       
   860 	TVolumeInfo volumeInfo;
       
   861 	User::LeaveIfError(iFs.Volume(volumeInfo, driveNum));
       
   862 
       
   863 	// Ensure the file still exists
       
   864 	RFile file;
       
   865 	TInt err = file.Open(iFs, aFile, EFileShareAny | EFileRead);
       
   866 	if (err != KErrNone)
       
   867 		{
       
   868 		User::Leave(KErrNotFound);
       
   869 		}
       
   870 	file.Close();
       
   871 
       
   872 	// Get the file type and sanity check its location and contents
       
   873 	TBool isControllerFile = EFalse;
       
   874 	isControllerFile = (fileName.Ext().Compare(KControllerFileExt)) ? EFalse : ETrue;
       
   875 	if (isControllerFile)
       
   876 		{
       
   877 		// Should be present in sys registry folder
       
   878 		User::LeaveIfError(fileName.PopDir());
       
   879 		if (fileName.Path().Compare(KRegistryPath) != 0)
       
   880 			{
       
   881 			User::Leave(KErrNotSupported);
       
   882 			}
       
   883 		}
       
   884 	else
       
   885 		{
       
   886 		// Should be present in the SWI Daemon private folder
       
   887 		if (fileName.Path().Compare(KSwiDaemonPrivateDirectory) != 0)
       
   888 			{
       
   889 			User::Leave(KErrNotSupported);
       
   890 			}
       
   891 		}
       
   892 
       
   893 	CleanupStack::PopAndDestroy(bufFileName);
       
   894 	return isControllerFile;
       
   895 	}
       
   896