/*
* Copyright (c) 2004-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:
* SisLauncher - client SisLaunchers interface implementation
*
*/
/**
@file
@released
@internalComponent
*/
#include<s32mem.h>
#include "sislauncherclient.h"
#include "sislauncherclientserver.h"
#include "sisregistryfiledescription.h"
#include "secutils.h"
#include "arrayutils.h" // from source/sisregistry/common/
#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
#include "swtypereginfo.h"
#endif
using namespace Swi;
static TInt StartSisLauncherServer()
{
const TUidType serverUid(KNullUid, KNullUid, KServerUid3);
RProcess server;
TInt err = server.Create(KSisLauncherServerImg, KNullDesC, serverUid);
if (err != KErrNone)
{
return err;
}
TRequestStatus stat;
server.Rendezvous(stat);
if (stat != KRequestPending)
{
server.Kill(0); // abort startup
}
else
{
server.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 = (server.ExitType() == EExitPanic) ? KErrGeneral : stat.Int();
server.Close();
return err;
}
EXPORT_C TInt RSisLauncherSession::Connect()
//
// Connect to the server, attempting to start it if necessary
//
{
TInt retry=2;
for (;;)
{
TInt err = CreateSession(KSisLauncherServerName, TVersion(0, 0, 0), 1);
if (err != KErrNotFound && err != KErrServerTerminated)
{
return err;
}
if (--retry==0)
{
return err;
}
err = StartSisLauncherServer();
if (err != KErrNone && err != KErrAlreadyExists)
{
return err;
}
}
}
EXPORT_C void RSisLauncherSession::RunExecutableL(const TDesC& aFileName, TBool aWait)
{
TPckgC<TBool> wait(aWait);
User::LeaveIfError(SendReceive(ERunExecutable, TIpcArgs(&aFileName, &wait)));
}
EXPORT_C void RSisLauncherSession::StartDocumentL(RFile& aFile, TBool aWait)
{
TPckgC<TBool> wait(aWait);
TIpcArgs ipcArgs;
aFile.TransferToServer(ipcArgs, 0, 1);
ipcArgs.Set(2, &wait);
User::LeaveIfError(SendReceive(EStartDocumentByHandle, ipcArgs));
}
EXPORT_C void RSisLauncherSession::StartByMimeL(RFile& aFile, const TDesC8& aMimeType, TBool aWait)
{
TPckgC<TBool> wait(aWait);
TIpcArgs ipcArgs;
aFile.TransferToServer(ipcArgs, 0, 1);
ipcArgs.Set(2, &aMimeType);
ipcArgs.Set(3, &wait);
User::LeaveIfError(SendReceive(EStartByMimeByHandle, ipcArgs));
}
EXPORT_C void RSisLauncherSession::StartDocumentL(const TDesC& aFileName, TBool aWait)
{
TPckgC<TBool> wait(aWait);
User::LeaveIfError(SendReceive(EStartDocument, TIpcArgs(&aFileName, &wait)));
}
EXPORT_C void RSisLauncherSession::StartByMimeL(const TDesC& aFileName, const TDesC8& aMimeType, TBool aWait)
{
TPckgC<TBool> wait(aWait);
User::LeaveIfError(SendReceive(EStartByMime, TIpcArgs(&aFileName, &aMimeType, &wait)));
}
EXPORT_C void RSisLauncherSession::ShutdownAllL()
{
User::LeaveIfError(SendReceive(EShutdownAll));
}
EXPORT_C void RSisLauncherSession::CheckApplicationInUseL(RArray<TAppInUse>& aUidList)
{
TInt uidCount=aUidList.Count();
if (uidCount)
{
HBufC8* appInUseBuf=HBufC8::NewLC(uidCount * sizeof(TAppInUse));
TPtr8 appInUsePtr=appInUseBuf->Des();
TUint8* dataPtr(NULL);
TInt i;
for (i = 0 ; i < uidCount ; ++i)
{
dataPtr=reinterpret_cast<TUint8*>(&aUidList[i]);
appInUsePtr.Append(dataPtr, sizeof(TAppInUse));
}
User::LeaveIfError((SendReceive(ECheckApplicationInUse, TIpcArgs(&appInUsePtr))));
//Copy the result back to the RArray
dataPtr=const_cast<TUint8*>(appInUsePtr.Ptr());
TAppInUse* appInUseDataPtr=reinterpret_cast<TAppInUse*>(dataPtr);
for (i = 0; i < uidCount; ++i)
{
aUidList[i]=appInUseDataPtr[i];
}
CleanupStack::PopAndDestroy(appInUseBuf);
}
}
EXPORT_C void RSisLauncherSession::ShutdownL(const RArray<TUid>& aUidList, TInt aTimeout)
{
TInt uidCount=aUidList.Count();
if (uidCount)
{
HBufC8* tUidBuf=HBufC8::NewLC(uidCount * sizeof(TUid));
TPtr8 tUidBufPtr=tUidBuf->Des();
const TUint8* dataPtr(NULL);
for (TInt i=0;i<uidCount;i++)
{
dataPtr=reinterpret_cast<const TUint8*>(&aUidList[i]);
tUidBufPtr.Append(dataPtr, sizeof(TUid));
}
User::LeaveIfError((SendReceive(EShutdown, TIpcArgs(&tUidBufPtr, aTimeout))));
CleanupStack::PopAndDestroy(tUidBuf);
}
}
EXPORT_C void RSisLauncherSession::NotifyNewAppsL(const RPointerArray<TDesC>& aFiles)
{
if (aFiles.Count() > 0)
{
CBufFlat* tmpBuf = CBufFlat::NewL(255);
CleanupStack::PushL(tmpBuf);
RBufWriteStream stream(*tmpBuf);
CleanupClosePushL(stream);
ExternalizePointerArrayL(aFiles, stream);
// Create an HBufC8 from the stream buf's length, and copy
// the stream buffer into this descriptor
HBufC8* buffer = HBufC8::NewLC(tmpBuf->Size());
TPtr8 ptr(buffer->Des());
tmpBuf->Read(0, ptr, tmpBuf->Size());
User::LeaveIfError(SendReceive(ENotifyNewApps, TIpcArgs(&ptr)));
CleanupStack::PopAndDestroy(3, tmpBuf);
}
}
EXPORT_C void RSisLauncherSession::RunAfterEcomNotificationL(const RPointerArray<CSisRegistryFileDescription>& aFileList)
{
TInt count = aFileList.Count();
if (count <= 0)
{
return;
}
RFs fs;
User::LeaveIfError(fs.Connect());
CleanupClosePushL(fs);
User::LeaveIfError(fs.ShareProtected());
for (TInt i = 0; i < count; ++i)
{
CSisRegistryFileDescription* fileDes = aFileList[i];
// open the file entry
TEntry entry;
if (fs.Entry(fileDes->Target(), entry) != KErrNone)
{
// just ignore, there's nothing we can do and we should try to process the
// remaining files.
continue;
}
TIpcArgs ipcArgs;
TBool waitEnd = 0 != (fileDes->OperationOptions() & Sis::EInstFileRunOptionWaitEnd);
TPckgC<TBool> wait(waitEnd);
ipcArgs.Set(2, &wait);
TInt err = KErrNone;
if (entry.IsTypeValid() && SecUtils::IsExe(entry))
{
ipcArgs.Set(0,&fileDes->Target());
err = SendReceive(EQueueRunExecutable, ipcArgs);
}
else
{
RFile file;
CleanupClosePushL(file);
err = file.Open(fs, fileDes->Target(), EFileShareExclusive|EFileWrite);
HBufC8* mimeType = 0;
if (err == KErrNone)
{
if (fileDes->OperationOptions() & Sis::EInstFileRunOptionByMimeType)
{
mimeType = HBufC8::NewLC(fileDes->MimeType().Length());
TPtr8 ptr = mimeType->Des();
ptr.Copy(fileDes->MimeType());
}
if (file.TransferToServer(ipcArgs, 0, 1) != KErrNone)
{
// best effort is to continue with remaining exes
}
else if (mimeType != 0)
{
TPtrC8 x = mimeType->Des();
ipcArgs.Set(3, &x);
err = SendReceive(EQueueStartByMimeByHandle, ipcArgs);
}
else
{
err = SendReceive(EQueueStartDocumentByHandle, ipcArgs);
}
if (mimeType != 0)
{
CleanupStack::PopAndDestroy(mimeType);
}
}
CleanupStack::PopAndDestroy(&file);
}
// best effort is to continue with other exes in the event of an error
// so do nothing here.
}
CleanupStack::PopAndDestroy(&fs);
User::LeaveIfError(SendReceive(EExecuteQueue));
}
#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
EXPORT_C void RSisLauncherSession::ParseSwTypeRegFileL(RFile& aFile, RPointerArray<CSoftwareTypeRegInfo>& aSwTypeRegInfoArray)
{
// Pack the file handle
TIpcArgs ipcArgs;
aFile.TransferToServer(ipcArgs, 0, 1);
// Allocate a buffer for the parsed registration info
TInt bufLen = 0;
User::LeaveIfError(aFile.Size(bufLen));
HBufC8* buf = HBufC8::NewLC(bufLen); // using the size of the file here is overhead but provides very simple code
// Packe the buffer
TPtr8 bufPtr(buf->Des());
ipcArgs.Set(2, &bufPtr);
// Send request to the server
User::LeaveIfError(SendReceive(EParseSwTypeRegFile, ipcArgs));
// Unpack the parsed registration info
RDesReadStream rs(*buf);
CleanupClosePushL(rs);
SoftwareTypeRegInfoUtils::UnserializeArrayL(rs, aSwTypeRegInfoArray);
CleanupStack::PopAndDestroy(2, buf); // rs
}
EXPORT_C void RSisLauncherSession::RegisterSifLauncherMimeTypesL(const RPointerArray<HBufC8>& aMimeTypes)
{
RegisterSifLauncherMimeTypesImplL(aMimeTypes, ETrue);
}
EXPORT_C void RSisLauncherSession::UnregisterSifLauncherMimeTypesL(const RPointerArray<HBufC8>& aMimeTypes)
{
RegisterSifLauncherMimeTypesImplL(aMimeTypes, EFalse);
}
void RSisLauncherSession::RegisterSifLauncherMimeTypesImplL(const RPointerArray<HBufC8>& aMimeTypes, TBool aRegister)
{
// Calculate the size of aMimeTypes in a buffer
TInt bufLen = sizeof(TInt);
for (TInt i=0; i<aMimeTypes.Count(); ++i)
{
bufLen += sizeof(TInt) + aMimeTypes[i]->Size();
}
// Externalize MIME types
HBufC8* buf = HBufC8::NewLC(bufLen);
TPtr8 bufPtr(buf->Des());
RDesWriteStream ws(bufPtr);
CleanupClosePushL(ws);
ExternalizePointerArrayL(aMimeTypes, ws);
ws.CommitL();
CleanupStack::PopAndDestroy(&ws);
// Send MIME types to the server
TIpcArgs ipcArgs(&bufPtr);
User::LeaveIfError(SendReceive(aRegister?ERegisterSifLauncherMimeTypes:EUnregisterSifLauncherMimeTypes, ipcArgs));
CleanupStack::PopAndDestroy(buf);
}
#endif