libraries/qr3/src/sandbox.cpp
changeset 0 7f656887cf89
--- /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 <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