--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/secure/t_sobject.cpp Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,1470 @@
+// Copyright (c) 2002-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:
+// e32test\secure\t_sobject.cpp
+// Overview:
+// Test the security aspects of the TFind??? (TFindChunk etc.) classes.
+// API Information:
+// TFind??? (TFindChunk, TFindThread etc.)
+// Details:
+// - Test TFindPhysicalDevices and attempt to open the found device.
+// Verify results are as expected.
+// - Test TFindLogicalDevices and attempt to open the found device.
+// Duplicate the object in another thread. Verify results are as expected.
+// - Test TFindLibrary and attempt to open the found device. Verify results
+// are as expected.
+// - Test TFindServer and attempt to open the found server. Test duplication
+// of a named or unnamed server. Verify results are as expected.
+// - Test TFindProcess and attempt to open the found process. Test duplication
+// of the object. Attempt to open the process by name and by id. Verify
+// results are as expected.
+// - Test TFindThread and attempt to open the found thread. Test duplication
+// of the object. Attempt to open the thread in various ways. Verify
+// results are as expected.
+// - Test TFindChunk and attempt to open the found object. Test duplication
+// of the object. Attempt to open the object in various ways. Verify
+// results are as expected.
+// - Test TFindSemaphore and attempt to open the found object. Attempt to
+// open the object in various ways. Test duplication of the object. Verify
+// results are as expected.
+// - Test TFindMutex and attempt to open the found object. Attempt to
+// open the object in various ways. Test duplication of the object. Verify
+// results are as expected.
+// - Create some RMsgQueue objects. Attempt to open the objects in various ways.
+// Test duplication of the objects. Verify results are as expected.
+// - Create some RCondVar objects. Attempt to open the objects in various ways.
+// Test duplication of the objects. Verify results are as expected.
+// - Test passing a handle via IPC: test sending LogicalChannel, Chunk,
+// Semaphore, Mutex, MsgQueue, CondVar and Session handles. Verify results
+// are as expected.
+// Platforms/Drives/Compatibility:
+// All.
+// Assumptions/Requirement/Pre-requisites:
+// Failures and causes:
+// Base Port information:
+//
+//
+
+#include <e32test.h>
+#include <e32msgqueue.h>
+#include <f32file.h>
+#include "d_sldd.h"
+
+LOCAL_D RTest test(_L("T_SOBJECT"));
+
+TInt PlatSecProcessIsolationError = 1;
+TInt PlatSecFindError = 1;
+
+_LIT(KTestMutexName,"T_SOBJECT-test-mutex");
+_LIT(KTestSemaphoreName,"T_SOBJECT-test-semaphore");
+_LIT(KTestChunkName,"T_SOBJECT-test-chunk");
+_LIT(KTestMsgQueueName,"T_SOBJECT-test-msgqueue");
+_LIT(KTestCondVarName,"T_SOBJECT-test-condvar");
+
+TFullName Name;
+TFullName Name2;
+
+void SetName(RHandleBase a)
+ {
+ Name = a.FullName();
+ }
+
+TBool CheckName(RHandleBase a)
+ {
+ Name2 = a.FullName();
+ return Name==Name2;
+ }
+
+class RTestHandle : public RHandleBase
+ {
+public:
+ inline TInt Open(const TFindHandleBase& aHandle,TOwnerType aType=EOwnerThread)
+ { return RHandleBase::Open(aHandle,aType); }
+ };
+
+
+
+enum TTestProcessFunctions
+ {
+ ETestProcessServer,
+ ETestProcessDuplicate,
+ ETestProcessOpenThreadById,
+ };
+
+#include "testprocess.h"
+
+
+TThreadId MainThreadId;
+
+TInt TestThreadDuplicate(TAny* aArg)
+ {
+ RHandleBase handle;
+ handle.SetHandle((TInt)aArg);
+ RThread thread;
+ TInt r = thread.Open(MainThreadId);
+ if(r!=KErrNone)
+ r = 999;
+ else
+ r = handle.Duplicate(thread);
+ thread.Close();
+ return r;
+ }
+
+TInt DuplicateInOtherThread(RHandleBase aHandle)
+ {
+ RThread thread;
+ TRequestStatus logonStatus;
+ thread.Create(_L(""),TestThreadDuplicate,KDefaultStackSize,KDefaultStackSize,KDefaultStackSize,(TAny*)aHandle.Handle());
+ MainThreadId = RThread().Id();
+ thread.Logon(logonStatus);
+ thread.Resume();
+ User::WaitForRequest(logonStatus);
+ test(thread.ExitType()==EExitKill);
+ CLOSE_AND_WAIT(thread);
+ return logonStatus.Int();
+ }
+
+TInt DuplicateInOtherProcess(RHandleBase aHandle)
+ {
+ RTestProcess process;
+ TRequestStatus logonStatus;
+ process.Create(ETestProcessDuplicate,RThread().Id(),aHandle.Handle());
+ process.Logon(logonStatus);
+ process.Resume();
+ User::WaitForRequest(logonStatus);
+ test(process.ExitType()==EExitKill);
+ CLOSE_AND_WAIT(process);
+ return logonStatus.Int();
+ }
+
+TInt OpenThreadByIdInOtherProcess(TThreadId aId)
+ {
+ RTestProcess process;
+ TRequestStatus logonStatus;
+ process.Create(ETestProcessOpenThreadById,aId);
+ process.Logon(logonStatus);
+ process.Resume();
+ User::WaitForRequest(logonStatus);
+ test(process.ExitType()==EExitKill);
+ CLOSE_AND_WAIT(process);
+ return logonStatus.Int();
+ }
+
+
+
+//
+// RTestSession
+//
+
+enum TServerName
+ {
+ EMainServer,EGlobalSharableServer,EAnonymousServer,ENumServerTypes
+ };
+
+_LIT(KServerName,"T_SOBJECT-MainServer");
+_LIT(KServerName2,"T_SOBJECT-GlobalSharableServer");
+
+inline const TDesC& ServerName(TServerName aName)
+ {
+ switch(aName)
+ {
+ case EMainServer:
+ return KServerName;
+ case EGlobalSharableServer:
+ return KServerName2;
+ default:
+ return KNullDesC;
+ }
+ }
+
+class RTestSession : public RSessionBase
+ {
+public:
+ inline TInt Connect(TServerName aName=EMainServer)
+ {
+ TInt r=CreateSession(ServerName(aName),TVersion());
+ if(r) return r;
+ return ShareAuto();
+ }
+ inline TInt ConnectProtected(TServerName aName=EMainServer)
+ {
+ TInt r=CreateSession(ServerName(aName),TVersion());
+ if(r) return r;
+ return ShareProtected();
+ }
+ inline TInt Open(RMessagePtr2 aMessage,TInt aParam,TOwnerType aType=EOwnerProcess)
+ { return RSessionBase::Open(aMessage,aParam,aType); }
+ inline TInt Open(RMessagePtr2 aMessage,TInt aParam,const TSecurityPolicy& aServerPolicy,TOwnerType aType=EOwnerProcess)
+ { return RSessionBase::Open(aMessage,aParam,aServerPolicy,aType); }
+ inline TInt Send(TInt aFunction)
+ { return RSessionBase::SendReceive(aFunction); }
+ inline TInt Send(TInt aFunction,const TIpcArgs& aArgs)
+ { return RSessionBase::SendReceive(aFunction,aArgs); }
+ inline void Send(TInt aFunction,TRequestStatus& aStatus)
+ { RSessionBase::SendReceive(aFunction,aStatus); }
+ inline void Send(TInt aFunction,const TIpcArgs& aArgs,TRequestStatus& aStatus)
+ { RSessionBase::SendReceive(aFunction,aArgs,aStatus); }
+ };
+
+
+
+//
+// CTestSession
+//
+
+class CTestSession : public CSession2
+ {
+public:
+ enum {EShutdown,EPing,ETestMutex,ETestSemaphore,ETestMsgQueue,ETestCondVar,ETestChunk,ETestChunkAdjust,ETestLdd,
+ ETestSession,ETestSession2,ETestSession3,ETestServerDuplicateInThread,ETestServerDuplicateInProcess};
+public:
+ CTestSession();
+ virtual void ServiceL(const RMessage2& aMessage);
+public:
+ };
+
+CTestSession::CTestSession()
+ : CSession2()
+ {
+ }
+
+const TInt KTestDataMaxLength8 = 20;
+const TInt KTestDataMaxLength16 = 40;
+_LIT8(KTestData8,"12345678");
+_LIT16(KTestData16,"1234567890123456");
+_LIT(KTestPanicCategory,"TEST PANIC");
+
+void CTestSession::ServiceL(const RMessage2& aMessage)
+ {
+ RMessagePtr2 m(aMessage);
+ TFullName name;
+ TInt r = KErrGeneral;
+
+ switch (aMessage.Function())
+ {
+ case CTestSession::EShutdown:
+ CActiveScheduler::Stop();
+ break;
+
+ case CTestSession::EPing:
+ r=aMessage.Int0();
+ break;
+
+ case CTestSession::ETestMutex:
+ {
+ RMutex object;
+
+ r = object.Open(m,0,EOwnerThread);
+ if(r!=KErrBadHandle || object.Handle())
+ goto fail;
+
+ r = object.Open(m,1,EOwnerProcess);
+ if(r!=KErrNone)
+ break;
+ name = object.FullName();
+ object.Close();
+ if(name!=KTestMutexName)
+ goto fail;
+
+ r = object.Open(m,2,EOwnerThread);
+ if(r!=KErrNone)
+ break;
+ SetName(object);
+ m.Read(3,Name2);
+ if(Name!=Name2)
+ goto fail;
+
+ m.Complete(object);
+ object.Close();
+ return;
+ }
+ break;
+
+ case CTestSession::ETestSemaphore:
+ {
+ RSemaphore object;
+
+ r = object.Open(m,0,EOwnerThread);
+ if(r!=KErrBadHandle || object.Handle())
+ goto fail;
+
+ r = object.Open(m,1,EOwnerProcess);
+ if(r!=KErrNone)
+ break;
+ name = object.FullName();
+ object.Close();
+ if(name!=KTestSemaphoreName)
+ goto fail;
+
+ r = object.Open(m,2,EOwnerThread);
+ if(r!=KErrNone)
+ break;
+ SetName(object);
+ m.Read(3,Name2);
+ if(Name!=Name2)
+ goto fail;
+
+ m.Complete(object);
+ object.Close();
+ return;
+ }
+ break;
+
+ case CTestSession::ETestMsgQueue:
+ {
+ RMsgQueue<TInt> object;
+
+ r = object.Open(m,0,EOwnerThread);
+ if(r!=KErrBadHandle || object.Handle())
+ goto fail;
+
+ r = object.Open(m,1,EOwnerProcess);
+ if(r!=KErrNone)
+ break;
+ name = object.FullName();
+ object.Close();
+ if(name!=KTestMsgQueueName)
+ goto fail;
+
+ r = object.Open(m,2,EOwnerThread);
+ if(r!=KErrNone)
+ break;
+ SetName(object);
+ m.Read(3,Name2);
+ if(Name!=Name2)
+ goto fail;
+
+ m.Complete(object);
+ object.Close();
+ return;
+ }
+ break;
+
+ case CTestSession::ETestCondVar:
+ {
+ RCondVar object;
+
+ r = object.Open(m,0,EOwnerThread);
+ if(r!=KErrBadHandle || object.Handle())
+ goto fail;
+
+ r = object.Open(m,1,EOwnerProcess);
+ if(r!=KErrNone)
+ break;
+ name = object.FullName();
+ object.Close();
+ if(name!=KTestCondVarName)
+ goto fail;
+
+ r = object.Open(m,2,EOwnerThread);
+ if(r!=KErrNone)
+ break;
+ SetName(object);
+ m.Read(3,Name2);
+ if(Name!=Name2)
+ goto fail;
+
+ m.Complete(object);
+ object.Close();
+ return;
+ }
+ break;
+
+ case CTestSession::ETestChunk:
+ {
+ RChunk object;
+
+ r = object.Open(m,0,EOwnerThread);
+ if(r!=KErrBadHandle || object.Handle())
+ goto fail;
+
+ r = object.Open(m,1,EOwnerProcess);
+ if(r!=KErrNone)
+ break;
+ name = object.FullName();
+ object.Close();
+ if(name!=KTestChunkName)
+ goto fail;
+
+ r = object.Open(m,2,EOwnerThread);
+ if(r!=KErrNone)
+ break;
+ SetName(object);
+ m.Read(3,Name2);
+ if(Name!=Name2)
+ goto fail;
+
+ m.Complete(object);
+ object.Close();
+ return;
+ }
+ break;
+
+ case CTestSession::ETestChunkAdjust:
+ {
+ RChunk object;
+ r = object.Open(m,0,EOwnerThread);
+ if(r==KErrNone)
+ r = object.Adjust(0x1000);
+ object.Close();
+ }
+ break;
+
+ case CTestSession::ETestLdd:
+ {
+ RLddTest object;
+ r = object.Open(m,0);
+ if(r!=KErrBadHandle || object.Handle())
+ goto fail;
+ r = object.Open(m,1);
+ if(r!=KErrNone)
+ break;
+ SetName(object);
+ m.Read(3,Name2);
+ if(Name!=Name2)
+ goto fail;
+ r = object.Test1();
+ if(r!=aMessage.Int2())
+ goto fail;
+ m.Complete(object);
+ object.Close();
+ return;
+ }
+
+ case CTestSession::ETestSession:
+ {
+ RTestSession object;
+ r = object.Open(m,0);
+ if(r!=KErrBadHandle || object.Handle())
+ goto fail;
+ r = object.Open(m,1,TSecurityPolicy(ECapabilityTCB));
+ if(r!=KErrPermissionDenied || object.Handle())
+ goto fail;
+ r = object.Open(m,1);
+ if(r!=KErrNone)
+ break;
+ SetName(object);
+ m.Read(3,Name2);
+ if(Name!=Name2)
+ goto fail;
+
+ RFs fs;
+ r = fs.Open(m,2,TSecurityPolicy(ECapabilityTCB));
+ if(r!=KErrNone)
+ goto fail;
+ fs.Close();
+
+ r=object.Send(CTestSession::EPing,TIpcArgs(234));
+ if(r!=234)
+ goto fail;
+
+ m.Complete(object);
+ object.Close();
+ return;
+ }
+
+ case CTestSession::ETestSession2:
+ {
+ RTestSession object;
+ object.Connect(EGlobalSharableServer);
+ m.Complete(object);
+ object.Close();
+ return;
+ }
+
+ case CTestSession::ETestSession3:
+ {
+ RFs object;
+ object.Connect();
+ object.ShareProtected();
+ m.Complete(object);
+ object.Close();
+ return;
+ }
+
+ case CTestSession::ETestServerDuplicateInThread:
+ r = DuplicateInOtherThread(Server()->Server());
+ break;
+
+ case CTestSession::ETestServerDuplicateInProcess:
+ r = DuplicateInOtherProcess(Server()->Server());
+ break;
+
+ default:
+ m.Complete(KErrNotSupported);
+ break;
+ }
+ m.Complete(r);
+ return;
+fail:
+ m.Complete(KErrGeneral);
+ return;
+ }
+
+RTestSession Session;
+
+
+
+//
+// CTestServer
+//
+
+class CTestServer : public CServer2
+ {
+public:
+ CTestServer(TInt aPriority,TInt aType=ESharableSessions);
+ virtual CSession2* NewSessionL(const TVersion& aVersion,const RMessage2& aMessage) const;
+ };
+
+CTestServer::CTestServer(TInt aPriority,TInt aType)
+ : CServer2(aPriority,(TServerType)aType)
+ {
+ }
+
+CSession2* CTestServer::NewSessionL(const TVersion& /*aVersion*/,const RMessage2& /*aMessage*/) const
+ {
+ return new (ELeave) CTestSession();
+ }
+
+
+
+//
+// CTestActiveScheduler
+//
+
+class CTestActiveScheduler : public CActiveScheduler
+ {
+public:
+ virtual void Error(TInt anError) const;
+ };
+
+void CTestActiveScheduler::Error(TInt anError) const
+ {
+ User::Panic(_L("TestServer Error"),anError);
+ }
+
+
+
+//
+// Server thread
+//
+
+const TInt KServerRendezvous = KRequestPending+1;
+
+RServer2 Servers[ENumServerTypes];
+
+void DoStartServer(TServerName aName)
+ {
+ CTestActiveScheduler* activeScheduler = new (ELeave) CTestActiveScheduler;
+ CActiveScheduler::Install(activeScheduler);
+ CleanupStack::PushL(activeScheduler);
+
+ TInt type = 1; // ESharableSessions
+ if(aName==EGlobalSharableServer)
+ type = 2; // EGlobalSharableSessions;
+ CTestServer* server = new (ELeave) CTestServer(0,type);
+ CleanupStack::PushL(server);
+
+ User::LeaveIfError(server->Start(ServerName(aName)));
+
+ Servers[aName] = server->Server();
+ RProcess::Rendezvous(KServerRendezvous);
+ RThread::Rendezvous(KServerRendezvous);
+
+ CActiveScheduler::Start();
+
+ Servers[aName].SetHandle(0);
+ CleanupStack::PopAndDestroy(2);
+ }
+
+TInt StartServer(TServerName aName)
+ {
+ CTrapCleanup* cleanupStack = CTrapCleanup::New();
+ if(!cleanupStack)
+ return KErrNoMemory;
+ TRAPD(leaveError,DoStartServer(aName))
+ delete cleanupStack;
+ return leaveError;
+ }
+
+TInt DoThreadStartServer(TAny* aArg)
+ {
+ return StartServer((TServerName)(TInt)aArg);
+ }
+
+TRequestStatus ThrdSvrStat;
+
+TInt StartServerInThread(TServerName aName)
+ {
+ RThread thread;
+ TRequestStatus rendezvousStatus;
+ thread.Create(_L(""),DoThreadStartServer,KDefaultStackSize,KDefaultStackSize,KDefaultStackSize,(TAny*)aName);
+ thread.NotifyDestruction(ThrdSvrStat);
+ thread.Rendezvous(rendezvousStatus);
+ thread.Resume();
+ User::WaitForRequest(rendezvousStatus);
+ thread.Close();
+ if(rendezvousStatus.Int()!=KServerRendezvous)
+ return KErrGeneral;
+ return KErrNone;
+ }
+
+
+
+void TestPhysicalDevices()
+ {
+ TFullName name;
+ TInt r;
+
+ test.Start(_L("Test find named object"));
+ TFindPhysicalDevice find(_L("*"));
+ test((r=find.Next(name))==KErrNone);
+
+ test.Next(_L("Try open found object"));
+ RTestHandle testObject;
+ test((r=testObject.Open(find))==PlatSecProcessIsolationError);
+ testObject.Close();
+
+ test.End();
+ }
+
+
+
+void TestLogicalDevices()
+ {
+ TFullName name;
+ TInt r;
+ RDevice device;
+
+ test.Start(_L("Test find named object"));
+ TFindLogicalDevice find(_L("*"));
+ test((r=find.Next(name))==KErrNone);
+
+ test.Next(_L("Test open found object"));
+ test((r=device.Open(find))==KErrNone);
+
+ test.Next(_L("Test duplicate object in other thread"));
+ test((r=DuplicateInOtherThread(device))==KErrNone);
+
+ test.Next(_L("Test duplicate object in other process"));
+ test((r=DuplicateInOtherProcess(device))==KErrNone);
+
+ device.Close();
+
+ test.Next(_L("Test open device by name"));
+ test((r=device.Open(name))==KErrNone);
+ device.Close();
+
+ test.End();
+ }
+
+
+
+void TestLibraries()
+ {
+ TFullName name;
+ TInt r;
+
+ test.Start(_L("Test find named object"));
+ TFindLibrary find(_L("*"));
+ test((r=find.Next(name))==KErrNone);
+
+ test.Next(_L("Try open found object"));
+ RTestHandle testObject;
+ test((r=testObject.Open(find))==PlatSecProcessIsolationError);
+ testObject.Close();
+
+ test.End();
+ }
+
+
+
+void TestServers()
+ {
+ TFullName name;
+ TInt r;
+ RServer2 localObject(Servers[EAnonymousServer]);
+
+ test.Start(_L("Test find named object"));
+ TFindServer find(ServerName(EMainServer));
+ test((r=find.Next(name))==KErrNone);
+
+ test.Next(_L("Try open found object"));
+ RTestHandle testObject;
+ test((r=testObject.Open(find))==KErrPermissionDenied);
+
+ test.Next(_L("Test duplicate named server in other thread"));
+ test((r=Session.Send(CTestSession::ETestServerDuplicateInThread))==KErrNone);
+
+ test.Next(_L("Try duplicate named server in other process"));
+ test((r=Session.Send(CTestSession::ETestServerDuplicateInProcess))==KErrPermissionDenied);
+
+ test.Next(_L("Test duplicate unnamed server in other thread"));
+ test((r=DuplicateInOtherThread(localObject))==KErrNone);
+
+ test.Next(_L("Try duplicate unnamed server in other process"));
+ test((r=DuplicateInOtherProcess(localObject))==KErrPermissionDenied);
+
+ test.End();
+ }
+
+
+
+void TestProcesses()
+ {
+ TFullName name;
+ TInt r;
+ RProcess process;
+
+ test.Start(_L("Test find named object"));
+ TFindProcess find(_L("EKern*"));
+ test((r=find.Next(name))==KErrNone);
+
+ test.Next(_L("Test open found object"));
+ test((r=process.Open(find))==KErrNone);
+
+ test.Next(_L("Test duplicate object in other thread"));
+ test((r=DuplicateInOtherThread(process))==KErrNone);
+
+ test.Next(_L("Test duplicate object in other process"));
+ test((r=DuplicateInOtherProcess(process))==KErrNone);
+
+ process.Close();
+
+ test.Next(_L("Test open process by name"));
+ test((r=process.Open(name))==KErrNone);
+ TProcessId id=process.Id();
+ process.Close();
+
+ test.Next(_L("Test open process by id"));
+ test((r=process.Open(id))==KErrNone);
+ test(name==process.FullName());
+ process.Close();
+
+ test.End();
+ }
+
+
+
+void TestThreads()
+ {
+ TFullName name;
+ TInt r;
+
+ test.Start(_L("Creating threads"));
+ RThread globalObject;
+ RThread localObject;
+ RThread testObject;
+ test((r=globalObject.Create(_L("T_SOBJECT-test-global-thread"),TestThreadDuplicate,KDefaultStackSize,KDefaultStackSize,KDefaultStackSize,NULL))==KErrNone);
+ test((r=localObject.Create(_L(""),TestThreadDuplicate,KDefaultStackSize,KDefaultStackSize,KDefaultStackSize,NULL))==KErrNone);
+
+ test.Next(_L("Test find named thread"));
+ TFindThread find(globalObject.FullName());
+ test((r=find.Next(name))==KErrNone);
+
+ test.Next(_L("Test open found object"));
+ test((r=testObject.Open(find))==KErrNone);
+ testObject.Close();
+
+ test.Next(_L("Check can't find unnamed thread"));
+ TName objectName(localObject.FullName());
+ find.Find(objectName);
+ test((r=find.Next(name))==PlatSecFindError);
+
+ test.Next(_L("Test open named thread by name"));
+ test((r=testObject.Open(globalObject.FullName()))==KErrNone);
+ testObject.Close();
+
+ test.Next(_L("Check can't open unnamed thread by name"));
+ test((r=testObject.Open(localObject.FullName()))==PlatSecFindError);
+ testObject.Close();
+
+ test.Next(_L("Check can't open with no name"));
+ test((r=testObject.Open(KNullDesC))==KErrNotFound);
+ testObject.Close();
+
+ test.Next(_L("Test open named thread by id (in same process)"));
+ test((r=testObject.Open(globalObject.Id()))==KErrNone);
+ testObject.Close();
+
+ test.Next(_L("Test open named thread by id (in other process)"));
+ test((r=OpenThreadByIdInOtherProcess(globalObject.Id()))==KErrNone);
+
+ test.Next(_L("Test open unnamed thread by id (in same process)"));
+ test((r=testObject.Open(localObject.Id()))==KErrNone);
+
+ test.Next(_L("Check can't open unnamed thread by id (in other process)"));
+ test((r=OpenThreadByIdInOtherProcess(localObject.Id()))==PlatSecProcessIsolationError);
+
+ test.Next(_L("Test duplicate named thread in other process"));
+ test((r=DuplicateInOtherProcess(globalObject))==KErrNone);
+
+ test.Next(_L("Check can't duplicate unnamed thread in other process"));
+ test((r=DuplicateInOtherProcess(localObject))==PlatSecProcessIsolationError);
+
+ test.Next(_L("Test duplicate named thread in other thread"));
+ test((r=DuplicateInOtherThread(globalObject))==KErrNone);
+
+ test.Next(_L("Test duplicate unnamed thread in other thead"));
+ test((r=DuplicateInOtherThread(localObject))==KErrNone);
+
+ test.Next(_L("Closing threads"));
+ globalObject.Close();
+ localObject.Close();
+
+ test.End();
+ }
+
+
+
+void TestChunks()
+ {
+ TFullName name;
+ TInt r;
+
+ test.Start(_L("Creating chunks"));
+ RChunk globalObject;
+ RChunk localObject;
+ RChunk testObject;
+ test((r=globalObject.CreateGlobal(_L("T_SOBJECT-test-global-chunk"),4096,1024*1024))==KErrNone);
+ test((r=localObject.CreateLocal(4096,1024*1024))==KErrNone);
+
+ test.Next(_L("Test find global object"));
+ TFindChunk find(globalObject.FullName());
+ test((r=find.Next(name))==KErrNone);
+
+ test.Next(_L("Test open found object"));
+ test((r=testObject.Open(find))==KErrNone);
+ testObject.Close();
+
+ test.Next(_L("Check can't find local object"));
+ TName objectName(localObject.FullName());
+ find.Find(objectName);
+ test((r=find.Next(name))==PlatSecFindError);
+
+ test.Next(_L("Test open with null name"));
+ test((r=testObject.OpenGlobal(KNullDesC,ETrue))==KErrNotFound);
+ testObject.Close();
+
+ test.Next(_L("Test open global object by name"));
+ test((r=testObject.OpenGlobal(globalObject.FullName(),ETrue))==KErrNone);
+ testObject.Close();
+
+ test.Next(_L("Check can't open local object by name"));
+ test((r=testObject.OpenGlobal(localObject.FullName(),ETrue))==PlatSecFindError);
+ testObject.Close();
+
+ test.Next(_L("Test duplicate global object in other process"));
+ test((r=DuplicateInOtherProcess(globalObject))==KErrNone);
+
+ test.Next(_L("Check can't duplicate local object in other process"));
+ test((r=DuplicateInOtherProcess(localObject))==PlatSecProcessIsolationError);
+
+ test.Next(_L("Test duplicate global object in other thread"));
+ test((r=DuplicateInOtherThread(globalObject))==KErrNone);
+
+ test.Next(_L("Test duplicate local object in other thead"));
+ test((r=DuplicateInOtherThread(localObject))==KErrNone);
+
+ test.Next(_L("Test Chunk protection"));
+ {
+ RChunk protectedChunk;
+ test((r=protectedChunk.CreateGlobal(KNullDesC,0x1000,0x100000,EOwnerProcess))==KErrNone);
+ test((r=Session.Send(CTestSession::ETestChunkAdjust,TIpcArgs(protectedChunk)))==KErrNone);
+ protectedChunk.SetRestrictions(RChunk::EPreventAdjust);
+ test((r=Session.Send(CTestSession::ETestChunkAdjust,TIpcArgs(protectedChunk)))==KErrAccessDenied);
+ protectedChunk.Close();
+ }
+
+ test.Next(_L("Closing chunks"));
+ globalObject.Close();
+ localObject.Close();
+
+ test.End();
+ }
+
+
+
+void TestSemaphores()
+ {
+ TFullName name;
+ TInt r;
+
+ test.Start(_L("Creating semaphores"));
+ RSemaphore globalObject;
+ RSemaphore localObject;
+ RSemaphore testObject;
+ test((r=globalObject.CreateGlobal(_L("T_SOBJECT-test-global-semaphore"),1))==KErrNone);
+ test((r=localObject.CreateLocal(1))==KErrNone);
+
+ test.Next(_L("Test find global object"));
+ TFindSemaphore find(globalObject.FullName());
+ test((r=find.Next(name))==KErrNone);
+
+ test.Next(_L("Test open found object"));
+ test((r=testObject.Open(find))==KErrNone);
+ testObject.Close();
+
+ test.Next(_L("Check can't find local object"));
+ TName objectName(localObject.FullName());
+ find.Find(objectName);
+ test((r=find.Next(name))==PlatSecFindError);
+
+ test.Next(_L("Test open with null name"));
+ test((r=testObject.OpenGlobal(KNullDesC))==KErrNotFound);
+ testObject.Close();
+
+ test.Next(_L("Test open global object by name"));
+ test((r=testObject.OpenGlobal(globalObject.FullName()))==KErrNone);
+ testObject.Close();
+
+ test.Next(_L("Check can't open local object by name"));
+ test((r=testObject.OpenGlobal(localObject.FullName()))==PlatSecFindError);
+ testObject.Close();
+
+ test.Next(_L("Test duplicate global object in other process"));
+ test((r=DuplicateInOtherProcess(globalObject))==KErrNone);
+
+ test.Next(_L("Check can't duplicate local object in other process"));
+ test((r=DuplicateInOtherProcess(localObject))==PlatSecProcessIsolationError);
+
+ test.Next(_L("Test duplicate global object in other thread"));
+ test((r=DuplicateInOtherThread(globalObject))==KErrNone);
+
+ test.Next(_L("Test duplicate local object in other thead"));
+ test((r=DuplicateInOtherThread(localObject))==KErrNone);
+
+ test.Next(_L("Closing Semaphores"));
+ globalObject.Close();
+ localObject.Close();
+
+ test.End();
+ }
+
+
+
+void TestMutexes()
+ {
+ TFullName name;
+ TInt r;
+
+ test.Start(_L("Creating mutexes"));
+ RMutex globalObject;
+ RMutex localObject;
+ RMutex testObject;
+ test((r=globalObject.CreateGlobal(_L("T_SOBJECT-test-global-mutex")))==KErrNone);
+ test((r=localObject.CreateLocal())==KErrNone);
+
+ test.Next(_L("Test find global object"));
+ TFindMutex find(globalObject.FullName());
+ test((r=find.Next(name))==KErrNone);
+
+ test.Next(_L("Test open found object"));
+ test((r=testObject.Open(find))==KErrNone);
+ testObject.Close();
+
+ test.Next(_L("Check can't find local object"));
+ TName objectName(localObject.FullName());
+ find.Find(objectName);
+ test((r=find.Next(name))==PlatSecFindError);
+
+ test.Next(_L("Test open with null name"));
+ test((r=testObject.OpenGlobal(KNullDesC))==KErrNotFound);
+ testObject.Close();
+
+ test.Next(_L("Test open global object by name"));
+ test((r=testObject.OpenGlobal(globalObject.FullName()))==KErrNone);
+ testObject.Close();
+
+ test.Next(_L("Check can't open local object by name"));
+ test((r=testObject.OpenGlobal(localObject.FullName()))==PlatSecFindError);
+ testObject.Close();
+
+ test.Next(_L("Test duplicate global object in other process"));
+ test((r=DuplicateInOtherProcess(globalObject))==KErrNone);
+
+ test.Next(_L("Check can't duplicate local object in other process"));
+ test((r=DuplicateInOtherProcess(localObject))==PlatSecProcessIsolationError);
+
+ test.Next(_L("Test duplicate global object in other thread"));
+ test((r=DuplicateInOtherThread(globalObject))==KErrNone);
+
+ test.Next(_L("Test duplicate local object in other thead"));
+ test((r=DuplicateInOtherThread(localObject))==KErrNone);
+
+ test.Next(_L("Closing mutexes"));
+ globalObject.Close();
+ localObject.Close();
+
+ test.End();
+ }
+
+
+
+void TestMessageQueues()
+ {
+ TInt r;
+
+ test.Start(_L("Creating message queues"));
+ RMsgQueue<TInt> globalObject;
+ RMsgQueue<TInt> localObject;
+ RMsgQueue<TInt> testObject;
+ test((r=globalObject.CreateGlobal(_L("T_SOBJECT-test-global-msgqueue"),1))==KErrNone);
+ test((r=localObject.CreateLocal(1))==KErrNone);
+
+ test.Next(_L("Test open with null name"));
+ test((r=testObject.OpenGlobal(KNullDesC))==KErrNotFound);
+ testObject.Close();
+
+ test.Next(_L("Test open global object by name"));
+ test((r=testObject.OpenGlobal(globalObject.FullName()))==KErrNone);
+ testObject.Close();
+
+ test.Next(_L("Check can't open local object by name"));
+ test((r=testObject.OpenGlobal(localObject.FullName()))==PlatSecFindError);
+ testObject.Close();
+
+ test.Next(_L("Test duplicate global object in other process"));
+ test((r=DuplicateInOtherProcess(globalObject))==KErrNone);
+
+ test.Next(_L("Check can't duplicate local object in other process"));
+ test((r=DuplicateInOtherProcess(localObject))==PlatSecProcessIsolationError);
+
+ test.Next(_L("Test duplicate global object in other thread"));
+ test((r=DuplicateInOtherThread(globalObject))==KErrNone);
+
+ test.Next(_L("Test duplicate local object in other thead"));
+ test((r=DuplicateInOtherThread(localObject))==KErrNone);
+
+ test.Next(_L("Closing message queues"));
+ globalObject.Close();
+ localObject.Close();
+
+ test.End();
+ }
+
+
+
+void TestConditionVariables()
+ {
+ TInt r;
+
+ test.Start(_L("Creating condition variables"));
+ RCondVar globalObject;
+ RCondVar localObject;
+ RCondVar testObject;
+ test((r=globalObject.CreateGlobal(_L("T_SOBJECT-test-global-condvar")))==KErrNone);
+ test((r=localObject.CreateLocal())==KErrNone);
+
+ test.Next(_L("Test open with null name"));
+ test((r=testObject.OpenGlobal(KNullDesC))==KErrNotFound);
+ testObject.Close();
+
+ test.Next(_L("Test open global object by name"));
+ test((r=testObject.OpenGlobal(globalObject.FullName()))==KErrNone);
+ testObject.Close();
+
+ test.Next(_L("Check can't open local object by name"));
+ test((r=testObject.OpenGlobal(localObject.FullName()))==PlatSecFindError);
+ testObject.Close();
+
+ test.Next(_L("Test duplicate global object in other process"));
+ test((r=DuplicateInOtherProcess(globalObject))==KErrNone);
+
+ test.Next(_L("Check can't duplicate local object in other process"));
+ test((r=DuplicateInOtherProcess(localObject))==PlatSecProcessIsolationError);
+
+ test.Next(_L("Test duplicate global object in other thread"));
+ test((r=DuplicateInOtherThread(globalObject))==KErrNone);
+
+ test.Next(_L("Test duplicate local object in other thead"));
+ test((r=DuplicateInOtherThread(localObject))==KErrNone);
+
+ test.Next(_L("Closing message queues"));
+ globalObject.Close();
+ localObject.Close();
+
+ test.End();
+ }
+
+
+
+void TestIPCHandles()
+ {
+ RTestProcess server;
+ TRequestStatus rendezvous;
+ TInt r;
+
+ test.Next(_L("Test sending LogicalChannel handles"));
+ {
+ RLddTest localLdd;
+ RLddTest protectedLdd;
+ RLddTest returnLdd;
+ r=User::LoadLogicalDevice(_L("D_SLDD.LDD"));
+ test(r==KErrNone || r==KErrAlreadyExists);
+ r=localLdd.OpenLocal();
+ test(r==KErrNone);
+ r=protectedLdd.OpenProtected();
+ test(r==KErrNone);
+ TInt lddValue=protectedLdd.Test1();
+ test(lddValue==RLddTest::ETest1Value);
+ SetName(protectedLdd);
+ r = Session.Send(CTestSession::ETestLdd,TIpcArgs(localLdd,protectedLdd,lddValue,&Name));
+ r = returnLdd.SetReturnedHandle(r);
+ test(r==KErrNone);
+ test(CheckName(returnLdd));
+ protectedLdd.Close();
+ returnLdd.Close();
+ localLdd.Close();
+ }
+
+ test.Next(_L("Test sending Chunk handles"));
+ {
+ RChunk localChunk;
+ RChunk globalChunk;
+ RChunk protectedChunk;
+ RChunk returnChunk;
+ test((r=localChunk.CreateLocal(0x1000,0x100000,EOwnerThread))==KErrNone);
+ test((r=globalChunk.CreateGlobal(KTestChunkName,0x1000,0x100000,EOwnerProcess))==KErrNone);
+ test((r=protectedChunk.CreateGlobal(KNullDesC,0x1000,0x100000,EOwnerProcess))==KErrNone);
+ SetName(protectedChunk);
+ r = Session.Send(CTestSession::ETestChunk,TIpcArgs(localChunk,globalChunk,protectedChunk,&Name));
+ r = returnChunk.SetReturnedHandle(r);
+ test(r==KErrNone);
+ test(CheckName(returnChunk));
+ returnChunk.Close();
+ protectedChunk.Close();
+ globalChunk.Close();
+ localChunk.Close();
+ }
+
+ test.Next(_L("Test sending Semaphore handles"));
+ {
+ RSemaphore localSemaphore;
+ RSemaphore globalSemaphore;
+ RSemaphore protectedSemaphore;
+ RSemaphore returnSemaphore;
+ test((r=localSemaphore.CreateLocal(1,EOwnerThread))==KErrNone);
+ test((r=globalSemaphore.CreateGlobal(KTestSemaphoreName,1,EOwnerProcess))==KErrNone);
+ test((r=protectedSemaphore.CreateGlobal(KNullDesC,1,EOwnerProcess))==KErrNone);
+ SetName(protectedSemaphore);
+ r = Session.Send(CTestSession::ETestSemaphore,TIpcArgs(localSemaphore,globalSemaphore,protectedSemaphore,&Name));
+ r = returnSemaphore.SetReturnedHandle(r);
+ test(r==KErrNone);
+ test(CheckName(returnSemaphore));
+ returnSemaphore.Close();
+ protectedSemaphore.Close();
+ globalSemaphore.Close();
+ localSemaphore.Close();
+ }
+
+ test.Next(_L("Test sending Mutex handles"));
+ {
+ RMutex localMutex;
+ RMutex globalMutex;
+ RMutex protectedMutex;
+ RMutex returnMutex;
+ test((r=localMutex.CreateLocal(EOwnerThread))==KErrNone);
+ test((r=globalMutex.CreateGlobal(KTestMutexName,EOwnerProcess))==KErrNone);
+ test((r=protectedMutex.CreateGlobal(KNullDesC,EOwnerProcess))==KErrNone);
+ SetName(protectedMutex);
+ r = Session.Send(CTestSession::ETestMutex,TIpcArgs(localMutex,globalMutex,protectedMutex,&Name));
+ r = returnMutex.SetReturnedHandle(r);
+ test(r==KErrNone);
+ test(CheckName(returnMutex));
+ returnMutex.Close();
+ protectedMutex.Close();
+ globalMutex.Close();
+ localMutex.Close();
+ }
+
+ test.Next(_L("Test sending MsgQueue handles"));
+ {
+ RMsgQueue<TInt> localMsgQueue;
+ RMsgQueue<TInt> globalMsgQueue;
+ RMsgQueue<TInt> protectedMsgQueue;
+ RMsgQueue<TInt> returnMsgQueue;
+ test((r=localMsgQueue.CreateLocal(1,EOwnerThread))==KErrNone);
+ test((r=globalMsgQueue.CreateGlobal(KTestMsgQueueName,1,EOwnerProcess))==KErrNone);
+ test((r=protectedMsgQueue.CreateGlobal(KNullDesC,1,EOwnerProcess))==KErrNone);
+ SetName(protectedMsgQueue);
+ r = Session.Send(CTestSession::ETestMsgQueue,TIpcArgs(localMsgQueue,globalMsgQueue,protectedMsgQueue,&Name));
+ r = returnMsgQueue.SetReturnedHandle(r);
+ test(r==KErrNone);
+ test(CheckName(returnMsgQueue));
+ returnMsgQueue.Close();
+ protectedMsgQueue.Close();
+ globalMsgQueue.Close();
+ localMsgQueue.Close();
+ }
+
+ test.Next(_L("Test sending CondVar handles"));
+ {
+ RCondVar localCondVar;
+ RCondVar globalCondVar;
+ RCondVar protectedCondVar;
+ RCondVar returnCondVar;
+ test((r=localCondVar.CreateLocal(EOwnerThread))==KErrNone);
+ test((r=globalCondVar.CreateGlobal(KTestCondVarName,EOwnerProcess))==KErrNone);
+ test((r=protectedCondVar.CreateGlobal(KNullDesC,EOwnerProcess))==KErrNone);
+ SetName(protectedCondVar);
+ r = Session.Send(CTestSession::ETestCondVar,TIpcArgs(localCondVar,globalCondVar,protectedCondVar,&Name));
+ r = returnCondVar.SetReturnedHandle(r);
+ test(r==KErrNone);
+ test(CheckName(returnCondVar));
+ returnCondVar.Close();
+ protectedCondVar.Close();
+ globalCondVar.Close();
+ localCondVar.Close();
+ }
+
+ test.Start(_L("Starting test server 2"));
+ server.Create(ETestProcessServer,EGlobalSharableServer);
+ server.Rendezvous(rendezvous);
+ server.Resume();
+ User::WaitForRequest(rendezvous);
+ test(rendezvous==KServerRendezvous);
+ server.Close();
+
+ test.Next(_L("Test sending Session handles"));
+ {
+ RTestSession localSession;
+ RTestSession protectedSession;
+ RTestSession returnSession;
+ RFs fsSession;
+ test((r=localSession.Connect(EGlobalSharableServer))==KErrNone);
+ test((r=localSession.Send(CTestSession::EPing,TIpcArgs(123)))==123);
+ test((r=protectedSession.ConnectProtected(EGlobalSharableServer))==KErrNone);
+ test((r=protectedSession.Send(CTestSession::EPing,TIpcArgs(123)))==123);
+ test((r=fsSession.Connect())==KErrNone);
+ test((r=fsSession.ShareProtected())==KErrNone);
+ SetName(protectedSession);
+ r = Session.Send(CTestSession::ETestSession,TIpcArgs(localSession,protectedSession,fsSession,&Name));
+ r = returnSession.SetReturnedHandle(r);
+ test(r==KErrNone);
+ test(CheckName(returnSession));
+ returnSession.Close();
+ protectedSession.Close();
+ localSession.Close();
+ fsSession.Close();
+ }
+
+ test.Next(_L("Test receiving Session handles"));
+ {
+ RTestSession returnSession;
+ r = Session.Send(CTestSession::ETestSession2);
+ r = returnSession.SetReturnedHandle(r);
+ test(r==KErrNone);
+ test((r=Session.Send(CTestSession::EPing,TIpcArgs(123)))==123); // So we know server has closed returnedSession
+ test((r=returnSession.Send(CTestSession::EPing,TIpcArgs(123)))==123);
+ returnSession.Close();
+ RFs returnFsSession;
+ r = Session.Send(CTestSession::ETestSession3);
+ r = returnSession.SetReturnedHandle(r,TSecurityPolicy(TSecureId(0x100039e3))); // f32 sid
+ test(r==KErrNone);
+ returnFsSession.Close();
+ }
+
+ test.Next(_L("Try global sharing of Sessions without server support"));
+ {
+ RTestSession protectedSession;
+ test((r=protectedSession.ConnectProtected(EMainServer))==KErrPermissionDenied);
+ }
+
+ test.Next(_L("Stopping test server 2"));
+ {
+ RTestSession session;
+ test((r=session.Connect(EGlobalSharableServer))==KErrNone);
+ session.Send(CTestSession::EShutdown);
+ session.Close();
+ }
+
+ test.End();
+ }
+
+// Test uniqness of object names is enforced by DObjectCon when creating objects
+void TestObjectNames()
+ {
+ _LIT(KNameFormat, "TestObject-%d");
+ const TInt KObjectCount = 10;
+ RMutex objects[KObjectCount];
+
+ test.Start(_L("Test uniqueness of object names"));
+
+ // Test creating named and unnamed objects is ok
+ TInt i;
+ for (i = 0 ; i < KObjectCount ; ++i)
+ {
+ if (i % 2)
+ test(objects[i].CreateLocal() == KErrNone);
+ else
+ {
+ TBuf<16> name;
+ name.AppendFormat(KNameFormat, i);
+ test(objects[i].CreateGlobal(name) == KErrNone);
+ }
+ }
+
+ // Test we cannot create objects with duplicate names
+ for (i = 0 ; i < KObjectCount ; i+=2)
+ {
+ TBuf<16> name;
+ name.AppendFormat(KNameFormat, i);
+ test(objects[i].CreateGlobal(name) == KErrAlreadyExists);
+ }
+
+ // Close all objects
+ for (i = 0 ; i < KObjectCount ; ++i)
+ {
+ objects[i].Close();
+ }
+
+ test.End();
+ }
+
+
+TInt DoTestProcess(TInt aTestNum,TInt aArg1,TInt aArg2)
+ {
+ TInt r;
+
+ switch(aTestNum)
+ {
+
+ case ETestProcessServer:
+ return StartServer((TServerName)aArg1);
+
+ case ETestProcessDuplicate:
+ {
+ RHandleBase handle;
+ handle.SetHandle(aArg2);
+ RThread thread;
+ r = thread.Open(TThreadId(aArg1));
+ if(r!=KErrNone)
+ r = 999;
+ else
+ r = handle.Duplicate(thread);
+ thread.Close();
+ }
+ return r;
+
+ case ETestProcessOpenThreadById:
+ {
+ RThread thread;
+ r = thread.Open(TThreadId(aArg1));
+ if(r==KErrNone)
+ thread.Close();
+ }
+ return r;
+
+
+ default:
+ User::Panic(_L("T_SOBJECT"),1);
+ }
+
+ return KErrNone;
+ }
+
+
+GLDEF_C TInt E32Main()
+ {
+ PlatSecProcessIsolationError = PlatSec::ConfigSetting(PlatSec::EPlatSecProcessIsolation)&&PlatSec::ConfigSetting(PlatSec::EPlatSecEnforcement)
+ ? KErrPermissionDenied : KErrNone;
+ PlatSecFindError = PlatSec::ConfigSetting(PlatSec::EPlatSecProcessIsolation)
+ ? KErrNotFound : KErrNone;
+
+ TBuf16<512> cmd;
+ User::CommandLine(cmd);
+ if(cmd.Length() && TChar(cmd[0]).IsDigit())
+ {
+ TInt function = -1;
+ TInt arg1 = -1;
+ TInt arg2 = -1;
+ TLex lex(cmd);
+ lex.Val(function);
+ lex.SkipSpace();
+ lex.Val(arg1);
+ lex.SkipSpace();
+ lex.Val(arg2);
+ return DoTestProcess(function,arg1,arg2);
+ }
+
+
+ test.Title();
+ TInt r;
+
+ test.Start(_L("Starting test servers"));
+ RTestProcess server;
+ TRequestStatus rendezvous;
+ TRequestStatus svrstat;
+ server.Create(ETestProcessServer,EMainServer);
+ server.NotifyDestruction(svrstat);
+ server.Rendezvous(rendezvous);
+ server.Resume();
+ User::WaitForRequest(rendezvous);
+ test(rendezvous==KServerRendezvous);
+ server.Close();
+ test((r=StartServerInThread(EAnonymousServer))==KErrNone);
+
+ test.Next(_L("Openning server session"));
+ test((r=Session.Connect())==KErrNone);
+
+ test.Next(_L("Test Find and Open PhysicalDevices"));
+ TestPhysicalDevices();
+
+ test.Next(_L("Test Find and Open LogicalDevices"));
+ TestLogicalDevices();
+
+ test.Next(_L("Test Find and Open Libraries"));
+ TestLibraries();
+
+ test.Next(_L("Test Find and Open Servers"));
+ TestServers();
+
+ test.Next(_L("Test Find and Open Processes"));
+ TestProcesses();
+
+ test.Next(_L("Test Find and Open Threads"));
+ TestThreads();
+
+ test.Next(_L("Test Find and Open Chunks"));
+ TestChunks();
+
+ test.Next(_L("Test Find and Open Semaphores"));
+ TestSemaphores();
+
+ test.Next(_L("Test Find and Open Mutexes"));
+ TestMutexes();
+
+ test.Next(_L("Test Message Queues"));
+ TestMessageQueues();
+
+ test.Next(_L("Test Condition Variables"));
+ TestConditionVariables();
+
+ test.Next(_L("Test passing handle via IPC"));
+ TestIPCHandles();
+
+ test.Next(_L("Test object names"));
+ TestObjectNames();
+
+ test.Next(_L("Stopping test server"));
+ Session.Send(CTestSession::EShutdown);
+ Session.Close();
+ User::WaitForRequest(svrstat);
+ test(svrstat == KErrNone);
+
+ test.End();
+
+ return(0);
+ }
+