kerneltest/e32test/secure/t_sserver.cpp
changeset 0 a41df078684a
child 271 dc268b18d709
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/secure/t_sserver.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,1228 @@
+// Copyright (c) 2001-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_sserver.cpp
+// Overview:
+// Test the security aspects of server connect by handle.
+// API Information:
+// CSession2, CServer2
+// Details:
+// - Test asynchronous server connect in various ways. Verify results
+// are as expected.
+// - Attempt to create a protected server without and without 
+// KCapabilityProtServ. Verify results are as expected.
+// - Attempt to connect to a serve with different Secure IDs, Vendor IDs
+// and capabilities. Verify results are as expected.
+// - Test creating a sub-session, sending it messages and closing it.
+// Verify the results.
+// - Test TIpcArgs::Set and IPC argument passing. Verify results are
+// as expected.
+// - Test TIpcArgs:: Also checks the integrity of the server and Kernel if client passes bad descriptor
+// for IPC transfer and the integrity of the client and Kernel if the server does the same.
+// - Test CServer2::RunError and CSession2::ServiceError and session
+// resource counting.
+// Platforms/Drives/Compatibility:
+// All.
+// Assumptions/Requirement/Pre-requisites:
+// Failures and causes:
+// Base Port information:
+// 
+//
+
+#include <e32test.h>
+#include "../misc/prbs.h"
+
+LOCAL_D RTest test(_L("T_SSERVER"));
+
+_LIT_SECURE_ID(KTestSecureId,0x101f534d);
+_LIT_SECURE_ID(KTestSecureId2,0x101f534e);
+_LIT_VENDOR_ID(KTestVendorId,0x01234567);
+_LIT_VENDOR_ID(KTestVendorId2,0x01234568);
+const TInt KTestRunErrorModifier = 111;
+const TInt KTestServiceErrorModifier = 222;
+_LIT(KProtectedServerName,"!T_SSERVER-protected-server");
+
+
+
+enum TTestProcessFunctions
+	{
+	ETestProcessServer,
+	ETestProcessCreateProtectedServer,
+	};
+
+#include "testprocess.h"
+
+
+
+//
+// RTestThread
+//
+
+class RTestThread : public RThread
+	{
+public:
+	void Create(TThreadFunction aFunction,TAny* aArg=0);
+	};
+
+void RTestThread::Create(TThreadFunction aFunction,TAny* aArg)
+	{
+	TInt r=RThread::Create(_L(""),aFunction,KDefaultStackSize,KDefaultStackSize,KDefaultStackSize,aArg);
+	test(r==KErrNone);
+	}
+
+
+
+//
+// CTestSession
+//
+
+enum TTestSessionFuntions
+	{
+	ETestShutdown,EPing,
+	ETestArgUnspecified,ETestArgDesC8,ETestArgDesC16,ETestArgDes8,ETestArgDes16,
+	ETestResourceCountPass=0x01234567,ETestResourceCountFail,ETestServiceLeave,
+	ETestCreateSubSession,ETestCloseSubSession,ETestCloseSubSessionHandle,
+	ETestEchoArgs,ETestEmptySubSessionMessage, ETestBadClientDescRead, ETestBadClientDescWrite,
+	ETestBadServerDescRead, ETestBadServerDescWrite
+	};
+
+class CTestSession : public CSession2
+	{
+public:
+	CTestSession();
+	virtual void ServiceL(const RMessage2& aMessage);
+	virtual void ServiceError(const RMessage2& aMessage,TInt aError);
+private:
+	TInt CountResources();
+private:
+	TInt iResourceCount;
+	TInt iSubSessionCloseHandle;
+	RMessage2 iMessage;
+	};
+
+class CTestSecureServer : public CServer2
+	{
+public:
+	CTestSecureServer(TInt aPriority);
+	virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const;
+private:
+	void CustomL(const RMessage2& aMessage);
+	void QueryL(const RMessage2& aMessage,HBufC8*& aQueryParams);
+	TInt RunError(TInt aError);
+private:
+	friend class CTestSession;
+	};
+
+CTestSession::CTestSession()
+	: CSession2()
+	{}
+
+void CTestSession::ServiceL(const RMessage2& aMessage)
+	{
+	TInt r = KErrNotSupported;
+	TBuf8<100> buf8;
+	buf8.Append(_L8("12345"));
+	TBuf16<100> buf16;
+	buf16.Append(_L16("12345"));
+	TInt testArg = ((TUint)aMessage.Function())>>28;
+
+	TInt badDescriptorError = PlatSec::ConfigSetting(PlatSec::EPlatSecProcessIsolation)&&PlatSec::ConfigSetting(PlatSec::EPlatSecEnforcement)
+		? KErrBadDescriptor : KErrNone;
+
+	switch(aMessage.Function()&0x0fffffff)
+		{
+		case ETestShutdown:
+			CActiveScheduler::Stop();
+			return;
+
+		case EPing:
+			r=aMessage.Int0();
+			break;
+
+		case ETestArgUnspecified:
+			r = aMessage.GetDesLength(testArg);
+			if(r!=KErrBadDescriptor)
+				goto fail;
+			r = aMessage.GetDesMaxLength(testArg);
+			if(r!=KErrBadDescriptor)
+				goto fail;
+			r = aMessage.Read(testArg,buf8);
+			if(r!=badDescriptorError)
+				goto fail;
+			TRAP(r,aMessage.ReadL(testArg,buf8));
+			if(r!=badDescriptorError)
+				goto fail;
+			r = aMessage.Read(testArg,buf16);
+			if(r!=badDescriptorError)
+				goto fail;
+			TRAP(r,aMessage.ReadL(testArg,buf16));
+			if(r!=badDescriptorError)
+				goto fail;
+			r = aMessage.Write(testArg,buf8);
+			if(r!=badDescriptorError)
+				goto fail;
+			TRAP(r,aMessage.WriteL(testArg,buf8));
+			if(r!=badDescriptorError)
+				goto fail;
+			r = aMessage.Write(testArg,buf16);
+			if(r!=badDescriptorError)
+				goto fail;
+			TRAP(r,aMessage.WriteL(testArg,buf16));
+			if(r!=badDescriptorError)
+				goto fail;
+			goto pass;
+
+		case ETestArgDesC8:
+			r = aMessage.GetDesLength(testArg);
+			if(r<0)
+				goto fail;
+			r = aMessage.GetDesMaxLength(testArg);
+			if(r<0)
+				goto fail;
+			r = aMessage.Read(testArg,buf8);
+			if(r!=KErrNone)
+				goto fail;
+			TRAP(r,aMessage.ReadL(testArg,buf8));
+			if(r!=KErrNone)
+				goto fail;
+			r = aMessage.Read(testArg,buf16);
+			if(r!=badDescriptorError)
+				goto fail;
+			TRAP(r,aMessage.ReadL(testArg,buf16));
+			if(r!=badDescriptorError)
+				goto fail;
+			r = aMessage.Write(testArg,buf8);
+			if(r!=badDescriptorError)
+				goto fail;
+			TRAP(r,aMessage.WriteL(testArg,buf8));
+			if(r!=badDescriptorError)
+				goto fail;
+			r = aMessage.Write(testArg,buf16);
+			if(r!=badDescriptorError)
+				goto fail;
+			TRAP(r,aMessage.WriteL(testArg,buf16));
+			if(r!=badDescriptorError)
+				goto fail;
+			goto pass;
+
+		case ETestArgDesC16:
+			r = aMessage.GetDesLength(testArg);
+			if(r<0)
+				goto fail;
+			r = aMessage.GetDesMaxLength(testArg);
+			if(r<0)
+				goto fail;
+			r = aMessage.Read(testArg,buf8);
+			if(r!=badDescriptorError)
+				goto fail;
+			TRAP(r,aMessage.ReadL(testArg,buf8));
+			if(r!=badDescriptorError)
+				goto fail;
+			r = aMessage.Read(testArg,buf16);
+			if(r!=KErrNone)
+				goto fail;
+			TRAP(r,aMessage.ReadL(testArg,buf16));
+			if(r!=KErrNone)
+				goto fail;
+			r = aMessage.Write(testArg,buf8);
+			if(r!=badDescriptorError)
+				goto fail;
+			TRAP(r,aMessage.WriteL(testArg,buf8));
+			if(r!=badDescriptorError)
+				goto fail;
+			r = aMessage.Write(testArg,buf16);
+			if(r!=badDescriptorError)
+				goto fail;
+			TRAP(r,aMessage.WriteL(testArg,buf16));
+			if(r!=badDescriptorError)
+				goto fail;
+			goto pass;
+
+		case ETestArgDes8:
+			r = aMessage.GetDesLength(testArg);
+			if(r<0)
+				goto fail;
+			r = aMessage.GetDesMaxLength(testArg);
+			if(r<0)
+				goto fail;
+			r = aMessage.Read(testArg,buf8);
+			if(r!=KErrNone)
+				goto fail;
+			TRAP(r,aMessage.ReadL(testArg,buf8));
+			if(r!=KErrNone)
+				goto fail;
+			r = aMessage.Read(testArg,buf16);
+			if(r!=badDescriptorError)
+				goto fail;
+			TRAP(r,aMessage.ReadL(testArg,buf16));
+			if(r!=badDescriptorError)
+				goto fail;
+			r = aMessage.Write(testArg,buf8);
+			if(r!=KErrNone)
+				goto fail;
+			TRAP(r,aMessage.WriteL(testArg,buf8));
+			if(r!=KErrNone)
+				goto fail;
+			r = aMessage.Write(testArg,buf16);
+			if(r!=badDescriptorError)
+				goto fail;
+			TRAP(r,aMessage.WriteL(testArg,buf16));
+			if(r!=badDescriptorError)
+				goto fail;
+			goto pass;
+
+		case ETestArgDes16:
+			r = aMessage.GetDesLength(testArg);
+			if(r<0)
+				goto fail;
+			r = aMessage.GetDesMaxLength(testArg);
+			if(r<0)
+				goto fail;
+			r = aMessage.Read(testArg,buf8);
+			if(r!=badDescriptorError)
+				goto fail;
+			TRAP(r,aMessage.ReadL(testArg,buf8));
+			if(r!=badDescriptorError)
+				goto fail;
+			r = aMessage.Read(testArg,buf16);
+			if(r!=KErrNone)
+				goto fail;
+			TRAP(r,aMessage.ReadL(testArg,buf16));
+			if(r!=KErrNone)
+				goto fail;
+			r = aMessage.Write(testArg,buf8);
+			if(r!=badDescriptorError)
+				goto fail;
+			TRAP(r,aMessage.WriteL(testArg,buf8));
+			if(r!=badDescriptorError)
+				goto fail;
+			r = aMessage.Write(testArg,buf16);
+			if(r!=KErrNone)
+				goto fail;
+			TRAP(r,aMessage.WriteL(testArg,buf16));
+			if(r!=KErrNone)
+				goto fail;
+			goto pass;
+		
+		case ETestBadClientDescRead:
+			//Testing the integrity of the server and Kernel if the client passes bad descriptor for IPC transfer
+			{
+			r = aMessage.GetDesLength(testArg);
+			TUint8* buff;
+			buff = (TUint8*)User::Alloc(r);
+			if (!buff)
+				{
+				r=KErrNoMemory;
+				break;
+				}
+			TPtr8 ptr8(buff, r, r);
+			r=aMessage.Read(testArg,ptr8);
+			User::Free(buff);
+			}
+			break;
+
+		case ETestBadClientDescWrite:
+			//Testing the integrity of the server and Kernel if the client passes bad descriptor for IPC transfer
+			{
+			r = aMessage.GetDesLength(testArg);
+			TUint8* buff;
+			buff = (TUint8*)User::Alloc(r);
+			if (!buff)
+				{
+				r=KErrNoMemory;
+				break;
+				}
+			TPtr8 ptr8(buff, r, r);
+			r=aMessage.Write(testArg,ptr8);
+			User::Free(buff);
+			}
+			break;
+
+		case ETestBadServerDescRead:
+		case ETestBadServerDescWrite:
+			//Testing the integrity of the client and Kernel if server passes bad descriptor for IPC transfer
+			{
+			//Create a chunk with a hole between addresses 0x1000 and 0x2000
+			RChunk c;
+			r=c.CreateDisconnectedLocal(0,0,0x200000);
+			test(r==KErrNone);
+			r=c.Commit(0,0x1000);
+			test(r==KErrNone);
+			r=c.Commit(0x2000,0x1000);
+			test(r==KErrNone);
+			
+			TInt base,len;
+			switch(aMessage.Function()>>28)
+				{ 
+				case 0:base=0x1000;len=0x500;break;
+				case 1:base=0x1001;len=0x500;break;
+				case 2:base=0x1007;len=0x500;break;
+				case 3:base=0x1ff0;len=0x100;break;
+				case 4:base=0x1ff1;len=0x100;break;
+				case 5:base=0x1ff2;len=0x100;break;
+				case 6:base=0xff3;len=0x100;break;	
+				default:base=0xfff;len=0x100;break;
+				}
+
+			TPtr8 ptr (c.Base()+base,len,len);
+			if ((aMessage.Function()&0x0fffffff) == ETestBadServerDescRead)
+				aMessage.Read(0,ptr);	//The server should panic here
+			else
+				aMessage.Write(0,ptr);	//The server should panic here
+			}
+			break;
+
+		case ETestResourceCountPass:
+			r=aMessage.Function();
+			ResourceCountMarkStart();
+			ResourceCountMarkEnd(aMessage);
+			break;
+
+		case ETestResourceCountFail:
+			r=aMessage.Function();
+			ResourceCountMarkStart();
+			++iResourceCount;
+			ResourceCountMarkEnd(aMessage);
+			break;
+
+		case ETestServiceLeave:
+			iMessage = aMessage;
+			User::Leave(aMessage.Int0());
+			break;
+
+		case ETestCreateSubSession:
+			{
+			TInt reply = aMessage.Int0();
+			r = aMessage.Write(3,TPtrC8((TUint8*)&reply,sizeof(reply)));
+			}
+			break;
+
+		case ETestCloseSubSession:
+			iSubSessionCloseHandle = aMessage.Int3();
+			r = KErrNone;
+			break;
+
+		case ETestCloseSubSessionHandle:
+			r = iSubSessionCloseHandle;
+			iSubSessionCloseHandle = 0;
+			break;
+
+		case ETestEchoArgs:
+			{
+			TInt reply[4];
+			reply[0] = aMessage.Int0();
+			reply[1] = aMessage.Int1();
+			reply[2] = aMessage.Int2();
+			reply[3] = aMessage.Int3();
+			r = aMessage.Write(0,TPtrC8((TUint8*)&reply,sizeof(reply)));
+			}
+			break;
+
+		case ETestEmptySubSessionMessage:
+			r = aMessage.Int3();
+			break;
+
+		default:
+			break;
+		}
+	if(aMessage.Handle())
+		aMessage.Complete(r);
+	return;
+fail:
+	aMessage.Complete(KErrGeneral);
+	return;
+pass:
+	aMessage.Complete(KErrNone);
+	return;
+	}
+
+TInt CTestSession::CountResources()
+	{
+	return iResourceCount;
+	}
+
+void CTestSession::ServiceError(const RMessage2& aMessage,TInt aError)
+	{
+	if(aMessage!=iMessage) 
+		aError = KErrGeneral;   // We got given the right message
+	else
+		aError += KTestServiceErrorModifier;   // Let test harnes know we came through this routine
+	CSession2::ServiceError(aMessage,aError);
+	}
+
+//
+// CTestSecureServer
+//
+
+CTestSecureServer::CTestSecureServer(TInt aPriority)
+	: CServer2(aPriority,EGlobalSharableSessions)
+	{
+	}
+
+CSession2* CTestSecureServer::NewSessionL(const TVersion& aVersion, const RMessage2& /*aMessage*/) const
+	{
+	if(*(TInt*)&aVersion)
+		User::Leave(KErrNotSupported); // Only accept version 0.0.00
+	return new (ELeave) CTestSession();
+	}
+
+TInt CTestSecureServer::RunError(TInt aError)
+	{
+	return CServer2::RunError(aError+KTestRunErrorModifier);    // Let test harnes know we came through this routine
+	}
+
+
+//
+// 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
+//
+
+_LIT(KServerName,"T_SSERVER-server");
+const TInt KServerRendezvous = KRequestPending+1;
+
+void DoStartServer()
+	{
+	CTestActiveScheduler* activeScheduler = new (ELeave) CTestActiveScheduler;
+	CActiveScheduler::Install(activeScheduler);
+	CleanupStack::PushL(activeScheduler);
+
+	CTestSecureServer* server = new (ELeave) CTestSecureServer(0);
+	CleanupStack::PushL(server);
+
+	User::LeaveIfError(server->Start(KServerName));
+
+	RProcess::Rendezvous(KServerRendezvous);
+
+	CActiveScheduler::Start();
+
+	CleanupStack::PopAndDestroy(2);
+	}
+
+TInt StartServer()
+	{
+	CTrapCleanup* cleanupStack = CTrapCleanup::New();
+	if(!cleanupStack)
+		return KErrNoMemory;
+	TRAPD(leaveError,DoStartServer())
+	delete cleanupStack;
+	return leaveError;
+	}
+
+
+
+//
+// RTestSession
+//
+
+class RTestSession : public RSessionBase
+	{
+public:
+	inline TInt Connect()
+		{
+		TInt r=CreateSession(KServerName,TVersion());
+		if(r) return r;
+		return ShareAuto();
+		}
+	inline TInt Connect(const TSecurityPolicy* aPolicy)
+		{
+		return CreateSession(KServerName,TVersion(),-1,EIpcSession_Unsharable,aPolicy,0);
+		}
+	inline TInt Connect(TVersion aVersion,TRequestStatus* aStatus)
+		{
+		return CreateSession(KServerName,aVersion,-1,EIpcSession_Unsharable,0,aStatus);
+		}
+	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); }
+	};
+
+
+
+//
+// RTestSubSession
+//
+
+class RTestSubSession : public RSubSessionBase
+	{
+public:
+	inline TInt CreateSubSession(RSessionBase& aSession,TInt aFunction,const TIpcArgs& aArgs)
+		{ return RSubSessionBase::CreateSubSession(aSession,aFunction,aArgs); }
+	inline TInt CreateSubSession(RSessionBase& aSession,TInt aFunction)
+		{ return RSubSessionBase::CreateSubSession(aSession,aFunction); }
+	inline void CloseSubSession(TInt aFunction)
+		{ RSubSessionBase::CloseSubSession(aFunction); }
+	inline TInt Send(TInt aFunction)
+		{ return RSubSessionBase::SendReceive(aFunction); }
+	inline TInt Send(TInt aFunction,const TIpcArgs& aArgs)
+		{ return RSubSessionBase::SendReceive(aFunction,aArgs); }
+	inline void Send(TInt aFunction,TRequestStatus& aStatus)
+		{ RSubSessionBase::SendReceive(aFunction,aStatus); }
+	inline void Send(TInt aFunction,const TIpcArgs& aArgs,TRequestStatus& aStatus)
+		{ RSubSessionBase::SendReceive(aFunction,aArgs,aStatus); }
+	};
+
+
+
+RTestSession Session;
+TInt TestParam = 0;
+
+TInt TestThreadFunction(TAny* aParam)
+	{
+	return Session.Send((TInt)aParam,TIpcArgs(TestParam));
+	}
+
+void DoTest(TInt aFunction,TExitType aExitType,TInt aExitReason,TInt aParam=0)
+	{
+	TBuf<256> title;
+	title.AppendFormat(_L("Function %d"),aFunction);
+	test.Next(title);
+
+	RTestThread thread;
+	thread.Create(TestThreadFunction,(TAny*)aFunction);
+	TRequestStatus logon;
+	thread.Logon(logon);
+	TestParam = aParam;
+
+	User::SetJustInTime(EFalse);
+	thread.Resume();
+	User::WaitForRequest(logon);
+	User::SetJustInTime(ETrue);
+
+	TExitType exitType=thread.ExitType();
+	TInt exitReason=thread.ExitReason();
+	test(exitType==aExitType);
+	test(exitReason==aExitReason);
+	CLOSE_AND_WAIT(thread);
+	}
+
+//
+// Anonymous server
+//
+
+class RTestAnonymousSession : public RTestSession
+	{
+public:
+	inline TInt Connect(RServer2 aServer)
+		{
+		TInt r=CreateSession(aServer,TVersion());
+		if(r) return r;
+		return ShareProtected();
+		}
+	inline TInt Connect()
+		{
+		return CreateSession(_L(""),TVersion());
+		}
+	};
+
+CTestSecureServer* AnonymousServer;
+
+void DoStartAnonymousServer()
+	{
+	CTestActiveScheduler* activeScheduler = new (ELeave) CTestActiveScheduler;
+	CActiveScheduler::Install(activeScheduler);
+	CleanupStack::PushL(activeScheduler);
+
+	CTestSecureServer* server = new (ELeave) CTestSecureServer(0);
+	CleanupStack::PushL(server);
+
+	User::LeaveIfError(server->Start(KNullDesC));
+
+	AnonymousServer = server;
+	RThread::Rendezvous(KServerRendezvous);
+
+	CActiveScheduler::Start();
+
+	CleanupStack::PopAndDestroy(2);
+	}
+
+TInt StartAnonymousServer(TAny* /*aPtr*/)
+	{
+	CTrapCleanup* cleanupStack = CTrapCleanup::New();
+	if(!cleanupStack)
+		return KErrNoMemory;
+	TRAPD(leaveError,DoStartAnonymousServer())
+	delete cleanupStack;
+	return leaveError;
+	}
+
+void TestConnectByHandle()
+	{
+	RTestAnonymousSession session;
+	TRequestStatus logon;
+	TInt r;
+
+	test.Start(_L("Starting a local server"));
+	RTestThread thread;
+	thread.Create(StartAnonymousServer);
+	TRequestStatus rendezvous;
+	TRequestStatus svrstat;
+	thread.Rendezvous(rendezvous);
+	thread.Logon(logon);
+	thread.NotifyDestruction(svrstat);
+	thread.Resume();
+	User::WaitForRequest(rendezvous);
+	test(rendezvous.Int()==KServerRendezvous);
+	thread.Close();
+
+	test.Next(_L("Check connect with null name fails"));
+	test((r=session.Connect())!=KErrNone);
+
+	test.Next(_L("Connecting to local server"));
+	test((r=session.Connect(AnonymousServer->Server()))==KErrNone);
+
+	test.Next(_L("Test the connection"));
+	test((r=session.Send(EPing,TIpcArgs(1234)))==1234);
+	test((r=session.Send(EPing,TIpcArgs(2345)))==2345);
+
+	test.Next(_L("Shutting server down"));
+	test(logon.Int()==KRequestPending);
+	test((r=session.Send(ETestShutdown))==KErrServerTerminated);
+	test(r==KErrServerTerminated);
+	session.Close();
+	User::WaitForRequest(logon);
+	test(logon.Int()==KErrNone);
+	User::WaitForRequest(svrstat);
+
+	test.End();
+	}
+
+TRequestStatus SvrStat;
+
+void RestartTestServer()
+	{
+	RTestProcess server;
+	TRequestStatus rendezvous;
+	server.Create(0,ETestProcessServer);
+	server.NotifyDestruction(SvrStat);
+	server.Rendezvous(rendezvous);
+	server.Resume();
+	User::WaitForRequest(rendezvous);
+	test(rendezvous==KServerRendezvous);
+	server.Close();
+	test(Session.Connect()==KErrNone);
+	}
+
+void TestIpc()
+	{
+	TBuf8<10> buf8((TUint8*)"abcdefghij");
+	TBuf16<10> buf16((TUint16*)L"abcdefghij");
+	TInt r;
+
+	test.Start(_L("Testing TIpcArgs::Set"));
+	{
+	TIpcArgs a(TIpcArgs::ENothing,123,(TAny*)&buf8);
+	TIpcArgs b;
+	b.Set(0,TIpcArgs::ENothing);
+	b.Set(1,123);
+	b.Set(2,(TAny*)&buf8);
+	test(a.iFlags==b.iFlags);
+	// iArgs[0] is uninitialised so don't test
+	test(a.iArgs[1]==b.iArgs[1]);
+	test(a.iArgs[2]==b.iArgs[2]);
+	}
+	{
+	TIpcArgs a((TDesC8*)&buf8,(TDesC16*)&buf16,&buf8,&buf16);
+	TIpcArgs b;
+	b.Set(0,(TDesC8*)&buf8);
+	b.Set(1,(TDesC16*)&buf16);
+	b.Set(2,&buf8);
+	b.Set(3,&buf16);
+	test(a.iFlags==b.iFlags);
+	test(a.iArgs[0]==b.iArgs[0]);
+	test(a.iArgs[1]==b.iArgs[1]);
+	test(a.iArgs[2]==b.iArgs[2]);
+	test(a.iArgs[3]==b.iArgs[3]);
+	}
+
+	test.Next(_L("Test Unspecified argument"));
+	r = Session.Send(ETestArgUnspecified,TIpcArgs((TAny*)&buf8));
+	test(r==KErrNone);
+	r = Session.Send(ETestArgUnspecified+(1<<28),TIpcArgs(0,(TAny*)&buf8));
+	test(r==KErrNone);
+	r = Session.Send(ETestArgUnspecified+(2<<28),TIpcArgs(0,0,(TAny*)&buf8));
+	test(r==KErrNone);
+	r = Session.Send(ETestArgUnspecified+(3<<28),TIpcArgs(0,0,0,(TAny*)&buf8));
+	test(r==KErrNone);
+
+	test.Next(_L("Test DesC8 argument"));
+	r = Session.Send(ETestArgDesC8,TIpcArgs((TDesC8*)&buf8));
+	test(r==KErrNone);
+	r = Session.Send(ETestArgDesC8+(1<<28),TIpcArgs(0,(TDesC8*)&buf8));
+	test(r==KErrNone);
+	r = Session.Send(ETestArgDesC8+(2<<28),TIpcArgs(0,0,(TDesC8*)&buf8));
+	test(r==KErrNone);
+	r = Session.Send(ETestArgDesC8+(3<<28),TIpcArgs(0,0,0,(TDesC8*)&buf8));
+	test(r==KErrNone);
+
+	test.Next(_L("Test DesC16 argument"));
+	r = Session.Send(ETestArgDesC16,TIpcArgs((TDesC16*)&buf16));
+	test(r==KErrNone);
+	r = Session.Send(ETestArgDesC16+(1<<28),TIpcArgs(0,(TDesC16*)&buf16));
+	test(r==KErrNone);
+	r = Session.Send(ETestArgDesC16+(2<<28),TIpcArgs(0,0,(TDesC16*)&buf16));
+	test(r==KErrNone);
+	r = Session.Send(ETestArgDesC16+(3<<28),TIpcArgs(0,0,0,(TDesC16*)&buf16));
+	test(r==KErrNone);
+
+	test.Next(_L("Test Des8 argument"));
+	r = Session.Send(ETestArgDes8,TIpcArgs(&buf8));
+	test(r==KErrNone);
+	r = Session.Send(ETestArgDes8+(1<<28),TIpcArgs(0,&buf8));
+	test(r==KErrNone);
+	r = Session.Send(ETestArgDes8+(2<<28),TIpcArgs(0,0,&buf8));
+	test(r==KErrNone);
+	r = Session.Send(ETestArgDes8+(3<<28),TIpcArgs(0,0,0,&buf8));
+	test(r==KErrNone);
+
+	test.Next(_L("Test Des16 argument"));
+	r = Session.Send(ETestArgDes16,TIpcArgs(&buf16));
+	test(r==KErrNone);
+	r = Session.Send(ETestArgDes16+(1<<28),TIpcArgs(0,&buf16));
+	test(r==KErrNone);
+	r = Session.Send(ETestArgDes16+(2<<28),TIpcArgs(0,0,&buf16));
+	test(r==KErrNone);
+	r = Session.Send(ETestArgDes16+(3<<28),TIpcArgs(0,0,0,&buf16));
+	test(r==KErrNone);
+
+
+	test.Next(_L("Test Bad Client Descriptor"));
+	//The test should ensure that both server and kernel are safe if client passes faulty descriptor to the server.
+	{
+	//Create a chunk with a hole between addresses 0x1000 & 0x2000
+	RChunk c;
+	r=c.CreateDisconnectedLocal(0,0,0x200000);
+	test(r==KErrNone);
+	r=c.Commit(0,0x1000);
+	test(r==KErrNone);
+	r=c.Commit(0x2000,0x1000);
+	test(r==KErrNone);
+
+	//Each of these steps will pass bad descriptor to the server for IPC transfer in both directions.
+	//KErrBadDescriptor should be returned.
+	{
+	TPtr8 ptr (c.Base()+0x1000,0x100,0x100);
+	r = Session.Send(ETestBadClientDescRead,TIpcArgs(&ptr));
+	test(KErrBadDescriptor == r);
+	r = Session.Send(ETestBadClientDescWrite,TIpcArgs(&ptr));
+	test(KErrBadDescriptor == r);
+	}
+	{
+	TPtr8 ptr (c.Base()+0x1003,0x100,0x100);
+	r = Session.Send(ETestBadClientDescRead,TIpcArgs(&ptr));
+	test(KErrBadDescriptor == r);
+	r = Session.Send(ETestBadClientDescWrite,TIpcArgs(&ptr));
+	test(KErrBadDescriptor == r);
+	}
+	{
+	TPtr8 ptr (c.Base()+0xe00,0x500,0x500);
+	r = Session.Send(ETestBadClientDescRead,TIpcArgs(&ptr));
+	test(KErrBadDescriptor == r);
+	r = Session.Send(ETestBadClientDescWrite,TIpcArgs(&ptr));
+	test(KErrBadDescriptor == r);
+	}
+	{
+	TPtr8 ptr (c.Base()+0xdff,0x500,0x500);
+	r = Session.Send(ETestBadClientDescRead,TIpcArgs(&ptr));
+	test(KErrBadDescriptor == r);
+	r = Session.Send(ETestBadClientDescWrite,TIpcArgs(&ptr));
+	test(KErrBadDescriptor == r);
+	}
+	{
+	TPtr8 ptr (c.Base()+0x1ff1,0x500,0x500);
+	r = Session.Send(ETestBadClientDescRead,TIpcArgs(&ptr));
+	test(KErrBadDescriptor == r);
+	r = Session.Send(ETestBadClientDescWrite,TIpcArgs(&ptr));
+	test(KErrBadDescriptor == r);
+	}
+
+	//The next step will send random descriptors for IPC transfer. Server should return either KErrNone or
+	//KErrBadDescriptor
+	{	
+	TUint seed[2];
+	seed[0]=User::TickCount();
+	seed[1]=0;
+	test.Printf(_L("The initial seed for the random function is:  S0=%xh S1=%xh\n"), seed[0], seed[1]);
+
+	TInt i;
+	TPtr8 ptr (0,0,0);
+	TInt noErrors = 0;
+	TInt badDescriptors = 0;
+
+	for (i=0;i<100;i++)
+		{
+		TInt descAddress = (TInt) (c.Base() + (Random(seed) % 0x1000));
+		TInt descSize=Random(seed)%0x1000;
+
+		TUint* descData = (TUint*)&ptr;
+		descData[0] = 0x20000000 + descSize;
+		descData[1] = descSize;
+		descData[2] = descAddress;
+
+		r = Session.Send(ETestBadClientDescRead,TIpcArgs(&ptr));
+		switch (r)
+			{
+			case KErrNone:			noErrors++;break;
+			case KErrBadDescriptor: badDescriptors++;break;
+			default:				test.Printf(_L("Error: %d returned"),r);
+			}
+
+		r = Session.Send(ETestBadClientDescWrite,TIpcArgs(&ptr));
+		switch (r)
+			{
+			case KErrNone:			noErrors++;break;
+			case KErrBadDescriptor: badDescriptors++;break;
+			default:				test.Printf(_L("Error: %d returned"),r);
+			}
+		}
+	test.Printf(_L("KErrNoError: %d  KErrBadDescriptor: %d"),noErrors, badDescriptors);
+	}
+
+	test.Next(_L("Test Bad Server Descriptor"));
+	//The test should ensure that kernel is safe if server passes faulty descriptor for IPC transfer
+	{
+	TPtr8 ptr (c.Base(),0x1000,0x1000);
+	TInt i;
+	for (i=0;i<=7;i++)
+		{
+		r = Session.Send(ETestBadServerDescRead | (i<<28),TIpcArgs(&ptr));
+		test(r==KErrServerTerminated);
+		RestartTestServer();
+		r = Session.Send(ETestBadServerDescWrite | (i<<28),TIpcArgs(&ptr));
+		test(r==KErrServerTerminated);
+		User::WaitForRequest(SvrStat);
+		RestartTestServer();
+		}
+	}
+
+	c.Close();
+	}
+	test.End();
+	}
+
+
+
+void TestSubSessions()
+	{
+	const TInt KSubSessionHandle = 0x87654321;
+	RTestSubSession sub;
+	TInt r;
+
+	test.Start(_L("Creating a subsession with no arguments"));
+	r = sub.CreateSubSession(Session,ETestCreateSubSession);	
+	test(r==KErrNone);
+	test(((TInt*)&sub)[0] == (*(TInt*)&Session | CObjectIx::ENoClose));  // check sub.iSession
+
+	test.Next(_L("Creating a subsession with arguments"));
+	r = sub.CreateSubSession(Session,ETestCreateSubSession,TIpcArgs(KSubSessionHandle));	
+	test(r==KErrNone);
+	test(((TInt*)&sub)[0] == (*(TInt*)&Session | CObjectIx::ENoClose));  // check sub.iSession
+
+	test(((TInt*)&sub)[1]==KSubSessionHandle);   // check sub.iSubSessionHandle
+
+	test.Next(_L("Sending message with arguments"));
+	TInt reply[4] = {0};
+	TPtr8 replyDes((TUint8*)&reply,sizeof(reply));
+	r = sub.Send(ETestEchoArgs,TIpcArgs(&replyDes,123,456,789));
+	test(r==KErrNone);
+	test(reply[0]==(TInt)&replyDes);
+	test(reply[1]==123);
+	test(reply[2]==456);
+	test(reply[3]==KSubSessionHandle);
+
+	test.Next(_L("Sending empty message"));
+	r = sub.Send(ETestEmptySubSessionMessage);
+	test(r==KSubSessionHandle);
+
+	test.Next(_L("Closing subsession"));
+	sub.CloseSubSession(ETestCloseSubSession);	
+	test(((TInt*)&sub)[0]==0);  // check sub.iSession
+	test(((TInt*)&sub)[1]==0);   // check sub.iSubSessionHandle
+	r = Session.Send(ETestCloseSubSessionHandle);
+	test(r==KSubSessionHandle);
+
+	test.End();
+	}
+
+
+void TestProtectedServers()
+	{
+	RTestProcess process;
+	TRequestStatus logonStatus;
+	
+	test.Start(_L("Trying to create a protected server without KCapabilityProtServ"));
+	process.Create(~(1u<<ECapabilityProtServ),ETestProcessCreateProtectedServer);
+	process.Logon(logonStatus);
+	process.Resume();
+	User::WaitForRequest(logonStatus);
+	if(PlatSec::IsCapabilityEnforced(ECapabilityProtServ))
+		{
+		test(process.ExitType()==EExitPanic); // Process should have got a Platform Security panic
+		test(logonStatus==EPlatformSecurityTrap);
+		}
+	else
+		{
+		test(process.ExitType()==EExitKill);
+		test(logonStatus==KErrNone);
+		}
+	CLOSE_AND_WAIT(process);
+
+	test.Next(_L("Trying to create a protected server with KCapabilityProtServ"));
+	process.Create(1<<ECapabilityProtServ,ETestProcessCreateProtectedServer);
+	process.Logon(logonStatus);
+	process.Resume();
+	User::WaitForRequest(logonStatus);
+	test(process.ExitType()==EExitKill);
+	test(logonStatus==KErrNone);
+	CLOSE_AND_WAIT(process);
+
+	test.End();
+	}
+
+
+void TestIdentifiedServers()
+	{
+	RTestSession session;
+	TInt r;
+	
+	test.Start(_L("Trying to connect to a server with wrong Secure ID"));
+	_LIT_SECURITY_POLICY_S0(wrongSid,KTestSecureId2);
+	r=session.Connect(&wrongSid);
+	test(r==(PlatSec::ConfigSetting(PlatSec::EPlatSecEnforcement)?KErrPermissionDenied:KErrNone));
+	session.Close();
+
+	test.Next(_L("Test connecting to a server with correct Secure ID"));
+	_LIT_SECURITY_POLICY_S0(correctSid,KTestSecureId);
+	r=session.Connect(&correctSid);
+	test(r==KErrNone);
+	session.Close();
+
+	test.Next(_L("Trying to connect to a server with wrong Vendor ID"));
+	_LIT_SECURITY_POLICY_V0(wrongVid,KTestVendorId2);
+	r=session.Connect(&wrongVid);
+	test(r==(PlatSec::ConfigSetting(PlatSec::EPlatSecEnforcement)?KErrPermissionDenied:KErrNone));
+	session.Close();
+
+	test.Next(_L("Test connecting to a server with correct Vendor ID"));
+	_LIT_SECURITY_POLICY_V0(correctVid,KTestVendorId);
+	r=session.Connect(&correctVid);
+	test(r==KErrNone);
+	session.Close();
+
+	test.Next(_L("Trying to connect to a server with wrong capabilities"));
+	_LIT_SECURITY_POLICY_C1(wrongCaps,ECapabilityReadUserData);
+	r=session.Connect(&wrongCaps);
+	test(r==(PlatSec::IsCapabilityEnforced(ECapabilityReadUserData)?KErrPermissionDenied:KErrNone));
+	session.Close();
+
+	test.Next(_L("Test connecting to a server with correct capabilities"));
+	_LIT_SECURITY_POLICY_C1(correctCaps,ECapability_None);
+	r=session.Connect(&correctCaps);
+	test(r==KErrNone);
+	session.Close();
+
+	test.Next(_L("Test connecting to a server without specifying a policy"));
+	r=session.Connect(0);
+	test(r==KErrNone);
+	session.Close();
+
+	test.End();
+	}
+
+
+
+#include <e32panic.h>
+
+TInt TestThreadAsyncConnect(TAny*)
+	{
+	RTestSession session;
+	TRequestStatus status;
+	TInt r=session.Connect(TVersion(1,1,1),&status);
+	if(r!=KErrNone)
+		return r;
+	if(status!=KRequestPending)   // server can't have created session yet because we have higher priority
+		return status.Int();
+	User::WaitForRequest(status);
+	if(status!=KErrNotSupported)
+		return status.Int();
+	return session.Send(EPing,TIpcArgs(1234));   // Should panic us
+	}
+
+void TestAsynchronousConnect()
+	{
+	RTestSession session;
+	TRequestStatus status;
+	TInt r;
+	
+	test.Start(_L("Test successful asynchronous connect"));
+	r=session.Connect(TVersion(0,0,0),&status);
+	test(r==KErrNone);
+	test(status==KRequestPending);   // server can't have created session yet because we have higher priority
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+	test((r=session.Send(EPing,TIpcArgs(1234)))==1234);
+	session.Close();
+
+	test.Next(_L("Test unsuccessful asynchronous connect"));
+	r=session.Connect(TVersion(1,1,1),&status);
+	test(r==KErrNone);
+	test(status==KRequestPending);   // server can't have created session yet because we have higher priority
+	User::WaitForRequest(status);
+	test(status==KErrNotSupported);
+	session.Close();
+
+	test.Next(_L("Test using unsuccessful asynchronous connect"));
+	RTestThread thread;
+	thread.Create(TestThreadAsyncConnect,0);
+	TRequestStatus logon;
+	thread.Logon(logon);
+	User::SetJustInTime(EFalse);
+	thread.Resume();
+	User::WaitForRequest(logon);
+	User::SetJustInTime(ETrue);
+	TExitType exitType=thread.ExitType();
+	TInt exitReason=thread.ExitReason();
+	test(exitType==EExitPanic);
+	test(exitReason==CServer2::ESessionNotConnected);
+	thread.Close();
+
+	test.End();
+	}
+
+
+
+TInt DoTestProcess(TInt aTestNum,TInt aArg1,TInt aArg2)
+	{
+	(void)aArg1;
+	(void)aArg2;
+	switch(aTestNum)
+		{
+
+	case ETestProcessServer:
+		RProcess().SetPriority(EPriorityLow);
+		return StartServer();
+
+	case ETestProcessCreateProtectedServer:
+		{
+		test.Title();
+		RServer2 server;
+		TInt r = server.CreateGlobal(KProtectedServerName);
+		server.Close();
+		return r;
+		}
+
+	default:
+		User::Panic(_L("T_SSERVER"),1);
+		}
+
+	return KErrNone;
+	}
+
+
+
+GLDEF_C TInt E32Main()
+    {
+	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);
+		}
+
+	TInt r;
+
+	test.Title();
+
+	test.Start(_L("Testing Server Connect by Handle"));
+	TestConnectByHandle();
+
+	test.Next(_L("Starting test server"));
+	RTestProcess server;
+	TRequestStatus rendezvous;
+	server.Create(0,ETestProcessServer);
+	server.Rendezvous(rendezvous);
+	server.Resume();
+	User::WaitForRequest(rendezvous);
+	test(rendezvous==KServerRendezvous);
+	server.Close();
+
+	test.Next(_L("Conecting to test server"));
+	test((r=Session.Connect())==KErrNone);
+
+	test.Next(_L("Test asynchronous server connect"));
+	TestAsynchronousConnect();
+
+	test.Next(_L("Test protected servers"));
+	TestProtectedServers();
+
+	test.Next(_L("Test connecting to identified servers"));
+	TestIdentifiedServers();
+
+	test.Next(_L("Testing SubSessions"));
+	TestSubSessions();
+
+	test.Next(_L("Testing IPC argument checking"));
+	TestIpc();
+
+	test.Next(_L("Testing CServer2::RunError and CSession2::ServiceError()"));
+	const TInt KTestServiceLeaveValue = 555;
+	r = Session.Send(ETestServiceLeave,TIpcArgs(KTestServiceLeaveValue));
+	test(r==KTestServiceLeaveValue+KTestRunErrorModifier+KTestServiceErrorModifier);
+
+	test.Next(_L("Testing session resource counting"));
+	test.Start(_L(""));
+	DoTest(ETestResourceCountPass,EExitKill,ETestResourceCountPass);
+	DoTest(ETestResourceCountFail,EExitPanic,CSession2::ESesFoundResCountHeaven);
+	test.End();
+
+	test.Next(_L("Shutting server down"));
+	{
+	Session.Send(ETestShutdown,TIpcArgs());
+	Session.Close();
+	}
+	User::WaitForRequest(SvrStat);
+
+	test.End();
+	return(0);
+    }
+