kerneltest/e32test/secure/t_sserver.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 137 8aab599e3476
parent 0 a41df078684a
child 271 dc268b18d709
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// 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);
    }