First submission to Symbian Foundation staging server.
// sandbox.cpp
//
// Copyright (c) 2010 Accenture. All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the "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:
// Accenture - Initial contribution
//
#include <e32base.h>
#include "sandbox.h"
#include <APMREC.H>
#include <fshell/memoryaccess.h>
enum TMsg
{
EGetRecog,
EGetRecog2,
ECloseServer,
EGetVTablePtr,
EMaxArgs,
};
#ifndef SERVER
class RSandboxSession : public RSessionBase
{
public:
TInt Connect(const TDesC& aServerName)
{
return CreateSession(aServerName, TVersion(0,0,0));
}
TInt GetRecogniserInfo(TUid aImplementationUid, RArray<TDataType>& aMimeTypes)
{
TInt size = SendReceive(EGetRecog, TIpcArgs(aImplementationUid.iUid));
if (size < 0) return size;
TInt err = aMimeTypes.Reserve(size/sizeof(TDataType));
if (err) return err;
RBuf8 buf;
err = buf.Create(size);
if (err) return err;
err = SendReceive(EGetRecog2, TIpcArgs(&buf));
if (err) { buf.Close(); return err; }
const TDataType* ptr = (const TDataType*)buf.Ptr();
for (TInt i = 0; i < size/sizeof(TDataType); i++)
{
err = aMimeTypes.Append(ptr[i]);
if (err) break;
}
buf.Close();
return err;
}
TInt GetVTablePtrFromEcomUid(TUid aUid, TAny*& vtablePtr)
{
TPckgBuf<TAny*> pkg(NULL);
TInt err = SendReceive(EGetVTablePtr, TIpcArgs(aUid.iUid, &pkg));
if (err) return err;
vtablePtr = pkg();
return KErrNone;
}
void Byebye()
{
SendReceive(ECloseServer);
}
};
#define GETSESSIONL(process, session) \
RProcess process; \
User::LeaveIfError(process.Create(_L("QR3Sandbox.exe"), KNullDesC)); \
TRequestStatus stat; \
process.Rendezvous(stat); \
process.Resume(); \
User::WaitForRequest(stat); \
\
RSandboxSession session; \
User::LeaveIfError(session.Connect(sandbox.FullName()));
void Sandbox::GetRecogniserInfoL(TUid aImplementationUid, RArray<TDataType>& aMimeTypes)
{
GETSESSIONL(sandbox, sess);
User::LeaveIfError(sess.GetRecogniserInfo(aImplementationUid, aMimeTypes));
sess.Byebye();
sandbox.Close();
}
void Sandbox::GetDllNameFromEcomUidL(RMemoryAccess& aMemAccess, TUid aUid, TFileName& aFileName)
{
// Try and instanciate object and figure out what DLL it belongs to by looking up its vtable pointer
// We do the instanciation in a separate process so as to avoid worrying about cleanup or side-effects of instanciation
GETSESSIONL(sandbox, sess);
TAny* vtablePtr = NULL;
TInt err = sess.GetVTablePtrFromEcomUid(aUid, vtablePtr);
TFullName8 dllName;
if (!err)
{
err = aMemAccess.FindAddressInCodeSegments(dllName, vtablePtr);
}
sess.Byebye(); // We have to call FindAddressInCodeSegments before sandbox exits, because when it does the code segment will most likely be unloaded!
sandbox.Close();
User::LeaveIfError(err);
aFileName.Copy(dllName);
}
#else
#include <e32property.h>
#include <ecom/ecom.h>
void GoL();
class CSandboxSession : public CSession2
{
void ServiceL(const RMessage2 &aMessage);
RBuf8 iBuf;
};
class CSandboxServer : public CServer2
{
public:
CSandboxServer() : CServer2(0,ESharableSessions) {}
protected:
CSession2* NewSessionL(const TVersion& /*aVersion*/, const RMessage2& /*aMessage*/) const
{
return new(ELeave) CSandboxSession();
}
};
TInt E32Main()
{
User::SetJustInTime(EFalse); // Don't want to debug problems in the sandbox
CTrapCleanup* cleanup=CTrapCleanup::New();
TRAPD(err, GoL());
return err;
}
void GoL()
{
CActiveScheduler* s=new(ELeave) CActiveScheduler;
CActiveScheduler::Install(s);
CSandboxServer* server = new(ELeave) CSandboxServer();
// Scope the TFullName
{
TFullName serverName = RProcess().FullName();
server->StartL(serverName);
}
RProcess::Rendezvous(KErrNone);
CActiveScheduler::Start();
}
void CSandboxSession::ServiceL(const RMessage2 &aMessage)
{
if (aMessage.Function() >= EMaxArgs)
{
aMessage.Complete(KErrArgument);
return;
}
if (aMessage.Function() == EGetRecog2)
{
aMessage.WriteL(0, iBuf);
iBuf.Close();
aMessage.Complete(KErrNone);
}
else if (aMessage.Function() == EGetRecog)
{
if (iBuf.MaxLength() == 0)
{
iBuf.ReAllocL(1024); // Must be > sizeof(TDataType) otherwise the reallocating logic below is flawed
}
TUid uid = TUid::Uid(aMessage.Int0());
TUid destructorKey;
CApaDataRecognizerType* rec = static_cast<CApaDataRecognizerType*>(REComSession::CreateImplementationL(uid, destructorKey));
TInt count = rec->MimeTypesCount();
for (TInt j = 0; j < count; j++)
{
TDataType type = rec->SupportedDataTypeL(j);
TPckg<TDataType> buf(type);
if (iBuf.Length() + buf.Length() >= iBuf.MaxLength())
{
iBuf.ReAllocL(iBuf.MaxLength() * 2);
}
iBuf.Append(buf);
}
aMessage.Complete(iBuf.Size());
}
else if (aMessage.Function() == ECloseServer)
{
aMessage.Complete(KErrNone);
CActiveScheduler::Stop();
}
else if (aMessage.Function() == EGetVTablePtr)
{
TUid destructorKey;
TAny* obj = NULL;
obj = REComSession::CreateImplementationL(TUid::Uid(aMessage.Int0()), destructorKey);
TAny* vtablePtr = *((TAny**)obj);
TPckg<TAny*> res(vtablePtr);
aMessage.WriteL(1, res);
aMessage.Complete(KErrNone);
}
else
{
ASSERT(0);
}
}
#endif