persistentstorage/sql/SRC/Server/SqlSrvSession.cpp
changeset 0 08ec8eefde2f
child 8 fa9941cf3867
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/sql/SRC/Server/SqlSrvSession.cpp	Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,1773 @@
+// Copyright (c) 2005-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 "SqlSrvMain.h"			//CSqlServer
+#include "SqlSrvSession.h"		//CSqlSrvSession
+#include "SqlSrvStatement.h"	//CSqlSrvStatement, HSqlSrvStmtParamBuf
+#include "SqlSecurityImpl.h"	//CSqlSecurityPolicy
+#include "SqlSrvUtil.h"			//Global server functions
+#include "SqlUtil.h"			// config length
+#include "SqlSrvDriveSpace.h"	//CSqlDriveSpace, RSqlDriveSpaceCol
+#include "SqlSrvBlob.h"
+#include "SqlResourceProfiler.h"
+#include "SqlCompact.h"
+#include "UTraceSql.h"
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef _DEBUG
+
+const TInt KDelayedDbHeapFailureMask = 0x1000;
+
+//Puts the database connection in a test mode
+//Returns true if the heap failure simulation has to be delayed untill the database is opened
+//Initialises iDbResourceTestMode and iFailedAllocNumber (if delayed simulation) data members
+inline TBool CSqlSrvSession::ActivateDbTestMode(TInt aHeapFailureMode, TInt aFailedAllocNumber)
+	{
+	iDbResourceTestMode = aHeapFailureMode;
+	if(aHeapFailureMode & KDelayedDbHeapFailureMask)
+		{
+		iFailedAllocNumber = aFailedAllocNumber;
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+//If the database connection is in a test mode then the macro will reset the heap allocation failure type.
+//and stop the test mode.
+inline void CSqlSrvSession::StopDbTestMode()
+	{
+	if(iDbResourceTestMode)
+		{
+		iDbResourceTestMode = 0;
+		User::__DbgSetAllocFail(RHeap::EUser, RHeap::ENone, 0);
+		}
+	}
+
+//If the database connection is in a test mode then the function will mark the allocated by the 
+//server resources.
+inline void CSqlSrvSession::DbResourceMark()
+	{
+	if(iDbResourceTestMode)
+		{
+		ResourceCountMarkStart();
+		}
+	}
+
+//If the database connection is in a test mode then the macro will check the allocated by the server resources,
+//comparing their count with the resource count at the moment DbResourceMark() has been called.
+//The client will be panicked if the resource count now is different.
+inline void CSqlSrvSession::DbResourceEnd(const RMessage2& aMessage)
+	{
+	if(iDbResourceTestMode)
+		{
+		ResourceCountMarkEnd(aMessage);
+		}
+	}
+
+//Executes the heap simulation failure.
+inline void CSqlSrvSession::DbSetAllocFail(TInt aHeapFailureMode, TInt aFailedAllocNumber)
+	{
+	User::__DbgSetAllocFail(RHeap::EUser, 
+							static_cast <RHeap::TAllocFail> (aHeapFailureMode & (KDelayedDbHeapFailureMask - 1)), 
+							aFailedAllocNumber);
+	}
+	
+//Executes the delayed heap simulation failure, if the connection is in test mode
+inline void CSqlSrvSession::DbSetDelayedAllocFail()
+	{
+	if(iDbResourceTestMode & KDelayedDbHeapFailureMask)
+		{
+		User::__DbgSetAllocFail(RHeap::EUser, 
+								static_cast <RHeap::TAllocFail> (iDbResourceTestMode & (KDelayedDbHeapFailureMask - 1)), 
+								iFailedAllocNumber);
+		}
+	}
+	
+#else //_DEBUG
+
+inline TBool CSqlSrvSession::ActivateDbTestMode(TInt, TInt)
+	{
+	return EFalse;
+	}
+
+inline void CSqlSrvSession::StopDbTestMode()
+	{
+	}
+
+inline void CSqlSrvSession::DbResourceMark()
+	{
+	}
+
+inline void CSqlSrvSession::DbResourceEnd(const RMessage2&)
+	{
+	}
+
+inline void CSqlSrvSession::DbSetAllocFail(TInt, TInt)
+	{
+	}
+	
+inline void CSqlSrvSession::DbSetDelayedAllocFail()
+	{
+	}
+
+#endif//_DEBUG
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+Searches aContainer for an object identified by aHandle.
+If such object exists, a reference to it is returned.
+If there is no object, the client gets a panic.
+
+@panic SqlDb 4 Client panic. Invalid aHandle parameter value (zero, negative or out of range).
+
+@internalComponent
+*/
+template <class T> T& SqlSessObjFind(RDbObjContainer<T>& aContainer, TInt aHandle, const RMessage2& aMessage)
+	{
+	T* obj = aContainer.Find(aHandle);
+	__SQLPANIC_CLIENT(obj != NULL, aMessage, ESqlPanicBadArgument);
+	return *obj;
+	}
+
+//This function return true, if there is free disk space on drive where the main database file is.
+static TBool HasFreeDiskSpace(RFs& aFs, TDriveNumber aDrive)
+	{
+	TVolumeInfo volInfo;
+	TInt err = aFs.Volume(volInfo, aDrive);
+	if(err == KErrNone)
+		{
+		const TInt64 KDiskSpaceThreshold = 1024 * 4;
+		return volInfo.iFree > KDiskSpaceThreshold;
+		}
+	return ETrue;
+	}
+	
+//If aError is KSqlErrFull and  there is no free disk space, then KSqlErrFull is converted to KErrDiskFull
+//and returned.
+static TInt ConvertSqlFull2DiskFullErr(TInt aError, RFs& aFs, TDriveNumber aDrive)
+	{
+	if(aError == KSqlErrFull && !HasFreeDiskSpace(aFs, aDrive))
+		{
+		aError = KErrDiskFull;
+		}
+	return aError;
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+Creates a new instance of CSqlSrvSession class.
+
+This function shall never be called directly.
+It is CSqlServer responsibility to create a new server side session object as a responce to the criation of a
+client side session instance.
+
+@return A pointer to the created CSqlSrvSession instance.
+
+@leave KErrNoMemory, an out of memory condition has occurred;
+
+@see CSqlServer
+@see CSqlServer::NewSessionL()
+*/
+CSqlSrvSession* CSqlSrvSession::NewL()
+	{
+	CSqlSrvSession* self = new (ELeave)	CSqlSrvSession;
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+/**
+Frees the allocated by CSqlSrvSession instance resources and memory.
+*/
+CSqlSrvSession::~CSqlSrvSession()
+	{
+	StopDbTestMode();
+	DbFreeReservedSpace();
+	iIpcStreams.Close();
+	iStatements.Close();
+	delete iDatabase;
+	}
+
+/**
+Receives and dispatches all client side requests.
+
+CSession2::ServiceL() implementation.
+
+@param aMessage Client message containing the request (function code and data)
+
+@leave The function may leave with some database specific 
+	   errors categorised as ESqlDbError or system-wide error codes.
+
+@see CSession2::ServiceL()
+*/
+void CSqlSrvSession::ServiceL(const RMessage2& aMessage)
+	{
+	TSqlSrvFunction funcCode = ESqlSrvTestBase;
+	TInt handle = 0;
+	Extract(aMessage, funcCode, handle);
+	TInt retCode = KErrNone;
+	if(funcCode >= ESqlSrvDbBase)
+		{
+		SQLPROFILER_REPORT_IPC(ESqlIpcRq, 0);
+		}
+	SYMBIAN_TRACE_SQL_EVENTS_ONLY(TPtrC8 funcName = GetIPCFuncStr(funcCode));
+	SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EBorder), KSrvMsgStr, &funcName));
+	
+	SQLPROFILER_IPC_START(iIpcCounter, iDatabase ? (TUint)iDatabase->RawDbHandle() : 0);
+	
+	switch(funcCode)
+		{
+		//////////////////////  resource check operations  ///////////////////////////
+		case ESqlSrvResourceMark:
+			ResourceCountMarkStart();
+			break;
+		case ESqlSrvResourceCheck:
+			ResourceCountMarkEnd(aMessage);
+			break;
+		case ESqlSrvResourceCount:
+			retCode = CountResources();					//Returns the recourse count
+			break;
+		case ESqlSrvSetDbHeapFailure:
+			if(ActivateDbTestMode(aMessage.Int0(), aMessage.Int1()))
+				{
+				break;	
+				}
+		case ESqlSrvSetHeapFailure:
+			DbSetAllocFail(aMessage.Int0(), aMessage.Int1());
+			break;
+		//////////////////////   profiling operations  //////////////////////////////////
+		case ESqlSrvProfilerStart:
+			TSqlSrvResourceProfiler::StartL(aMessage);
+			break;
+		case ESqlSrvProfilerStop:
+			TSqlSrvResourceProfiler::StopL(aMessage);
+			break;
+		case ESqlSrvProfilerReset:
+			TSqlSrvResourceProfiler::ResetL(aMessage);
+			break;
+		case ESqlSrvProfilerQuery:
+			ProfilerQueryL(aMessage);
+			break;
+		//////////////////////   database operations //////////////////////////////////
+		case ESqlSrvDbCreate:
+		case ESqlSrvDbCreateSecure:
+		case ESqlSrvDbOpen:
+			DbResourceMark();
+			DbCreateObjectL(aMessage, funcCode);
+			DbSetDelayedAllocFail();
+			break;
+		case ESqlSrvDbOpenFromHandle:
+			DbResourceMark();
+			DbCreateObjectFromHandleL(aMessage);
+			DbSetDelayedAllocFail();
+			break;
+		case ESqlSrvDbAttach:
+			DbAttachL(aMessage);
+			break;
+		case ESqlSrvDbAttachFromHandle:
+			DbAttachFromHandleL(aMessage);
+			break;
+		case ESqlSrvDbDetach:
+			DbDetachL(aMessage);
+			break;
+		case ESqlSrvDbClose:
+			DbDestroyObject();
+			DbResourceEnd(aMessage);
+			StopDbTestMode();
+			break;
+		case ESqlSrvDbCopy:
+			DbResourceMark();
+			DbCopyFileL(aMessage);
+			break;
+		case ESqlSrvDbDelete:
+			DbResourceMark();
+			DbDeleteFileL(aMessage);
+			break;
+		case ESqlSrvLastErrorMsg:
+			retCode = DbLastErrorMessageL(aMessage);//may return that the client buffer is not big enough for the message
+			break;
+		case ESqlSrvDbLastInsertedRowId:
+			DbLastInsertedRowIdL(aMessage);
+			break;
+		case ESqlSrvDbExec8:
+			retCode = DbExecSql8L(aMessage);		//returns the count of affected records
+			break;
+		case ESqlSrvDbExec16:
+			retCode = DbExecSql16L(aMessage);	//returns the count of affected records
+			break;
+		case ESqlSrvDbSetIsolationLevel:
+			DbSetIsolationLevelL(aMessage);
+			break;
+		case ESqlSrvDbGetSecurityPolicy:
+			retCode = DbGetSecurityPolicyL(aMessage);//may return that the client buffer is not big enough for the security policy
+			break;
+		case ESqlSrvDbScalarFullSelect8:
+			retCode = DbScalarFullSelectL(aMessage, EFalse);//may return that the client buffer is not big enough for the column value
+			break;
+		case ESqlSrvDbScalarFullSelect16:
+			retCode = DbScalarFullSelectL(aMessage, ETrue);//may return that the client buffer is not big enough for the column value
+			break;
+		case ESqlSrvDbInTransaction:
+			retCode = DbInTransaction(aMessage);	//Returns whether the database in in transaction or not - true/false
+			break;
+		case ESqlSrvDbSize:
+			retCode = DbSizeL(aMessage);			//Returns the database size
+			break;
+		case ESqlSrvDbSize2:
+			DbSize2L(aMessage);
+			break;
+		case ESqlSrvDbCompact:
+			retCode = DbCompactL(aMessage);			//Returns the amount of the removed free database space
+			break;
+		//////////////////////   reserved drive space management ////////////////////////
+		case ESqlSrvDbReserveDriveSpace:
+			__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+			DbReserveDriveSpaceL();
+			break;
+		case ESqlSrvDbFreeReservedSpace:
+			__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+			DbFreeReservedSpace();
+			break;
+		case ESqlSrvDbGetReserveAccess:
+			__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+			DbGetReserveAccessL();
+			break;
+		case ESqlSrvDbReleaseReserveAccess:
+			__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+			DbReleaseReserveAccess();
+			break;
+		//////////////////////   BLOB source ///////////////////////////////////////////
+		case ESqlSrvDbBlobSource:
+			retCode = DbBlobSourceL(aMessage);		//Returns the BLOB handle
+			break;
+		//////////////////////   statement operations //////////////////////////////////
+		case ESqlSrvStmtPrepare8:
+			retCode = StmtPrepareL(aMessage, EFalse);//returns the statement handle
+			break;
+		case ESqlSrvStmtPrepare16:
+			retCode = StmtPrepareL(aMessage, ETrue);//returns the statement handle
+			break;
+		case ESqlSrvStmtClose:
+			iStatements.Remove(handle);
+			break;
+		case ESqlSrvStmtReset:
+			retCode = ::SqlSessObjFind(iStatements, handle, aMessage).Reset();//May return that the statement has expired
+			break;
+		case ESqlSrvStmtExec:
+		case ESqlSrvStmtAsyncExec:
+		case ESqlSrvStmtBindExec:
+		case ESqlSrvStmtAsyncBindExec:
+			retCode = StmtExecL(aMessage, handle, funcCode);//returns the count of affected records
+			break;
+		case ESqlSrvStmtNext:
+		case ESqlSrvStmtBindNext:
+			retCode = StmtNextL(aMessage, handle, funcCode);//returns a non-negative number if the client side buffer is too small
+			break;
+		case ESqlSrvStmtColumnNames:
+		case ESqlSrvStmtParamNames:
+			retCode = StmtNamesL(aMessage, handle, funcCode);//returns a non-negative number if the client side buffer is too small
+			break;
+		case ESqlSrvStmtColumnSource:
+			retCode = StmtColumnSourceL(aMessage, handle);//returns an IPC stream handle
+			break;
+		case ESqlSrvStmtBinParamSink:
+		case ESqlSrvStmtTxtParamSink16:
+			retCode = StmtParamSinkL(aMessage, handle, funcCode);//returns an IPC stream handle
+			break;
+		case ESqlSrvStmtBufFlat:
+			StmtGetBufFlatL(aMessage, handle);
+			break;
+		case ESqlSrvStmtColumnValue:
+			StmtColumnValueL(aMessage, handle);
+			break;
+		case ESqlSrvStmtDeclColumnTypes:
+			StmtDeclColumnTypesL(aMessage, handle);
+			break;
+		//////////////////////   stream operations //////////////////////////////////
+		case ESqlSrvStreamRead:
+			retCode = ::SqlSessObjFind(iIpcStreams, handle, aMessage).ReadL(aMessage);
+			break;
+		case ESqlSrvStreamWrite:
+			::SqlSessObjFind(iIpcStreams, handle, aMessage).WriteL(aMessage);
+			break;
+		case ESqlSrvStreamSize:
+			retCode = ::SqlSessObjFind(iIpcStreams, handle, aMessage).SizeL();
+			break;
+		case ESqlSrvStreamSynch:
+			::SqlSessObjFind(iIpcStreams, handle, aMessage).SynchL();
+			break;
+		case ESqlSrvStreamClose:
+			iIpcStreams.Remove(handle);
+			break;
+		//////////////////////                     //////////////////////////////////
+		default:	
+			retCode = KErrNotSupported;
+			break;
+		}
+	Server().Compactor().RestartTimer();
+	Server().MinimizeBuffers();		
+	if(!aMessage.IsNull())
+		{
+		aMessage.Complete(retCode);
+		}
+    SQLPROFILER_IPC_END(iIpcCounter, funcCode, iDatabase ? (TUint)iDatabase->RawDbHandle() : 0, iIpcTraceData, retCode);
+	}
+
+/**
+If aError is KErrBadDescriptor, then panic the client, else - default error handling.
+KErrBadDescriptor error may be thrown from "message write" operations, if the client supplied a bad
+descriptor to the server.
+*/
+void CSqlSrvSession::ServiceError(const RMessage2& aMessage, TInt aError)
+ 	{
+	Server().MinimizeBuffers();		
+	aError = ::ConvertSqlFull2DiskFullErr(aError, Server().FileData().Fs(), iDrive);
+ 	if(aError == KErrBadDescriptor)
+ 		{
+		//The __SQLPANIC_CLIENT() macro cannot be used here because it calls a leaving function. A leaving call
+		//from a leaving call will terminate the server.
+		_LIT(KPanicCategory, "SqlDb");
+		
+		SYMBIAN_TRACE_SQL_ERR_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EError), KSqlSrvPanicClient, aError));
+		aMessage.Panic(KPanicCategory, ESqlPanicBadDescriptor);
+ 		}
+ 	
+ 	SYMBIAN_TRACE_SQL_ERR_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EError), KSqlSrvError, aError));
+ 	SQLPROFILER_IPC_ERROR(iIpcCounter, static_cast <TSqlSrvFunction> (KSqlSrvFunctionMask & aMessage.Function()), 
+ 	       iDatabase ? (TUint)iDatabase->RawDbHandle() : 0, aError);
+ 	CSession2::ServiceError(aMessage, aError);
+   	}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////          Profiler  operations           ///////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+Retrieves the counter values for the specified profiling counter.
+
+@leave  KErrNone, the operation completed successfully,
+        KErrOverflow, the receiving buffer size is too small;
+                  One of the other system-wide error codes may also be returned.
+
+@see TSqlResourceProfiler
+
+Usage of the IPC call arguments:
+ - Arg 0: [in]  profiling counter type, one of the TSqlResourceProfiler::TSqlCounter enum item values.
+ - Arg 1: [in]  the size of the buffer for the profiling counter values.
+ - Arg 2: [out] the buffer for the profiling counter values.
+
+@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
+*/
+void CSqlSrvSession::ProfilerQueryL(const RMessage2& aMessage)
+	{
+	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+	if(aMessage.Int0() == TSqlResourceProfiler::ESqlCounterConfig)
+		{
+		const TInt KConfigBufLen = 128;
+		if(aMessage.Int1() < KConfigBufLen)
+			{
+			__SQLLEAVE(KErrOverflow);	
+			}
+		TBuf8<KConfigBufLen> res;
+		iDatabase->QueryConfigL(res);
+		aMessage.WriteL(2, res);
+		}
+	else
+		{
+		TSqlSrvResourceProfiler::QueryL(aMessage);
+		}				
+	}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////          Database operations           ///////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+Processes the request for creating/opening a database.
+
+The function initializes iDatabase and iDrive data members.
+
+Usage of the IPC call arguments:
+Arg 0: [in]  database file name length in 16-bit characters
+Arg 1: [in]  database file name
+Arg 2: [in]  PPPPCCCC, where PPPP is the security policy length, CCCC is the config string length.
+Arg 3: [in]  security policies buffer | config string
+
+@leave KErrArgument If config string length or security policy length is invalid (negative length or too big length)
+@panic SqlDb 1 Client panic. iDatabase is not NULL (it has been created already)
+*/
+void CSqlSrvSession::DbCreateObjectL(const RMessage2& aMessage, TSqlSrvFunction aFunction)
+	{
+	__SQLPANIC_CLIENT(!iDatabase, aMessage, ESqlPanicObjExists);
+	const TInt KSecurityPolicyLen = (aMessage.Int2() & 0x7fff0000) >> 16;
+	const TInt KConfigStringLen = aMessage.Int2() & 0xffff;
+	if(KSecurityPolicyLen < 0 || KConfigStringLen < 0 || KConfigStringLen > KSqlSrvMaxConfigStrLen)
+		{
+		__SQLLEAVE(KErrArgument);	
+		}
+	TBuf8<KSqlSrvMaxConfigStrLen> configStr;
+	if(KConfigStringLen > 0)
+		{
+		aMessage.ReadL(3, configStr, KSecurityPolicyLen);
+		SQLPROFILER_REPORT_IPC(ESqlIpcRead, KConfigStringLen);
+		}
+	TSqlSrvFileData& fileData = Server().FileData();
+	fileData.SetL(aMessage, aMessage.Int0(), 1, &configStr);
+	iDrive = fileData.Drive();
+	switch(aFunction)
+		{
+		case ESqlSrvDbCreate:
+			if(fileData.IsSecureFileNameFmt())
+				{
+				__SQLLEAVE(KErrArgument);	
+				}
+			iDatabase = CSqlSrvDatabase::CreateL(fileData);
+			break;
+		case ESqlSrvDbCreateSecure:
+			{
+			if(!fileData.IsSecureFileNameFmt())
+				{
+				__SQLLEAVE(KErrArgument);	
+				}
+			//The caller can create a secure database which secure UID matches his secure UID.
+			if(fileData.SecureUid() != aMessage.SecureId())
+				{
+				__SQLLEAVE(KErrPermissionDenied);	
+				}
+			CSqlSecurityPolicy* policy = InternalizeSecurityPolicyL(aMessage);
+			iDatabase = CSqlSrvDatabase::CreateSecureL(fileData, policy);
+			}
+			break;
+		case ESqlSrvDbOpen:
+			iDatabase = CSqlSrvDatabase::OpenL(fileData);
+			break;
+		default:
+			__SQLLEAVE(KErrArgument);	
+			break;
+		}
+	}
+
+/**
+Processes the request for opening a database from file handle.
+The server expects that the database to be opened/created is in the applicatio's private data cage.
+
+Usage of the IPC call arguments:
+ - Arg 0: [in]  The 32 bits of the argument are used as follow:
+ @code
+ MSB                                                                                 LSB
+ 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ Ro Cr  C  C  C  C  C  C  C  C  C  C  C  C  C  C  F  F  F  F  F  F F F F F F F F F F F 
+ @endcode
+ Where:
+ @code
+  - "Ro" - read-only flag, true if the file is read-only;
+  - "Cr" - create/open flag, true if the file was created, false if the file was opened;
+  - "C"  - config string length in 16-bit characters;
+  - "F"  - database file name length in 16-bit characters;
+ @endcode
+ - Arg 1: [in]  database file name | config string
+ - Arg 2: [in]  file session handle
+ - Arg 3: [in]  database file handle
+
+@panic SqlDb 1 Client panic. iDatabase is not NULL (it has been created already)
+*/
+void CSqlSrvSession::DbCreateObjectFromHandleL(const RMessage2& aMessage)
+	{
+	__SQLPANIC_CLIENT(!iDatabase, aMessage, ESqlPanicObjExists);
+	const TBool KReadOnly = (aMessage.Int0() & 0x80000000) != 0;
+	const TBool KCreated = (aMessage.Int0() & 0x40000000) != 0;
+	const TInt KDbFileNameLen = aMessage.Int0() & 0x0000FFFF;
+	const TInt KConfigStringLen = (aMessage.Int0() & 0x3FFF0000) >> 16;
+	if(KConfigStringLen < 0 || KConfigStringLen > KSqlSrvMaxConfigStrLen)
+		{
+		__SQLLEAVE(KErrArgument);	
+		}
+	if(KDbFileNameLen < 1 || KDbFileNameLen > KMaxFileName)
+		{
+		__SQLLEAVE(KErrBadName);
+		}
+	TDes16& buffer = Server().GetBuf16L(KDbFileNameLen + KConfigStringLen);
+	aMessage.ReadL(1, buffer);
+	SQLPROFILER_REPORT_IPC(ESqlIpcRead, ((KDbFileNameLen + KConfigStringLen) * sizeof(TText)));
+	TFileName dbFileName;
+	dbFileName.Copy(buffer.LeftTPtr(KDbFileNameLen));
+	TBuf8<KSqlSrvMaxConfigStrLen> configStr;
+	if(KConfigStringLen > 0)
+		{
+		configStr.Copy(buffer.MidTPtr(KDbFileNameLen, KConfigStringLen));
+		}
+	TSqlSrvFileData& fileData = Server().FileData();
+	fileData.SetFromHandleL(aMessage, dbFileName, KCreated, KReadOnly, &configStr);
+	iDrive = fileData.Drive();
+	iDatabase = CSqlSrvDatabase::OpenL(fileData);
+	}
+
+/**
+Processes the request for copying a database.
+
+Only the database creator can copy the database if the database is a secure database.
+
+Usage of the IPC call arguments:
+Arg 0: [in]  source database file name length
+Arg 1: [in]  source database file name
+Arg 2: [in]  destination database file name length
+Arg 3: [in]  destination database file name
+*/
+void CSqlSrvSession::DbCopyFileL(const RMessage2& aMessage)
+	{
+	const TInt KDbCnt = 2;											//"2" - because we have 2 dbases: src and dest
+	const TInt KSrcDbIdx = 0;
+	const TInt KDestDbIdx = 1;
+	TInt fileNameLen[KDbCnt] = {aMessage.Int0(), aMessage.Int2()};
+	TSqlSrvFileData& fileData = Server().FileData();
+	TUint dbSecureFlag[KDbCnt];
+	TUid  dbSID[KDbCnt] = {KNullUid, KNullUid};
+	TFileName dbFileName[KDbCnt];
+	//Initialize dbSecureFlag[], dbSID[] and dbFileName[] array elements
+	for(TInt i=0;i<KDbCnt;++i)									
+		{
+		fileData.SetL(aMessage, fileNameLen[i], i * KDbCnt + 1);	//"i * KDbCnt + 1" is the RMessage2 parameter number: 1 for src db, 3 for dest db
+		dbSecureFlag[i] = fileData.IsSecureFileNameFmt() ? 1 : 0;
+		if(dbSecureFlag[i])
+			{
+			dbSID[i] = fileData.SecureUid();
+			}
+		dbFileName[i].Copy(fileData.FileName());
+		}
+	//It is not allowed to copy non-secure to a secure or secure to a non-secure database.
+	if(dbSecureFlag[KSrcDbIdx] ^ dbSecureFlag[KDestDbIdx])
+		{
+		__SQLLEAVE(KErrPermissionDenied);	
+		}
+	//If this is a secure database "copy" operation, then...
+	if(dbSecureFlag[KSrcDbIdx])
+		{
+		TUid callerSid = aMessage.SecureId();
+		//A secure database can be copied only by its owner (database SID matches caller SID).
+		if(callerSid != dbSID[KSrcDbIdx] || callerSid != dbSID[KDestDbIdx])
+			{
+			__SQLLEAVE(KErrPermissionDenied);	
+			}
+		}
+	//Copy the database
+	CFileMan* fileMan = CFileMan::NewL(fileData.Fs());
+	CleanupStack::PushL(fileMan);
+	__SQLLEAVE_IF_ERROR(fileMan->Copy(dbFileName[KSrcDbIdx], dbFileName[KDestDbIdx]));
+	//"Copy" operation executed without errors. Now it is a time to turn off the read-only
+	//flag of the target file (which may be on if the source file is on a read-only drive)
+	__SQLLEAVE_IF_ERROR(fileData.Fs().SetAtt(dbFileName[KDestDbIdx], 0, KEntryAttReadOnly));
+	CleanupStack::PopAndDestroy(fileMan);
+	}
+
+/**
+Processes the request for deleting a database.
+
+Only the database creator can delete the database if the database is a secure database.
+
+Usage of the IPC call arguments:
+Arg 0: [in]  database file name length
+Arg 1: [in]  database file name
+*/
+void CSqlSrvSession::DbDeleteFileL(const RMessage2& aMessage)
+	{	
+	TSqlSrvFileData& fileData = Server().FileData();
+	fileData.SetL(aMessage, aMessage.Int0(), 1);
+	if(fileData.IsSecureFileNameFmt())
+		{
+		//A secure database can be deleted only by its owner (database SID matches caller SID).
+		if(fileData.SecureUid() != aMessage.SecureId())
+			{
+			__SQLLEAVE(KErrPermissionDenied);	
+			}
+		}
+	#ifdef _NOTIFY
+	TPtrC fname = fileData.FileName();
+	RDebug::Print(_L("--SrvSess, delete, fname=\"%S\"\r\n"), &fname);
+	#endif		
+	__SQLLEAVE_IF_ERROR(fileData.Fs().Delete(fileData.FileName()));
+	}
+
+/**
+Processes the request for retrieving the last error message.
+
+If the client side buffer size is not big enough, the function returns the needed 
+buffer size + KSqlClientBufOverflowCode.
+In this case the client must increase the buffer and try again to get the message.
+
+Usage of the IPC call arguments:
+Arg 0: [in]		Message buffer length in 16-bit characters
+Arg 1: [in/out]	Message buffer
+
+@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
+@panic SqlDb 4 Client panic. Negative client message buffer length (Arg 0).
+*/
+TInt CSqlSrvSession::DbLastErrorMessageL(const RMessage2& aMessage)
+	{
+	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+	TPtrC msg = iDatabase->LastErrorMessage();
+	TInt msgLen = msg.Length();
+	TInt bufSize = aMessage.Int0();
+	__SQLPANIC_CLIENT(bufSize >= 0, aMessage, ESqlPanicBadArgument);
+	if(msgLen <= bufSize)
+		{
+		aMessage.WriteL(1, msg);
+		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, (msgLen * sizeof(TText)));
+		return 0;
+		}
+	return msgLen + KSqlClientBufOverflowCode;
+	}
+	
+/**
+Processes the request for retrieving the last inserted ROWID of this database connection.
+
+Usage of the IPC call arguments:
+Arg 0: [in/out]	Receiving buffer
+
+@panic SqlDb 2 Client panic. The database object is not yet created yet (iDatabase is NULL).
+*/
+void CSqlSrvSession::DbLastInsertedRowIdL(const RMessage2& aMessage)
+	{
+	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+	TInt64 rowid = iDatabase->LastInsertedRowId();
+	aMessage.WriteL(0, TPtrC8(reinterpret_cast <const TUint8*> (&rowid), sizeof(rowid)));
+	SQLPROFILER_REPORT_IPC(ESqlIpcWrite, sizeof(rowid));
+	}
+
+/**
+Processes the request for retrieving the database security policies.
+
+The method leaves with KErrNotSupported if the database is not a secure database.
+
+If the client side buffer size is not big enough, the function returns the needed 
+buffer size + KSqlClientBufOverflowCode.
+In this case the client must increase the buffer and try again to get the database security policy.
+
+Usage of the IPC call arguments:
+Arg 0: [in]		security policy buffer length in bytes
+Arg 1: [in/out]	buffer for the database security policies
+
+@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
+*/
+TInt CSqlSrvSession::DbGetSecurityPolicyL(const RMessage2& aMessage)
+	{
+	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+	const CSqlSecurityPolicy* securityPolicy = iDatabase->SecurityPolicy();
+	if(!securityPolicy)
+		{
+		__SQLLEAVE(KErrNotSupported);
+		}
+	const RSqlBufFlat& bufFlat = securityPolicy->BufFlat();
+	TInt size = bufFlat.Size();
+	if(size <= aMessage.Int0())
+		{
+		aMessage.WriteL(1, bufFlat.BufDes());
+		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, size);
+		return 0;
+		}
+	return size + KSqlClientBufOverflowCode;
+	}
+
+/**
+If an error occurs during the execution the function leaves with the error code.
+Possible non-leaving return values:
+ - KErrNone              - the function has completed successfully;
+ - Positive return value - the length of the column, which means - the destination buffer is too small.
+                           This return value is possible only with text or binary columns.
+
+@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
+
+Usage of the IPC call arguments: 
+Arg 0: [in]		(8/16-bit character length of SQL statement) | (expected column value type << 24).
+Arg 1: [in]		SQL statement.
+Arg 2: [in]		Byte max length of the receiving buffer
+Arg 3: [in/out]	The receiving buffer
+*/
+TInt CSqlSrvSession::DbScalarFullSelectL(const RMessage2& aMessage, TBool aIsText16)
+	{
+	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+	TUint sqlLen = static_cast <TUint> (aMessage.Int0()) & 0x00FFFFFF;
+	TSqlColumnType  colType = static_cast <TSqlColumnType> ((static_cast <TUint> (aMessage.Int0()) & 0xFF000000) >> 24);
+	TInt columnCount = -1;
+	TInt paramCount = -1;
+	CSqlSrvStatement*  stmt = aIsText16 ? 
+								CSqlSrvStatement::NewLC(iDatabase->RawDbHandle(), ReadString16ZL(aMessage, 1, sqlLen), columnCount, paramCount) :
+								CSqlSrvStatement::NewLC(iDatabase->RawDbHandle(), ReadString8ZL(aMessage, 1, sqlLen), columnCount, paramCount);
+	if(columnCount != 1 || paramCount != 0)
+		{
+		__SQLLEAVE(KErrArgument);	
+		}
+	TInt err = stmt->Next();
+	if(err == KSqlAtRow)
+		{
+		err = GetColumnValueL(aMessage, *stmt, colType);
+		}
+	else
+		{
+		__SQLLEAVE(err == KSqlAtEnd ? KErrNotFound : err);
+		}
+	CleanupStack::PopAndDestroy(stmt);
+	return err;
+	}
+
+/**
+@return True, if the database is in transaction, false otherwise.
+
+@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
+*/
+TBool CSqlSrvSession::DbInTransaction(const RMessage2& aMessage)
+	{
+	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+	return iDatabase->InTransaction();
+	}
+
+/**
+Main database size in bytes.
+
+@return Main database size in bytes.
+
+@leave KErrNoMemory, an out of memory condition has occurred,
+                     Note that the function may also leave with some other system wide errors or 
+                     database specific errors categorised as ESqlDbError,
+	   KErrTooBig,   The database is very big and the size cannot fit in a 32-bit signed integer.
+
+@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
+*/
+TInt CSqlSrvSession::DbSizeL(const RMessage2& aMessage)
+	{
+	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+	TInt64 size = iDatabase->SizeL();
+	if(size > KMaxTInt)
+		{
+		__SQLLEAVE(KErrTooBig);
+		}
+	return size;
+	}
+
+/**
+Retrieves the database size and free space.
+
+Usage of the IPC call arguments:
+Arg 0: [in/out]	Points to a RSqlDatabase::TSize object, where the database size and free space values
+			    will be copied.
+Arg 1: [in]		The database name length in 16-bit characters
+Arg 2: [in]		The attached database name or KNullDesC for the main database
+
+@leave KErrNoMemory, an out of memory condition has occurred,
+                     Note that the function may also leave with some other system wide errors or 
+                     database specific errors categorised as ESqlDbError.
+       KErrBadName, Invalid database name
+
+@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
+*/
+void CSqlSrvSession::DbSize2L(const RMessage2& aMessage)
+	{
+	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+	const TInt KDbNameLen = aMessage.Int1();
+	if(KDbNameLen < 0 || KDbNameLen > KMaxFileName)
+		{
+		__SQLLEAVE(KErrBadName);
+		}
+	TPtrC dbName(KNullDesC);
+	if(KDbNameLen > 0)
+		{
+		dbName.Set(ReadString16L(aMessage, 2, KDbNameLen));
+		}
+	TPckgBuf<RSqlDatabase::TSize> data;
+	data().iSize = iDatabase->SizeL(dbName);
+	data().iFree = iDatabase->FreeSpaceL(dbName);
+	aMessage.WriteL(0, data);
+	SQLPROFILER_REPORT_IPC(ESqlIpcWrite, sizeof(RSqlDatabase::TSize));
+	}
+
+/**
+Runs database compaction.
+
+Usage of the IPC call arguments:
+Arg 0: [in]	    How much space in bytes should be compacted, all free pages should be removed if the
+				parameter value is RSqlDatabase::EMaxCompaction.
+				Note that the requested space to be compacted will be rounded up to the nearest page count,
+				e.g. request for removing 1 byte will remove one free page from the database file. 
+Arg 1: [in]		The database name length in characters
+Arg 2: [in]		The attached database name or KNullDesC for the main database
+
+@return The size of the removed free space
+
+@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
+*/
+TInt CSqlSrvSession::DbCompactL(const RMessage2& aMessage)
+	{
+	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+	const TInt KSize = aMessage.Int0();
+	if(KSize < 0)
+		{
+		if(KSize != RSqlDatabase::EMaxCompaction)
+			{
+			__SQLLEAVE(KErrArgument);
+			}
+		}
+	if(KSize == 0)
+		{
+		return 0;	
+		}
+	const TInt KDbNameLen = aMessage.Int1();
+	if(KDbNameLen < 0 || KDbNameLen > KMaxFileName)
+		{
+		__SQLLEAVE(KErrBadName);
+		}
+	TPtrC dbName(KNullDesC);
+	if(KDbNameLen > 0)
+		{
+		dbName.Set(ReadString16L(aMessage, 2, KDbNameLen));
+		}
+	return iDatabase->CompactL(KSize, dbName);
+	}
+	
+/**
+Usage of the IPC call arguments:
+Arg 0: [in]		requested size of the space to be reserved - not used
+
+The function leaves with KErrAlreadyExists if a drive space has been reserved already by this session.
+*/
+void CSqlSrvSession::DbReserveDriveSpaceL()
+	{
+	if(iDriveSpaceReserved)
+		{
+		__SQLLEAVE(KErrAlreadyExists);
+		}
+	RSqlDriveSpaceCol& driveSpaceCol = Server().DriveSpaceCol();
+    if(!driveSpaceCol.Find(iDrive))
+    	{
+    	(void)driveSpaceCol.AddL(iDrive);
+    	}
+	
+	iDriveSpaceReserved = ETrue;
+	//Only iDriveSpaceReserved is set, nothing more needs to be done, because RSqlDriveSpaceCol::AddL() will
+	//reserve a drive space on the specified drive.
+	//Although it looks like that the implementation can ommit "iDriveSpaceReserved" flag, this flag plays important
+	//role, because it is used to ensure that every "reserve drive space" request is matched by a "free drive space"
+	//call.
+	}
+	
+/**
+If the client has been given an access to the reserved drive space, that access will be released.
+*/
+void CSqlSrvSession::DbFreeReservedSpace()
+	{
+	DbReleaseReserveAccess();
+	iDriveSpaceReserved = EFalse;
+	}
+	
+/**
+The function leaves with KErrInUse if an access to the reserved drive space has been given to the client.
+The function leaves with KErrNotFound if no drive space has been reserved for the drive, where the database file is.
+*/
+void CSqlSrvSession::DbGetReserveAccessL()
+	{
+	if(iDriveSpaceInUse)
+		{
+		__SQLLEAVE(KErrInUse);	
+		}
+	if(!iDriveSpaceReserved)
+		{
+		__SQLLEAVE(KErrNotFound);
+		}
+	CSqlDriveSpace* driveSpace = Server().DriveSpaceCol().Find(iDrive);
+   	if(!driveSpace)
+   		{
+		__SQLLEAVE(KErrNotFound);
+   		}
+   	driveSpace->GetAccessL();
+   	iDriveSpaceInUse = ETrue;
+	}
+	
+/**
+Releases the drive space reserve if it has been in use by this session (resp. client).
+*/
+void CSqlSrvSession::DbReleaseReserveAccess()
+	{
+	if(iDriveSpaceInUse)
+		{
+		CSqlDriveSpace* driveSpace = Server().DriveSpaceCol().Find(iDrive);
+		if(driveSpace)
+			{
+   			driveSpace->ReleaseAccess();
+			}
+   		iDriveSpaceInUse = EFalse;
+		}
+	}
+
+/**
+Processes the request for attaching a secure or non-secure database.
+
+Usage of the IPC call arguments: 
+Arg 0: [in]	Database file name length (counted in 16-bit characters).
+Arg 1: [in]	Database file name.
+Arg 2: [in]	Logical database name length (counted in 16-bit characters).
+Arg 3: [in]	Logical database name.
+
+@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
+*/
+void CSqlSrvSession::DbAttachL(const RMessage2& aMessage)
+	{
+	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+	TSqlSrvFileData& fileData = Server().FileData();
+	fileData.SetL(aMessage, aMessage.Int0(), 1);
+	TInt logicalDbNameLen = aMessage.Int2();
+	if(logicalDbNameLen < 1 || logicalDbNameLen > KMaxFileName)
+		{
+		__SQLLEAVE(KErrBadName);
+		}
+	iDatabase->AttachDbL(fileData, ReadString16L(aMessage, 3, logicalDbNameLen));
+	}
+
+/**
+Processes the request for attaching a database using file session and file handles sent by the client.
+
+Usage of the IPC call arguments:
+ - Arg 0: [in]  The 32 bits of the argument are used as follow:
+ @code
+ MSB                                                                                 LSB
+ 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+ Ro  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F  F F F F F F F F F F F
+ @endcode
+ Where:
+ @code
+  - "Ro" - read-only flag, true if the file is read-only;
+  - "F"  - database file name length in 16-bit characters;
+ @endcode
+Arg 1: [in]  db names buffer
+Arg 2: [in]  file session handle
+Arg 3: [in]  database file handle
+
+@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
+*/
+void CSqlSrvSession::DbAttachFromHandleL(const RMessage2& aMessage)
+	{
+	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+	//Read-only flag, buffer length, buffer allocation
+	TBool readOnly = (aMessage.Int0() & 0x80000000) != 0;
+	const TInt KBufLen = aMessage.Int0() & 0x7FFFFFFF;
+	if(KBufLen <= 0)
+		{
+		__SQLLEAVE(KErrArgument);
+		}
+	HBufC8* buf = HBufC8::NewLC(KBufLen);
+	TPtr8 bufPtr = buf->Des();
+	aMessage.ReadL(1, bufPtr);
+	SQLPROFILER_REPORT_IPC(ESqlIpcRead, KBufLen);
+	if(KBufLen != bufPtr.Length())
+		{
+		__SQLLEAVE(KErrArgument);
+		}
+	RDesReadStream in(bufPtr);
+	TDes& dbFileName = Server().FileNameBuf();
+	TDes16& dbName = Server().GetBuf16L(KMaxFileName);
+	in >> dbFileName;
+	in >> dbName;
+	CleanupStack::PopAndDestroy(buf);
+	TSqlSrvFileData& fileData = Server().FileData();
+	fileData.SetFromHandleL(aMessage, dbFileName, EFalse, readOnly);
+	iDatabase->AttachDbL(fileData, dbName);
+	}
+	
+/**
+Processes the request for detaching a secure or non-secure database.
+
+Usage of the IPC call arguments: 
+Arg 0: [in]	Logical database name length (counted in 16-bit characters).
+Arg 1: [in]	Logical database name.
+
+@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
+*/
+void CSqlSrvSession::DbDetachL(const RMessage2& aMessage)
+	{
+	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+	TInt logicalDbNameLen = aMessage.Int0();
+	if(logicalDbNameLen < 1 || logicalDbNameLen > KMaxFileName)
+		{
+		__SQLLEAVE(KErrBadName);
+		}
+	iDatabase->DetachDbL(ReadString16L(aMessage, 1, logicalDbNameLen));
+	}
+
+/**
+Reads a 16-bit string from the specified stream and returns it in zero-terminated
+8-bit format in aNameOut.
+If the string is of zero length then the substitute string provided will be used instead.
+
+@param aStrm 				The read stream
+@param aNameOut 			The output parameter that will contain the string read
+@param aEmptyNameSubstitute The substitute string to use if the string to be read from
+							the stream is zero length
+
+@leave KErrNoMemory, 		 An out of memory condition has occurred;
+	   KErrArgument, 		 The UTF-16 to UTF-8 string conversion failed;	
+	   KErrBadName,	 		 The string has an invalid length;
+*/
+void CSqlSrvSession::ExtractNameL(RDesReadStream& aStrm, TDes8& aNameOut, const TDesC& aEmptyNameSubstitute)
+	{
+	 TBool replace = EFalse;
+	 TInt32 len;
+	 aStrm >> len;
+
+	 if(len == 0)
+	 	{
+	   	if(aEmptyNameSubstitute.Length() > 0)
+			{
+		 	len = aEmptyNameSubstitute.Length();
+	 	 	replace = ETrue;
+			}
+	 	else
+			{
+			__SQLLEAVE(KErrBadName);
+			}
+	  	}
+
+	 if(len < 1 || len > KMaxFileName)
+	  {
+	  __SQLLEAVE(KErrBadName);
+	  }
+
+	 HBufC* buf = HBufC::NewLC(len + 1);
+	 TPtr ptr = buf->Des();
+	 if(replace)
+	 	{
+	  	ptr.Copy(aEmptyNameSubstitute);
+	  	}
+	 else
+	 	{
+	  	aStrm >> ptr;
+	 	}
+	 ptr.Append(0);
+	 
+	 if(!::UTF16ZToUTF8Z(ptr, aNameOut))
+	  {
+	  __SQLLEAVE(KErrArgument);
+	  }
+	  
+	 CleanupStack::PopAndDestroy(buf);
+	 }
+
+/**
+Processes the request for creating an IPC stream for accessing the content of a blob column.
+
+@param aMessage The client request wrapped in an IPC message
+
+@return The blob stream handle
+
+@leave KErrNoMemory, 		 An out of memory condition has occurred;
+	   KErrArgument, 		 The IPC data buffer length is invalid, or the ROWID is invalid,
+	   				 		 or UTF-16 to UTF-8 string conversion failed;	
+	   KErrBadDescriptor 	 The transferred data is bigger than the specified length;
+	   KErrBadName,	 		 The table name, column name or database name has an invalid length;
+       KErrPermissionDenied, The client does not have the required security capabilites for this operation; 						 
+       						 Note that the function may also leave with some other system wide errors or 
+                     		 database specific errors categorised as ESqlDbError.
+
+@panic SqlDb 2 Client panic. The database object is not yet created (iDatabase is NULL)
+@panic SqlDb 3 Client panic. Failed to create a blob stream handle
+
+Usage of the IPC call arguments:
+Arg 0: [in]	    The length of the IPC data buffer
+Arg 1: [in]	    IPC data buffer containing blob parameters: table name, column name, rowid, mode, database name.
+Arg 2: [out]	IPC buffer containing the blob stream handle
+*/
+TInt CSqlSrvSession::DbBlobSourceL(const RMessage2& aMessage)
+	{	
+	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+	
+	iIpcStreams.AllocL();
+	
+	TInt ipcPrmLen = aMessage.Int0();
+	if(ipcPrmLen < 1)
+		{
+		__SQLLEAVE(KErrArgument);
+		}
+	TDes8& ipcPrmDes = ReadString8ZL(aMessage, 1, ipcPrmLen);
+	RDesReadStream strm(ipcPrmDes);
+	
+	TBuf8<KMaxFileName + 1> tblName;
+	ExtractNameL(strm, tblName);
+	
+	TBuf8<KMaxFileName + 1> colName;
+	ExtractNameL(strm, colName);
+	
+	TInt64 rowId;
+	strm >> rowId;
+	if(rowId == -1)
+		{
+		rowId = iDatabase->LastInsertedRowId();
+		}
+	if(rowId <= 0)
+		{
+		__SQLLEAVE(KErrArgument);
+		}
+
+	TInt32 tmp;	
+	strm >> tmp;
+	TBool isReadOnly = tmp != 0;
+	
+	TBuf8<KMaxFileName + 1> dbName;
+	ExtractNameL(strm, dbName, KMainDb16);
+						
+	strm.Close();
+			 		
+	// If the database is secure then check that the client has the required capabilities for the operation
+	TInt dbOpType = isReadOnly ? SQLITE_READ : SQLITE_UPDATE;
+	if(CSqlSrvDatabase::AuthorizeCallback(iDatabase, dbOpType, (char*)tblName.Ptr(), (char*)colName.Ptr(), (char*)dbName.Ptr(), '\0') != SQLITE_OK)	
+		{
+		__SQLLEAVE(KErrPermissionDenied);	
+		}
+
+	// Create the stream buffer
+	HBlobBuf* blobBuf = HBlobBuf::NewL(iDatabase->RawDbHandle(), dbName, tblName, colName, rowId, isReadOnly ? HBlobBuf::EReadOnly : HBlobBuf::EReadWrite);
+	blobBuf->PushL();
+		
+	// Return the blob size to the client
+	TPckgBuf<TIpcStreamBuf> ipcBuf;
+	TInt size = blobBuf->SizeL();
+	ipcBuf().iExt = size;
+	
+	// If this is a read stream then return the first client buffer-full of data
+	TInt len = 0;
+	if(isReadOnly && (size > 0))
+		{
+		len = Min(size, KIpcBufSize);
+		blobBuf->ReadL(ipcBuf().iData, len);	
+		}
+	
+	// Create the stream object
+	HIpcStream* ipcStream = new (ELeave) HIpcStream(blobBuf, len);
+	TInt strmHandle = iIpcStreams.Add(ipcStream);
+	__SQLPANIC_CLIENT(strmHandle > 0, aMessage, ESqlPanicBadHandle);
+	CleanupStack::Pop(blobBuf);
+
+	// Send the size and data to the client
+	aMessage.WriteL(2, ipcBuf);
+	SQLPROFILER_REPORT_IPC(ESqlIpcWrite, size);
+
+	return strmHandle;
+	}
+	
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////          Statement operations           //////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+Processes the request for preparing a 8/16-bit SQL statement.
+
+@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
+@panic SqlDb 3 Client panic. Internal error - invalid statement handle.
+
+Usage of the IPC call arguments:
+Arg 0: [out]	Column count and parameter count
+Arg 1: [in]		8/16-bit character length of SQL statement
+Arg 2: [in]		SQL statement
+*/
+TInt CSqlSrvSession::StmtPrepareL(const RMessage2& aMessage, TBool aIsText16)
+	{
+	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+	iStatements.AllocL();
+	TInt columnCount = -1;
+	TInt paramCount = -1;
+	TUint len = static_cast <TUint> (aMessage.Int1());
+	CSqlSrvStatement*  stmt = aIsText16 ? 
+						CSqlSrvStatement::NewLC(iDatabase->RawDbHandle(), ReadString16ZL(aMessage, 2, len), columnCount, paramCount) :
+						CSqlSrvStatement::NewLC(iDatabase->RawDbHandle(), ReadString8ZL(aMessage, 2, len), columnCount, paramCount);
+	TPckgBuf<TSqlIpcData> data;
+	data().iPrm1 = static_cast <TUint32> (columnCount);
+	data().iPrm2 = static_cast <TUint32> (paramCount);
+	aMessage.WriteL(0, data);
+	SQLPROFILER_REPORT_IPC(ESqlIpcWrite, sizeof(TSqlIpcData));
+	TInt stmtHandle = iStatements.Add(stmt);
+	__SQLPANIC_CLIENT(stmtHandle > 0, aMessage, ESqlPanicBadHandle);
+	CleanupStack::Pop(stmt);
+	return stmtHandle;
+	}
+
+/**
+Processes the request for executing the SQL statement.
+
+@param aFunction ESqlSrvStmtExec, ESqlSrvStmtAsyncExec, ESqlSrvStmtBindExec, ESqlSrvStmtBindExecRowId, ESqlSrvStmtAsyncBindExec
+
+Usage of the IPC call arguments:
+Arg 0: [in]    parameter buffer length in bytes (if aFunction == ESqlSrvStmtBindExec || aFunction == ESqlSrvStmtAsyncBindExec)
+Arg 1: [in]    parameter buffer 		(if aFunction == ESqlSrvStmtBindExec || aFunction == ESqlSrvStmtAsyncBindExec)
+*/
+TInt CSqlSrvSession::StmtExecL(const RMessage2& aMessage, TInt aStmtHandle, TSqlSrvFunction aFunction)
+	{	
+	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
+	if(aFunction == ESqlSrvStmtBindExec || aFunction == ESqlSrvStmtAsyncBindExec)
+		{
+		DoStmtBindL(aMessage, stmt);
+		}
+	__SQLLEAVE_IF_ERROR(stmt.Exec());
+	return iDatabase->LastChangesCount();
+	}
+
+/**
+Processes the request for moving the SQL statement on the next record.
+
+If the call does not fail, the only valid acceptable return codes should be KSqlAtRow and KSqlAtEnd.
+
+@panic SqlDb 7 In _DEBUG mode. The call completed with no error but the return code is not KSqlAtRow or KSqlAtEnd.
+
+Usage of the IPC call arguments:
+Arg 0: [in]    parameter buffer length in bytes (if aFunction == ESqlSrvStmtBindNext)
+Arg 1: [in]    parameter buffer 		(if aFunction == ESqlSrvStmtBindNext)
+Arg 2: [in]    client side column buffer length in bytes
+Arg 3: [out]   column buffer
+*/
+TInt CSqlSrvSession::StmtNextL(const RMessage2& aMessage, TInt aStmtHandle, TSqlSrvFunction aFunction)
+	{
+	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
+	if(aFunction == ESqlSrvStmtBindNext)
+		{
+		DoStmtBindL(aMessage, stmt);
+		}
+	TInt err = stmt.Next();
+	if(err == KSqlAtRow)
+		{
+		const RSqlBufFlat& bufFlat = stmt.ColumnValuesL();
+		TInt size = bufFlat.Size();
+		if(size > aMessage.Int2())
+			{
+			return size + KSqlClientBufOverflowCode;
+			}
+		aMessage.WriteL(3, bufFlat.BufDes());
+		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, size);
+		}
+	__SQLLEAVE_IF_ERROR(err);
+	__SQLASSERT(err == KSqlAtRow || err == KSqlAtEnd, ESqlPanicInternalError);
+	return err;
+	}
+
+/**
+Processes the request for retrieving the statement column or parameter names.
+
+If the client side buffer size is not big enough, the function returns the size + KSqlClientBufOverflowCode.
+In this case the client must increase the buffer and try again to get the buffer only.
+
+Usage of the IPC call arguments:
+Arg 0: [in]		size of the client side buffer for the names (in bytes)
+Arg 1: [out]	ipc buffer, column or parameter names
+*/
+TInt CSqlSrvSession::StmtNamesL(const RMessage2& aMessage, TInt aStmtHandle, TSqlSrvFunction aFunction)
+	{
+	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
+	const RSqlBufFlat& namesBuf = aFunction == ESqlSrvStmtParamNames ? stmt.ParamNamesL() : stmt.ColumnNamesL();
+	TInt size = namesBuf.Size();
+	if(size <= aMessage.Int0())
+		{
+		aMessage.WriteL(1, namesBuf.BufDes());
+		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, size);
+		return 0;
+		}
+	return size + KSqlClientBufOverflowCode;
+	}
+
+/**
+Processes the request for accessing a large column value as a stream of bytes/characters.
+
+Usage of the IPC call arguments:
+Arg 0: [in]		column index (0 based)
+Arg 2: [out]	ipc buffer, column source
+*/
+TInt CSqlSrvSession::StmtColumnSourceL(const RMessage2& aMessage, TInt aStmtHandle)
+	{
+	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
+	TInt columnIndex = aMessage.Int0();
+	TPtrC8 columnSource;
+	TInt err = stmt.ColumnSource(columnIndex, columnSource);
+	__SQLLEAVE_IF_ERROR(err);
+	HIpcReadBuf* ipcBuf = HIpcReadBuf::NewL(columnSource);
+	return NewOutputStreamL(aMessage, ipcBuf);
+	}
+
+/**
+Processes the request for setting a large parameter value from a stream of bytes or 8/16-bit characters.
+
+@panic SqlDb 3 Client panic. Internal error - invalid stream handle.
+
+Usage of the IPC call arguments:
+Arg 0: [in]		parameter index (0 based)
+Arg 2: [out]	ipc buffer, parameter source
+*/
+TInt CSqlSrvSession::StmtParamSinkL(const RMessage2& aMessage, TInt aStmtHandle, TSqlSrvFunction aFunction)
+	{
+	iIpcStreams.AllocL();
+	TInt parameterIndex = aMessage.Int0();
+	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
+	HSqlSrvStmtParamBuf::TDataType dataType = aFunction == ESqlSrvStmtBinParamSink ? HSqlSrvStmtParamBuf::EBinary : HSqlSrvStmtParamBuf::EText16;
+	HSqlSrvStmtParamBuf* paramBuf = stmt.GetParamBufL(parameterIndex, dataType, HSqlSrvStmtParamBuf::EBufIpcStream);
+	HIpcStream* ipcStream = new (ELeave) HIpcStream(paramBuf, 0);
+	TInt strmHandle = iIpcStreams.Add(ipcStream);
+	__SQLPANIC_CLIENT(strmHandle > 0, aMessage, ESqlPanicBadHandle);
+	return strmHandle;
+	}
+
+/**
+Usage of the IPC call arguments:
+Arg 0: [in]		the client side buffer length in bytes
+Arg 1: [out]	refers to a place where the buffer data will be copied to.
+*/
+void CSqlSrvSession::StmtGetBufFlatL(const RMessage2& aMessage, TInt aStmtHandle)
+	{
+	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
+	const RSqlBufFlat& bufFlat = stmt.BufFlatL(static_cast <TSqlBufFlatType> (aMessage.Int0()));
+	aMessage.WriteL(1, bufFlat.BufDes());
+	SQLPROFILER_REPORT_IPC(ESqlIpcWrite, bufFlat.Size());
+	}
+
+/**
+Usage of the IPC call arguments:
+Arg 0: [in]		column index
+Arg 1: [in]		column buffer length in bytes
+Arg 2: [in/out]	column buffer
+*/
+void CSqlSrvSession::StmtColumnValueL(const RMessage2& aMessage, TInt aStmtHandle)
+	{
+	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
+	TPtrC8 columnSource;
+	TInt columnIndex = aMessage.Int0();
+	TInt err = stmt.ColumnSource(columnIndex, columnSource);
+	__SQLLEAVE_IF_ERROR(err);
+	TInt len = aMessage.Int1();
+	if(columnSource.Length() > len)
+		{
+		TPtr8 ptr(const_cast <TUint8*> (columnSource.Ptr()), columnSource.Length(), columnSource.Length());
+		ptr.SetLength(len);
+		aMessage.WriteL(2, ptr);
+		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, len);
+		__SQLLEAVE(KErrOverflow);	
+		}
+	else
+		{
+		aMessage.WriteL(2, columnSource);
+		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, len);
+		}
+	}
+
+/**
+Usage of the IPC call arguments:
+Arg 0: [in]    parameter buffer length in bytes
+Arg 1: [in]    parameter buffer
+*/
+void CSqlSrvSession::DoStmtBindL(const RMessage2& aMessage, CSqlSrvStatement& aStmt)
+	{
+	TInt prmLen = aMessage.Int0();
+	RSqlBufFlat& prmBuf = Server().GetFlatBufL(prmLen);
+	aMessage.ReadL(1, prmBuf.BufPtr());
+	SQLPROFILER_REPORT_IPC(ESqlIpcRead, prmLen);
+	aStmt.BindL(prmBuf);
+	}
+
+/**
+Usage of the IPC call arguments:
+Arg 0: [in]    	input buffer max length in 16-bit characters
+Arg 1: [in/out]	buffer
+*/
+void CSqlSrvSession::StmtDeclColumnTypesL(const RMessage2& aMessage, TInt aStmtHandle)
+	{
+	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
+	HBufC* colTypesBuf = stmt.GetDeclColumnTypesL();
+	CleanupStack::PushL(colTypesBuf);
+	if(colTypesBuf->Des().Length() > aMessage.Int0())
+		{
+		__SQLLEAVE(KErrOverflow);
+		}
+	aMessage.WriteL(1, colTypesBuf->Des());
+	SQLPROFILER_REPORT_IPC(ESqlIpcWrite, (colTypesBuf->Des().Length() * sizeof(TText)));
+	CleanupStack::PopAndDestroy(colTypesBuf);
+	}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////	
+////////////////////////              Helper methods                     /////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////////////////////	
+
+/**
+Creates a new output IPC stream object using the aStreamBuf parameter as a stream buffer (stream data source).
+
+This method immediately pushes aStreamBuf onto the cleanup stack before creating a new output IPC 
+stream and so callers of this method should ensure that aStreamBuf is not already on the cleanup stack.
+
+Returns the handle of the created stream.
+
+@panic SqlDb 3 Client panic. Internal error - invalid stream handle.
+
+Usage of the IPC call arguments:
+Arg 2: [in/out]   IPC buffer
+*/
+TInt CSqlSrvSession::NewOutputStreamL(const RMessage2& aMessage, MStreamBuf* aStreamBuf)
+	{
+	aStreamBuf->PushL();
+	iIpcStreams.AllocL();
+	TInt size = aStreamBuf->SizeL();
+	TPckgBuf<TIpcStreamBuf> ipcBuf;
+	if(size > 0)						// read the first buffer-full
+		{
+		TInt len = Min(size, KIpcBufSize);
+		aStreamBuf->ReadL(ipcBuf().iData, len);
+		}
+	TInt handle = 0;
+	if(size < 0 || size > KIpcBufSize)
+		{								// create the stream object
+		HIpcStream* ipcStream = new (ELeave) HIpcStream(aStreamBuf, KIpcBufSize);
+		handle = iIpcStreams.Add(ipcStream);
+		__SQLPANIC_CLIENT(handle > 0, aMessage, ESqlPanicBadHandle);
+		CleanupStack::Pop(aStreamBuf);
+		}
+	else								// no more data to send
+		{
+		CleanupStack::PopAndDestroy(aStreamBuf);
+		}
+	if(size >= 0)
+		{
+		ipcBuf().iExt = size;
+		aMessage.WriteL(2, ipcBuf);
+		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, size);
+		}
+	return handle;
+	}
+
+/**
+Reads a 8-bit string with "aByteLen" bytes length, which is in "aArgNum" argument of aMessage.
+The string will be zero terminated after the "read" operation.
+Returns TDes8 reference pointing to the zero-terminated string.
+
+@leave KErrBadDescriptor The transferred data length is bigger than the aByteLen value 
+
+@panic SqlDb 4 Client panic. Negative aByteLen value.
+*/
+TDes8& CSqlSrvSession::ReadString8ZL(const RMessage2& aMessage, TInt aArgNum, TInt aByteLen)
+	{
+	__SQLPANIC_CLIENT(aByteLen >= 0, aMessage, ESqlPanicBadArgument);
+	TDes8& buf = Server().GetBuf8L(aByteLen + 1);
+	aMessage.ReadL(aArgNum, buf);
+	SQLPROFILER_REPORT_IPC(ESqlIpcRead, aByteLen);
+	if(buf.Length() > aByteLen)
+		{
+		__SQLLEAVE(KErrBadDescriptor);
+		}
+	buf.Append(TChar(0));
+	return buf;
+	}
+
+/**
+Reads a 16-bit string with "aCharLen" character length, which is in "aArgNum" argument of aMessage.
+The string will be zero terminated after the "read" operation.
+Returns TDes16 reference pointing to the zero-terminated string.
+
+@leave KErrBadDescriptor The transferred data length is bigger than the aCharLen value
+
+@panic SqlDb 4 Client panic. Negative aCharLen value.
+*/
+TDes16& CSqlSrvSession::ReadString16ZL(const RMessage2& aMessage, TInt aArgNum, TInt aCharLen)
+	{
+	__SQLPANIC_CLIENT(aCharLen >= 0, aMessage, ESqlPanicBadArgument);
+	TDes16& buf = Server().GetBuf16L(aCharLen + 1);
+	aMessage.ReadL(aArgNum, buf);
+	SQLPROFILER_REPORT_IPC(ESqlIpcRead, (aCharLen * sizeof(TText)));
+	if(buf.Length() > aCharLen)
+		{
+		__SQLLEAVE(KErrBadDescriptor);
+		}
+	buf.Append(TChar(0));
+	return buf;
+	}
+
+/**
+Reads a 16-bit string with "aCharLen" character length, which is in "aArgNum" argument of aMessage.
+Returns TDes16 reference pointing to the string.
+
+@leave KErrBadDescriptor The transferred data length is bigger than the aCharLen value
+
+@panic SqlDb 4 Client panic. Negative aCharLen value.
+*/
+TDes16& CSqlSrvSession::ReadString16L(const RMessage2& aMessage, TInt aArgNum, TInt aCharLen)
+	{
+	__SQLPANIC_CLIENT(aCharLen >= 0, aMessage, ESqlPanicBadArgument);
+	TDes16& buf = Server().GetBuf16L(aCharLen);
+	aMessage.ReadL(aArgNum, buf);
+	SQLPROFILER_REPORT_IPC(ESqlIpcRead, (aCharLen * sizeof(TText)));
+	if(buf.Length() > aCharLen)
+		{
+		__SQLLEAVE(KErrBadDescriptor);
+		}
+	return buf;
+	}
+
+/**
+The method reads the message argument 1 data and constructs a CSqlSecurityPolicy object from the data.
+
+@param aMessage Client request encapsulated in RMessage2 object.
+
+@return A pointer to the created CSqlSecurityPolicy instance.
+
+@leave KErrArgument, if aMessage argument 0 length is 0 or negative (no security data);
+       KErrNoMemory, out of memory condition has occured.
+
+Usage of the IPC call arguments:
+Arg 2: [in]  security policies buffer length in bytes if aFunction is ESqlSrvDbCreateSecure
+Arg 3: [in]  security policies buffer if aFunction is ESqlSrvDbCreateSecure
+*/
+CSqlSecurityPolicy* CSqlSrvSession::InternalizeSecurityPolicyL(const RMessage2& aMessage)
+	{
+	// Leave if there is no security policy data
+	// The format of arg[2] is an unsigned int
+	// with the policy length shifted and concated to the config length
+	// the policy data is the first part of arg[3]
+	const TUint KConfigStrLenBitWidth = 16;
+	TInt securityPolicyLen = aMessage.Int2() >> KConfigStrLenBitWidth;
+	if(securityPolicyLen < 1)
+		{
+		__SQLLEAVE(KErrArgument);
+		}
+	TSecurityPolicy defaultPolicy(TSecurityPolicy::EAlwaysFail);
+	CSqlSecurityPolicy* dbPolicy = CSqlSecurityPolicy::NewLC(defaultPolicy);
+	RSqlBufFlat& bufFlat = dbPolicy->BufFlat();
+	if(securityPolicyLen > bufFlat.MaxSize())
+		{
+		__SQLLEAVE_IF_ERROR(bufFlat.ReAlloc(securityPolicyLen));
+		}
+	TPtr8& ptr = bufFlat.BufPtr();
+	aMessage.ReadL(3, ptr);
+	SQLPROFILER_REPORT_IPC(ESqlIpcRead, securityPolicyLen);
+	// trim off config data if any
+	TInt extraBytes = ptr.Length() - securityPolicyLen;
+	if(extraBytes > 0)
+		{
+		ptr.Delete(securityPolicyLen, extraBytes);
+		}
+	CleanupStack::Pop(dbPolicy);
+	return dbPolicy;
+	}
+
+/**
+Reports how many objects are allocated by the client.
+If the database connection is not in a test mode, the allocated memory cells count will be ignored.
+*/
+TInt CSqlSrvSession::CountResources()
+	{
+	return iStatements.Count() + iIpcStreams.Count() + (iDbResourceTestMode ? User::CountAllocCells() : 0);
+	}
+
+/**
+Extracts from aMessage:
+- function code;
+- stream or statement handle;
+The function will panic the client if aMessage contains bad function code or bad handle encoded in it.
+*/
+void CSqlSrvSession::Extract(const RMessage2& aMessage, TSqlSrvFunction& aFunction, TInt& aHandle)
+	{
+	TInt msgCode = aMessage.Function();
+	aFunction = static_cast <TSqlSrvFunction> (KSqlSrvFunctionMask & msgCode);
+	//All operations with code > ESqlSrvDbDelete require valid iDatabase object.
+	if(aFunction > ESqlSrvDbDelete)
+		{
+		__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
+		}
+	if(aFunction >= ESqlSrvStmtClose)
+		{
+		//Extracting handle and handle type from the message code
+		TSqlSrvHandleType handleType = static_cast <TSqlSrvHandleType> (msgCode & KSqlSrvHandleTypeMask);
+		aHandle = (msgCode & KSqlSrvHandleMask) >> KSqlSrvHandleShiftBits;
+		__SQLPANIC_CLIENT(aHandle > 0, aMessage, ESqlPanicBadArgument);
+		if(aFunction >= ESqlSrvStmtClose && aFunction < ESqlSrvStreamBase)
+			{
+			__SQLPANIC_CLIENT(handleType == ESqlSrvStatementHandle, aMessage, ESqlPanicBadArgument);
+			}
+		else if(aFunction > ESqlSrvStreamBase)
+			{
+			__SQLPANIC_CLIENT(handleType == ESqlSrvStreamHandle, aMessage, ESqlPanicBadArgument);
+			}
+		}
+	}
+
+/**
+The function reads aStmt column 0 value and copies it into the client buffer, accessed via aMessage argument.
+
+If an error occurs during the execution the function leaves with the error code.
+Possible non-leaving return values:
+ - KErrNone              - the function has completed successfully;
+ - Positive return value - the length of the column, which means - the destination buffer is too small.
+                           This return value is possible only with text or binary columns.
+
+Usage of the IPC call arguments: 
+Arg 0: [in]		(8/16-bit character length of SQL statement) | (expected column value type << 24).
+Arg 1: [in]		SQL statement.
+Arg 2: [in]		Byte max length of the receiving buffer
+Arg 3: [in/out]	The receiving buffer
+*/
+TInt CSqlSrvSession::GetColumnValueL(const RMessage2& aMessage, CSqlSrvStatement& aStmt, TSqlColumnType aColType)
+	{
+	TInt rc = KErrNone;
+	switch(aColType)
+		{
+		case ESqlInt:
+			{
+			TInt val = aStmt.ColumnInt(0);
+			aMessage.WriteL(3, TPtrC8(reinterpret_cast <const TUint8*> (&val), sizeof(val)));
+			SQLPROFILER_REPORT_IPC(ESqlIpcWrite, sizeof(val));
+			}
+			break;
+		case ESqlInt64:
+			{
+			TInt64 val = aStmt.ColumnInt64(0);
+			aMessage.WriteL(3, TPtrC8(reinterpret_cast <const TUint8*> (&val), sizeof(val)));
+			SQLPROFILER_REPORT_IPC(ESqlIpcWrite, sizeof(val));
+			}
+			break;
+		case ESqlReal:
+			{
+			TReal val = aStmt.ColumnReal(0);
+			aMessage.WriteL(3, TPtrC8(reinterpret_cast <const TUint8*> (&val), sizeof(val)));
+			SQLPROFILER_REPORT_IPC(ESqlIpcWrite, sizeof(val));
+			}
+			break;
+		case ESqlText:
+		case ESqlBinary:
+		default:
+			{
+			TPtrC8 val;
+			if(aColType == ESqlText)
+				{
+				TPtrC textVal = aStmt.ColumnText(0);
+				val.Set(reinterpret_cast <const TUint8*> (textVal.Ptr()), textVal.Length() * sizeof(TUint16));
+				}
+			else
+				{
+				val.Set(aStmt.ColumnBinary(0));
+				}
+			TInt len = val.Length();
+			if(len > aMessage.Int2())
+				{
+				rc = aColType == ESqlText ? (TUint)len / sizeof(TUint16) : len;
+				len = aMessage.Int2();
+				}
+			aMessage.WriteL(3, val.Left(len));
+			SQLPROFILER_REPORT_IPC(ESqlIpcWrite, len);
+			}
+			break;
+		}
+	return rc;
+	}