--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/installationservices/swi/source/sishelper/sishelper.cpp Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,1063 @@
+/*
+* Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+* SISHelper is a layer between a client (EpocInstall, Installer UI, or Control
+* Panel applet) that starts [un]installation.
+*
+*/
+
+
+#include <s32mem.h>
+#include <caf/caf.h>
+#include <ecom/ecom.h>
+#include <bautils.h>
+#include <e32math.h> // for Math::Random()
+
+#include "swi/launcher.h"
+#include "sishelper.h"
+#include "filesisdataprovider.h"
+#include "log.h"
+#include "swi/sisparser.h"
+#include "swi/siscontents.h"
+#include "securitypolicy.h"
+#include "cafsisdataprovider.h"
+#include "sisregistrypackage.h"
+#include "sisregistrysession.h"
+#include "sisregistryentry.h"
+
+
+namespace Swi
+{
+
+// RMessagePtr2::Panic() also completes the message. This is
+// (a) important for efficient cleanup within the kernel
+// (b) a problem if the message is completed the second time
+void PanicClient(const RMessagePtr2& aMessage, TSisHelperPanic aPanic)
+ {
+ aMessage.Panic(KSisHelperServerName, aPanic);
+ }
+
+//
+// Swi::CSisHelperShutdown helper class implementation
+//
+
+inline CSisHelperShutdown::CSisHelperShutdown() : CTimer(-1)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+CSisHelperShutdown::~CSisHelperShutdown()
+ {
+ Deque();
+ }
+
+inline void CSisHelperShutdown::ConstructL()
+ {
+ CTimer::ConstructL();
+ }
+
+inline void CSisHelperShutdown::Start()
+ {
+ After(KShutdownDelay);
+ }
+
+// Initiate server exit when the timer expires
+void CSisHelperShutdown::RunL()
+ {
+ CActiveScheduler::Stop();
+ }
+
+//
+// CSisHelperSession
+//
+
+inline CSisHelperSession::CSisHelperSession(MSisDataProvider& aDataProvider)
+: iDataProvider(aDataProvider)
+ {
+ }
+
+inline CSisHelperServer& CSisHelperSession::Server()
+ {
+ return *static_cast<CSisHelperServer*>(
+ const_cast<CServer2*>(CSession2::Server()));
+ }
+
+inline TBool CSisHelperSession::ReceivePending() const
+ {
+ return !iReceiveMsg.IsNull();
+ }
+
+// Second phase constructor, called by CServer2 framework
+void CSisHelperSession::CreateL()
+ {
+ Server().AddSession();
+ }
+
+CSisHelperSession::~CSisHelperSession()
+ {
+ delete iCurrentContents;
+ // Ignore any leave codes from CleanupAsyncExtractionL -
+ // they can't really be handled from the destructor.
+ TRAP_IGNORE(CleanupAsyncExtractionL());
+
+ Server().DropSession();
+ CSecurityPolicy::ReleaseResource();
+ }
+
+
+// Handle a client request. Leaving is handled by
+// CSisHelperServer::ServiceError() which reports the error code to the client
+void CSisHelperSession::ServiceL(const RMessage2& aMessage)
+ {
+ DEBUG_PRINTF2(_L8("Sis Helper - Servicing Message Type %d."), aMessage.Function());
+
+ TInt err = KErrNone;
+ switch (aMessage.Function())
+ {
+ case ESisHelperGetController:
+ {
+ TRAP(err, GetControllerL(aMessage));
+ if (err != KErrNone)
+ {
+ // Map unexpected KErrOverflow errors to KErrCorrupt; otherwise,
+ // sishelperclient will interpret this as a signal to resize the request
+ // buffer
+ aMessage.Complete((err == KErrOverflow ? KErrCorrupt : err));
+ }
+ break;
+ }
+
+ case ESisHelperExtractFile:
+ {
+ TRAP(err, ExtractFileL(aMessage));
+ aMessage.Complete(err);
+ break;
+ }
+
+ case ESisHelperFillDrivesAndSpaces:
+ {
+ // calculate the likely size of the data transfer buffer
+ const TInt KMaxBufSize=
+ sizeof(TInt)+ // number of entries
+ KMaxDrives*sizeof(TUint)+ // drive letters stored as TUints
+ KMaxDrives*sizeof(TInt64); // drive free spaces
+
+ // allocate buffer for the returned arrays
+ HBufC8* buf=HBufC8::NewMaxLC(KMaxBufSize);
+
+ // create stream on the buffer
+ TPtr8 des=buf->Des();
+ RDesWriteStream outs(des);
+ CleanupClosePushL(outs);
+
+ // get drive letter and free space information
+ RArray<TChar> driveLetters;
+ CleanupClosePushL(driveLetters);
+ RArray<TInt64> driveSpaces;
+ CleanupClosePushL(driveSpaces);
+ FillDrivesAndSpacesL(driveLetters, driveSpaces);
+
+ // externalise the arrays
+ TInt count=driveLetters.Count();
+ outs.WriteInt32L(count);
+ TInt i;
+ for (i = 0; i < count; ++i)
+ {
+ outs.WriteInt32L(static_cast<TUint>(driveLetters[i]));
+ }
+
+ for (i = 0; i < count; ++i)
+ {
+ outs.WriteInt32L(I64LOW(driveSpaces[i]));
+ outs.WriteInt32L(I64HIGH(driveSpaces[i]));
+ }
+
+ // write the buffer to the passed buffer
+ outs.CommitL();
+ aMessage.WriteL(0, *buf);
+
+ // cleanup
+ // driveSpaces, driveLetters, outs, buf
+ CleanupStack::PopAndDestroy(4, buf);
+ aMessage.Complete(KErrNone);
+ break;
+ }
+
+ case ESisHelperOpenDrmContent:
+ {
+ ContentAccess::TIntent intent
+ = static_cast<ContentAccess::TIntent>(aMessage.Int0());
+
+ TRAPD(err, iDataProvider.OpenDrmContentL(intent));
+ aMessage.Complete(err);
+ break;
+ }
+
+ case ESisHelperExecuteDrmIntent:
+ {
+ ContentAccess::TIntent intent
+ = static_cast<ContentAccess::TIntent>(aMessage.Int0());
+
+ aMessage.Complete(iDataProvider.ExecuteDrmIntent(intent));
+ break;
+ }
+
+ case ESisHelperSetupAsyncExtraction:
+ SetupAsyncExtractionL(aMessage);
+ break;
+
+ case ESisHelperAsyncExtraction:
+ AsyncExtractionL(aMessage);
+ break;
+
+ case ESisHelperEndAsyncExtraction:
+ EndAsyncExtractionL(aMessage);
+ break;
+
+ case ESisHelperCreateSisStub:
+ {
+ // write stub
+ TRAPD(err, CreateSisStubL(aMessage));
+
+ // cleanup
+ aMessage.Complete(err);
+ break;
+ }
+ case ESisHelperIsStub:
+ {
+ TRAPD(err,IsStubL(aMessage));
+ aMessage.Complete(err);
+ break;
+ }
+ case ESisHelperGetSisFileDrive:
+ {
+ TRAPD(err,GetSisFileDriveL(aMessage));
+ aMessage.Complete(err);
+ break;
+ }
+ case ESisHelperIsSisFileReadOnly:
+ {
+ TRAPD(err,IsSisFileReadOnlyL(aMessage));
+ aMessage.Complete(err);
+ break;
+ }
+ case ESisHelperGetSisFileName:
+ {
+ TRAP(err, GetSisFileNameL(aMessage));
+ aMessage.Complete(err);
+ break;
+ }
+ case ESisHelperGetControllerFromSis:
+ {
+ TRAP(err, GetControllerFromSisL(aMessage));
+ aMessage.Complete(err);
+ break;
+ }
+ #ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+ case ESisHelperIsDrmProtected:
+ {
+ TRAP(err, IsDrmProtectedL(aMessage));
+ aMessage.Complete(err);
+ break;
+ }
+ #endif
+ case ESisHelperGetEquivalentLanguages:
+ {
+ TRAP(err, GetEquivalentLanguagesL(aMessage));
+ aMessage.Complete(err);
+ break;
+ }
+ default:
+ {
+ DEBUG_PRINTF(_L8("Sis Helper - Illegal Message Type."));
+ PanicClient(aMessage, EPanicIllegalFunction);
+ break;
+ }
+ }
+ }
+
+void CSisHelperSession::GetControllerL(const RMessage2& aMessage)
+ {
+ // Extract raw controller data into a buffer
+ HBufC8* controllerData = CurrentContentsL().ReadControllerL();
+ CleanupStack::PushL(controllerData);
+
+ // Get the data to the client using the standard overflow protocol
+ // - get the size of the supplied descriptor (parameter 0)
+ TInt size=aMessage.GetDesMaxLengthL(0);
+ // - see if we have enough space on the client
+ if (size < controllerData->Size())
+ {
+ // not enough space, complete with KErrOverflow and encode the
+ // required size into the passed descriptor
+ TPckgC<TInt> sizePckg(controllerData->Size());
+
+ // is there enough space for an integer?
+ if (size >= sizePckg.Size())
+ {
+ aMessage.WriteL(0, sizePckg);
+ }
+ // complete the message with KErrOverflow when resizing requires
+ aMessage.Complete(KErrOverflow);
+ }
+ else
+ {
+ // enough space, write the controller to the supplied buffer
+ aMessage.WriteL(0, *controllerData);
+ //Everything went fine so complete the message with KErrNone.
+ aMessage.Complete(KErrNone);
+ }
+ CleanupStack::PopAndDestroy(controllerData); // controllerData
+ }
+
+void CSisHelperSession::ExtractFileL(const RMessage2& aMessage)
+ {
+ RFile file;
+ file.AdoptFromClient(aMessage, 0, 1);
+ CleanupClosePushL(file);
+ TInt fileIndex = aMessage.Int2();
+ TInt dataUnit = aMessage.Int3();
+
+ CurrentContentsL().ReadDataL(file, fileIndex, dataUnit);
+ User::LeaveIfError(file.Flush());
+ CleanupStack::PopAndDestroy(&file); // file
+ }
+
+void CSisHelperSession::IsStubL(const RMessage2& aMessage)
+ {
+ TBool stub = CurrentContentsL().IsStub();
+ TPckg<TBool> stubPckg(stub);
+ aMessage.WriteL(0, stubPckg);
+ }
+
+void CSisHelperSession::GetSisFileDriveL(const RMessage2& aMessage)
+ {
+ TChar drive;
+ User::LeaveIfError(RFs::DriveToChar(Server().GetSisFileDrive(), drive));
+ TPckg<TChar> drivePckg(drive);
+ aMessage.WriteL(0, drivePckg);
+ }
+
+void CSisHelperSession::IsSisFileReadOnlyL(const RMessage2& aMessage)
+ {
+ TBool readOnly = Server().IsSisFileReadOnly();
+ TPckg<TBool> readOnlyPckg(readOnly);
+ aMessage.WriteL(0, readOnlyPckg);
+ }
+
+void CSisHelperSession::GetSisFileNameL(const RMessage2& aMessage)
+ {
+ TInt clientDesLength = aMessage.GetDesMaxLengthL(0);
+ TPtrC filename = Server().GetSisFileNameL();
+ if (clientDesLength < filename.Length())
+ {
+ User::Leave(KErrOverflow);
+ }
+ if (filename.Length() == 0)
+ {
+ User::Leave(KErrNotFound);
+ }
+ aMessage.WriteL(0, filename);
+ }
+
+void CSisHelperSession::GetControllerFromSisL(const RMessage2& aMessage)
+ {
+ // Get the file handle
+ RFile file;
+ // Adopt the file using the RFs handle from message slot 1 and the RFile handle from slot 2
+ User::LeaveIfError(file.AdoptFromClient(aMessage, 1, 2));
+ CleanupClosePushL(file);
+
+ // Create a file data provider
+ MSisDataProvider* dataProvider = NULL;
+ CSecurityPolicy* securityPolicy = CSecurityPolicy::GetSecurityPolicyL();
+ TBool drmEnabled = securityPolicy->DrmEnabled();
+ securityPolicy->ReleaseResource();
+ if (drmEnabled)
+ {
+ dataProvider = CCafSisDataProvider::NewLC(file);
+ dataProvider->OpenDrmContentL(ContentAccess::EInstall);
+ User::LeaveIfError(dataProvider->ExecuteDrmIntent(ContentAccess::EUnknown));
+ }
+ else
+ {
+ dataProvider = CFileSisDataProvider::NewLC(file);
+ }
+
+ // Extract raw controller data into a buffer
+ TInt64 pos(0);
+ User::LeaveIfError(dataProvider->Seek(ESeekStart, pos));
+ Sis::CContents *contents = Sis::Parser::ContentsL(*dataProvider);
+ CleanupStack::PushL(contents);
+ HBufC8* controllerData = NULL;
+ TRAPD(err, controllerData = contents->ReadControllerL());
+ if(err == KErrOverflow)
+ {
+ User::Leave(KErrCorrupt);
+ }
+ User::LeaveIfError(err);
+ CleanupStack::PushL(controllerData);
+
+ // Get the data to the client using the standard overflow protocol
+ // - get the size of the supplied descriptor (parameter 0)
+ TInt size = aMessage.GetDesMaxLengthL(0);
+ // - see if we have enough space on the client
+ if (size < controllerData->Size())
+ {
+ // Not enough space, complete with KErrOverflow and encode the
+ // required size into the passed descriptor
+ TPckgC<TInt> sizePckg(controllerData->Size());
+
+ // Is there enough space for an integer?
+ if (size >= sizePckg.Size())
+ {
+ aMessage.WriteL(0, sizePckg);
+ }
+ // complete the message with KErrOverflow when resizing requires
+ User::Leave(KErrOverflow);
+ }
+ else
+ {
+ // Enough space, write the controller to the supplied buffer
+ aMessage.WriteL(0, *controllerData);
+ }
+ CleanupStack::PopAndDestroy(4, &file); // dataProvider, contents, controllerData
+ }
+
+
+ // Functions for asynchronous extraction
+void CSisHelperSession::SetupAsyncExtractionL(const RMessage2& aMessage)
+ {
+ // We only support extracting one file at once currently
+ if (iInAsyncExtraction)
+ {
+ aMessage.Complete(KErrInUse);
+ }
+ else
+ {
+ // Get file and session handles
+ User::LeaveIfError(iAsyncFs.Open(aMessage, 0));
+
+ // Adopt the filehandle;
+ User::LeaveIfError(iAsyncFile.Adopt(iAsyncFs, aMessage.Int1()));
+
+ iAsyncFileIndex=aMessage.Int2();
+ iAsyncDataUnit=aMessage.Int3();
+
+ iInAsyncExtraction=ETrue;
+ aMessage.Complete(KErrNone);
+ }
+ }
+
+void CSisHelperSession::AsyncExtractionL(const RMessage2& aMessage)
+ {
+ TInt lengthHigh=aMessage.Int0();
+ TInt lengthLow=aMessage.Int1();
+ TInt64 length= lengthHigh;
+ length=( length << 32) + lengthLow;
+
+ CurrentContentsL().ReadDataL(iAsyncFile, iAsyncFileIndex, iAsyncDataUnit, length);
+ TInt err = iAsyncFile.Flush();
+
+ aMessage.Complete(err);
+ }
+
+void CSisHelperSession::EndAsyncExtractionL(const RMessage2& aMessage)
+ {
+ if (!iInAsyncExtraction)
+ {
+ aMessage.Complete(KErrArgument);
+ }
+ else
+ {
+ CleanupAsyncExtractionL();
+ aMessage.Complete(KErrNone);
+ }
+ }
+
+void CSisHelperSession::CleanupAsyncExtractionL()
+ {
+ if (iInAsyncExtraction)
+ {
+ iAsyncFile.Close();
+ iAsyncFs.Close();
+ iInAsyncExtraction=EFalse;
+ }
+ }
+
+// Handle an error from CSisHelperSession::ServiceL(). A bad descriptor
+// error implies a badly programmed client, so panic it; otherwise use the
+// default handling (report error to the client)
+void CSisHelperSession::ServiceError(const RMessage2& aMessage, TInt aError)
+ {
+ if (aError==KErrBadDescriptor)
+ {
+ PanicClient(aMessage, EPanicBadDescriptor);
+ }
+ CSession2::ServiceError(aMessage, aError);
+ }
+
+void CSisHelperSession::FillDrivesAndSpacesL(RArray<TChar>& aDriveLetters,
+ RArray<TInt64>& aDriveSpaces)
+ {
+ // This is the LFSS free space threshold
+ TInt freeSpaceAdjustment = 1024 * 128; // Bytes
+
+ // get information about drives
+ TDriveList driveList;
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+ CleanupClosePushL(fs);
+
+ // List all drives in the system
+ User::LeaveIfError(fs.DriveList(driveList));
+
+ // Check all drives
+ for (TInt driveNumber=EDriveA; driveNumber<=EDriveZ; driveNumber++)
+ {
+ if (!driveList[driveNumber])
+ {
+ // Not a recognised drive
+ continue;
+ }
+
+ TVolumeInfo volInfo;
+ if (fs.Volume(volInfo, driveNumber) != KErrNone)
+ {
+ // The volume is not usable (e.g. no media card inserted)
+ continue;
+ }
+
+ if (volInfo.iDrive.iType==EMediaNotPresent ||
+ volInfo.iDrive.iType==EMediaRom ||
+ volInfo.iDrive.iType==EMediaRemote)
+ {
+ // Exclude drives not suitable for installation
+ continue;
+ }
+
+ // Do not list read only and substituted drives as an option to install to
+ if (volInfo.iDrive.iDriveAtt & KDriveAttRom ||
+ volInfo.iDrive.iDriveAtt & KDriveAttSubsted)
+ {
+ continue;
+ }
+
+ TInt64 volSpace = volInfo.iFree - freeSpaceAdjustment; // bytes
+ if (volSpace < 0)
+ {
+ volSpace = 0;
+ }
+
+ TChar aDrive;
+ User::LeaveIfError(fs.DriveToChar(driveNumber, aDrive));
+ User::LeaveIfError(aDriveLetters.Append(TChar(aDrive)));
+ User::LeaveIfError(aDriveSpaces.Append(volSpace));
+ }
+ CleanupStack::PopAndDestroy(&fs);
+ }
+
+
+void CSisHelperSession::CreateSisStubL(const RMessage2& aMessage)
+ {
+ RFile file;
+ file.AdoptFromClient(aMessage, 0, 1);
+ CleanupClosePushL(file);
+
+ // rewind the data provider
+ TInt64 pos(0);
+ User::LeaveIfError(iDataProvider.Seek(ESeekStart, pos));
+
+ Sis::Parser::CreateSisStubL(file, iDataProvider);
+ CleanupStack::PopAndDestroy(&file); //close
+ }
+
+//
+// CSisHelperServer implementation
+//
+
+// All functions can only be accessed by SWIS
+const TInt CSisHelperServer::iRanges[iRangeCount] =
+ {
+ 0 // All connect attempts
+ };
+
+const TUint8 CSisHelperServer::iElementsIndex[iRangeCount] =
+ {
+ 0 //Only SWIS can use sishelper. This is policed by the SID of SWIS
+ };
+
+const CPolicyServer::TPolicyElement CSisHelperServer::iPolicyElements[2] =
+ {
+ {_INIT_SECURITY_POLICY_S0(0x101F7295), //SWIS' SID = 0x101F7295
+ CPolicyServer::EFailClient},
+
+
+
+ };
+
+const CPolicyServer::TPolicy CSisHelperServer::iPolicy =
+ {
+ 0, //specifies all connect attempts need SWIS' SID
+ iRangeCount,
+ iRanges,
+ iElementsIndex,
+ iPolicyElements,
+ };
+
+// Construction, the result is on the cleanup stack
+EXPORT_C CSisHelperServer* CSisHelperServer::NewLC(TSisHelperStartParams& aParams)
+ {
+ CSisHelperServer* self=new(ELeave) CSisHelperServer;
+ CleanupStack::PushL(self);
+ self->ConstructL(aParams);
+ return self;
+ }
+
+// Construction
+EXPORT_C CSisHelperServer* CSisHelperServer::NewL(TSisHelperStartParams& aParams)
+ {
+ CSisHelperServer* self=NewLC(aParams);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+// 2nd phase constructor; ensure the timer and server objects are running
+void CSisHelperServer::ConstructL(TSisHelperStartParams& aParams)
+ {
+ // See what kind of startup information is passed to the server
+ switch (aParams.iType)
+ {
+ case TSisHelperStartParams::ETypeFileName:
+ {
+ // Create a file data provider
+ User::LeaveIfError(iFs.Connect());
+ iSessionConnected=ETrue;
+
+ CSecurityPolicy* securityPolicy=CSecurityPolicy::GetSecurityPolicyL();
+
+ _LIT(KDriveSeparator, ":\\");
+ TPtrC sisFileName(*aParams.iFileName);
+ if (sisFileName.Find(KDriveSeparator) != 1)
+ {
+ // The full path (inc. drive letter) has not been specified
+ TEntry* fileExits = new(ELeave) TEntry;
+ CleanupStack::PushL(fileExits);
+ TInt err = iFs.Entry(sisFileName, *fileExits);
+ if (err == KErrNone)
+ {
+ // Found it, must be /xxxxx.sis. Fill in the missing
+ // drive path
+ TParse* sisFileWithDrv = new(ELeave) TParse;
+ CleanupStack::PushL(sisFileWithDrv);
+ iFs.Parse(sisFileName, *sisFileWithDrv);
+ // Get the SIS file name
+ iSisFileName = sisFileWithDrv->FullName().AllocL();
+ User::LeaveIfError(RFs::CharToDrive(sisFileWithDrv->Drive()[0], iSisFileDrive));
+ CleanupStack::PopAndDestroy(sisFileWithDrv);
+ }
+ CleanupStack::PopAndDestroy(fileExits);
+ }
+ else
+ {
+ // figure out which drive this SIS file came from
+ TParsePtrC parser(sisFileName);
+ User::LeaveIfError(RFs::CharToDrive(parser.Drive()[0], iSisFileDrive));
+ // Get the SIS file name
+ iSisFileName = sisFileName.AllocL();
+ }
+
+ if (securityPolicy->DrmEnabled())
+ {
+ iDataProvider=CCafSisDataProvider::NewL(sisFileName);
+ }
+ else
+ {
+ iDataProvider=CFileSisDataProvider::NewL(iFs, sisFileName);
+ }
+
+ iDeleteDataProvider=ETrue;
+
+ // Figure out whether the sis file is read only or the drive is
+ // write-protected or ROM.
+ TDriveInfo driveInfo;
+ User::LeaveIfError(iFs.Drive(driveInfo,iSisFileDrive));
+ if (!((driveInfo.iMediaAtt & KMediaAttWriteProtected) ||
+ (driveInfo.iDriveAtt & KDriveAttRom)))
+ {
+ TEntry entry;
+ User::LeaveIfError(iFs.Entry(sisFileName, entry));
+ iSisFileReadOnly = entry.IsReadOnly();
+ }
+ }
+ break;
+
+ case TSisHelperStartParams::ETypeFileHandle:
+ {
+ CSecurityPolicy* securityPolicy=CSecurityPolicy::GetSecurityPolicyL();
+
+ if (securityPolicy->DrmEnabled())
+ {
+ iDataProvider=CCafSisDataProvider::NewL(*aParams.iFileHandle);
+ }
+ else
+ {
+ iDataProvider=CFileSisDataProvider::NewL(*aParams.iFileHandle);
+ }
+
+ iDeleteDataProvider=ETrue;
+
+ // figure out which drive this SIS file came from
+ TDriveInfo driveInfo;
+ User::LeaveIfError(aParams.iFileHandle->Drive(iSisFileDrive, driveInfo));
+
+ // Figure out whether the sis file is read only or the drive is
+ // write-protected or ROM.
+ if (!((driveInfo.iMediaAtt & KMediaAttWriteProtected) ||
+ (driveInfo.iDriveAtt & KDriveAttRom)))
+ {
+ TUint attributes;
+ User::LeaveIfError(aParams.iFileHandle->Att(attributes));
+ iSisFileReadOnly = (attributes & KEntryAttReadOnly) ? ETrue : EFalse;
+ }
+
+ // Get SIS file name
+ TFileName tempFileName;
+ User::LeaveIfError(aParams.iFileHandle->FullName(tempFileName));
+ iSisFileName = tempFileName.AllocL();
+ DEBUG_PRINTF2(_L("Sis Helper - processing %S by file handle"), iSisFileName);
+ }
+ break;
+ case TSisHelperStartParams::ETypeDataProvider:
+ // store the pointer, assuming ownership, check for NULL
+ iDataProvider=aParams.iDataProvider;
+ iDeleteDataProvider=EFalse;
+ if (iDataProvider==NULL)
+ {
+ PanicClient(Message(), EPanicBadDataProvider);
+ }
+ break;
+ case TSisHelperStartParams::ETypeNull:
+ // For use where file is passed in later along with request
+ break;
+
+ default:
+ // panic the client
+ PanicClient(Message(), EPanicBadStartupDataType);
+ break;
+ }
+
+ StartL(KSisHelperServerName);
+ iShutdown=new(ELeave) CSisHelperShutdown;
+ iShutdown->ConstructL();
+
+ // ensure that the server still exists even if the 1st client fails
+ // to connect; the server will be terminated if no one connects to it
+ iShutdown->Start();
+ }
+
+CSisHelperServer::CSisHelperServer()
+: CPolicyServer(CActive::EPriorityStandard, iPolicy, ESharableSessions),
+ iSisFileDrive(-1),
+ iSisFileReadOnly(ETrue)
+ {
+ }
+
+// Destruction; delete a data provider since we own it whether it was
+// transferred from outside or created in the server.
+CSisHelperServer::~CSisHelperServer()
+ {
+ delete iShutdown;
+
+ if (iDeleteDataProvider)
+ {
+ delete iDataProvider;
+ }
+
+ if (iSessionConnected)
+ {
+ iFs.Close();
+ }
+
+ if (iSisFileName)
+ {
+ delete iSisFileName;
+ }
+
+ // Free ECOM memory reserved in this thread
+ // for example, plugins loaded by the CAF framework
+ REComSession::FinalClose();
+
+
+
+ }
+
+// Create a new client session
+CSession2* CSisHelperServer::NewSessionL(const TVersion&,
+ const RMessage2& ) const
+ {
+
+ return new(ELeave) CSisHelperSession(*iDataProvider);
+ }
+
+// A new session is being created; cancel the shutdown timer if it was running
+void CSisHelperServer::AddSession()
+ {
+ ++iSessionCount;
+ DEBUG_PRINTF2(_L8("Sis Helper - Adding Session (%d active.)"), iSessionCount);
+ // stop shutdown object once the first (and only) session is connected
+ delete iShutdown;
+ iShutdown=NULL;
+ }
+
+// A session is being destroyed; terminate server immediately
+void CSisHelperServer::DropSession()
+ {
+ if (--iSessionCount==0)
+ {
+ CActiveScheduler::Stop();
+ }
+ DEBUG_PRINTF2(_L8("Sis Helper - Dropping Session (%d active.)"), iSessionCount);
+ }
+
+CSisRegistryPackage* CSisHelperServer::MainPackageEntryL(TUid aUid)
+ {
+ RSisRegistrySession registrySession;
+ User::LeaveIfError(registrySession.Connect());
+ CleanupClosePushL(registrySession);
+
+ RSisRegistryEntry registryEntry;
+ User::LeaveIfError(registryEntry.Open(registrySession, aUid));
+ CleanupClosePushL(registryEntry);
+
+ // Get the package object associated with the entry
+ CSisRegistryPackage* package = registryEntry.PackageL();
+
+ CleanupStack::PopAndDestroy(2, ®istrySession);
+ return package;
+ }
+
+//
+// Starts SISHelper in a new thread
+//
+TInt CSisHelperServer::StartSisHelper(TSisHelperStartParams& aParams, RThread& aServer)
+ {
+ // We might be trying to restart a server, in which case we could
+ // get a thread name clash. We could make the name unique/random,
+ // but the server name would still clash...
+
+ const TInt KSisHelperServerStackSize=0x2000;
+ TInt err = KErrNone;
+
+ for (TInt retry=0; retry < 2; ++retry)
+ {
+ err = aServer.Create(KSisHelperServerName, SisHelperThreadFunction,
+ KSisHelperServerStackSize, NULL, static_cast<TAny*>(&aParams),
+ EOwnerThread);
+
+ if (err == KErrAlreadyExists || err == KErrInUse)
+ {
+ User::After(80000);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (err==KErrAlreadyExists)
+ {
+ return KErrServerBusy;
+ }
+
+ if (err!=KErrNone)
+ {
+ return err;
+ }
+
+ // The following code is the same whether the server runs in a new thread
+ // or process
+ TRequestStatus stat;
+ aServer.Rendezvous(stat);
+ if (stat!=KRequestPending)
+ {
+ aServer.Kill(0); // abort startup
+ }
+ else
+ {
+ aServer.Resume(); // logon OK, start the server
+ }
+
+ User::WaitForRequest(stat); // wait for start or death
+
+ // we can't use the 'exit reason' if the server panicked as this is the
+ // panic 'reason' and may be 0 which cannot be distinguished from KErrNone
+ err=(aServer.ExitType()==EExitPanic) ? KErrGeneral : stat.Int();
+ //We don't close aServer here. If asynchlauncher called, it will be closed
+ //in the RunL() method of uissclienthandler to make sure that SISHelper has been
+ //disconnected by SWISInstaller. Otherwise, just after this function call.
+ return err;
+ }
+
+void CSisHelperServer::Abort()
+ {
+ TFullName fullName = RProcess().FullName();
+ fullName.Append(':');
+ fullName.Append(':');
+ fullName.Append(KSisHelperServerName);
+
+ RThread server;
+ TInt err = server.Open(fullName);
+ if (err == KErrNone)
+ {
+ server.Terminate(KErrAbort);
+ server.Close();
+ }
+ }
+
+// Entry point for the thread the SISHelper runs in
+TInt CSisHelperServer::SisHelperThreadFunction(TAny *aPtr)
+ {
+ if (aPtr==NULL)
+ {
+ return KErrArgument;
+ }
+
+ CTrapCleanup* cleanup = CTrapCleanup::New(); // get clean-up stack
+
+ TSisHelperStartParams* params=
+ static_cast<TSisHelperStartParams*>(aPtr);
+
+ CActiveScheduler* scheduler=new(ELeave) CActiveScheduler;
+ if (!scheduler)
+ {
+ return KErrNoMemory;
+ }
+
+ DEBUG_PRINTF(_L8("Sis Helper - Starting Server"));
+
+ CActiveScheduler::Install(scheduler);
+ CSisHelperServer* server=NULL;
+
+ TRAPD(err, server=CSisHelperServer::NewL(*params));
+
+ if (err==KErrNone)
+ {
+ // only continue launching the server if no error
+ RThread::Rendezvous(KErrNone);
+ scheduler->Start();
+ }
+
+ DEBUG_PRINTF(_L8("Sis Helper - Stopping Server"));
+
+ CActiveScheduler::Install(NULL);
+ delete server;
+ delete scheduler;
+ delete cleanup; // destroy clean-up stack
+
+ CSecurityPolicy::ReleaseResource();
+
+ return err;
+ }
+
+TInt CSisHelperServer::GetSisFileDrive()
+ {
+ return iSisFileDrive;
+ }
+
+TBool CSisHelperServer::IsSisFileReadOnly()
+ {
+ return iSisFileReadOnly;
+ }
+
+const TDesC& CSisHelperServer::GetSisFileNameL()
+ {
+ if (!iSisFileName)
+ {
+ User::Leave(KErrNotFound);
+ }
+ return *iSisFileName;
+ }
+
+Sis::CContents& CSisHelperSession::CurrentContentsL()
+ {
+ if(iCurrentContents == NULL)
+ {
+ TInt64 pos(0);
+ User::LeaveIfError(iDataProvider.Seek(ESeekStart, pos));
+ iCurrentContents=Sis::Parser::ContentsL(iDataProvider);
+ }
+ return *iCurrentContents;
+ }
+
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+void CSisHelperSession::IsDrmProtectedL(const RMessage2& aMessage)
+ {
+ // Data provider will be of CCafSisDataProvider only when DRM is enabled in SWI policy.
+ // So, check the policy before querying content protection status from the data provider.
+ CSecurityPolicy* securityPolicy = CSecurityPolicy::GetSecurityPolicyL();
+ if (securityPolicy->DrmEnabled())
+ {
+ CCafSisDataProvider* cafDataProvider = static_cast<CCafSisDataProvider*>(&iDataProvider);
+ TBool isProtected = cafDataProvider->IsContentProtected();
+ TPckgBuf<TBool> isContentProtected(isProtected);
+ aMessage.WriteL(0, isContentProtected);
+ securityPolicy->ReleaseResource();
+ }
+ // If DRM is NOT enabled in SWI policy, no way to query the protection status. So, set it to Fasle.
+ else
+ {
+ aMessage.WriteL(0, TPckgBuf<TBool>(EFalse));
+ }
+ }
+#endif
+
+void CSisHelperSession::GetEquivalentLanguagesL(const RMessage2& aMessage)
+ {
+ TLanguage srcLangID = (TLanguage)aMessage.Int1();
+
+ TLanguagePath equivalentLangs;
+ BaflUtils::GetEquivalentLanguageList(srcLangID,equivalentLangs);
+
+ // calculate the likely size of the data transfer buffer
+ const TInt KMaxBufSize=
+ sizeof(TInt)+ // number of entries
+ (KMaxDowngradeLanguages+1)*sizeof(TLanguage); // Languages IDs stored as TLanguage
+
+ // allocate buffer for the array
+ HBufC8* buf=HBufC8::NewMaxLC(KMaxBufSize);
+
+ TInt size = 1;
+ while (equivalentLangs[size++] != ELangNone){}
+
+ TPtr8 pBuf=buf->Des();
+ RDesWriteStream outs(pBuf);
+ CleanupClosePushL(outs);
+
+ // Since the size contains the source language ID and ELangNone, the actual size is equal to size - 2
+ outs.WriteInt32L(size-2);
+ TInt i;
+ for (i = 1; i < size-1; ++i)
+ {
+ outs.WriteInt32L(static_cast<TInt>(equivalentLangs[i]));
+ }
+
+ outs.CommitL();
+ aMessage.WriteL(0, *buf);
+
+ CleanupStack::PopAndDestroy(2,buf); //outs,buf
+ }
+
+
+} // namespace Swi