Fixed lots of issues with installing a low-caps version of fshell from SIS file.
* Fixed issue in CCommandFactory whereby some APIs like GetCommandInfoL could trigger allocations on the wrong heap or signals to the wrong thread. The symptoms were often seen as a crash in the which_00 thread when running ciftest.
* Lots of build fixes for when FSHELL_PROTECTED_UIDS isn't defined and when all capabilities aren't available.
* Added new platform.mmh macro FSHELL_OPEN_SIGNED.
* Open signing of fshell SIS files is now supported for production S60 handsets. Build fshell with the FSHELL_OPEN_SIGNED macro defined (and without defining FSHELL_CAP_ALL or FSHELL_PROTECTED_UIDS) in your platform.mmh and submit \epoc32\fshell\fshell.unsigned.sis to https://www.symbiansigned.com/app/page/public/openSignedOnline.do . The following commands are not available when using Open Signing due to Platform Security restrictions: fdb; kerninfo; chunkinfo; svrinfo; objinfo; sudo; fsck; localdrive; ramdefrag; readmem; reboot; setcritical; setpriority. Others such as chkdeps, e32header, ps, and fshell itself will run but in a restricted capacity (for example, fshell will no longer allow you to modify files in the \sys\bin directory).
* Removed commands objinfo, svrinfo, chunkinfo, readmem, fsck completely when memory access isn't present - previously they would still appear in the help but would give an error if you tried to run them.
// 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 SERVERclass 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