diff -r 000000000000 -r 7f656887cf89 libraries/qr3/src/sandbox.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libraries/qr3/src/sandbox.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,226 @@ +// 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 +#include "sandbox.h" +#include +#include + +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& 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 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& 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 +#include + +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(REComSession::CreateImplementationL(uid, destructorKey)); + TInt count = rec->MimeTypesCount(); + for (TInt j = 0; j < count; j++) + { + TDataType type = rec->SupportedDataTypeL(j); + TPckg 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 res(vtablePtr); + aMessage.WriteL(1, res); + aMessage.Complete(KErrNone); + } + else + { + ASSERT(0); + } + } + +#endif