installationservices/swi/source/sishelper/sishelper.cpp
changeset 0 ba25891c3a9e
child 17 741e5bba2bd1
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 1997-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 * SISHelper is a layer between a client (EpocInstall, Installer UI, or Control
       
    16 * Panel applet) that starts [un]installation.
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 #include <s32mem.h>
       
    22 #include <caf/caf.h>
       
    23 #include <ecom/ecom.h>
       
    24 #include <bautils.h>
       
    25 #include <e32math.h> // for Math::Random()
       
    26 
       
    27 #include "swi/launcher.h"
       
    28 #include "sishelper.h"
       
    29 #include "filesisdataprovider.h"
       
    30 #include "log.h"
       
    31 #include "swi/sisparser.h"
       
    32 #include "swi/siscontents.h"
       
    33 #include "securitypolicy.h"
       
    34 #include "cafsisdataprovider.h"
       
    35 #include "sisregistrypackage.h"
       
    36 #include "sisregistrysession.h"
       
    37 #include "sisregistryentry.h"
       
    38 
       
    39 
       
    40 namespace Swi
       
    41 {
       
    42 
       
    43 // RMessagePtr2::Panic() also completes the message. This is 
       
    44 // (a) important for efficient cleanup within the kernel
       
    45 // (b) a problem if the message is completed the second time
       
    46 void PanicClient(const RMessagePtr2& aMessage, TSisHelperPanic aPanic)
       
    47 	{
       
    48 	aMessage.Panic(KSisHelperServerName, aPanic);
       
    49 	}
       
    50 
       
    51 //
       
    52 // Swi::CSisHelperShutdown helper class implementation
       
    53 //
       
    54 
       
    55 inline CSisHelperShutdown::CSisHelperShutdown() : CTimer(-1)
       
    56 	{
       
    57 	CActiveScheduler::Add(this);
       
    58 	}
       
    59 
       
    60 CSisHelperShutdown::~CSisHelperShutdown()
       
    61 	{
       
    62 	Deque();
       
    63 	}
       
    64 
       
    65 inline void CSisHelperShutdown::ConstructL()
       
    66 	{
       
    67 	CTimer::ConstructL();
       
    68 	}
       
    69 
       
    70 inline void CSisHelperShutdown::Start()
       
    71 	{
       
    72 	After(KShutdownDelay);
       
    73 	}
       
    74 
       
    75 // Initiate server exit when the timer expires
       
    76 void CSisHelperShutdown::RunL()
       
    77 	{
       
    78 	CActiveScheduler::Stop();
       
    79 	}
       
    80 
       
    81 //
       
    82 // CSisHelperSession
       
    83 //
       
    84 
       
    85 inline CSisHelperSession::CSisHelperSession(MSisDataProvider& aDataProvider)
       
    86 :	iDataProvider(aDataProvider)
       
    87 	{
       
    88 	}
       
    89 
       
    90 inline CSisHelperServer& CSisHelperSession::Server()
       
    91 	{
       
    92 	return *static_cast<CSisHelperServer*>(
       
    93 		const_cast<CServer2*>(CSession2::Server()));
       
    94 	}
       
    95 
       
    96 inline TBool CSisHelperSession::ReceivePending() const
       
    97 	{
       
    98 	return !iReceiveMsg.IsNull();
       
    99 	}
       
   100 
       
   101 // Second phase constructor, called by CServer2 framework
       
   102 void CSisHelperSession::CreateL()
       
   103 	{
       
   104 	Server().AddSession();
       
   105 	}
       
   106 
       
   107 CSisHelperSession::~CSisHelperSession()
       
   108 	{
       
   109 	delete iCurrentContents;
       
   110 	// Ignore any leave codes from CleanupAsyncExtractionL -
       
   111 	// they can't really be handled from the destructor.
       
   112 	TRAP_IGNORE(CleanupAsyncExtractionL());
       
   113 
       
   114 	Server().DropSession();
       
   115 	CSecurityPolicy::ReleaseResource();
       
   116 	}
       
   117 
       
   118 
       
   119 // Handle a client request. Leaving is handled by 
       
   120 // CSisHelperServer::ServiceError() which reports the error code to the client
       
   121 void CSisHelperSession::ServiceL(const RMessage2& aMessage)
       
   122 	{
       
   123 	DEBUG_PRINTF2(_L8("Sis Helper - Servicing Message Type %d."), aMessage.Function());
       
   124 	
       
   125 	TInt err = KErrNone;
       
   126 	switch (aMessage.Function())
       
   127 		{
       
   128 		case ESisHelperGetController:
       
   129 			{
       
   130 			TRAP(err, GetControllerL(aMessage));
       
   131 			if (err != KErrNone)
       
   132 				{
       
   133 				// Map unexpected KErrOverflow errors to KErrCorrupt; otherwise,
       
   134 				// sishelperclient will interpret this as a signal to resize the request
       
   135 				// buffer
       
   136 				aMessage.Complete((err == KErrOverflow ? KErrCorrupt : err));
       
   137 				}
       
   138 			break;
       
   139 			}
       
   140 			
       
   141 		case ESisHelperExtractFile:
       
   142 			{
       
   143 			TRAP(err, ExtractFileL(aMessage));
       
   144 			aMessage.Complete(err);
       
   145 			break;
       
   146 			}
       
   147 			
       
   148 		case ESisHelperFillDrivesAndSpaces:
       
   149 			{
       
   150 			// calculate the likely size of the data transfer buffer
       
   151 			const TInt KMaxBufSize=
       
   152 				sizeof(TInt)+                 // number of entries
       
   153 				KMaxDrives*sizeof(TUint)+  // drive letters stored as TUints
       
   154 				KMaxDrives*sizeof(TInt64); // drive free spaces
       
   155 			
       
   156 			// allocate buffer for the returned arrays
       
   157 			HBufC8* buf=HBufC8::NewMaxLC(KMaxBufSize);
       
   158 			
       
   159 			// create stream on the buffer
       
   160 			TPtr8 des=buf->Des();
       
   161 			RDesWriteStream outs(des);
       
   162 			CleanupClosePushL(outs);
       
   163 			
       
   164 			// get drive letter and free space information
       
   165 			RArray<TChar> driveLetters;
       
   166 			CleanupClosePushL(driveLetters);
       
   167 			RArray<TInt64> driveSpaces;
       
   168 			CleanupClosePushL(driveSpaces);
       
   169 			FillDrivesAndSpacesL(driveLetters, driveSpaces);
       
   170 			
       
   171 			// externalise the arrays
       
   172 			TInt count=driveLetters.Count();
       
   173 			outs.WriteInt32L(count);
       
   174 			TInt i;
       
   175 			for (i = 0; i < count; ++i)
       
   176 				{
       
   177 				outs.WriteInt32L(static_cast<TUint>(driveLetters[i]));
       
   178 				}
       
   179 			
       
   180 			for (i = 0; i < count; ++i)
       
   181 				{
       
   182 				outs.WriteInt32L(I64LOW(driveSpaces[i]));
       
   183 				outs.WriteInt32L(I64HIGH(driveSpaces[i]));
       
   184 				}
       
   185 			
       
   186 			// write the buffer to the passed buffer
       
   187 			outs.CommitL();
       
   188 			aMessage.WriteL(0, *buf);
       
   189 			
       
   190 			// cleanup
       
   191 			// driveSpaces, driveLetters, outs, buf
       
   192 			CleanupStack::PopAndDestroy(4, buf);
       
   193 			aMessage.Complete(KErrNone);
       
   194 			break;
       
   195 			}
       
   196 
       
   197 		case ESisHelperOpenDrmContent:
       
   198 			{
       
   199 			ContentAccess::TIntent intent
       
   200 				= static_cast<ContentAccess::TIntent>(aMessage.Int0());
       
   201 			
       
   202 			TRAPD(err, iDataProvider.OpenDrmContentL(intent));
       
   203 			aMessage.Complete(err);
       
   204 			break;
       
   205 			}
       
   206 		
       
   207 		case ESisHelperExecuteDrmIntent:
       
   208 			{
       
   209 			ContentAccess::TIntent intent
       
   210 				= static_cast<ContentAccess::TIntent>(aMessage.Int0());
       
   211 	
       
   212 			aMessage.Complete(iDataProvider.ExecuteDrmIntent(intent));
       
   213 			break;
       
   214 			}
       
   215 		
       
   216 		case ESisHelperSetupAsyncExtraction:
       
   217 			SetupAsyncExtractionL(aMessage);
       
   218 			break;
       
   219 			
       
   220 		case ESisHelperAsyncExtraction:
       
   221 			AsyncExtractionL(aMessage);
       
   222 			break;
       
   223 			
       
   224 		case ESisHelperEndAsyncExtraction:
       
   225 			EndAsyncExtractionL(aMessage);
       
   226 			break;
       
   227 
       
   228 		case ESisHelperCreateSisStub:
       
   229 			{
       
   230 			// write stub
       
   231 			TRAPD(err, CreateSisStubL(aMessage));
       
   232 			
       
   233 			// cleanup
       
   234 			aMessage.Complete(err);
       
   235 			break;
       
   236 			}
       
   237 		case ESisHelperIsStub:
       
   238 			{	
       
   239 			TRAPD(err,IsStubL(aMessage));
       
   240 			aMessage.Complete(err);
       
   241 			break;
       
   242 			}
       
   243 		case ESisHelperGetSisFileDrive:
       
   244 			{
       
   245 			TRAPD(err,GetSisFileDriveL(aMessage));	
       
   246 			aMessage.Complete(err);
       
   247 			break;
       
   248 			}
       
   249 		case ESisHelperIsSisFileReadOnly:
       
   250 			{
       
   251 			TRAPD(err,IsSisFileReadOnlyL(aMessage));	
       
   252 			aMessage.Complete(err);
       
   253 			break;
       
   254 			}
       
   255 		case ESisHelperGetSisFileName:
       
   256 			{
       
   257 			TRAP(err, GetSisFileNameL(aMessage));
       
   258 			aMessage.Complete(err);
       
   259 			break;
       
   260 			}			
       
   261 		case ESisHelperGetControllerFromSis:
       
   262 			{
       
   263 			TRAP(err, GetControllerFromSisL(aMessage));
       
   264 			aMessage.Complete(err);
       
   265 			break;
       
   266 			}
       
   267 		#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
       
   268 		case ESisHelperIsDrmProtected:
       
   269 			{
       
   270 			TRAP(err, IsDrmProtectedL(aMessage));
       
   271 			aMessage.Complete(err);
       
   272 			break;
       
   273 			}
       
   274 		#endif
       
   275 		case ESisHelperGetEquivalentLanguages:
       
   276 			{
       
   277 			TRAP(err, GetEquivalentLanguagesL(aMessage));
       
   278 			aMessage.Complete(err);
       
   279 			break;
       
   280 			}	
       
   281 		default:
       
   282 			{
       
   283 			DEBUG_PRINTF(_L8("Sis Helper - Illegal Message Type."));
       
   284 			PanicClient(aMessage, EPanicIllegalFunction);
       
   285 			break;
       
   286 			}
       
   287 		}
       
   288 	}
       
   289 
       
   290 void CSisHelperSession::GetControllerL(const RMessage2& aMessage)
       
   291 	{
       
   292 	// Extract raw controller data into a buffer
       
   293 	HBufC8* controllerData = CurrentContentsL().ReadControllerL();
       
   294 	CleanupStack::PushL(controllerData);
       
   295 
       
   296 	// Get the data to the client using the standard overflow protocol
       
   297 	// - get the size of the supplied descriptor (parameter 0)
       
   298 	TInt size=aMessage.GetDesMaxLengthL(0);
       
   299 	// - see if we have enough space on the client
       
   300 	if (size < controllerData->Size())
       
   301 		{
       
   302 		// not enough space, complete with KErrOverflow and encode the
       
   303 		// required size into the passed descriptor
       
   304 		TPckgC<TInt> sizePckg(controllerData->Size());
       
   305 
       
   306 		// is there enough space for an integer?
       
   307 		if (size >= sizePckg.Size())
       
   308 			{
       
   309 			aMessage.WriteL(0, sizePckg);
       
   310 			}
       
   311 		// complete the message with KErrOverflow when resizing requires
       
   312 		aMessage.Complete(KErrOverflow);
       
   313 		}
       
   314 	else
       
   315 		{
       
   316 		// enough space, write the controller to the supplied buffer
       
   317 		aMessage.WriteL(0, *controllerData);
       
   318 		//Everything went fine so complete the message with KErrNone.
       
   319 		aMessage.Complete(KErrNone);
       
   320 		}
       
   321 	CleanupStack::PopAndDestroy(controllerData); // controllerData				
       
   322 	}
       
   323 
       
   324 void CSisHelperSession::ExtractFileL(const RMessage2& aMessage)
       
   325 	{
       
   326 	RFile file;
       
   327 	file.AdoptFromClient(aMessage, 0, 1);			
       
   328 	CleanupClosePushL(file);
       
   329 	TInt fileIndex = aMessage.Int2();
       
   330 	TInt dataUnit = aMessage.Int3();
       
   331 
       
   332 	CurrentContentsL().ReadDataL(file, fileIndex, dataUnit);
       
   333 	User::LeaveIfError(file.Flush());
       
   334 	CleanupStack::PopAndDestroy(&file); // file
       
   335 	}
       
   336 
       
   337 void CSisHelperSession::IsStubL(const RMessage2& aMessage)
       
   338 	{
       
   339 	TBool stub = CurrentContentsL().IsStub();	
       
   340 	TPckg<TBool> stubPckg(stub);
       
   341 	aMessage.WriteL(0, stubPckg);
       
   342 	}
       
   343 
       
   344 void CSisHelperSession::GetSisFileDriveL(const RMessage2& aMessage)
       
   345 	{
       
   346 	TChar drive;
       
   347 	User::LeaveIfError(RFs::DriveToChar(Server().GetSisFileDrive(), drive));
       
   348 	TPckg<TChar> drivePckg(drive);
       
   349 	aMessage.WriteL(0, drivePckg);
       
   350 	}
       
   351 
       
   352 void CSisHelperSession::IsSisFileReadOnlyL(const RMessage2& aMessage)
       
   353 	{
       
   354 	TBool readOnly = Server().IsSisFileReadOnly();
       
   355 	TPckg<TBool> readOnlyPckg(readOnly);
       
   356 	aMessage.WriteL(0, readOnlyPckg);
       
   357 	}
       
   358 
       
   359 void CSisHelperSession::GetSisFileNameL(const RMessage2& aMessage)
       
   360 	{
       
   361 	TInt clientDesLength = aMessage.GetDesMaxLengthL(0);
       
   362 	TPtrC filename = Server().GetSisFileNameL();
       
   363 	if (clientDesLength < filename.Length())
       
   364 		{
       
   365 		User::Leave(KErrOverflow);
       
   366 		}
       
   367 	if (filename.Length() == 0)
       
   368 		{
       
   369 		User::Leave(KErrNotFound);
       
   370 		}
       
   371 	aMessage.WriteL(0, filename);
       
   372 	}
       
   373 
       
   374 void CSisHelperSession::GetControllerFromSisL(const RMessage2& aMessage)
       
   375 	{
       
   376 	// Get the file handle
       
   377 	RFile file;
       
   378 	// Adopt the file using the RFs handle from message slot 1 and the RFile handle from slot 2
       
   379 	User::LeaveIfError(file.AdoptFromClient(aMessage, 1, 2));          
       
   380 	CleanupClosePushL(file);
       
   381 
       
   382 	// Create a file data provider
       
   383 	MSisDataProvider* dataProvider = NULL;
       
   384 	CSecurityPolicy* securityPolicy = CSecurityPolicy::GetSecurityPolicyL();
       
   385 	TBool drmEnabled = securityPolicy->DrmEnabled();
       
   386 	securityPolicy->ReleaseResource();
       
   387 	if (drmEnabled)
       
   388 		{
       
   389 		dataProvider = CCafSisDataProvider::NewLC(file);
       
   390 		dataProvider->OpenDrmContentL(ContentAccess::EInstall);
       
   391 		User::LeaveIfError(dataProvider->ExecuteDrmIntent(ContentAccess::EUnknown));
       
   392 		}
       
   393 	else
       
   394 		{
       
   395 		dataProvider = CFileSisDataProvider::NewLC(file);
       
   396 		}
       
   397 
       
   398 	// Extract raw controller data into a buffer
       
   399 	TInt64 pos(0);
       
   400 	User::LeaveIfError(dataProvider->Seek(ESeekStart, pos));
       
   401 	Sis::CContents *contents = Sis::Parser::ContentsL(*dataProvider);
       
   402 	CleanupStack::PushL(contents);
       
   403 	HBufC8* controllerData = NULL;
       
   404 	TRAPD(err, controllerData = contents->ReadControllerL());
       
   405 	if(err == KErrOverflow)
       
   406    		{
       
   407    		User::Leave(KErrCorrupt);			
       
   408    		}
       
   409 	User::LeaveIfError(err);
       
   410 	CleanupStack::PushL(controllerData);
       
   411 
       
   412 	// Get the data to the client using the standard overflow protocol
       
   413 	// - get the size of the supplied descriptor (parameter 0)
       
   414 	TInt size = aMessage.GetDesMaxLengthL(0);
       
   415 	// - see if we have enough space on the client
       
   416 	if (size < controllerData->Size())
       
   417 		{
       
   418 		// Not enough space, complete with KErrOverflow and encode the
       
   419 		// required size into the passed descriptor
       
   420 		TPckgC<TInt> sizePckg(controllerData->Size());
       
   421 
       
   422 		// Is there enough space for an integer?
       
   423 		if (size >= sizePckg.Size())
       
   424 			{
       
   425 			aMessage.WriteL(0, sizePckg);
       
   426 			}
       
   427 		// complete the message with KErrOverflow when resizing requires
       
   428 		User::Leave(KErrOverflow);
       
   429 		}
       
   430 	else
       
   431 		{
       
   432 		// Enough space, write the controller to the supplied buffer
       
   433 		aMessage.WriteL(0, *controllerData);
       
   434 		}
       
   435 	CleanupStack::PopAndDestroy(4, &file); // dataProvider, contents, controllerData
       
   436 	}
       
   437 
       
   438 
       
   439 	// Functions for asynchronous extraction
       
   440 void CSisHelperSession::SetupAsyncExtractionL(const RMessage2& aMessage)
       
   441 	{
       
   442 	// We only support extracting one file at once currently
       
   443 	if (iInAsyncExtraction)
       
   444 		{
       
   445 		aMessage.Complete(KErrInUse);
       
   446 		}
       
   447 	else
       
   448 		{
       
   449 		// Get file and session handles
       
   450 		User::LeaveIfError(iAsyncFs.Open(aMessage, 0));
       
   451 
       
   452 		// Adopt the filehandle;
       
   453 		User::LeaveIfError(iAsyncFile.Adopt(iAsyncFs, aMessage.Int1()));
       
   454 	
       
   455 		iAsyncFileIndex=aMessage.Int2();
       
   456 		iAsyncDataUnit=aMessage.Int3();
       
   457 	
       
   458 		iInAsyncExtraction=ETrue;
       
   459 		aMessage.Complete(KErrNone);
       
   460 		}
       
   461 	}
       
   462 
       
   463 void CSisHelperSession::AsyncExtractionL(const RMessage2& aMessage)
       
   464 	{
       
   465 	TInt lengthHigh=aMessage.Int0();
       
   466 	TInt lengthLow=aMessage.Int1();
       
   467 	TInt64 length= lengthHigh;
       
   468 	length=( length << 32) + lengthLow;
       
   469 				
       
   470 	CurrentContentsL().ReadDataL(iAsyncFile, iAsyncFileIndex, iAsyncDataUnit, length);
       
   471 	TInt err = iAsyncFile.Flush();
       
   472 
       
   473 	aMessage.Complete(err);
       
   474 	}
       
   475 
       
   476 void CSisHelperSession::EndAsyncExtractionL(const RMessage2& aMessage)
       
   477 	{
       
   478 	if (!iInAsyncExtraction)
       
   479 		{
       
   480 		aMessage.Complete(KErrArgument);
       
   481 		}
       
   482 	else
       
   483 		{
       
   484 		CleanupAsyncExtractionL();
       
   485 		aMessage.Complete(KErrNone);
       
   486 		}
       
   487 	}
       
   488 
       
   489 void CSisHelperSession::CleanupAsyncExtractionL()
       
   490 	{
       
   491 	if (iInAsyncExtraction)
       
   492 		{
       
   493 		iAsyncFile.Close();
       
   494 		iAsyncFs.Close();
       
   495 		iInAsyncExtraction=EFalse;
       
   496 		}
       
   497 	}
       
   498 
       
   499 // Handle an error from CSisHelperSession::ServiceL(). A bad descriptor 
       
   500 // error implies a badly programmed client, so panic it; otherwise use the
       
   501 // default handling (report error to the client)
       
   502 void CSisHelperSession::ServiceError(const RMessage2& aMessage, TInt aError)
       
   503 	{
       
   504 	if (aError==KErrBadDescriptor)
       
   505 		{
       
   506 		PanicClient(aMessage, EPanicBadDescriptor);
       
   507 		}
       
   508 	CSession2::ServiceError(aMessage, aError);
       
   509 	}
       
   510 
       
   511 void CSisHelperSession::FillDrivesAndSpacesL(RArray<TChar>& aDriveLetters, 
       
   512 					                        RArray<TInt64>& aDriveSpaces)
       
   513 	{
       
   514 	// This is the LFSS free space threshold
       
   515 	TInt freeSpaceAdjustment = 1024 * 128;    // Bytes	
       
   516 
       
   517     // get information about drives
       
   518     TDriveList driveList;
       
   519     RFs fs;
       
   520     User::LeaveIfError(fs.Connect());
       
   521     CleanupClosePushL(fs);
       
   522     
       
   523     // List all drives in the system
       
   524     User::LeaveIfError(fs.DriveList(driveList));
       
   525 
       
   526 	// Check all drives
       
   527     for (TInt driveNumber=EDriveA; driveNumber<=EDriveZ; driveNumber++)
       
   528         {
       
   529         if (!driveList[driveNumber])
       
   530  			{
       
   531  			// Not a recognised drive
       
   532             continue;
       
   533 			}
       
   534 			
       
   535     	TVolumeInfo volInfo;
       
   536         if (fs.Volume(volInfo, driveNumber) != KErrNone)
       
   537 			{
       
   538 			// The volume is not usable (e.g. no media card inserted)
       
   539             continue;
       
   540 			}
       
   541 
       
   542         if (volInfo.iDrive.iType==EMediaNotPresent || 
       
   543             volInfo.iDrive.iType==EMediaRom || 
       
   544             volInfo.iDrive.iType==EMediaRemote)
       
   545 			{
       
   546 			// Exclude drives not suitable for installation
       
   547             continue;
       
   548 			}
       
   549 			
       
   550         // Do not list read only and substituted drives as an option to install to
       
   551         if (volInfo.iDrive.iDriveAtt & KDriveAttRom || 
       
   552          	volInfo.iDrive.iDriveAtt & KDriveAttSubsted) 
       
   553 			{
       
   554             continue;
       
   555 			}
       
   556 
       
   557         TInt64 volSpace = volInfo.iFree - freeSpaceAdjustment;  // bytes
       
   558         if (volSpace < 0)
       
   559 			{
       
   560             volSpace = 0;
       
   561 			}
       
   562 			
       
   563 		TChar aDrive;
       
   564 		User::LeaveIfError(fs.DriveToChar(driveNumber, aDrive));
       
   565 		User::LeaveIfError(aDriveLetters.Append(TChar(aDrive)));
       
   566         User::LeaveIfError(aDriveSpaces.Append(volSpace));
       
   567         }
       
   568     CleanupStack::PopAndDestroy(&fs);
       
   569 	}
       
   570 
       
   571 
       
   572 void CSisHelperSession::CreateSisStubL(const RMessage2& aMessage)
       
   573 	{
       
   574 	RFile file;
       
   575 	file.AdoptFromClient(aMessage, 0, 1);			
       
   576 	CleanupClosePushL(file);
       
   577 		
       
   578 	// rewind the data provider
       
   579 	TInt64 pos(0);
       
   580 	User::LeaveIfError(iDataProvider.Seek(ESeekStart, pos));
       
   581 	
       
   582 	Sis::Parser::CreateSisStubL(file, iDataProvider);	
       
   583 	CleanupStack::PopAndDestroy(&file);  //close
       
   584 	}
       
   585 
       
   586 //
       
   587 // CSisHelperServer implementation
       
   588 //
       
   589 
       
   590 // All functions can only be accessed by SWIS
       
   591 const TInt CSisHelperServer::iRanges[iRangeCount] = 
       
   592                 {
       
   593                 0 // All connect attempts
       
   594                 };
       
   595 
       
   596 const TUint8 CSisHelperServer::iElementsIndex[iRangeCount] = 
       
   597                 {
       
   598                 0 //Only SWIS can use sishelper. This is policed by the SID of SWIS
       
   599                 };
       
   600 
       
   601 const CPolicyServer::TPolicyElement CSisHelperServer::iPolicyElements[2] = 
       
   602                 {
       
   603                 {_INIT_SECURITY_POLICY_S0(0x101F7295), //SWIS' SID = 0x101F7295
       
   604                 	CPolicyServer::EFailClient},		
       
   605                 
       
   606                               
       
   607    
       
   608                 };
       
   609 
       
   610 const CPolicyServer::TPolicy CSisHelperServer::iPolicy =
       
   611                 {
       
   612                 0,					//specifies all connect attempts need SWIS' SID
       
   613                 iRangeCount,
       
   614                 iRanges,
       
   615                 iElementsIndex,
       
   616                 iPolicyElements,
       
   617                 };
       
   618 
       
   619 // Construction, the result is on the cleanup stack
       
   620 EXPORT_C CSisHelperServer* CSisHelperServer::NewLC(TSisHelperStartParams& aParams)
       
   621 	{
       
   622 	CSisHelperServer* self=new(ELeave) CSisHelperServer;
       
   623 	CleanupStack::PushL(self);
       
   624 	self->ConstructL(aParams);
       
   625 	return self;
       
   626 	}
       
   627 
       
   628 // Construction
       
   629 EXPORT_C CSisHelperServer* CSisHelperServer::NewL(TSisHelperStartParams& aParams)
       
   630 	{
       
   631 	CSisHelperServer* self=NewLC(aParams);
       
   632 	CleanupStack::Pop(self);
       
   633 	return self;
       
   634 	}
       
   635 
       
   636 // 2nd phase constructor; ensure the timer and server objects are running
       
   637 void CSisHelperServer::ConstructL(TSisHelperStartParams& aParams)
       
   638 	{
       
   639 	// See what kind of startup information is passed to the server
       
   640 	switch (aParams.iType)
       
   641 		{
       
   642 		case TSisHelperStartParams::ETypeFileName:
       
   643 			{
       
   644 			// Create a file data provider
       
   645 			User::LeaveIfError(iFs.Connect());
       
   646 			iSessionConnected=ETrue;
       
   647 
       
   648 			CSecurityPolicy* securityPolicy=CSecurityPolicy::GetSecurityPolicyL();
       
   649 			
       
   650 			_LIT(KDriveSeparator, ":\\");
       
   651 			TPtrC sisFileName(*aParams.iFileName);	
       
   652 			if (sisFileName.Find(KDriveSeparator) != 1)
       
   653 				{
       
   654 				// The full path (inc. drive letter) has not been specified
       
   655 				TEntry* fileExits = new(ELeave) TEntry;
       
   656 				CleanupStack::PushL(fileExits);
       
   657 				TInt err = iFs.Entry(sisFileName, *fileExits);
       
   658 				if (err == KErrNone)
       
   659 					{
       
   660 					// Found it, must be /xxxxx.sis. Fill in the missing
       
   661 					// drive path
       
   662 					TParse* sisFileWithDrv = new(ELeave) TParse;
       
   663 					CleanupStack::PushL(sisFileWithDrv);
       
   664 					iFs.Parse(sisFileName, *sisFileWithDrv);
       
   665 					// Get the SIS file name
       
   666 					iSisFileName = sisFileWithDrv->FullName().AllocL();
       
   667 					User::LeaveIfError(RFs::CharToDrive(sisFileWithDrv->Drive()[0], iSisFileDrive));
       
   668 					CleanupStack::PopAndDestroy(sisFileWithDrv);				
       
   669 					}
       
   670 				CleanupStack::PopAndDestroy(fileExits);		
       
   671 				}
       
   672 			else
       
   673 				{
       
   674 				// figure out which drive this SIS file came from
       
   675 				TParsePtrC parser(sisFileName);
       
   676 				User::LeaveIfError(RFs::CharToDrive(parser.Drive()[0], iSisFileDrive));
       
   677 				// Get the SIS file name
       
   678 				iSisFileName = sisFileName.AllocL();
       
   679 				}
       
   680 			
       
   681 			if (securityPolicy->DrmEnabled())
       
   682 				{
       
   683 				iDataProvider=CCafSisDataProvider::NewL(sisFileName);
       
   684 				}
       
   685 			else
       
   686 				{
       
   687 				iDataProvider=CFileSisDataProvider::NewL(iFs, sisFileName);
       
   688 				}	
       
   689 
       
   690 			iDeleteDataProvider=ETrue;
       
   691 
       
   692 			// Figure out whether the sis file is read only or the drive is
       
   693 			// write-protected or ROM.
       
   694 			TDriveInfo driveInfo;
       
   695 			User::LeaveIfError(iFs.Drive(driveInfo,iSisFileDrive));
       
   696 			if (!((driveInfo.iMediaAtt & KMediaAttWriteProtected) ||
       
   697 				(driveInfo.iDriveAtt & KDriveAttRom)))
       
   698 				{
       
   699 				TEntry entry;
       
   700 				User::LeaveIfError(iFs.Entry(sisFileName, entry));
       
   701 				iSisFileReadOnly = entry.IsReadOnly();
       
   702 				}
       
   703 			}
       
   704 			break;
       
   705 
       
   706 		case TSisHelperStartParams::ETypeFileHandle:
       
   707 			{
       
   708 			CSecurityPolicy* securityPolicy=CSecurityPolicy::GetSecurityPolicyL();
       
   709 
       
   710 			if (securityPolicy->DrmEnabled())
       
   711 				{
       
   712 				iDataProvider=CCafSisDataProvider::NewL(*aParams.iFileHandle);
       
   713 				}
       
   714 			else
       
   715 				{
       
   716 				iDataProvider=CFileSisDataProvider::NewL(*aParams.iFileHandle);
       
   717 				}	
       
   718 
       
   719 			iDeleteDataProvider=ETrue;
       
   720 			
       
   721 			// figure out which drive this SIS file came from
       
   722 			TDriveInfo driveInfo;
       
   723 			User::LeaveIfError(aParams.iFileHandle->Drive(iSisFileDrive, driveInfo));
       
   724 
       
   725 			// Figure out whether the sis file is read only or the drive is
       
   726 			// write-protected or ROM.
       
   727 			if (!((driveInfo.iMediaAtt & KMediaAttWriteProtected) ||
       
   728 				(driveInfo.iDriveAtt & KDriveAttRom)))
       
   729 				{
       
   730 				TUint attributes;
       
   731 				User::LeaveIfError(aParams.iFileHandle->Att(attributes));
       
   732 				iSisFileReadOnly = (attributes & KEntryAttReadOnly) ? ETrue : EFalse;
       
   733 				}
       
   734 
       
   735 			// Get SIS file name
       
   736 			TFileName tempFileName;
       
   737 			User::LeaveIfError(aParams.iFileHandle->FullName(tempFileName));
       
   738 			iSisFileName = tempFileName.AllocL();
       
   739 			DEBUG_PRINTF2(_L("Sis Helper - processing %S by file handle"), iSisFileName);
       
   740 			}			
       
   741 			break;			
       
   742 		case TSisHelperStartParams::ETypeDataProvider:
       
   743 			// store the pointer, assuming ownership, check for NULL
       
   744 			iDataProvider=aParams.iDataProvider;
       
   745 			iDeleteDataProvider=EFalse;
       
   746 			if (iDataProvider==NULL)
       
   747 				{
       
   748 				PanicClient(Message(), EPanicBadDataProvider);
       
   749 				}
       
   750 			break;
       
   751 		case TSisHelperStartParams::ETypeNull:
       
   752 			// For use where file is passed in later along with request
       
   753 			break;
       
   754 
       
   755 		default:
       
   756 			// panic the client
       
   757 			PanicClient(Message(), EPanicBadStartupDataType);
       
   758 			break;
       
   759 		}
       
   760 		
       
   761 	StartL(KSisHelperServerName);
       
   762 	iShutdown=new(ELeave) CSisHelperShutdown;
       
   763 	iShutdown->ConstructL();
       
   764 	
       
   765 	// ensure that the server still exists even if the 1st client fails 
       
   766 	// to connect; the server will be terminated if no one connects to it
       
   767 	iShutdown->Start();
       
   768 	}
       
   769 
       
   770 CSisHelperServer::CSisHelperServer()
       
   771 :	CPolicyServer(CActive::EPriorityStandard, iPolicy, ESharableSessions),
       
   772 	iSisFileDrive(-1),
       
   773 	iSisFileReadOnly(ETrue)
       
   774 	{
       
   775 	}
       
   776 
       
   777 // Destruction; delete a data provider since we own it whether it was 
       
   778 // transferred from outside or created in the server.
       
   779 CSisHelperServer::~CSisHelperServer()
       
   780 	{
       
   781 	delete iShutdown;
       
   782 	
       
   783 	if (iDeleteDataProvider)
       
   784 		{
       
   785 		delete iDataProvider;
       
   786 		}
       
   787 
       
   788 	if (iSessionConnected)
       
   789 		{
       
   790 		iFs.Close();
       
   791 		}
       
   792 
       
   793 	if (iSisFileName)
       
   794 		{
       
   795 		delete iSisFileName;
       
   796 		}
       
   797 	
       
   798 	// Free ECOM memory reserved in this thread
       
   799 	// for example, plugins loaded by the CAF framework	
       
   800 	REComSession::FinalClose();
       
   801 
       
   802 
       
   803 		
       
   804 	}
       
   805 
       
   806 // Create a new client session
       
   807 CSession2* CSisHelperServer::NewSessionL(const TVersion&,
       
   808 	const RMessage2& ) const
       
   809 	{
       
   810 	
       
   811 	return new(ELeave) CSisHelperSession(*iDataProvider);
       
   812 	}
       
   813 	
       
   814 // A new session is being created; cancel the shutdown timer if it was running
       
   815 void CSisHelperServer::AddSession()
       
   816 	{
       
   817 	++iSessionCount;
       
   818 	DEBUG_PRINTF2(_L8("Sis Helper - Adding Session (%d active.)"), iSessionCount);
       
   819 	// stop shutdown object once the first (and only) session is connected
       
   820 	delete iShutdown;
       
   821 	iShutdown=NULL;
       
   822 	}
       
   823 
       
   824 // A session is being destroyed; terminate server immediately
       
   825 void CSisHelperServer::DropSession()
       
   826 	{
       
   827 	if (--iSessionCount==0)
       
   828 		{
       
   829 		CActiveScheduler::Stop();
       
   830 		}
       
   831 	DEBUG_PRINTF2(_L8("Sis Helper - Dropping Session (%d active.)"), iSessionCount);
       
   832 	}
       
   833 
       
   834 CSisRegistryPackage* CSisHelperServer::MainPackageEntryL(TUid aUid)
       
   835 	{
       
   836 	RSisRegistrySession registrySession;
       
   837 	User::LeaveIfError(registrySession.Connect());
       
   838 	CleanupClosePushL(registrySession);
       
   839 
       
   840 	RSisRegistryEntry registryEntry;
       
   841 	User::LeaveIfError(registryEntry.Open(registrySession, aUid));
       
   842 	CleanupClosePushL(registryEntry);
       
   843 
       
   844     // Get the package object associated with the entry
       
   845     CSisRegistryPackage* package = registryEntry.PackageL();
       
   846 
       
   847     CleanupStack::PopAndDestroy(2, &registrySession);
       
   848 	return package;
       
   849 	}
       
   850 
       
   851 //
       
   852 // Starts SISHelper in a new thread
       
   853 //
       
   854 TInt CSisHelperServer::StartSisHelper(TSisHelperStartParams& aParams, RThread& aServer)
       
   855 	{
       
   856 	// We might be trying to restart a server, in which case we could
       
   857 	// get a thread name clash. We could make the name unique/random,
       
   858 	// but the server name would still clash...
       
   859 
       
   860 	const TInt KSisHelperServerStackSize=0x2000;
       
   861 	TInt err = KErrNone;
       
   862 		
       
   863 	for (TInt retry=0; retry < 2; ++retry)
       
   864 		{
       
   865 		err = aServer.Create(KSisHelperServerName, SisHelperThreadFunction, 
       
   866 					   		KSisHelperServerStackSize, NULL, static_cast<TAny*>(&aParams), 
       
   867 					   		EOwnerThread);
       
   868 					   		
       
   869 		if (err == KErrAlreadyExists || err == KErrInUse)
       
   870 			{
       
   871 			  User::After(80000);
       
   872 			}
       
   873 		else
       
   874 			{
       
   875 			break;
       
   876 			}
       
   877 		}
       
   878 
       
   879 	if (err==KErrAlreadyExists)
       
   880 		{
       
   881 		return KErrServerBusy;
       
   882 		}
       
   883 
       
   884 	if (err!=KErrNone)
       
   885 		{
       
   886 		return err;
       
   887 		}
       
   888 	
       
   889 	// The following code is the same whether the server runs in a new thread 
       
   890 	// or process
       
   891 	TRequestStatus stat;
       
   892 	aServer.Rendezvous(stat);
       
   893 	if (stat!=KRequestPending)
       
   894 		{
       
   895 		aServer.Kill(0); // abort startup
       
   896 		}
       
   897 	else
       
   898 		{
       
   899 		aServer.Resume(); // logon OK, start the server
       
   900 		}
       
   901 
       
   902 	User::WaitForRequest(stat); // wait for start or death
       
   903 	
       
   904 	// we can't use the 'exit reason' if the server panicked as this is the 
       
   905 	// panic 'reason' and may be 0 which cannot be distinguished from KErrNone
       
   906 	err=(aServer.ExitType()==EExitPanic) ? KErrGeneral : stat.Int();
       
   907 	//We don't close aServer here. If asynchlauncher called, it will be closed
       
   908 	//in the RunL() method of uissclienthandler to make sure that SISHelper has been 
       
   909 	//disconnected by SWISInstaller. Otherwise, just after this function call.
       
   910 	return err;
       
   911 	}
       
   912 
       
   913 void CSisHelperServer::Abort()
       
   914 	{
       
   915 	TFullName fullName = RProcess().FullName();
       
   916 	fullName.Append(':');
       
   917 	fullName.Append(':');
       
   918 	fullName.Append(KSisHelperServerName);
       
   919 
       
   920 	RThread server;
       
   921 	TInt err = server.Open(fullName);
       
   922 	if (err == KErrNone)
       
   923 		{
       
   924 		server.Terminate(KErrAbort);
       
   925 		server.Close();
       
   926 		}
       
   927 	}
       
   928 
       
   929 // Entry point for the thread the SISHelper runs in
       
   930 TInt CSisHelperServer::SisHelperThreadFunction(TAny *aPtr)
       
   931 	{
       
   932 	if (aPtr==NULL)
       
   933 		{
       
   934 		return KErrArgument;
       
   935 		}
       
   936 		
       
   937 	CTrapCleanup* cleanup = CTrapCleanup::New(); // get clean-up stack
       
   938 	
       
   939 	TSisHelperStartParams* params=
       
   940 	static_cast<TSisHelperStartParams*>(aPtr);
       
   941 
       
   942 	CActiveScheduler* scheduler=new(ELeave) CActiveScheduler;
       
   943 	if (!scheduler)
       
   944 		{
       
   945 		return KErrNoMemory;
       
   946 		}
       
   947 		
       
   948 	DEBUG_PRINTF(_L8("Sis Helper - Starting Server"));
       
   949 
       
   950 	CActiveScheduler::Install(scheduler);
       
   951 	CSisHelperServer* server=NULL;
       
   952 	
       
   953 	TRAPD(err, server=CSisHelperServer::NewL(*params));
       
   954 
       
   955 	if (err==KErrNone)
       
   956 		{
       
   957 		// only continue launching the server if no error
       
   958 		RThread::Rendezvous(KErrNone);
       
   959 		scheduler->Start();
       
   960 		}
       
   961 		
       
   962 	DEBUG_PRINTF(_L8("Sis Helper - Stopping Server"));
       
   963 
       
   964 	CActiveScheduler::Install(NULL);
       
   965 	delete server;
       
   966 	delete scheduler;
       
   967 	delete cleanup; // destroy clean-up stack
       
   968 
       
   969 	CSecurityPolicy::ReleaseResource();
       
   970 	
       
   971 	return err;
       
   972 	}
       
   973 
       
   974 TInt CSisHelperServer::GetSisFileDrive()
       
   975 	{
       
   976 	return iSisFileDrive;
       
   977 	}
       
   978 
       
   979 TBool CSisHelperServer::IsSisFileReadOnly()
       
   980 	{
       
   981 	return iSisFileReadOnly;
       
   982 	}
       
   983 
       
   984 const TDesC& CSisHelperServer::GetSisFileNameL()
       
   985 	{
       
   986 	if (!iSisFileName)
       
   987 		{
       
   988 		User::Leave(KErrNotFound);
       
   989 		}
       
   990 	return *iSisFileName;
       
   991 	}
       
   992 
       
   993 Sis::CContents& CSisHelperSession::CurrentContentsL()
       
   994 	{
       
   995 	if(iCurrentContents == NULL)
       
   996 		{
       
   997 		TInt64 pos(0);
       
   998 		User::LeaveIfError(iDataProvider.Seek(ESeekStart, pos));
       
   999 		iCurrentContents=Sis::Parser::ContentsL(iDataProvider);
       
  1000 		}
       
  1001 	return *iCurrentContents;
       
  1002 	}
       
  1003 
       
  1004 #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
       
  1005 void CSisHelperSession::IsDrmProtectedL(const RMessage2& aMessage)
       
  1006 	{
       
  1007 	// Data provider will be of CCafSisDataProvider only when DRM is enabled in SWI policy.
       
  1008 	// So, check the policy before querying content protection status from the data provider.
       
  1009 	CSecurityPolicy* securityPolicy = CSecurityPolicy::GetSecurityPolicyL();
       
  1010 	if (securityPolicy->DrmEnabled())
       
  1011 		{
       
  1012 		CCafSisDataProvider* cafDataProvider = static_cast<CCafSisDataProvider*>(&iDataProvider);
       
  1013  		TBool isProtected = cafDataProvider->IsContentProtected();	
       
  1014    		TPckgBuf<TBool> isContentProtected(isProtected);
       
  1015    		aMessage.WriteL(0, isContentProtected);
       
  1016    		securityPolicy->ReleaseResource();
       
  1017 		}
       
  1018 	// If DRM is NOT enabled in SWI policy, no way to query the protection status. So, set it to Fasle.
       
  1019 	else
       
  1020 		{
       
  1021 		aMessage.WriteL(0, TPckgBuf<TBool>(EFalse));
       
  1022 		}
       
  1023 	}
       
  1024 #endif
       
  1025 
       
  1026 void CSisHelperSession::GetEquivalentLanguagesL(const RMessage2& aMessage)
       
  1027 	{
       
  1028 	TLanguage srcLangID = (TLanguage)aMessage.Int1();
       
  1029 	
       
  1030 	TLanguagePath equivalentLangs;
       
  1031 	BaflUtils::GetEquivalentLanguageList(srcLangID,equivalentLangs);
       
  1032 	
       
  1033 	// calculate the likely size of the data transfer buffer
       
  1034 	const TInt KMaxBufSize=
       
  1035 		sizeof(TInt)+                 // number of entries
       
  1036 		(KMaxDowngradeLanguages+1)*sizeof(TLanguage);  // Languages IDs stored as TLanguage
       
  1037 	
       
  1038 	// allocate buffer for the array
       
  1039 	HBufC8* buf=HBufC8::NewMaxLC(KMaxBufSize);
       
  1040 	
       
  1041 	TInt size = 1;
       
  1042 	while (equivalentLangs[size++] != ELangNone){}
       
  1043 		
       
  1044 	TPtr8 pBuf=buf->Des();
       
  1045 	RDesWriteStream outs(pBuf);
       
  1046 	CleanupClosePushL(outs);
       
  1047 	
       
  1048 	// Since the size contains the source language ID and ELangNone, the actual size is equal to size - 2
       
  1049 	outs.WriteInt32L(size-2);
       
  1050 	TInt i;
       
  1051 	for (i = 1; i < size-1; ++i)
       
  1052 		{
       
  1053 		outs.WriteInt32L(static_cast<TInt>(equivalentLangs[i]));
       
  1054 		}
       
  1055 	
       
  1056 	outs.CommitL();
       
  1057 	aMessage.WriteL(0, *buf);
       
  1058 	
       
  1059 	CleanupStack::PopAndDestroy(2,buf); //outs,buf
       
  1060 	}
       
  1061 
       
  1062 
       
  1063 } // namespace Swi