applayerpluginsandutils/bookmarksupport/test/cenrepsrv/srvsess.cpp
changeset 0 b16258d2340f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/applayerpluginsandutils/bookmarksupport/test/cenrepsrv/srvsess.cpp	Tue Feb 02 01:09:52 2010 +0200
@@ -0,0 +1,1099 @@
+// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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:
+//
+
+#include "panic.h"
+#include "sessnotf.h"
+#include "srvreqs.h"
+#include "srvsess.h"
+#include "cachemgr.h"
+#include <centralrepository.h>
+
+#include "backup.h"
+
+using namespace NCentralRepositoryConstants;
+
+#ifdef __CENTREP_SERVER_PERFTEST__
+// Function EncodeEventAndData
+// Put event Id in upper 8 bit and data in lower 24 bit.
+inline
+TUint32 EncodeEventAndData(TUint aEventId, TUint32 aData)
+	{
+	return ((aEventId & KEventIdMask) << KEventIdShiftBits) |
+		   (aData & KDataMask);
+	}
+#endif //__CENTREP_SERVER_PERFTEST__
+
+inline CSessionManager& CServerSession::Server()
+	{return *static_cast<CSessionManager*>(const_cast<CServer2*>(CSession2::Server()));}
+
+CServerSession::~CServerSession()
+	{
+	iFindResult.Close();
+
+#ifdef __CENTREP_SERVER_PERFTEST__
+	DoEventStart();
+#endif
+
+	iRepository.Close(iNotifier);
+
+#ifdef __CENTREP_SERVER_PERFTEST__
+	if (iInitialised)
+		{
+		DoEventEnd(ESessionClose);
+		}
+#endif
+	}
+
+// if ServiceL Leaves, execution resumes in this method.
+// this allows us to panic clients using bad descriptors, to deal with OOM conditions
+// and to fail transactions with the correct reason: OOM etc.
+void CServerSession::ServiceError(const RMessage2 &aMessage, TInt aError)
+	{
+	// ensure any transaction is failed for the reason aError
+	iRepository.FailTransaction(aError, KUnspecifiedKey);
+	CSession2::ServiceError(aMessage, aError);
+	}
+
+void CServerSession::ServiceL(const RMessage2& aMessage)
+	{
+	const TClientRequest msg(aMessage);
+	
+	struct SAction
+		{
+		TServerRequest req;
+		TInt (CServerSession::*groupFuncL)(const TClientRequest&, TServerFunc);
+		TServerFunc funcL;
+		};
+		
+	static const SAction actionTable[] =
+		{
+			{EInitialise,				&CServerSession::GeneralOperationsL,	&CServerSession::InitialiseL},
+			{ECreateInt,				&CServerSession::WriteOperationsL,		&CServerSession::CreateIntL},
+			{ECreateReal,				&CServerSession::WriteOperationsL,		&CServerSession::CreateRealL},
+			{ECreateString,				&CServerSession::WriteOperationsL,		&CServerSession::CreateStringL},
+			{EDelete,					&CServerSession::WriteOperationsL,		&CServerSession::DeleteL},
+			{EGetInt,					&CServerSession::ReadOperationsL,		&CServerSession::GetIntL},
+			{ESetInt,					&CServerSession::WriteOperationsL,		&CServerSession::SetIntL},
+			{EGetReal,					&CServerSession::ReadOperationsL,		&CServerSession::GetRealL},
+			{ESetReal,					&CServerSession::WriteOperationsL,		&CServerSession::SetRealL},
+			{EGetString,				&CServerSession::ReadOperationsL,		&CServerSession::GetStringL},
+			{ESetString,				&CServerSession::WriteOperationsL,		&CServerSession::SetStringL},
+			{EFind,						&CServerSession::ReadOperationsL,		&CServerSession::FindL},
+			{EFindEqInt,				&CServerSession::ReadOperationsL,		&CServerSession::FindEqIntL},
+			{EFindEqReal,				&CServerSession::ReadOperationsL,		&CServerSession::FindEqRealL},
+			{EFindEqString,				&CServerSession::ReadOperationsL,		&CServerSession::FindEqStringL},
+			{EFindNeqInt,				&CServerSession::ReadOperationsL,		&CServerSession::FindNeqIntL},
+			{EFindNeqReal,				&CServerSession::ReadOperationsL,		&CServerSession::FindNeqRealL},
+			{EFindNeqString,			&CServerSession::ReadOperationsL,		&CServerSession::FindNeqStringL},
+			{EGetFindResult,			&CServerSession::ReadOperationsL,		&CServerSession::GetFindResultL},
+			{ENotifyRequestCheck,		&CServerSession::GeneralOperationsL,	&CServerSession::NotifyRequestCheck},
+			{ENotifyRequest,			&CServerSession::GeneralOperationsL,	&CServerSession::NotifyRequest},
+			{ENotifyCancel,				&CServerSession::GeneralOperationsL,	&CServerSession::NotifyCancel},
+			{ENotifyCancelAll,			&CServerSession::GeneralOperationsL,	&CServerSession::NotifyCancelAll},
+			{EGroupNotifyRequest,		&CServerSession::GeneralOperationsL,	&CServerSession::GroupNotifyRequest},
+			{EGroupNotifyCancel,		&CServerSession::GeneralOperationsL,	&CServerSession::GroupNotifyCancel},
+			{EReset,					&CServerSession::ResetOperationsL,		&CServerSession::ResetL},
+			{EResetAll,					&CServerSession::ResetOperationsL,		&CServerSession::ResetAllL},
+			{ETransactionStart,			&CServerSession::GeneralOperationsL,	&CServerSession::TransactionStart},
+  			{ETransactionCommit,		&CServerSession::GeneralOperationsL,	&CServerSession::TransactionCommitL},
+  			{ETransactionCancel,		&CServerSession::GeneralOperationsL,	&CServerSession::TransactionCancel},
+			{EMove,						&CServerSession::WriteOperationsL,		&CServerSession::MoveL},
+			{ETransactionState,			&CServerSession::GeneralOperationsL,	&CServerSession::TransactionStateL},
+			{ETransactionFail,			&CServerSession::GeneralOperationsL,	&CServerSession::TransactionFail},
+			{EDeleteRange,				&CServerSession::WriteOperationsL,		&CServerSession::DeleteRangeL}
+		};
+	 
+	TInt r;
+	TServerRequest fn = static_cast<TServerRequest>(aMessage.Function());
+
+#if defined(__CENTREP_SERVER_PERFTEST__) || defined(__CENTREP_SERVER_MEMTEST__) || defined(__CENTREP_SERVER_CACHETEST__)
+	if (fn == EGetSetParameters)
+		{
+		r = GetSetParameters(msg);
+		aMessage.Complete(r);
+		return;
+		}
+#endif
+#ifdef __CENTREP_SERVER_PERFTEST__
+    DoEventStart();
+	if (EInitialise == fn)
+		{
+		iRepositoryUid = aMessage.Int0();
+		}
+#endif
+
+	__ASSERT_ALWAYS(iInitialised || fn==EInitialise,
+		PanicClient(ESessionNotInitialised, msg));
+
+	if(fn>ELastInTable)
+		{
+		r = KErrNotSupported; // or panic client??
+		}
+	else
+		{
+		iRepository.RestoreConsistencyL();
+		// plus need to check we are initialised
+		r = (this->*actionTable[fn].groupFuncL)(aMessage, actionTable[fn].funcL);
+		}
+			
+#ifdef __CENTREP_SERVER_PERFTEST__
+	DoEventEnd(fn);
+#endif
+
+	if (r != KDontComplete)
+		{
+		aMessage.Complete(r);
+		}
+	}
+
+//method allows transactions and notify requests to get through during backup/restore
+//process to prevent them from being blocked.
+//Transactions being blocked would lead clients to be panicked
+//if they were trying to open a second transaction in the same session. 
+// Notify cancels must be allowed through because they must always succeed.
+TInt CServerSession::GeneralOperationsL(const TClientRequest& aMessage, TServerFunc aFuncL)
+	{
+	ASSERT(aFuncL != NULL);
+	return (this->*aFuncL)(aMessage);
+	}
+
+// method allows read operations to share transaction-related tasks.
+// Read operations are allowed only during backup process. 
+// During restore it fails transactions with KErrLocked and returns KErrAbort
+// and if it is a standalone read oparation it rejects it with KErrServerBusy.
+TInt CServerSession::ReadOperationsL(const TClientRequest& aMessage, TServerFunc aFuncL)
+	{
+	TInt backupStatus = CRepositoryBackupClient::GetBackupStatus();
+		
+	if (iRepository.IsInFailedTransaction())
+		{
+		return KErrAbort;
+		}
+	else if (iRepository.IsInTransaction() && (backupStatus == ERestoreInProgress) )
+	    {
+	    iRepository.FailTransaction(KErrLocked,KUnspecifiedKey);
+	    return KErrAbort;
+	    }
+	else if (backupStatus == ERestoreInProgress)
+	    {
+	    return KErrServerBusy;
+	    }
+
+	ASSERT(aFuncL != NULL);
+	return (this->*aFuncL)(aMessage);
+	}
+
+// method allows write operations to share transaction-related tasks
+// All write operations are not allowed either during backup or restore process.
+// If backup or restore is in progress it fails transaction with KErrLocked, 
+// returns KErrAbort or if it is a standalone operation it returns KErrServerBusy. 
+TInt CServerSession::WriteOperationsL(const TClientRequest& aMessage, TServerFunc aFuncL)
+	{
+	TInt backupStatus = CRepositoryBackupClient::GetBackupStatus();
+	
+	if (iRepository.IsInFailedTransaction())
+		{
+		return KErrAbort;
+		}
+	else if (iRepository.IsInTransaction() && (backupStatus != ENoBackupActivty) )
+	    {
+	    iRepository.FailTransaction(KErrLocked,KUnspecifiedKey);
+	    return KErrAbort;
+	    }
+    else if (CRepositoryBackupClient::GetBackupStatus() != ENoBackupActivty)
+        {
+        return KErrServerBusy;
+        }
+    
+	// if not already in a transaction, create a temporary concurrent read/write transaction
+	const TBool tempTransaction = !iRepository.IsInTransaction();
+	if (tempTransaction)
+		{
+		// concurrent read/write transaction is guaranteed to start
+		iRepository.StartTransaction(EConcurrentReadWriteTransaction);
+		// to protect against Leaves:
+		iRepository.CleanupCancelTransactionPushL();
+		}
+	else
+		{
+		if (iRepository.IsInActiveReadTransaction())
+			{
+			// must be a read/write transaction to continue
+			iRepository.AttemptPromoteTransactionToReadWrite();
+			// Note we don't check the return value of the above and return it here.
+			// Instead we call the next level write function and expect it to have the
+			// following code:
+			//	if (iRepository.IsInActiveReadTransaction())
+			//		{
+			//		return iRepository.FailTransaction(KErrLocked, key);
+			//		}
+			// this ensures CommitTransaction reports the failing key. 
+			}
+		// Note ServiceError will fail the transaction if write operation leaves
+		}
+
+	// call the server function
+	ASSERT(aFuncL != NULL);
+	TInt result = (this->*aFuncL)(aMessage);
+	
+	// commit the temporary transaction
+	if (tempTransaction)
+		{
+		CleanupStack::Pop(); // remove cleanup item from earlier
+		// absorb result and keyInfo from commit of temporary transaction
+		TUint32 tempKeyInfo;
+		User::LeaveIfError(iRepository.CommitTransaction(tempKeyInfo));
+		}
+	return result;
+	}
+
+TInt CServerSession::ResetOperationsL(const TClientRequest& aMessage, TServerFunc aFuncL)
+	{
+	// reset operations are not currently supported in transactions
+	if (iRepository.IsInTransaction())
+		{
+		// fail transaction otherwise client may be misled to believe operation worked
+		return iRepository.FailTransaction(KErrNotSupported, KUnspecifiedKey);
+		}
+   //can't reset when backup or restore is in progress
+   else if (CRepositoryBackupClient::GetBackupStatus() != ENoBackupActivty)
+        {
+        return KErrServerBusy;
+        }		
+	ASSERT(aFuncL != NULL);
+	return (this->*aFuncL)(aMessage);
+	}
+
+TInt CServerSession::InitialiseL(const TClientRequest& aMessage)
+	{
+	__ASSERT_ALWAYS(!iInitialised,
+		PanicClient(ESessionAlreadyInitialised, aMessage));
+	// We let anyone to open a repository... 
+	// it's not considered a breach of security to let people know
+	// that a repository is there... 
+	TUid repositoryUid = TUid::Uid(aMessage.Int0());
+	iRepository.OpenL(repositoryUid, iNotifier);
+
+	iInitialised = ETrue;
+
+	return KErrNone;
+	}
+
+TInt CServerSession::CreateIntL(const TClientRequest& aMessage)
+	{
+	TUint32 key = aMessage.Int0();
+
+	// cannot make changes in a read transaction - upgrade must have failed due to write lock being used
+	if (iRepository.IsInActiveReadTransaction())
+		{
+		return iRepository.FailTransaction(KErrLocked, key);
+		}
+
+	if(KErrNone !=  CheckPolicy(aMessage,iRepository.GetWriteAccessPolicy(key),
+			__PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerSession::CreateIntL - Attempt made to create a setting")))
+		return iRepository.FailTransaction(KErrPermissionDenied, key);
+
+	TInt val = aMessage.Int1();
+		
+	TInt r = iRepository.TransactionCreateL(key, val, 0);
+
+	return r;
+	}
+
+TInt CServerSession::CreateRealL(const TClientRequest& aMessage)
+	{
+	TUint32 key = aMessage.Int0();
+
+	// cannot make changes in a read transaction - upgrade must have failed due to write lock being used
+	if (iRepository.IsInActiveReadTransaction())
+		{
+		return iRepository.FailTransaction(KErrLocked, key);
+		}
+
+	if(KErrNone != CheckPolicy(aMessage,iRepository.GetWriteAccessPolicy(key),
+			__PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerSession::CreateRealL - Attempt made to create a setting")))
+		return iRepository.FailTransaction(KErrPermissionDenied, key);
+
+	TReal val;
+	TPckg<TReal> p(val);
+	aMessage.ReadL(1, p);
+	
+	TInt r = iRepository.TransactionCreateL(key, val, 0);
+
+	return r;
+	}
+	
+TInt CServerSession::CreateStringL(const TClientRequest& aMessage)
+	{
+	TUint32 key = aMessage.Int0();
+
+	// cannot make changes in a read transaction - upgrade must have failed due to write lock being used
+	if (iRepository.IsInActiveReadTransaction())
+		{
+		return iRepository.FailTransaction(KErrLocked, key);
+		}
+
+	// sometime: must ensure bad descriptor results in client being panic'd
+
+	// check for descriptor-too-long was previously on the client side,
+	// hence test code expects KErrArgument response before KErrPermissionDenied
+	TInt length = aMessage.GetDesLengthL(1);
+	if (length > KMaxBinaryLength)
+		{
+		return iRepository.FailTransaction(KErrArgument, key);
+		}
+
+	if(KErrNone != CheckPolicy(aMessage,iRepository.GetWriteAccessPolicy(key),
+			__PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerSession::CreateStringL - Attempt made to create a setting")))
+		return iRepository.FailTransaction(KErrPermissionDenied, key);
+
+	TBuf8<KMaxBinaryLength> val;
+	aMessage.ReadL(1, val);
+	
+	TInt error = iRepository.TransactionCreateL(key, val, 0);
+
+	return error;
+	}
+
+TInt CServerSession::DeleteL(const TClientRequest& aMessage)
+	{
+	TUint32 key = aMessage.Int0();
+
+	// cannot make changes in a read transaction - upgrade must have failed due to write lock being used
+	if (iRepository.IsInActiveReadTransaction())
+		{
+		return iRepository.FailTransaction(KErrLocked, key);
+		}
+
+	if(KErrNone != CheckPolicy(aMessage,iRepository.GetWriteAccessPolicy(key),
+			__PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerSession::DeleteL - Attempt made to delete a setting")))
+		return iRepository.FailTransaction(KErrPermissionDenied, key);
+
+	TInt r = iRepository.TransactionDeleteL(key);
+
+	return r;
+	}
+
+TInt CServerSession::GetIntL(const TClientRequest& aMessage)
+	{
+	TUint32 key = aMessage.Int0();
+
+	if(KErrNone != CheckPolicy(aMessage,iRepository.GetReadAccessPolicy(key),
+				__PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerSession::GetIntL - Attempt made to read a setting")))
+		return KErrPermissionDenied;
+
+	TInt val;
+	TInt error = iRepository.Get(key, val);
+
+	if (error == KErrNone)
+		{
+		TPckg<TInt> p(val);
+		aMessage.WriteL(1, p);
+		}
+
+	return error;
+	}
+
+TInt CServerSession::SetIntL(const TClientRequest& aMessage)
+	{
+	TUint32 key = aMessage.Int0();
+
+	// cannot make changes in a read transaction - upgrade must have failed due to write lock being used
+	if (iRepository.IsInActiveReadTransaction())
+		{
+		return iRepository.FailTransaction(KErrLocked, key);
+		}
+	
+	if(KErrNone != CheckPolicy(aMessage,iRepository.GetWriteAccessPolicy(key),
+				__PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerSession::SetIntL - Attempt made to write a setting")))
+		return iRepository.FailTransaction(KErrPermissionDenied, key);
+	
+	TInt val = aMessage.Int1();
+	TInt error = iRepository.TransactionSetL(key, val);
+
+	return error;
+	}
+
+TInt CServerSession::GetRealL(const TClientRequest& aMessage)
+	{
+	TUint32 key = aMessage.Int0();
+
+	if(KErrNone != CheckPolicy(aMessage,iRepository.GetReadAccessPolicy(key),
+				__PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerSession::GetRealL - Attempt made to read a setting")))
+		return KErrPermissionDenied;
+	
+	TReal val;
+	TInt error = iRepository.Get(key, val);
+
+	if(error==KErrNone)
+		{
+		TPckg<TReal> p(val);
+		aMessage.WriteL(1, p);
+		}
+
+	return error;
+	}
+
+TInt CServerSession::SetRealL(const TClientRequest& aMessage)
+	{
+	TUint32 key = aMessage.Int0();
+
+	// cannot make changes in a read transaction - upgrade must have failed due to write lock being used
+	if (iRepository.IsInActiveReadTransaction())
+		{
+		return iRepository.FailTransaction(KErrLocked, key);
+		}
+	
+	if(KErrNone != CheckPolicy(aMessage,iRepository.GetWriteAccessPolicy(key),
+				__PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerSession::SetRealL - Attempt made to write a setting")))
+		return iRepository.FailTransaction(KErrPermissionDenied, key);
+
+	TReal val;
+	TPckg<TReal> p(val);
+	aMessage.ReadL(1, p);
+
+	TInt error = iRepository.TransactionSetL(key, val);
+
+	return error;
+	}
+
+TInt CServerSession::GetStringL(const TClientRequest& aMessage)
+	{
+	TUint32 key = aMessage.Int0();
+
+	if(KErrNone != CheckPolicy(aMessage,iRepository.GetReadAccessPolicy(key),
+				__PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerSession::GetStringL - Attempt made to read a setting")))
+		return KErrPermissionDenied;
+
+	TBuf8<KMaxBinaryLength> val;
+
+	TInt error = iRepository.Get(key, val);
+
+	if(error==KErrNone)
+		{
+		TInt clientMaxDescriptorLength;
+		TPckg<TInt> pInt (clientMaxDescriptorLength);
+		aMessage.Read(2, pInt);
+		
+		TInt descriptorLength = val.Length();
+		
+		// write the descriptor length to aMessage			
+		TPckg<TInt> p(descriptorLength);
+		error = aMessage.Write(2, p);
+		
+		if(error==KErrNone)
+			{
+			if(descriptorLength > clientMaxDescriptorLength)
+				{
+				// if it is, fill the descriptor up to its max length
+				error = aMessage.Write(1, val.Left(clientMaxDescriptorLength));
+
+				// if client-side descriptor is too small to take the value, which it is, returns KErrOverflow
+				if(error == KErrNone)
+					{
+					error = KErrOverflow;
+					}
+				}
+			else
+				{
+				error = aMessage.Write(1, val);
+				}
+			}
+			
+		// if error is KErrOverflow should not failing transaction
+		if ((error != KErrNone) && (error != KErrOverflow))
+			{
+			// ServiceError will fail transaction
+			User::Leave(error);
+			}
+		}
+	return error;
+	}
+
+TInt CServerSession::SetStringL(const TClientRequest& aMessage)
+	{
+	TUint32 key = aMessage.Int0();
+
+	// cannot make changes in a read transaction - upgrade must have failed due to write lock being used
+	if (iRepository.IsInActiveReadTransaction())
+		{
+		return iRepository.FailTransaction(KErrLocked, key);
+		}
+
+	// check for descriptor-too-long was previously on the client side,
+	// hence test code expects KErrArgument response before KErrPermissionDenied
+	TInt length = aMessage.GetDesLengthL(1);
+	if (length > KMaxBinaryLength)
+		{
+		return iRepository.FailTransaction(KErrArgument, key);
+		}
+	
+	if(KErrNone != CheckPolicy(aMessage,iRepository.GetWriteAccessPolicy(key),
+				__PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerSession::SetStringL - Attempt made to write a setting")))
+		return iRepository.FailTransaction(KErrPermissionDenied, key);
+
+	TBuf8<KMaxBinaryLength> val;
+	aMessage.ReadL(1, val);  // no error if too long, truncated instead
+
+	TInt error = iRepository.TransactionSetL(key, val);
+
+	return error;
+	}
+
+TInt CServerSession::FindL(const TClientRequest& aMessage)
+	{
+// PLATSEC NOTE:
+// There are no read policy checks on FindL.
+// Client is returned the full list of keys whether they have read permission or not.
+// They were able to find this out by brute force using FindL on single setting ranges
+// anyway (because it would return KErrPermissionDenied if it existed, KErrNotFound otherwise).
+// Revealing the existence of settings is not considered a breach of security.
+	TInt partialId = aMessage.Int0();
+	TInt idMask = aMessage.Int1();
+	// we reset results first since we do not police GetResult
+	// and this way we can guarantee no results are available if access not granted
+	iFindResult.Reset();
+	RSettingPointerArray settings;
+	CleanupClosePushL(settings);
+	TInt error = iRepository.FindSettings(partialId, idMask, settings);
+	
+	if(error == KErrNone)
+		{
+		const TInt numSettings = settings.Count();
+		
+		if (numSettings == 0)
+			{
+			error = KErrNotFound;
+			}
+		else
+			{
+			RArray<TUint32> settingsToSend;
+			CleanupClosePushL(settingsToSend);
+			const TInt numInitial = numSettings > KCentRepFindBufSize ? KCentRepFindBufSize : numSettings;
+			const TInt numFinal = numSettings > KCentRepFindBufSize ? numSettings - KCentRepFindBufSize : 0;
+			
+			//reserve memory for everything that needs to be added to the array
+			settingsToSend.Reserve(numSettings + 1);
+			
+			//first append the number of found settings
+			settingsToSend.AppendL(numSettings);
+			
+			//now append up to KCentRepFindBufSize settings
+			for(TInt i = 0; i < numInitial; i++)
+				{
+				ASSERT(settings[i]);
+				// all settings flagged as deleted should have been removed by now, but just to be safe:
+				ASSERT(!settings[i]->IsDeleted());
+				settingsToSend.AppendL(settings[i]->Key());
+				}
+				
+			//fill the iFindResult array with any remaining settings that we were not able to send
+			//with the first ipc
+			if(numFinal)
+				{
+				for(TInt i = numInitial; i < numSettings; i++)
+					{
+					ASSERT(settings[i]);
+					// all settings flagged as deleted should have been removed by now, but just to be safe:
+					ASSERT(!settings[i]->IsDeleted());
+					iFindResult.AppendL(settings[i]->Key());
+					}
+				}
+				
+			//send:
+			//1 - the count of total settings found
+			//2 - the settings that fit in the buffer allocated for the first IPC 
+			TPtrC8 p(reinterpret_cast<TUint8*>(&(settingsToSend[0])), (numInitial+1)*sizeof(TUint32));
+			error = aMessage.Write(3, p);
+			CleanupStack::PopAndDestroy(); //settingsToSend
+			}
+		}
+	
+	if(error != KErrNone)
+		{
+		iFindResult.Reset();
+		if ((error != KErrNone) && (error != KErrNotFound))
+			{
+			CleanupStack::PopAndDestroy(); //settings
+			// ServiceError will fail transaction
+			User::Leave(error);
+			}
+		}
+	CleanupStack::PopAndDestroy(); //settings
+	return error;
+	}
+
+TInt CServerSession::FindEqIntL(const TClientRequest& aMessage)
+	{
+	TInt val = aMessage.Int2();
+	// PlatSec check done in FindValueL
+	return FindValueL(aMessage, val);
+	}
+
+TInt CServerSession::FindEqRealL(const TClientRequest& aMessage)
+	{
+	TReal val;
+	TPckg<TReal> p(val);
+	aMessage.Read(2, p);
+	// PlatSec check done in FindValueL
+	return FindValueL(aMessage, val);
+	}
+
+TInt CServerSession::FindEqStringL(const TClientRequest& aMessage)
+	{
+	TBuf8<KMaxBinaryLength> val;
+	aMessage.ReadL(2, val);  // no error if too long, truncated instead
+	// PlatSec check done in FindValueL
+	return FindValueL(aMessage, val);
+	}
+
+TInt CServerSession::FindNeqIntL(const TClientRequest& aMessage)
+	{
+	TInt val = aMessage.Int2();
+	// PlatSec check done in FindValueL
+	return FindValueL(aMessage, val, ENotEqual);
+	}
+
+TInt CServerSession::FindNeqRealL(const TClientRequest& aMessage)
+	{
+	TReal val;
+	TPckg<TReal> p(val);
+	aMessage.Read(2, p);
+	// PlatSec check done in FindValueL
+	return FindValueL(aMessage, val, ENotEqual);
+	}
+
+TInt CServerSession::FindNeqStringL(const TClientRequest& aMessage)
+	{
+	TBuf8<KMaxBinaryLength> val;
+	aMessage.ReadL(2, val);  // no error if too long, truncated instead
+	// PlatSec check done in FindValueL
+	return FindValueL(aMessage, val, ENotEqual);
+	}
+
+template <class T>
+TInt CServerSession::FindValueL(const TClientRequest& aMessage, const T& aVal,
+	TComparison aComparison)
+	{
+	// IMPORTANT PLATSEC NOTE:
+	// MUST return KErrPermissionDenied if read policy of ANY setting in the search range not passed.
+	// MUST NOT merely check read policy of matching entries, otherwise it is possible to determine
+	// secret values by brute force: Using single-value ranges, cycling through the possible values and
+	// confirming a match when it returns KErrPermissionDenied rather than KErrNotFound.
+	TInt partialId = aMessage.Int0();
+	TInt idMask = aMessage.Int1();
+	// we reset results first since we do not police GetResult
+	// and this way we can guarantee no results are available if access not granted
+	iFindResult.Reset();
+	RSettingPointerArray settings;
+	CleanupClosePushL(settings);
+	TInt error = iRepository.FindSettings(partialId, idMask, settings);
+	if (error == KErrNone)
+		{
+		error = iRepository.MakeComparisonFindResultsCheckingReadPolicies(settings, aMessage,
+			__PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerSession::FindValueL - Attempt made to search settings"),
+			aVal, aComparison, iFindResult);
+			
+		if ((error == KErrNone) && (iFindResult.Count() == 0))
+			{
+			error = KErrNotFound;
+			}
+			
+		if(error == KErrNone)
+			{
+			const TInt numSettings = iFindResult.Count();
+			const TInt numInitial = numSettings > KCentRepFindBufSize ? KCentRepFindBufSize : numSettings;
+			RArray<TUint32> settingsToSend;
+			CleanupClosePushL(settingsToSend);
+			
+			//reserve memory for everything that needs to be added to the array
+			settingsToSend.Reserve(numInitial);
+			
+			//first append the number of found settings
+			settingsToSend.AppendL(numSettings);
+			
+			//now append up to KCentRepFindBufSize settings
+			for(TInt i = 0; i < numInitial; i++)
+				{
+				settingsToSend.AppendL(iFindResult[0]);
+				iFindResult.Remove(0);
+				}
+				
+			if(iFindResult.Count() == 0)
+				{
+				iFindResult.Reset();
+				}
+				
+			//send:
+			//1 - the count of total settings found
+			//2 - the settings that fit in the buffer allocated for the first IPC 
+			TPtrC8 p(reinterpret_cast<TUint8*>(&(settingsToSend[0])), (numInitial+1)*sizeof(TUint32));
+			error = aMessage.Write(3, p);
+			CleanupStack::PopAndDestroy(); //settingsToSend
+			}
+		}
+		
+	if ((error != KErrNone) && (error != KErrNotFound) && (error != KErrPermissionDenied))
+		{
+		iFindResult.Reset();
+		CleanupStack::PopAndDestroy(); //settings
+		
+		// ServiceError will fail transaction
+		User::Leave(error);
+		}
+		
+	CleanupStack::PopAndDestroy(); //settings
+	return error;
+	}
+
+TInt CServerSession::GetFindResultL(const TClientRequest& aMessage)
+	{
+	TInt n = iFindResult.Count();
+	if (n == 0)
+		{
+		// should never call this if it's zero
+		return KErrNotFound;
+		}
+  	TPtrC8 p(reinterpret_cast<TUint8*>(&(iFindResult[0])), n*sizeof(TUint32));
+  	TInt error = aMessage.Write(0, p);
+  	// Free up iFindResult - it's no longer needed
+  	iFindResult.Reset();
+	// ServiceError will fail transaction
+	return User::LeaveIfError(error);
+	}
+
+TInt CServerSession::NotifyRequestCheck(const TClientRequest& aMessage)
+	{
+	TUint32 key = aMessage.Int0();
+	if(KErrNone != CheckPolicy(aMessage,iRepository.GetReadAccessPolicy(key),
+				__PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerSession::NotifyRequestCheck - Attempt made to check Notify request")))
+		return KErrPermissionDenied;
+
+	return iRepository.GetPersistentSetting(key) ? KErrNone : KErrNotFound;
+	}
+
+TInt CServerSession::NotifyRequest(const TClientRequest& aMessage)
+	{
+	TUint32 key = aMessage.Int0();
+	if(KErrNone != CheckPolicy(aMessage,iRepository.GetReadAccessPolicy(key),
+				__PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerSession::NotifyRequest - Attempt made to register for Notify")))
+		return KErrPermissionDenied;
+	TInt r = iNotifier.AddRequest(key, aMessage);
+	return r==KErrNone ? KDontComplete : r;
+	}
+
+TInt CServerSession::NotifyCancel(const TClientRequest& aMessage)
+	{
+	TUint32 key = aMessage.Int0();
+	return iNotifier.CancelRequest(key);
+	}
+
+TInt CServerSession::NotifyCancelAll(const TClientRequest& /*aMessage*/)
+	{
+	return iNotifier.CancelAllRequests();
+	}
+
+TInt CServerSession::GroupNotifyRequest(const TClientRequest& aMessage)
+	{
+	TUint32 partialId = aMessage.Int0();
+	TUint32 idMask = aMessage.Int1();
+	RSettingPointerArray settings;
+	TInt error = iRepository.FindPersistentSettings(partialId, idMask, settings);
+	if (error == KErrNone)
+		{
+		error = iRepository.CheckReadPermissions(settings, aMessage,
+			__PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerSession::GroupNotifyRequest - Attempt made to register for group Notify"));
+		}
+	settings.Reset();
+	if (error != KErrNone)
+		{
+		return KErrPermissionDenied;
+		}
+
+	error = iNotifier.AddRequest(partialId, idMask, aMessage);
+	return error==KErrNone ? KDontComplete : error;
+	}
+
+TInt CServerSession::GroupNotifyCancel(const TClientRequest& aMessage)
+	{
+	const TUint32 partialId = aMessage.Int0();
+	const TUint32 idMask = aMessage.Int1();
+	RSettingPointerArray settings;
+	TInt error = iRepository.FindPersistentSettings(partialId, idMask, settings);
+	settings.Reset();
+	if (error != KErrNone)
+		{
+		return error;
+		}
+
+	return iNotifier.CancelRequest(partialId, idMask);
+	}
+
+TInt CServerSession::ResetL(const TClientRequest& aMessage)
+	{
+	// individual setting reset is not yet supported in transactions
+	ASSERT(!iRepository.IsInTransaction());
+	TUint32 key = aMessage.Int0();
+	if(KErrNone != CheckPolicy(aMessage,iRepository.GetWriteAccessPolicy(key),
+				__PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerSession::ResetL - Attempt made to reset a setting")))
+		return iRepository.FailTransaction(KErrPermissionDenied, key);
+
+	TInt r = iRepository.ResetL(key);
+
+	return r;
+	}
+
+TInt CServerSession::ResetAllL(const TClientRequest& aMessage)
+	{
+	// factory reset operation is not yet supported in transactions
+	ASSERT(!iRepository.IsInTransaction());
+	if(KErrNone != CheckPolicy(aMessage,iRepository.GetDefaultWriteAccessPolicy(),
+				__PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerSession::ResetAllL - Attempt made to reset repository")))
+		return KErrPermissionDenied;
+	
+	iNotifier.IdReportingOff();
+	TInt r = iRepository.ResetAllL();
+	iNotifier.IdReportingOn();
+	
+	if(r==KErrNone)
+	iRepository.CommitChangesL();  // temporary measure
+
+	return r;
+	}
+
+TInt CServerSession::MoveL(const TClientRequest& aMessage)
+	{
+	if (iRepository.IsInActiveReadTransaction())
+		{
+		// could not promote to read/write: fail & give the source partialKey as the error key
+		TUint32 sourcePartialKey = aMessage.Int0();
+		return iRepository.FailTransaction(KErrLocked, sourcePartialKey);
+		}
+	TUint32 errorKey = KUnspecifiedKey;
+	TInt result = iRepository.TransactionMoveL(aMessage, errorKey);
+	if (result != KErrNone)
+		{
+		TPckg<TUint32> p(errorKey);
+		aMessage.WriteL(3, p);
+		}
+	return result;
+	}
+	
+TInt CServerSession::TransactionStart(const TClientRequest& aMessage)
+	{
+	// panic client if attempting to start a transaction when already in one
+	__ASSERT_ALWAYS(!iRepository.IsInTransaction(), PanicClient(EStartAlreadyInTransaction, aMessage));
+
+	const TInt mode = aMessage.Int0();
+	return iRepository.StartTransaction(mode);
+	}
+
+// serves as both rollback and async cancel
+TInt CServerSession::TransactionCancel(const TClientRequest& /*aMessage*/)
+	{
+	iRepository.CancelTransaction();
+	return KErrNone;
+	}
+
+TInt CServerSession::TransactionCommitL(const TClientRequest& aMessage)
+	{
+	__ASSERT_ALWAYS(iRepository.IsInTransaction(), PanicClient(ECommitNotInTransaction, aMessage));
+
+	TUint32 keyInfo = KUnspecifiedKey;
+	TInt result = iRepository.CommitTransaction(keyInfo);
+
+	TPckg<TUint32> p(keyInfo);
+	aMessage.WriteL(0, p);
+
+	return result;
+	}
+
+TInt CServerSession::DeleteRangeL(const TClientRequest& aMessage)
+	{
+	if (iRepository.IsInActiveReadTransaction())
+		{
+		// could not promote to read/write: fail & give the partialKey as the error key
+		TUint32 partialKey = aMessage.Int0();
+		return iRepository.FailTransaction(KErrLocked, partialKey);
+		}
+	TUint32 errorKey = KUnspecifiedKey;
+	TInt result = iRepository.TransactionDeleteRangeL(aMessage, errorKey);
+	if (result != KErrNone)
+		{
+		TPckg<TUint32> p(errorKey);
+		aMessage.WriteL(2, p);
+		}
+	return result;
+	}	
+
+TInt CServerSession::TransactionStateL(const TClientRequest& aMessage)
+	{
+	TInt iState = iRepository.TransactionState();
+	
+	TPckg<TInt> p(iState);
+	aMessage.WriteL(0, p);
+	
+	return KErrNone;
+	}
+	
+TInt CServerSession::TransactionFail(const TClientRequest& /*aMessage*/)
+	{
+	iRepository.FailTransaction(KErrAbort, KUnspecifiedKey);
+	return KErrNone;
+	}
+
+/**
+@internalTechnology
+Check the security policy against a RMessage.
+*/
+TInt CServerSession::CheckPolicy(const TClientRequest& msg,
+								 const TSecurityPolicy& aPolicy, 
+								 const char *aDiagnostic)
+	{
+	return msg.CheckPolicy(aPolicy,aDiagnostic) ? KErrNone : KErrPermissionDenied;
+	}
+
+#ifdef __CENTREP_SERVER_PERFTEST__
+// DoEventStart
+// Save initial values of timer and MEM allocated.
+void CServerSession::DoEventStart()
+	{
+	if(iPerfData.IsFinished())
+		return;
+	
+	iStartTick = User::FastCounter();
+	}
+
+// DoEventEnd
+// store CPU and MEM usage, time of event, etc. in performance
+// array.
+void CServerSession::DoEventEnd(TUint aEventId)
+	{
+	if (iPerfData.IsFinished())
+		return;
+
+	TUint32 endTick = User::FastCounter();
+
+	// Performance data has 3 parts. First: time spent to
+	// service the request. 2nd if event is open/close/evict
+	// time of the event. 3rd, if open/close/evict repository UID
+
+	// First part: event ID and CPU time spent servicing the request
+	TUint32 entry = EncodeEventAndData(aEventId, endTick - iStartTick);
+	iPerfData.Append(entry);
+
+	if (aEventId == EInitialise)
+		iPerfData.SessionOpen();
+
+	TBool repOpenCloseEvict = aEventId == EInitialise || aEventId == ESessionClose || aEventId == EEvict;
+
+	// Third part: repository UID if event is open/close/evict.
+	if (repOpenCloseEvict)
+		{
+		iPerfData.Append(iStartTick);
+		iPerfData.Append(iRepositoryUid);  // Append will check if array IsFull.
+		}
+
+	// One last thing to do: check if all concurrent sessions close.
+	if (aEventId == ESessionClose)
+		{
+		iPerfData.SessionClose();
+
+		// This is a temporary solution to detect end-of-boot until SS code is 
+		// modified to return end-of-boot state and Centrep becomes SSA 
+		if (iRepositoryUid == 0xCCCCCC00)
+			{
+			iPerfData.IncEndOfBoot();
+			}
+		}
+	}
+#endif // __CENTREP_SERVER_PERFTEST__
+
+
+#if defined(__CENTREP_SERVER_PERFTEST__) || defined (__CENTREP_SERVER_MEMTEST__) || defined(__CENTREP_SERVER_CACHETEST__)
+// GetSetParameters
+// The function code EGetSetParameters is a generic msg reserved
+// for testing purpose. Int0 specifies the function to perform.
+TInt CServerSession::GetSetParameters(const TClientRequest& aMessage)
+	{
+	TServerGetSetParametersSubCmd cmd = static_cast<TServerGetSetParametersSubCmd>(aMessage.Int0());
+
+#ifdef __CENTREP_SERVER_PERFTEST__
+	if (cmd == EGetPerfResults)
+		{
+		TInt desSize = aMessage.GetDesMaxLength(1);
+		TInt numVals = desSize / sizeof(TUint32);
+		if (numVals < KCentRepPerfTestArraySize)
+			{
+			return KErrOverflow;
+			}
+		TPtrC8 p(reinterpret_cast<const TUint8*>(iPerfData.Entries()),
+				   KCentRepPerfTestArraySize * sizeof(TUint32));
+		TInt ret = aMessage.Write(1, p);
+		if (ret == KErrNone)
+			{
+			TUint lastCompleteAccess = iPerfData.LastCompleteAccess();
+			TPckg<TUint> p2(lastCompleteAccess);
+			ret = aMessage.Write(2, p2);
+			}
+		return ret;
+		}
+	else if (cmd == ERestartPerfTests)
+		{
+		iPerfData.Reset();
+		return KErrNone;
+		}
+	else if (cmd == EStopPerfTests)
+		{
+		iPerfData.Stop();
+		return KErrNone;
+		}
+#endif // __CENTREP_SERVER_PERFTEST__
+
+#ifdef __CENTREP_SERVER_MEMTEST__
+	if(cmd == EGetMemResults)
+		{
+		TInt count = TServerResources::iMemTestDataCount;
+		TPckg<TInt> pCount(count);
+		
+		TInt err = aMessage.Write(1, pCount);
+		if(err == KErrNone && count > 0)
+			{
+			TPtrC8 pBuf(reinterpret_cast<TUint8*>(TServerResources::iMemTestData), (TServerResources::iMemTestDataCount)*sizeof(TInt32));
+			err = aMessage.Write(2, pBuf);
+			}
+		// Stop recording results
+		TServerResources::StopRecordTimerResult();
+		return err;
+		}
+#endif // __CENTREP_SERVER_MEMTEST__
+
+#ifdef __CENTREP_SERVER_CACHETEST__
+	if (cmd == EEnableCache)
+		{
+		// First parameter is Timer Interval, second is cache size
+		TServerResources::iCacheManager->EnableCache(aMessage.Int1(), aMessage.Int2());
+		return KErrNone;
+		}
+	
+	if (cmd == EDisableCache)
+		{
+		TServerResources::iCacheManager->DisableCache();
+		return KErrNone;
+		}
+#endif  // __CENTREP_SERVER_CACHETEST__
+	return KErrNotSupported;
+	}
+#endif // __CENTREP_SERVER_PERFTEST__ || __CENTREP_SERVER_MEMTEST__ || __CENTREP_SERVER_CACHETEST__