os/persistentdata/persistentstorage/sql/SRC/Server/SqlSrvSession.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/persistentstorage/sql/SRC/Server/SqlSrvSession.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1766 @@
     1.4 +// Copyright (c) 2005-2010 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +// NTT DOCOMO, INC - Fix for Bug 1915 "SQL server panics when using long column type strings"
    1.16 +//
    1.17 +// Description:
    1.18 +//
    1.19 +
    1.20 +#include "SqlSrvMain.h"			//CSqlServer
    1.21 +#include "SqlSrvSession.h"		//CSqlSrvSession
    1.22 +#include "SqlSrvStatement.h"	//CSqlSrvStatement, HSqlSrvStmtParamBuf
    1.23 +#include "SqlSecurityImpl.h"	//CSqlSecurityPolicy
    1.24 +#include "SqlSrvUtil.h"			//Global server functions
    1.25 +#include "SqlUtil.h"			// config length
    1.26 +#include "SqlSrvDriveSpace.h"	//CSqlDriveSpace, RSqlDriveSpaceCol
    1.27 +#include "SqlSrvBlob.h"
    1.28 +#include "SqlResourceProfiler.h"
    1.29 +#include "SqlCompact.h"
    1.30 +#include "OstTraceDefinitions.h"
    1.31 +#ifdef OST_TRACE_COMPILER_IN_USE
    1.32 +#include "SqlSrvSessionTraces.h"
    1.33 +#endif
    1.34 +#include "SqlTraceDef.h"
    1.35 +
    1.36 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1.37 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    1.38 +
    1.39 +#pragma BullseyeCoverage off
    1.40 +
    1.41 +#ifdef _DEBUG
    1.42 +
    1.43 +const TInt KDelayedDbHeapFailureMask = 0x1000;
    1.44 +
    1.45 +//Puts the database connection in a test mode
    1.46 +//Returns true if the heap failure simulation has to be delayed untill the database is opened
    1.47 +//Initialises iDbResourceTestMode and iFailedAllocNumber (if delayed simulation) data members
    1.48 +inline TBool CSqlSrvSession::ActivateDbTestMode(TInt aHeapFailureMode, TInt aFailedAllocNumber)
    1.49 +	{
    1.50 +	iDbResourceTestMode = aHeapFailureMode;
    1.51 +	if(aHeapFailureMode & KDelayedDbHeapFailureMask)
    1.52 +		{
    1.53 +		iFailedAllocNumber = aFailedAllocNumber;
    1.54 +		return ETrue;
    1.55 +		}
    1.56 +	return EFalse;
    1.57 +	}
    1.58 +
    1.59 +//If the database connection is in a test mode then the macro will reset the heap allocation failure type.
    1.60 +//and stop the test mode.
    1.61 +inline void CSqlSrvSession::StopDbTestMode()
    1.62 +	{
    1.63 +	if(iDbResourceTestMode)
    1.64 +		{
    1.65 +		iDbResourceTestMode = 0;
    1.66 +		User::__DbgSetAllocFail(RHeap::EUser, RHeap::ENone, 0);
    1.67 +		}
    1.68 +	}
    1.69 +
    1.70 +//If the database connection is in a test mode then the function will mark the allocated by the 
    1.71 +//server resources.
    1.72 +inline void CSqlSrvSession::DbResourceMark()
    1.73 +	{
    1.74 +	if(iDbResourceTestMode)
    1.75 +		{
    1.76 +		ResourceCountMarkStart();
    1.77 +		}
    1.78 +	}
    1.79 +
    1.80 +//If the database connection is in a test mode then the macro will check the allocated by the server resources,
    1.81 +//comparing their count with the resource count at the moment DbResourceMark() has been called.
    1.82 +//The client will be panicked if the resource count now is different.
    1.83 +inline void CSqlSrvSession::DbResourceEnd(const RMessage2& aMessage)
    1.84 +	{
    1.85 +	if(iDbResourceTestMode)
    1.86 +		{
    1.87 +		ResourceCountMarkEnd(aMessage);
    1.88 +		}
    1.89 +	}
    1.90 +
    1.91 +//Executes the heap simulation failure.
    1.92 +inline void CSqlSrvSession::DbSetAllocFail(TInt aHeapFailureMode, TInt aFailedAllocNumber)
    1.93 +	{
    1.94 +	TInt mode = aHeapFailureMode & (KDelayedDbHeapFailureMask - 1);
    1.95 +	if(mode >= RAllocator::EBurstRandom && mode <= RAllocator::EBurstFailNext)
    1.96 +	    {
    1.97 +	    const TUint KBurst = 50; 
    1.98 +	    User::__DbgSetBurstAllocFail(RHeap::EUser, static_cast <RHeap::TAllocFail> (mode), aFailedAllocNumber, KBurst);
    1.99 +	    }
   1.100 +	else
   1.101 +	    {
   1.102 +        User::__DbgSetAllocFail(RHeap::EUser, static_cast <RHeap::TAllocFail> (mode), aFailedAllocNumber);
   1.103 +	    }
   1.104 +	}
   1.105 +	
   1.106 +//Executes the delayed heap simulation failure, if the connection is in test mode
   1.107 +inline void CSqlSrvSession::DbSetDelayedAllocFail()
   1.108 +	{
   1.109 +	if(iDbResourceTestMode & KDelayedDbHeapFailureMask)
   1.110 +		{
   1.111 +	    TInt mode = iDbResourceTestMode & (KDelayedDbHeapFailureMask - 1);
   1.112 +	    if(mode >= RAllocator::EBurstRandom && mode <= RAllocator::EBurstFailNext)
   1.113 +	        {
   1.114 +	        const TUint KBurst = 50; 
   1.115 +	        User::__DbgSetBurstAllocFail(RHeap::EUser, static_cast <RHeap::TAllocFail> (mode), iFailedAllocNumber, KBurst);
   1.116 +	        }
   1.117 +	    else
   1.118 +	        {
   1.119 +	        User::__DbgSetAllocFail(RHeap::EUser, static_cast <RHeap::TAllocFail> (mode), iFailedAllocNumber);
   1.120 +	        }
   1.121 +		}
   1.122 +	}
   1.123 +	
   1.124 +#else //_DEBUG
   1.125 +
   1.126 +inline TBool CSqlSrvSession::ActivateDbTestMode(TInt, TInt)
   1.127 +	{
   1.128 +	return EFalse;
   1.129 +	}
   1.130 +
   1.131 +inline void CSqlSrvSession::StopDbTestMode()
   1.132 +	{
   1.133 +	}
   1.134 +
   1.135 +inline void CSqlSrvSession::DbResourceMark()
   1.136 +	{
   1.137 +	}
   1.138 +
   1.139 +inline void CSqlSrvSession::DbResourceEnd(const RMessage2&)
   1.140 +	{
   1.141 +	}
   1.142 +
   1.143 +inline void CSqlSrvSession::DbSetAllocFail(TInt, TInt)
   1.144 +	{
   1.145 +	}
   1.146 +	
   1.147 +inline void CSqlSrvSession::DbSetDelayedAllocFail()
   1.148 +	{
   1.149 +	}
   1.150 +
   1.151 +#endif//_DEBUG
   1.152 +
   1.153 +#pragma BullseyeCoverage on
   1.154 +
   1.155 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.156 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.157 +
   1.158 +/**
   1.159 +Searches aContainer for an object identified by aHandle.
   1.160 +If such object exists, a reference to it is returned.
   1.161 +If there is no object, the client gets a panic.
   1.162 +
   1.163 +@panic SqlDb 4 Client panic. Invalid aHandle parameter value (zero, negative or out of range).
   1.164 +
   1.165 +@internalComponent
   1.166 +*/
   1.167 +template <class T> T& SqlSessObjFind(RDbObjContainer<T>& aContainer, TInt aHandle, const RMessage2& aMessage)
   1.168 +	{
   1.169 +	T* obj = aContainer.Find(aHandle);
   1.170 +	__SQLPANIC_CLIENT2(obj != NULL, aMessage, ESqlPanicBadArgument);
   1.171 +	return *obj;
   1.172 +	}
   1.173 +
   1.174 +//This function return true, if there is free disk space on drive where the main database file is.
   1.175 +static TBool HasFreeDiskSpace(RFs& aFs, TDriveNumber aDrive)
   1.176 +	{
   1.177 +	TVolumeInfo volInfo;
   1.178 +	TInt err = aFs.Volume(volInfo, aDrive);
   1.179 +	if(err == KErrNone)
   1.180 +		{
   1.181 +		const TInt64 KDiskSpaceThreshold = 1024 * 4;
   1.182 +		return volInfo.iFree > KDiskSpaceThreshold;
   1.183 +		}
   1.184 +	return ETrue;
   1.185 +	}
   1.186 +	
   1.187 +//If aError is KSqlErrFull and  there is no free disk space, then KSqlErrFull is converted to KErrDiskFull
   1.188 +//and returned.
   1.189 +static TInt ConvertSqlFull2DiskFullErr(TInt aError, RFs& aFs, TDriveNumber aDrive)
   1.190 +	{
   1.191 +	if(aError == KSqlErrFull && !HasFreeDiskSpace(aFs, aDrive))
   1.192 +		{
   1.193 +		aError = KErrDiskFull;
   1.194 +		SQL_TRACE_SESSION(OstTrace1(TRACE_INTERNALS, CONVERTSQLFULL2DISKFULLERRROR, "0;ConvertSqlFull2DiskFullErr;aError=KSqlErrFull;!HasFreeDiskSpace();aDrive=%d", (TInt)aDrive));
   1.195 +		}
   1.196 +	return aError;
   1.197 +	}
   1.198 +
   1.199 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.200 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.201 +
   1.202 +/**
   1.203 +Creates a new instance of CSqlSrvSession class.
   1.204 +
   1.205 +This function shall never be called directly.
   1.206 +It is CSqlServer responsibility to create a new server side session object as a responce to the criation of a
   1.207 +client side session instance.
   1.208 +
   1.209 +@return A pointer to the created CSqlSrvSession instance.
   1.210 +
   1.211 +@leave KErrNoMemory, an out of memory condition has occurred;
   1.212 +
   1.213 +@see CSqlServer
   1.214 +@see CSqlServer::NewSessionL()
   1.215 +*/
   1.216 +CSqlSrvSession* CSqlSrvSession::NewL()
   1.217 +	{
   1.218 +	SQL_TRACE_SESSION(OstTrace0(TRACE_INTERNALS, CSQLSRVSESSION_NEWL_ENTRY, "Entry;0;CSqlSrvSession::NewL"));
   1.219 +	CSqlSrvSession* self = new (ELeave)	CSqlSrvSession;
   1.220 +	CleanupStack::PushL(self);
   1.221 +	self->ConstructL();
   1.222 +	CleanupStack::Pop(self);
   1.223 +	SQL_TRACE_SESSION(OstTrace1(TRACE_INTERNALS, CSQLSRVSESSION_NEWL_EXIT, "Exit;0x%X;CSqlSrvSession::NewL", (TUint)self));
   1.224 +	return self;
   1.225 +	}
   1.226 +
   1.227 +/**
   1.228 +Frees the allocated by CSqlSrvSession instance resources and memory.
   1.229 +*/
   1.230 +CSqlSrvSession::~CSqlSrvSession()
   1.231 +	{
   1.232 +	SQL_TRACE_SESSION(OstTraceExt2(TRACE_INTERNALS, CSQLSRVSESSION_CSQLSRVSESSION2_ENTRY, "Entry;0x%X;CSqlSrvSession::~CSqlSrvSession;iDatabase=0x%X", (TUint)this, (TUint)iDatabase));
   1.233 +	StopDbTestMode();
   1.234 +	DbFreeReservedSpace();
   1.235 +	iIpcStreams.Close();
   1.236 +	iStatements.Close();
   1.237 +	delete iDatabase;
   1.238 +	SQL_TRACE_SESSION(OstTrace1(TRACE_INTERNALS, CSQLSRVSESSION_CSQLSRVSESSION2_EXIT, "Exit;0x%X;CSqlSrvSession::~CSqlSrvSession", (TUint)this));
   1.239 +	}
   1.240 +
   1.241 +/**
   1.242 +Receives and dispatches all client side requests.
   1.243 +
   1.244 +CSession2::ServiceL() implementation.
   1.245 +
   1.246 +@param aMessage Client message containing the request (function code and data)
   1.247 +
   1.248 +@leave The function may leave with some database specific 
   1.249 +	   errors categorised as ESqlDbError or system-wide error codes.
   1.250 +
   1.251 +@see CSession2::ServiceL()
   1.252 +*/
   1.253 +void CSqlSrvSession::ServiceL(const RMessage2& aMessage)
   1.254 +	{
   1.255 +	TSqlSrvFunction funcCode = ESqlSrvTestBase;
   1.256 +	TInt handle = 0;
   1.257 +	Extract(aMessage, funcCode, handle);
   1.258 +	TInt retCode = KErrNone;
   1.259 +	if(funcCode >= ESqlSrvDbBase)
   1.260 +		{
   1.261 +		SQLPROFILER_REPORT_IPC(ESqlIpcRq, 0);
   1.262 +		}
   1.263 +	__SQLTRACE_SESSIONEXPR(++iIpcCallCounter);
   1.264 +    SQL_TRACE_SESSION(OstTraceExt4(TRACE_INTERNALS, CSQLSRVSESSION_SERVICEL_ENTRY, "Entry;0x%X;CSqlSrvSession::ServiceL;aMessage.Handle()=0x%X;funcCode=0x%X;iIpcCallCounter=%u", (TUint)this, (TUint)aMessage.Handle(), (TUint)funcCode, iIpcCallCounter));
   1.265 +	SQLPROFILER_IPC_START(iIpcCallCounter, iDatabase ? (TUint)iDatabase->RawDbHandle() : 0);
   1.266 +	switch(funcCode)
   1.267 +		{
   1.268 +		//////////////////////  resource check operations  ///////////////////////////
   1.269 +		case ESqlSrvResourceMark:
   1.270 +			ResourceCountMarkStart();
   1.271 +			break;
   1.272 +		case ESqlSrvResourceCheck:
   1.273 +			ResourceCountMarkEnd(aMessage);
   1.274 +			break;
   1.275 +		case ESqlSrvResourceCount:
   1.276 +			retCode = CountResources();					//Returns the recourse count
   1.277 +			break;
   1.278 +		case ESqlSrvSetDbHeapFailure:
   1.279 +			if(ActivateDbTestMode(aMessage.Int0(), aMessage.Int1()))
   1.280 +				{
   1.281 +				break;	
   1.282 +				}
   1.283 +		case ESqlSrvSetHeapFailure:
   1.284 +			DbSetAllocFail(aMessage.Int0(), aMessage.Int1());
   1.285 +			break;
   1.286 +		//////////////////////   profiling operations  //////////////////////////////////
   1.287 +		case ESqlSrvProfilerStart:
   1.288 +			TSqlSrvResourceProfiler::StartL(aMessage);
   1.289 +			break;
   1.290 +		case ESqlSrvProfilerStop:
   1.291 +			TSqlSrvResourceProfiler::StopL(aMessage);
   1.292 +			break;
   1.293 +		case ESqlSrvProfilerReset:
   1.294 +			TSqlSrvResourceProfiler::ResetL(aMessage);
   1.295 +			break;
   1.296 +		case ESqlSrvProfilerQuery:
   1.297 +			ProfilerQueryL(aMessage);
   1.298 +			break;
   1.299 +		//////////////////////   database operations //////////////////////////////////
   1.300 +		case ESqlSrvDbCreate:
   1.301 +		case ESqlSrvDbCreateSecure:
   1.302 +		case ESqlSrvDbOpen:
   1.303 +			DbResourceMark();
   1.304 +			DbCreateObjectL(aMessage, funcCode);
   1.305 +			DbSetDelayedAllocFail();
   1.306 +			break;
   1.307 +		case ESqlSrvDbOpenFromHandle:
   1.308 +			DbResourceMark();
   1.309 +			DbCreateObjectFromHandleL(aMessage);
   1.310 +			DbSetDelayedAllocFail();
   1.311 +			break;
   1.312 +		case ESqlSrvDbAttach:
   1.313 +			DbAttachL(aMessage);
   1.314 +			break;
   1.315 +		case ESqlSrvDbAttachFromHandle:
   1.316 +			DbAttachFromHandleL(aMessage);
   1.317 +			break;
   1.318 +		case ESqlSrvDbDetach:
   1.319 +			DbDetachL(aMessage);
   1.320 +			break;
   1.321 +		case ESqlSrvDbClose:
   1.322 +			DbDestroyObject();
   1.323 +			DbResourceEnd(aMessage);
   1.324 +			StopDbTestMode();
   1.325 +			break;
   1.326 +		case ESqlSrvDbCopy:
   1.327 +			DbResourceMark();
   1.328 +			DbCopyFileL(aMessage);
   1.329 +			break;
   1.330 +		case ESqlSrvDbDelete:
   1.331 +			DbResourceMark();
   1.332 +			DbDeleteFileL(aMessage);
   1.333 +			break;
   1.334 +		case ESqlSrvLastErrorMsg:
   1.335 +			retCode = DbLastErrorMessageL(aMessage);//may return that the client buffer is not big enough for the message
   1.336 +			break;
   1.337 +		case ESqlSrvDbLastInsertedRowId:
   1.338 +			DbLastInsertedRowIdL(aMessage);
   1.339 +			break;
   1.340 +		case ESqlSrvDbExec8:
   1.341 +			retCode = DbExecSql8L(aMessage);		//returns the count of affected records
   1.342 +			break;
   1.343 +		case ESqlSrvDbExec16:
   1.344 +			retCode = DbExecSql16L(aMessage);	//returns the count of affected records
   1.345 +			break;
   1.346 +		case ESqlSrvDbSetIsolationLevel:
   1.347 +			DbSetIsolationLevelL(aMessage);
   1.348 +			break;
   1.349 +		case ESqlSrvDbGetSecurityPolicy:
   1.350 +			retCode = DbGetSecurityPolicyL(aMessage);//may return that the client buffer is not big enough for the security policy
   1.351 +			break;
   1.352 +		case ESqlSrvDbScalarFullSelect8:
   1.353 +			retCode = DbScalarFullSelectL(aMessage, EFalse);//may return that the client buffer is not big enough for the column value
   1.354 +			break;
   1.355 +		case ESqlSrvDbScalarFullSelect16:
   1.356 +			retCode = DbScalarFullSelectL(aMessage, ETrue);//may return that the client buffer is not big enough for the column value
   1.357 +			break;
   1.358 +		case ESqlSrvDbInTransaction:
   1.359 +			retCode = DbInTransaction(aMessage);	//Returns whether the database in in transaction or not - true/false
   1.360 +			break;
   1.361 +		case ESqlSrvDbSize:
   1.362 +			retCode = DbSizeL(aMessage);			//Returns the database size
   1.363 +			break;
   1.364 +		case ESqlSrvDbSize2:
   1.365 +			DbSize2L(aMessage);
   1.366 +			break;
   1.367 +		case ESqlSrvDbCompact:
   1.368 +			retCode = DbCompactL(aMessage);			//Returns the amount of the removed free database space
   1.369 +			break;
   1.370 +		//////////////////////   reserved drive space management ////////////////////////
   1.371 +		case ESqlSrvDbReserveDriveSpace:
   1.372 +			__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
   1.373 +			DbReserveDriveSpaceL();
   1.374 +			break;
   1.375 +		case ESqlSrvDbFreeReservedSpace:
   1.376 +			__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
   1.377 +			DbFreeReservedSpace();
   1.378 +			break;
   1.379 +		case ESqlSrvDbGetReserveAccess:
   1.380 +			__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
   1.381 +			DbGetReserveAccessL();
   1.382 +			break;
   1.383 +		case ESqlSrvDbReleaseReserveAccess:
   1.384 +			__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
   1.385 +			DbReleaseReserveAccess();
   1.386 +			break;
   1.387 +		//////////////////////   BLOB source ///////////////////////////////////////////
   1.388 +		case ESqlSrvDbBlobSource:
   1.389 +			retCode = DbBlobSourceL(aMessage);		//Returns the BLOB handle
   1.390 +			break;
   1.391 +		//////////////////////   statement operations //////////////////////////////////
   1.392 +		case ESqlSrvStmtPrepare8:
   1.393 +			retCode = StmtPrepareL(aMessage, EFalse);//returns the statement handle
   1.394 +			break;
   1.395 +		case ESqlSrvStmtPrepare16:
   1.396 +			retCode = StmtPrepareL(aMessage, ETrue);//returns the statement handle
   1.397 +			break;
   1.398 +		case ESqlSrvStmtClose:
   1.399 +			iStatements.Remove(handle);
   1.400 +			break;
   1.401 +		case ESqlSrvStmtReset:
   1.402 +			retCode = ::SqlSessObjFind(iStatements, handle, aMessage).Reset();//May return that the statement has expired
   1.403 +			break;
   1.404 +		case ESqlSrvStmtExec:
   1.405 +		case ESqlSrvStmtAsyncExec:
   1.406 +		case ESqlSrvStmtBindExec:
   1.407 +		case ESqlSrvStmtAsyncBindExec:
   1.408 +			retCode = StmtExecL(aMessage, handle, funcCode);//returns the count of affected records
   1.409 +			break;
   1.410 +		case ESqlSrvStmtNext:
   1.411 +		case ESqlSrvStmtBindNext:
   1.412 +			retCode = StmtNextL(aMessage, handle, funcCode);//returns a non-negative number if the client side buffer is too small
   1.413 +			break;
   1.414 +		case ESqlSrvStmtColumnNames:
   1.415 +		case ESqlSrvStmtParamNames:
   1.416 +			retCode = StmtNamesL(aMessage, handle, funcCode);//returns a non-negative number if the client side buffer is too small
   1.417 +			break;
   1.418 +		case ESqlSrvStmtColumnSource:
   1.419 +			retCode = StmtColumnSourceL(aMessage, handle);//returns an IPC stream handle
   1.420 +			break;
   1.421 +		case ESqlSrvStmtBinParamSink:
   1.422 +		case ESqlSrvStmtTxtParamSink16:
   1.423 +			retCode = StmtParamSinkL(aMessage, handle, funcCode);//returns an IPC stream handle
   1.424 +			break;
   1.425 +		case ESqlSrvStmtBufFlat:
   1.426 +			StmtGetBufFlatL(aMessage, handle);
   1.427 +			break;
   1.428 +		case ESqlSrvStmtColumnValue:
   1.429 +			StmtColumnValueL(aMessage, handle);
   1.430 +			break;
   1.431 +		case ESqlSrvStmtDeclColumnTypes:
   1.432 +			retCode = StmtDeclColumnTypesL(aMessage, handle);
   1.433 +			break;
   1.434 +		//////////////////////   stream operations //////////////////////////////////
   1.435 +		case ESqlSrvStreamRead:
   1.436 +			retCode = ::SqlSessObjFind(iIpcStreams, handle, aMessage).ReadL(aMessage);
   1.437 +			break;
   1.438 +		case ESqlSrvStreamWrite:
   1.439 +			::SqlSessObjFind(iIpcStreams, handle, aMessage).WriteL(aMessage);
   1.440 +			break;
   1.441 +		case ESqlSrvStreamSize:
   1.442 +			retCode = ::SqlSessObjFind(iIpcStreams, handle, aMessage).SizeL();
   1.443 +			break;
   1.444 +		case ESqlSrvStreamSynch:
   1.445 +			::SqlSessObjFind(iIpcStreams, handle, aMessage).SynchL();
   1.446 +			break;
   1.447 +		case ESqlSrvStreamClose:
   1.448 +			iIpcStreams.Remove(handle);
   1.449 +			break;
   1.450 +		//////////////////////                     //////////////////////////////////
   1.451 +		default:	
   1.452 +			retCode = KErrNotSupported;
   1.453 +			break;
   1.454 +		}
   1.455 +	Server().Compactor().RestartTimer();
   1.456 +	Server().MinimizeBuffers();		
   1.457 +	if(!aMessage.IsNull())
   1.458 +		{
   1.459 +		aMessage.Complete(retCode);
   1.460 +		}
   1.461 +	SQL_TRACE_SESSION(OstTraceExt4(TRACE_INTERNALS, CSQLSRVSESSION_SERVICEL_EXIT, "Exit;0x%X;CSqlSrvSession::ServiceL;funcCode=0x%X;retCode=%d;iIpcCallCounter=%u", (TUint)this, (TUint)funcCode, retCode, iIpcCallCounter));
   1.462 +	}
   1.463 +
   1.464 +/**
   1.465 +If aError is KErrBadDescriptor, then panic the client, else - default error handling.
   1.466 +KErrBadDescriptor error may be thrown from "message write" operations, if the client supplied a bad
   1.467 +descriptor to the server.
   1.468 +*/
   1.469 +void CSqlSrvSession::ServiceError(const RMessage2& aMessage, TInt aError)
   1.470 + 	{
   1.471 +	SQL_TRACE_SESSION(OstTraceExt4(TRACE_INTERNALS, CSQLSRVSESSION_SERVICEERROR_ENTRY, "Entry;0x%X;CSqlSrvSession::ServiceError;aMessage.Function()=0x%X;aError=%d;iIpcCallCounter=%u", (TUint)this, (TUint)aMessage.Function(), aError, iIpcCallCounter));
   1.472 +	Server().MinimizeBuffers();		
   1.473 +	aError = ::ConvertSqlFull2DiskFullErr(aError, Server().FileData().Fs(), iDrive);
   1.474 + 	if(aError == KErrBadDescriptor)
   1.475 + 		{
   1.476 +		//The __SQLPANIC_CLIENT() macro cannot be used here because it calls a leaving function. A leaving call
   1.477 +		//from a leaving call will terminate the server.
   1.478 +		_LIT(KPanicCategory, "SqlDb");
   1.479 +		aMessage.Panic(KPanicCategory, ESqlPanicBadDescriptor);
   1.480 + 		}
   1.481 + 	SQLPROFILER_IPC_ERROR(iIpcCallCounter, static_cast <TSqlSrvFunction> (KSqlSrvFunctionMask & aMessage.Function()), 
   1.482 + 	       iDatabase ? (TUint)iDatabase->RawDbHandle() : 0, aError);
   1.483 + 	CSession2::ServiceError(aMessage, aError);
   1.484 + 	SQL_TRACE_SESSION(OstTraceExt3(TRACE_INTERNALS, CSQLSRVSESSION_SERVICEERROR_EXIT, "Exit;0x%X;CSqlSrvSession::ServiceError;aMessage.Function()=0x%X;iIpcCallCounter=%u", (TUint)this, (TUint)aMessage.Function(), iIpcCallCounter));
   1.485 +   	}
   1.486 +
   1.487 +///////////////////////////////////////////////////////////////////////////////////////////////////////
   1.488 +////////////////////////////          Profiler  operations           ///////////////////////////////////
   1.489 +///////////////////////////////////////////////////////////////////////////////////////////////////////
   1.490 +
   1.491 +#pragma BullseyeCoverage off
   1.492 +
   1.493 +/**
   1.494 +Retrieves the counter values for the specified profiling counter.
   1.495 +
   1.496 +@leave  KErrNone, the operation completed successfully,
   1.497 +        KErrOverflow, the receiving buffer size is too small;
   1.498 +                  One of the other system-wide error codes may also be returned.
   1.499 +
   1.500 +@see TSqlResourceProfiler
   1.501 +
   1.502 +Usage of the IPC call arguments:
   1.503 + - Arg 0: [in]  profiling counter type, one of the TSqlResourceProfiler::TSqlCounter enum item values.
   1.504 + - Arg 1: [in]  the size of the buffer for the profiling counter values.
   1.505 + - Arg 2: [out] the buffer for the profiling counter values.
   1.506 +
   1.507 +@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
   1.508 +*/
   1.509 +void CSqlSrvSession::ProfilerQueryL(const RMessage2& aMessage)
   1.510 +	{
   1.511 +	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
   1.512 +	if(aMessage.Int0() == TSqlResourceProfiler::ESqlCounterConfig)
   1.513 +		{
   1.514 +		const TInt KConfigBufLen = 128;
   1.515 +		if(aMessage.Int1() < KConfigBufLen)
   1.516 +			{
   1.517 +			__SQLLEAVE(KErrOverflow);	
   1.518 +			}
   1.519 +		TBuf8<KConfigBufLen> res;
   1.520 +		iDatabase->QueryConfigL(res);
   1.521 +		aMessage.WriteL(2, res);
   1.522 +		}
   1.523 +	else
   1.524 +		{
   1.525 +		TSqlSrvResourceProfiler::QueryL(aMessage);
   1.526 +		}				
   1.527 +	}
   1.528 +
   1.529 +#pragma BullseyeCoverage on
   1.530 +
   1.531 +///////////////////////////////////////////////////////////////////////////////////////////////////////
   1.532 +////////////////////////////          Database operations           ///////////////////////////////////
   1.533 +///////////////////////////////////////////////////////////////////////////////////////////////////////
   1.534 +
   1.535 +/**
   1.536 +Processes the request for creating/opening a database.
   1.537 +
   1.538 +The function initializes iDatabase and iDrive data members.
   1.539 +
   1.540 +Usage of the IPC call arguments:
   1.541 +Arg 0: [in]  database file name length in 16-bit characters
   1.542 +Arg 1: [in]  database file name
   1.543 +Arg 2: [in]  PPPPCCCC, where PPPP is the security policy length, CCCC is the config string length.
   1.544 +Arg 3: [in]  security policies buffer | config string
   1.545 +
   1.546 +@panic SqlDb 1 Client panic. iDatabase is not NULL (it has been created already)
   1.547 +@panic SqlDb 4 Client panic. Negative or too big config string length
   1.548 +@panic SqlDb 4 Client panic. Negative security policy length, or zero length if the request is to create a secure database 
   1.549 +*/
   1.550 +void CSqlSrvSession::DbCreateObjectL(const RMessage2& aMessage, TSqlSrvFunction aFunction)
   1.551 +	{
   1.552 +	__SQLPANIC_CLIENT(!iDatabase, aMessage, ESqlPanicObjExists);
   1.553 +	const TInt KSecurityPolicyLen = (aMessage.Int2() & 0x7fff0000) >> 16;
   1.554 +    //If the security policy length is negative then this is a programming error.
   1.555 +    __SQLPANIC_CLIENT(KSecurityPolicyLen >= 0, aMessage, ESqlPanicBadArgument);
   1.556 +	const TInt KConfigStringLen = aMessage.Int2() & 0xffff;
   1.557 +	//If KConfigStringLen is invalid then this is a programming error. 
   1.558 +	//If the client sends a too big config string - this is handled in the client side session.
   1.559 +    __SQLPANIC_CLIENT((TUint)KConfigStringLen <= KSqlSrvMaxConfigStrLen, aMessage, ESqlPanicBadArgument);
   1.560 +	RBuf8 securityAndConfigBuf;
   1.561 +	CleanupClosePushL(securityAndConfigBuf);
   1.562 +	if((KSecurityPolicyLen + KConfigStringLen) > 0)
   1.563 +	    {
   1.564 +	    securityAndConfigBuf.CreateL(KSecurityPolicyLen + KConfigStringLen);
   1.565 +        aMessage.ReadL(3, securityAndConfigBuf); 
   1.566 +        SQLPROFILER_REPORT_IPC(ESqlIpcRead, (KSecurityPolicyLen + KConfigStringLen));
   1.567 +	    }
   1.568 +	TSqlSrvFileData& fileData = Server().FileData();
   1.569 +	TPtrC8 configStr(KNullDesC8);
   1.570 +	if(KConfigStringLen > 0)
   1.571 +	    {
   1.572 +	    configStr.Set(securityAndConfigBuf.Mid(KSecurityPolicyLen));//the first part of the buffer is for the security policies
   1.573 +	    }
   1.574 +	fileData.SetL(aMessage, aMessage.Int0(), 1, &configStr);
   1.575 +	iDrive = fileData.Drive();
   1.576 +	switch(aFunction)
   1.577 +		{
   1.578 +		case ESqlSrvDbCreate:
   1.579 +			if(fileData.IsSecureFileNameFmt())
   1.580 +				{
   1.581 +				__SQLLEAVE(KErrArgument);	
   1.582 +				}
   1.583 +			iDatabase = CSqlSrvDatabase::CreateL(fileData);
   1.584 +			break;
   1.585 +		case ESqlSrvDbCreateSecure:
   1.586 +			{
   1.587 +		    __SQLPANIC_CLIENT(KSecurityPolicyLen > 0, aMessage, ESqlPanicBadArgument);
   1.588 +			if(!fileData.IsSecureFileNameFmt())
   1.589 +				{
   1.590 +				__SQLLEAVE(KErrArgument);	
   1.591 +				}
   1.592 +			//The caller can create a secure database which secure UID matches his secure UID.
   1.593 +			if(fileData.SecureUid() != aMessage.SecureId())
   1.594 +				{
   1.595 +				__SQLLEAVE(KErrPermissionDenied);	
   1.596 +				}
   1.597 +			CSqlSecurityPolicy* policy = CreateSecurityPolicyL(securityAndConfigBuf.Left(KSecurityPolicyLen));
   1.598 +			iDatabase = CSqlSrvDatabase::CreateSecureL(fileData, policy);
   1.599 +			}
   1.600 +			break;
   1.601 +		case ESqlSrvDbOpen:
   1.602 +			iDatabase = CSqlSrvDatabase::OpenL(fileData);
   1.603 +			break;
   1.604 +		default:
   1.605 +			__SQLLEAVE(KErrArgument);	
   1.606 +			break;
   1.607 +		}
   1.608 +	CleanupStack::PopAndDestroy(&securityAndConfigBuf);
   1.609 +	}
   1.610 +
   1.611 +/**
   1.612 +Processes the request for opening a database from file handle.
   1.613 +The server expects that the database to be opened/created is in the applicatio's private data cage.
   1.614 +
   1.615 +Usage of the IPC call arguments:
   1.616 + - Arg 0: [in]  The 32 bits of the argument are used as follow:
   1.617 + @code
   1.618 + MSB                                                                                 LSB
   1.619 + 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
   1.620 + 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 
   1.621 + @endcode
   1.622 + Where:
   1.623 + @code
   1.624 +  - "Ro" - read-only flag, true if the file is read-only;
   1.625 +  - "Cr" - create/open flag, true if the file was created, false if the file was opened;
   1.626 +  - "C"  - config string length in 16-bit characters;
   1.627 +  - "F"  - database file name length in 16-bit characters;
   1.628 + @endcode
   1.629 + - Arg 1: [in]  database file name | config string
   1.630 + - Arg 2: [in]  file session handle
   1.631 + - Arg 3: [in]  database file handle
   1.632 +
   1.633 +@panic SqlDb 1 Client panic. iDatabase is not NULL (it has been created already)
   1.634 +*/
   1.635 +void CSqlSrvSession::DbCreateObjectFromHandleL(const RMessage2& aMessage)
   1.636 +	{
   1.637 +	__SQLPANIC_CLIENT(!iDatabase, aMessage, ESqlPanicObjExists);
   1.638 +	const TBool KReadOnly = (aMessage.Int0() & 0x80000000) != 0;
   1.639 +	const TBool KCreated = (aMessage.Int0() & 0x40000000) != 0;
   1.640 +	const TInt KDbFileNameLen = aMessage.Int0() & 0x0000FFFF;
   1.641 +	const TInt KConfigStringLen = (aMessage.Int0() & 0x3FFF0000) >> 16;
   1.642 +    __SQLPANIC_CLIENT((TUint)KConfigStringLen <= KSqlSrvMaxConfigStrLen, aMessage, ESqlPanicBadArgument);
   1.643 +    __SQLPANIC_CLIENT((TUint)KDbFileNameLen <= KMaxFileName, aMessage, ESqlPanicBadArgument);
   1.644 +	TDes16& buffer = Server().GetBuf16L(KDbFileNameLen + KConfigStringLen);
   1.645 +	aMessage.ReadL(1, buffer);
   1.646 +	SQLPROFILER_REPORT_IPC(ESqlIpcRead, ((KDbFileNameLen + KConfigStringLen) * sizeof(TText)));
   1.647 +	TFileName dbFileName;
   1.648 +	dbFileName.Copy(buffer.LeftTPtr(KDbFileNameLen));
   1.649 +	TBuf8<KSqlSrvMaxConfigStrLen> configStr;
   1.650 +	if(KConfigStringLen > 0)
   1.651 +		{
   1.652 +		configStr.Copy(buffer.MidTPtr(KDbFileNameLen, KConfigStringLen));
   1.653 +		}
   1.654 +	TSqlSrvFileData& fileData = Server().FileData();
   1.655 +	fileData.SetFromHandleL(aMessage, dbFileName, KCreated, KReadOnly, &configStr);
   1.656 +	iDrive = fileData.Drive();
   1.657 +	iDatabase = CSqlSrvDatabase::OpenL(fileData);
   1.658 +	}
   1.659 +
   1.660 +/**
   1.661 +Processes the request for copying a database.
   1.662 +
   1.663 +Only the database creator can copy the database if the database is a secure database.
   1.664 +
   1.665 +Usage of the IPC call arguments:
   1.666 +Arg 0: [in]  source database file name length
   1.667 +Arg 1: [in]  source database file name
   1.668 +Arg 2: [in]  destination database file name length
   1.669 +Arg 3: [in]  destination database file name
   1.670 +*/
   1.671 +void CSqlSrvSession::DbCopyFileL(const RMessage2& aMessage)
   1.672 +	{
   1.673 +	const TInt KDbCnt = 2;											//"2" - because we have 2 dbases: src and dest
   1.674 +	const TInt KSrcDbIdx = 0;
   1.675 +	const TInt KDestDbIdx = 1;
   1.676 +	TInt fileNameLen[KDbCnt] = {aMessage.Int0(), aMessage.Int2()};
   1.677 +	TSqlSrvFileData& fileData = Server().FileData();
   1.678 +	TUint dbSecureFlag[KDbCnt];
   1.679 +	TUid  dbSID[KDbCnt] = {KNullUid, KNullUid};
   1.680 +	TFileName dbFileName[KDbCnt];
   1.681 +	//Initialize dbSecureFlag[], dbSID[] and dbFileName[] array elements
   1.682 +	for(TInt i=0;i<KDbCnt;++i)									
   1.683 +		{
   1.684 +		fileData.SetL(aMessage, fileNameLen[i], i * KDbCnt + 1);	//"i * KDbCnt + 1" is the RMessage2 parameter number: 1 for src db, 3 for dest db
   1.685 +		dbSecureFlag[i] = fileData.IsSecureFileNameFmt() ? 1 : 0;
   1.686 +		if(dbSecureFlag[i])
   1.687 +			{
   1.688 +			dbSID[i] = fileData.SecureUid();
   1.689 +			}
   1.690 +		dbFileName[i].Copy(fileData.FileName());
   1.691 +		}
   1.692 +	//It is not allowed to copy non-secure to a secure or secure to a non-secure database.
   1.693 +	if(dbSecureFlag[KSrcDbIdx] ^ dbSecureFlag[KDestDbIdx])
   1.694 +		{
   1.695 +		__SQLLEAVE(KErrPermissionDenied);	
   1.696 +		}
   1.697 +	//If this is a secure database "copy" operation, then...
   1.698 +	if(dbSecureFlag[KSrcDbIdx])
   1.699 +		{
   1.700 +		TUid callerSid = aMessage.SecureId();
   1.701 +		//A secure database can be copied only by its owner (database SID matches caller SID).
   1.702 +		if(callerSid != dbSID[KSrcDbIdx] || callerSid != dbSID[KDestDbIdx])
   1.703 +			{
   1.704 +			__SQLLEAVE(KErrPermissionDenied);	
   1.705 +			}
   1.706 +		}
   1.707 +	//Copy the database
   1.708 +	CFileMan* fileMan = CFileMan::NewL(fileData.Fs());
   1.709 +	CleanupStack::PushL(fileMan);
   1.710 +	__SQLLEAVE_IF_ERROR(fileMan->Copy(dbFileName[KSrcDbIdx], dbFileName[KDestDbIdx]));
   1.711 +	//"Copy" operation executed without errors. Now it is a time to turn off the read-only
   1.712 +	//flag of the target file (which may be on if the source file is on a read-only drive)
   1.713 +	__SQLLEAVE_IF_ERROR(fileData.Fs().SetAtt(dbFileName[KDestDbIdx], 0, KEntryAttReadOnly));
   1.714 +	CleanupStack::PopAndDestroy(fileMan);
   1.715 +	}
   1.716 +
   1.717 +/**
   1.718 +Processes the request for deleting a database.
   1.719 +
   1.720 +Only the database creator can delete the database if the database is a secure database.
   1.721 +
   1.722 +Usage of the IPC call arguments:
   1.723 +Arg 0: [in]  database file name length
   1.724 +Arg 1: [in]  database file name
   1.725 +*/
   1.726 +void CSqlSrvSession::DbDeleteFileL(const RMessage2& aMessage)
   1.727 +	{	
   1.728 +	TSqlSrvFileData& fileData = Server().FileData();
   1.729 +	fileData.SetL(aMessage, aMessage.Int0(), 1);
   1.730 +	if(fileData.IsSecureFileNameFmt())
   1.731 +		{
   1.732 +		//A secure database can be deleted only by its owner (database SID matches caller SID).
   1.733 +		if(fileData.SecureUid() != aMessage.SecureId())
   1.734 +			{
   1.735 +			__SQLLEAVE(KErrPermissionDenied);	
   1.736 +			}
   1.737 +		}
   1.738 +	__SQLTRACE_SESSIONVAR(TPtrC fname(fileData.FileName()));
   1.739 +	SQL_TRACE_SESSION(OstTraceExt2(TRACE_INTERNALS, CSQLSRVSESSION_DBDELETEFILEL, "0x%X;CSqlSrvSession::DbDeleteFileL;file='%S'", (TUint)this, __SQLPRNSTR(fname)));
   1.740 +	__SQLLEAVE_IF_ERROR(fileData.Fs().Delete(fileData.FileName()));
   1.741 +	}
   1.742 +
   1.743 +/**
   1.744 +Processes the request for retrieving the last error message.
   1.745 +
   1.746 +If the client side buffer size is not big enough, the function returns the needed 
   1.747 +buffer size + KSqlClientBufOverflowCode.
   1.748 +In this case the client must increase the buffer and try again to get the message.
   1.749 +
   1.750 +Usage of the IPC call arguments:
   1.751 +Arg 0: [in]		Message buffer length in 16-bit characters
   1.752 +Arg 1: [in/out]	Message buffer
   1.753 +
   1.754 +@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
   1.755 +@panic SqlDb 4 Client panic. Negative client message buffer length (Arg 0).
   1.756 +*/
   1.757 +TInt CSqlSrvSession::DbLastErrorMessageL(const RMessage2& aMessage)
   1.758 +	{
   1.759 +	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
   1.760 +	TPtrC msg = iDatabase->LastErrorMessage();
   1.761 +	TInt msgLen = msg.Length();
   1.762 +	TInt bufSize = aMessage.Int0();
   1.763 +	__SQLPANIC_CLIENT(bufSize >= 0, aMessage, ESqlPanicBadArgument);
   1.764 +	if(msgLen <= bufSize)
   1.765 +		{
   1.766 +		aMessage.WriteL(1, msg);
   1.767 +		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, (msgLen * sizeof(TText)));
   1.768 +		return 0;
   1.769 +		}
   1.770 +	return msgLen + KSqlClientBufOverflowCode;
   1.771 +	}
   1.772 +	
   1.773 +/**
   1.774 +Processes the request for retrieving the last inserted ROWID of this database connection.
   1.775 +
   1.776 +Usage of the IPC call arguments:
   1.777 +Arg 0: [in/out]	Receiving buffer
   1.778 +
   1.779 +@panic SqlDb 2 Client panic. The database object is not yet created yet (iDatabase is NULL).
   1.780 +*/
   1.781 +void CSqlSrvSession::DbLastInsertedRowIdL(const RMessage2& aMessage)
   1.782 +	{
   1.783 +	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
   1.784 +	TInt64 rowid = iDatabase->LastInsertedRowId();
   1.785 +	aMessage.WriteL(0, TPtrC8(reinterpret_cast <const TUint8*> (&rowid), sizeof(rowid)));
   1.786 +	SQLPROFILER_REPORT_IPC(ESqlIpcWrite, sizeof(rowid));
   1.787 +	}
   1.788 +
   1.789 +/**
   1.790 +Processes the request for retrieving the database security policies.
   1.791 +
   1.792 +The method leaves with KErrNotSupported if the database is not a secure database.
   1.793 +
   1.794 +If the client side buffer size is not big enough, the function returns the needed 
   1.795 +buffer size + KSqlClientBufOverflowCode.
   1.796 +In this case the client must increase the buffer and try again to get the database security policy.
   1.797 +
   1.798 +Usage of the IPC call arguments:
   1.799 +Arg 0: [in]		security policy buffer length in bytes
   1.800 +Arg 1: [in/out]	buffer for the database security policies
   1.801 +
   1.802 +@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
   1.803 +*/
   1.804 +TInt CSqlSrvSession::DbGetSecurityPolicyL(const RMessage2& aMessage)
   1.805 +	{
   1.806 +	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
   1.807 +	const CSqlSecurityPolicy* securityPolicy = iDatabase->SecurityPolicy();
   1.808 +	if(!securityPolicy)
   1.809 +		{
   1.810 +		__SQLLEAVE(KErrNotSupported);
   1.811 +		}
   1.812 +	const RSqlBufFlat& bufFlat = securityPolicy->BufFlat();
   1.813 +	TInt size = bufFlat.Size();
   1.814 +	if(size <= aMessage.Int0())
   1.815 +		{
   1.816 +		aMessage.WriteL(1, bufFlat.BufDes());
   1.817 +		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, size);
   1.818 +		return 0;
   1.819 +		}
   1.820 +	return size + KSqlClientBufOverflowCode;
   1.821 +	}
   1.822 +
   1.823 +/**
   1.824 +If an error occurs during the execution the function leaves with the error code.
   1.825 +Possible non-leaving return values:
   1.826 + - KErrNone              - the function has completed successfully;
   1.827 + - Positive return value - the length of the column, which means - the destination buffer is too small.
   1.828 +                           This return value is possible only with text or binary columns.
   1.829 +
   1.830 +@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
   1.831 +
   1.832 +Usage of the IPC call arguments: 
   1.833 +Arg 0: [in]		(8/16-bit character length of SQL statement) | (expected column value type << 24).
   1.834 +Arg 1: [in]		SQL statement.
   1.835 +Arg 2: [in]		Byte max length of the receiving buffer
   1.836 +Arg 3: [in/out]	The receiving buffer
   1.837 +*/
   1.838 +TInt CSqlSrvSession::DbScalarFullSelectL(const RMessage2& aMessage, TBool aIsText16)
   1.839 +	{
   1.840 +	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
   1.841 +	TUint sqlLen = static_cast <TUint> (aMessage.Int0()) & 0x00FFFFFF;
   1.842 +	TSqlColumnType  colType = static_cast <TSqlColumnType> ((static_cast <TUint> (aMessage.Int0()) & 0xFF000000) >> 24);
   1.843 +	TInt columnCount = -1;
   1.844 +	TInt paramCount = -1;
   1.845 +	CSqlSrvStatement*  stmt = aIsText16 ? 
   1.846 +								CSqlSrvStatement::NewLC(iDatabase->RawDbHandle(), ReadString16ZL(aMessage, 1, sqlLen), columnCount, paramCount) :
   1.847 +								CSqlSrvStatement::NewLC(iDatabase->RawDbHandle(), ReadString8ZL(aMessage, 1, sqlLen), columnCount, paramCount);
   1.848 +	if(columnCount != 1 || paramCount != 0)
   1.849 +		{
   1.850 +		__SQLLEAVE(KErrArgument);	
   1.851 +		}
   1.852 +	TInt err = stmt->Next();
   1.853 +	if(err == KSqlAtRow)
   1.854 +		{
   1.855 +		err = GetColumnValueL(aMessage, *stmt, colType);
   1.856 +		}
   1.857 +	else
   1.858 +		{
   1.859 +		__SQLLEAVE(err == KSqlAtEnd ? KErrNotFound : err);
   1.860 +		}
   1.861 +	CleanupStack::PopAndDestroy(stmt);
   1.862 +	return err;
   1.863 +	}
   1.864 +
   1.865 +/**
   1.866 +@return True, if the database is in transaction, false otherwise.
   1.867 +
   1.868 +@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
   1.869 +*/
   1.870 +TBool CSqlSrvSession::DbInTransaction(const RMessage2& aMessage)
   1.871 +	{
   1.872 +	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
   1.873 +	return iDatabase->InTransaction();
   1.874 +	}
   1.875 +
   1.876 +/**
   1.877 +Main database size in bytes.
   1.878 +
   1.879 +@return Main database size in bytes.
   1.880 +
   1.881 +@leave KErrNoMemory, an out of memory condition has occurred,
   1.882 +                     Note that the function may also leave with some other system wide errors or 
   1.883 +                     database specific errors categorised as ESqlDbError,
   1.884 +	   KErrTooBig,   The database is very big and the size cannot fit in a 32-bit signed integer.
   1.885 +
   1.886 +@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
   1.887 +*/
   1.888 +TInt CSqlSrvSession::DbSizeL(const RMessage2& aMessage)
   1.889 +	{
   1.890 +	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
   1.891 +	TInt64 size = iDatabase->SizeL();
   1.892 +	if(size > KMaxTInt)
   1.893 +		{
   1.894 +		__SQLLEAVE(KErrTooBig);
   1.895 +		}
   1.896 +	return size;
   1.897 +	}
   1.898 +
   1.899 +/**
   1.900 +Retrieves the database size and free space.
   1.901 +
   1.902 +Usage of the IPC call arguments:
   1.903 +Arg 0: [in/out]	Points to a RSqlDatabase::TSize object, where the database size and free space values
   1.904 +			    will be copied.
   1.905 +Arg 1: [in]		The database name length in 16-bit characters
   1.906 +Arg 2: [in]		The attached database name or KNullDesC for the main database
   1.907 +
   1.908 +@leave KErrNoMemory, an out of memory condition has occurred,
   1.909 +                     Note that the function may also leave with some other system wide errors or 
   1.910 +                     database specific errors categorised as ESqlDbError.
   1.911 +       KErrBadName, Invalid database name
   1.912 +
   1.913 +@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
   1.914 +*/
   1.915 +void CSqlSrvSession::DbSize2L(const RMessage2& aMessage)
   1.916 +	{
   1.917 +	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
   1.918 +	const TInt KDbNameLen = aMessage.Int1();
   1.919 +	if((TUint)KDbNameLen > KMaxFileName)
   1.920 +		{
   1.921 +		__SQLLEAVE(KErrBadName);
   1.922 +		}
   1.923 +	TPtrC dbName(KNullDesC);
   1.924 +	if(KDbNameLen > 0)
   1.925 +		{
   1.926 +		dbName.Set(ReadString16L(aMessage, 2, KDbNameLen));
   1.927 +		}
   1.928 +	TPckgBuf<RSqlDatabase::TSize> data;
   1.929 +	data().iSize = iDatabase->SizeL(dbName);
   1.930 +	data().iFree = iDatabase->FreeSpaceL(dbName);
   1.931 +	aMessage.WriteL(0, data);
   1.932 +	SQLPROFILER_REPORT_IPC(ESqlIpcWrite, sizeof(RSqlDatabase::TSize));
   1.933 +	}
   1.934 +
   1.935 +/**
   1.936 +Runs database compaction.
   1.937 +
   1.938 +Usage of the IPC call arguments:
   1.939 +Arg 0: [in]	    How much space in bytes should be compacted, all free pages should be removed if the
   1.940 +				parameter value is RSqlDatabase::EMaxCompaction.
   1.941 +				Note that the requested space to be compacted will be rounded up to the nearest page count,
   1.942 +				e.g. request for removing 1 byte will remove one free page from the database file. 
   1.943 +Arg 1: [in]		The database name length in characters
   1.944 +Arg 2: [in]		The attached database name or KNullDesC for the main database
   1.945 +
   1.946 +@return The size of the removed free space
   1.947 +
   1.948 +@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
   1.949 +*/
   1.950 +TInt CSqlSrvSession::DbCompactL(const RMessage2& aMessage)
   1.951 +	{
   1.952 +	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
   1.953 +	const TInt KSize = aMessage.Int0();
   1.954 +	if(KSize < 0)
   1.955 +		{
   1.956 +		if(KSize != RSqlDatabase::EMaxCompaction)
   1.957 +			{
   1.958 +			__SQLLEAVE(KErrArgument);
   1.959 +			}
   1.960 +		}
   1.961 +	if(KSize == 0)
   1.962 +		{
   1.963 +		return 0;	
   1.964 +		}
   1.965 +	const TInt KDbNameLen = aMessage.Int1();
   1.966 +	if((TUint)KDbNameLen > KMaxFileName)
   1.967 +		{
   1.968 +		__SQLLEAVE(KErrBadName);
   1.969 +		}
   1.970 +	TPtrC dbName(KNullDesC);
   1.971 +	if(KDbNameLen > 0)
   1.972 +		{
   1.973 +		dbName.Set(ReadString16L(aMessage, 2, KDbNameLen));
   1.974 +		}
   1.975 +	return iDatabase->CompactL(KSize, dbName);
   1.976 +	}
   1.977 +	
   1.978 +/**
   1.979 +Usage of the IPC call arguments:
   1.980 +Arg 0: [in]		requested size of the space to be reserved - not used
   1.981 +
   1.982 +The function leaves with KErrAlreadyExists if a drive space has been reserved already by this session.
   1.983 +*/
   1.984 +void CSqlSrvSession::DbReserveDriveSpaceL()
   1.985 +	{
   1.986 +	if(iDriveSpaceReserved)
   1.987 +		{
   1.988 +		__SQLLEAVE(KErrAlreadyExists);
   1.989 +		}
   1.990 +	RSqlDriveSpaceCol& driveSpaceCol = Server().DriveSpaceCol();
   1.991 +    if(!driveSpaceCol.Find(iDrive))
   1.992 +    	{
   1.993 +    	(void)driveSpaceCol.AddL(iDrive);
   1.994 +    	}
   1.995 +	
   1.996 +	iDriveSpaceReserved = ETrue;
   1.997 +	//Only iDriveSpaceReserved is set, nothing more needs to be done, because RSqlDriveSpaceCol::AddL() will
   1.998 +	//reserve a drive space on the specified drive.
   1.999 +	//Although it looks like that the implementation can ommit "iDriveSpaceReserved" flag, this flag plays important
  1.1000 +	//role, because it is used to ensure that every "reserve drive space" request is matched by a "free drive space"
  1.1001 +	//call.
  1.1002 +	}
  1.1003 +	
  1.1004 +/**
  1.1005 +If the client has been given an access to the reserved drive space, that access will be released.
  1.1006 +*/
  1.1007 +void CSqlSrvSession::DbFreeReservedSpace()
  1.1008 +	{
  1.1009 +	DbReleaseReserveAccess();
  1.1010 +	iDriveSpaceReserved = EFalse;
  1.1011 +	}
  1.1012 +	
  1.1013 +/**
  1.1014 +The function leaves with KErrInUse if an access to the reserved drive space has been given to the client.
  1.1015 +The function leaves with KErrNotFound if no drive space has been reserved for the drive, where the database file is.
  1.1016 +*/
  1.1017 +void CSqlSrvSession::DbGetReserveAccessL()
  1.1018 +	{
  1.1019 +	if(iDriveSpaceInUse)
  1.1020 +		{
  1.1021 +		__SQLLEAVE(KErrInUse);	
  1.1022 +		}
  1.1023 +	if(!iDriveSpaceReserved)
  1.1024 +		{
  1.1025 +		__SQLLEAVE(KErrNotFound);
  1.1026 +		}
  1.1027 +	CSqlDriveSpace* driveSpace = Server().DriveSpaceCol().Find(iDrive);
  1.1028 +   	if(!driveSpace)
  1.1029 +   		{
  1.1030 +		__SQLLEAVE(KErrNotFound);
  1.1031 +   		}
  1.1032 +   	driveSpace->GetAccessL();
  1.1033 +   	iDriveSpaceInUse = ETrue;
  1.1034 +	}
  1.1035 +	
  1.1036 +/**
  1.1037 +Releases the drive space reserve if it has been in use by this session (resp. client).
  1.1038 +*/
  1.1039 +void CSqlSrvSession::DbReleaseReserveAccess()
  1.1040 +	{
  1.1041 +	if(iDriveSpaceInUse)
  1.1042 +		{
  1.1043 +		CSqlDriveSpace* driveSpace = Server().DriveSpaceCol().Find(iDrive);
  1.1044 +		if(driveSpace)
  1.1045 +			{
  1.1046 +   			driveSpace->ReleaseAccess();
  1.1047 +			}
  1.1048 +   		iDriveSpaceInUse = EFalse;
  1.1049 +		}
  1.1050 +	}
  1.1051 +
  1.1052 +/**
  1.1053 +Processes the request for attaching a secure or non-secure database.
  1.1054 +
  1.1055 +Usage of the IPC call arguments: 
  1.1056 +Arg 0: [in]	Database file name length (counted in 16-bit characters).
  1.1057 +Arg 1: [in]	Database file name.
  1.1058 +Arg 2: [in]	Logical database name length (counted in 16-bit characters).
  1.1059 +Arg 3: [in]	Logical database name.
  1.1060 +
  1.1061 +@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
  1.1062 +*/
  1.1063 +void CSqlSrvSession::DbAttachL(const RMessage2& aMessage)
  1.1064 +	{
  1.1065 +	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
  1.1066 +	TSqlSrvFileData& fileData = Server().FileData();
  1.1067 +	fileData.SetL(aMessage, aMessage.Int0(), 1);
  1.1068 +	TInt logicalDbNameLen = aMessage.Int2();
  1.1069 +	if(logicalDbNameLen < 1 || logicalDbNameLen > KMaxFileName)
  1.1070 +		{
  1.1071 +		__SQLLEAVE(KErrBadName);
  1.1072 +		}
  1.1073 +	iDatabase->AttachDbL(fileData, ReadString16L(aMessage, 3, logicalDbNameLen));
  1.1074 +	}
  1.1075 +
  1.1076 +/**
  1.1077 +Processes the request for attaching a database using file session and file handles sent by the client.
  1.1078 +
  1.1079 +Usage of the IPC call arguments:
  1.1080 + - Arg 0: [in]  The 32 bits of the argument are used as follow:
  1.1081 + @code
  1.1082 + MSB                                                                                 LSB
  1.1083 + 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
  1.1084 + 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
  1.1085 + @endcode
  1.1086 + Where:
  1.1087 + @code
  1.1088 +  - "Ro" - read-only flag, true if the file is read-only;
  1.1089 +  - "F"  - database file name length in 16-bit characters;
  1.1090 + @endcode
  1.1091 +Arg 1: [in]  db names buffer
  1.1092 +Arg 2: [in]  file session handle
  1.1093 +Arg 3: [in]  database file handle
  1.1094 +
  1.1095 +@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
  1.1096 +@panic SqlDb 4 Client panic. Invalid IPC data, an indication of a problme in client side sql library.
  1.1097 +*/
  1.1098 +void CSqlSrvSession::DbAttachFromHandleL(const RMessage2& aMessage)
  1.1099 +	{
  1.1100 +	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
  1.1101 +	//Read-only flag, buffer length, buffer allocation
  1.1102 +	TBool readOnly = (aMessage.Int0() & 0x80000000) != 0;
  1.1103 +	const TInt KBufLen = aMessage.Int0() & 0x7FFFFFFF;
  1.1104 +    __SQLPANIC_CLIENT(KBufLen > 0, aMessage, ESqlPanicBadArgument);
  1.1105 +	HBufC8* buf = HBufC8::NewLC(KBufLen);
  1.1106 +	TPtr8 bufPtr = buf->Des();
  1.1107 +	aMessage.ReadL(1, bufPtr);
  1.1108 +	SQLPROFILER_REPORT_IPC(ESqlIpcRead, KBufLen);
  1.1109 +	if(KBufLen != bufPtr.Length())
  1.1110 +		{
  1.1111 +		__SQLLEAVE(KErrArgument);
  1.1112 +		}
  1.1113 +	RDesReadStream in(bufPtr);
  1.1114 +	TDes& dbFileName = Server().FileNameBuf();
  1.1115 +	TDes16& dbName = Server().GetBuf16L(KMaxFileName);
  1.1116 +	in >> dbFileName;
  1.1117 +	in >> dbName;
  1.1118 +	CleanupStack::PopAndDestroy(buf);
  1.1119 +	TSqlSrvFileData& fileData = Server().FileData();
  1.1120 +	fileData.SetFromHandleL(aMessage, dbFileName, EFalse, readOnly);
  1.1121 +	iDatabase->AttachDbL(fileData, dbName);
  1.1122 +	}
  1.1123 +	
  1.1124 +/**
  1.1125 +Processes the request for detaching a secure or non-secure database.
  1.1126 +
  1.1127 +Usage of the IPC call arguments: 
  1.1128 +Arg 0: [in]	Logical database name length (counted in 16-bit characters).
  1.1129 +Arg 1: [in]	Logical database name.
  1.1130 +
  1.1131 +@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
  1.1132 +*/
  1.1133 +void CSqlSrvSession::DbDetachL(const RMessage2& aMessage)
  1.1134 +	{
  1.1135 +	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
  1.1136 +	TInt logicalDbNameLen = aMessage.Int0();
  1.1137 +	if(logicalDbNameLen < 1 || logicalDbNameLen > KMaxFileName)
  1.1138 +		{
  1.1139 +		__SQLLEAVE(KErrBadName);
  1.1140 +		}
  1.1141 +	iDatabase->DetachDbL(ReadString16L(aMessage, 1, logicalDbNameLen));
  1.1142 +	}
  1.1143 +
  1.1144 +/**
  1.1145 +Reads a 16-bit string from the specified stream and returns it in zero-terminated
  1.1146 +8-bit format in aNameOut.
  1.1147 +If the string is of zero length then the substitute string provided will be used instead.
  1.1148 +
  1.1149 +@param aStrm 				The read stream
  1.1150 +@param aNameOut 			The output parameter that will contain the string read
  1.1151 +@param aEmptyNameSubstitute The substitute string to use if the string to be read from
  1.1152 +							the stream is zero length
  1.1153 +
  1.1154 +@leave KErrNoMemory, 		 An out of memory condition has occurred;
  1.1155 +	   KErrArgument, 		 The UTF-16 to UTF-8 string conversion failed;	
  1.1156 +	   KErrBadName,	 		 The string has an invalid length;
  1.1157 +*/
  1.1158 +void CSqlSrvSession::ExtractNameL(RDesReadStream& aStrm, TDes8& aNameOut, const TDesC& aEmptyNameSubstitute)
  1.1159 +	{
  1.1160 +	 TBool replace = EFalse;
  1.1161 +	 TInt32 len;
  1.1162 +	 aStrm >> len;
  1.1163 +
  1.1164 +	 if(len == 0)
  1.1165 +	 	{
  1.1166 +	   	if(aEmptyNameSubstitute.Length() > 0)
  1.1167 +			{
  1.1168 +		 	len = aEmptyNameSubstitute.Length();
  1.1169 +	 	 	replace = ETrue;
  1.1170 +			}
  1.1171 +	 	else
  1.1172 +			{
  1.1173 +			__SQLLEAVE(KErrBadName);
  1.1174 +			}
  1.1175 +	  	}
  1.1176 +	 __ASSERT_DEBUG(len > 0, __SQLPANIC2(ESqlPanicInternalError));//The "if" above should have hanled the case with "len == 0"
  1.1177 +	 if((TUint)len > KMaxFileName)
  1.1178 +	  {
  1.1179 +	  __SQLLEAVE(KErrBadName);
  1.1180 +	  }
  1.1181 +
  1.1182 +	 HBufC* buf = HBufC::NewLC(len + 1);
  1.1183 +	 TPtr ptr = buf->Des();
  1.1184 +	 if(replace)
  1.1185 +	 	{
  1.1186 +	  	ptr.Copy(aEmptyNameSubstitute);
  1.1187 +	  	}
  1.1188 +	 else
  1.1189 +	 	{
  1.1190 +	  	aStrm >> ptr;
  1.1191 +	 	}
  1.1192 +	 ptr.Append(0);
  1.1193 +	 
  1.1194 +	 if(!::UTF16ZToUTF8Z(ptr, aNameOut))
  1.1195 +	  {
  1.1196 +	  __SQLLEAVE(KErrArgument);
  1.1197 +	  }
  1.1198 +	  
  1.1199 +	 CleanupStack::PopAndDestroy(buf);
  1.1200 +	 }
  1.1201 +
  1.1202 +/**
  1.1203 +Processes the request for creating an IPC stream for accessing the content of a blob column.
  1.1204 +
  1.1205 +@param aMessage The client request wrapped in an IPC message
  1.1206 +
  1.1207 +@return The blob stream handle
  1.1208 +
  1.1209 +@leave KErrNoMemory, 		 An out of memory condition has occurred;
  1.1210 +	   KErrArgument, 		 The ROWID is invalid or UTF-16 to UTF-8 string conversion failed;	
  1.1211 +	   KErrBadDescriptor 	 The transferred data is bigger than the specified length;
  1.1212 +	   KErrBadName,	 		 The table name, column name or database name has an invalid length;
  1.1213 +       KErrPermissionDenied, The client does not have the required security capabilites for this operation; 						 
  1.1214 +       						 Note that the function may also leave with some other system wide errors or 
  1.1215 +                     		 database specific errors categorised as ESqlDbError.
  1.1216 +
  1.1217 +@panic SqlDb 2 Client panic. The database object is not yet created (iDatabase is NULL).
  1.1218 +@panic SqlDb 3 Client panic. Failed to create a blob stream handle.
  1.1219 +@panic SqlDb 4 Client panic. IPC buffer length is 0.
  1.1220 +
  1.1221 +Usage of the IPC call arguments:
  1.1222 +Arg 0: [in]	    The length of the IPC data buffer
  1.1223 +Arg 1: [in]	    IPC data buffer containing blob parameters: table name, column name, rowid, mode, database name.
  1.1224 +Arg 2: [out]	IPC buffer containing the blob stream handle
  1.1225 +*/
  1.1226 +TInt CSqlSrvSession::DbBlobSourceL(const RMessage2& aMessage)
  1.1227 +	{	
  1.1228 +	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
  1.1229 +	
  1.1230 +	TInt ipcPrmLen = aMessage.Int0();
  1.1231 +	__SQLPANIC_CLIENT(ipcPrmLen > 0, aMessage, ESqlPanicBadArgument);
  1.1232 +	
  1.1233 +	iIpcStreams.AllocL();
  1.1234 +	
  1.1235 +	TDes8& ipcPrmDes = ReadString8ZL(aMessage, 1, ipcPrmLen);
  1.1236 +	RDesReadStream strm(ipcPrmDes);
  1.1237 +	
  1.1238 +	TBuf8<KMaxFileName + 1> tblName;
  1.1239 +	ExtractNameL(strm, tblName);
  1.1240 +	
  1.1241 +	TBuf8<KMaxFileName + 1> colName;
  1.1242 +	ExtractNameL(strm, colName);
  1.1243 +	
  1.1244 +	TInt64 rowId;
  1.1245 +	strm >> rowId;
  1.1246 +	if(rowId == -1)
  1.1247 +		{
  1.1248 +		rowId = iDatabase->LastInsertedRowId();
  1.1249 +		}
  1.1250 +	if(rowId <= 0)
  1.1251 +		{
  1.1252 +		__SQLLEAVE(KErrArgument);
  1.1253 +		}
  1.1254 +
  1.1255 +	TInt32 tmp;	
  1.1256 +	strm >> tmp;
  1.1257 +	TBool isReadOnly = tmp != 0;
  1.1258 +	
  1.1259 +	TBuf8<KMaxFileName + 1> dbName;
  1.1260 +	ExtractNameL(strm, dbName, KMainDb16);
  1.1261 +						
  1.1262 +	strm.Close();
  1.1263 +			 		
  1.1264 +	// If the database is secure then check that the client has the required capabilities for the operation
  1.1265 +	TInt dbOpType = isReadOnly ? SQLITE_READ : SQLITE_UPDATE;
  1.1266 +	if(CSqlSrvDatabase::AuthorizeCallback(iDatabase, dbOpType, (char*)tblName.Ptr(), (char*)colName.Ptr(), (char*)dbName.Ptr(), '\0') != SQLITE_OK)	
  1.1267 +		{
  1.1268 +		__SQLLEAVE(KErrPermissionDenied);	
  1.1269 +		}
  1.1270 +
  1.1271 +	// Create the stream buffer
  1.1272 +	HBlobBuf* blobBuf = HBlobBuf::NewL(iDatabase->RawDbHandle(), dbName, tblName, colName, rowId, isReadOnly ? HBlobBuf::EReadOnly : HBlobBuf::EReadWrite);
  1.1273 +	blobBuf->PushL();
  1.1274 +		
  1.1275 +	// Return the blob size to the client
  1.1276 +	TPckgBuf<TIpcStreamBuf> ipcBuf;
  1.1277 +	TInt size = blobBuf->SizeL();
  1.1278 +	ipcBuf().iExt = size;
  1.1279 +	
  1.1280 +	// If this is a read stream then return the first client buffer-full of data
  1.1281 +	TInt len = 0;
  1.1282 +	if(isReadOnly && (size > 0))
  1.1283 +		{
  1.1284 +		len = Min(size, KIpcBufSize);
  1.1285 +		blobBuf->ReadL(ipcBuf().iData, len);	
  1.1286 +		}
  1.1287 +	
  1.1288 +	// Create the stream object
  1.1289 +	HIpcStream* ipcStream = new (ELeave) HIpcStream(blobBuf, len);
  1.1290 +	TInt strmHandle = iIpcStreams.Add(ipcStream);
  1.1291 +	__SQLPANIC_CLIENT(strmHandle > 0, aMessage, ESqlPanicBadHandle);
  1.1292 +	CleanupStack::Pop(blobBuf);
  1.1293 +
  1.1294 +	// Send the size and data to the client
  1.1295 +	aMessage.WriteL(2, ipcBuf);
  1.1296 +	SQLPROFILER_REPORT_IPC(ESqlIpcWrite, size);
  1.1297 +
  1.1298 +	return strmHandle;
  1.1299 +	}
  1.1300 +	
  1.1301 +///////////////////////////////////////////////////////////////////////////////////////////////////////
  1.1302 +////////////////////////////          Statement operations           //////////////////////////////////
  1.1303 +///////////////////////////////////////////////////////////////////////////////////////////////////////
  1.1304 +
  1.1305 +/**
  1.1306 +Processes the request for preparing a 8/16-bit SQL statement.
  1.1307 +
  1.1308 +@panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
  1.1309 +@panic SqlDb 3 Client panic. Internal error - invalid statement handle.
  1.1310 +
  1.1311 +Usage of the IPC call arguments:
  1.1312 +Arg 0: [out]	Column count and parameter count
  1.1313 +Arg 1: [in]		8/16-bit character length of SQL statement
  1.1314 +Arg 2: [in]		SQL statement
  1.1315 +*/
  1.1316 +TInt CSqlSrvSession::StmtPrepareL(const RMessage2& aMessage, TBool aIsText16)
  1.1317 +	{
  1.1318 +	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
  1.1319 +	iStatements.AllocL();
  1.1320 +	TInt columnCount = -1;
  1.1321 +	TInt paramCount = -1;
  1.1322 +	TUint len = static_cast <TUint> (aMessage.Int1());
  1.1323 +	CSqlSrvStatement*  stmt = aIsText16 ? 
  1.1324 +						CSqlSrvStatement::NewLC(iDatabase->RawDbHandle(), ReadString16ZL(aMessage, 2, len), columnCount, paramCount) :
  1.1325 +						CSqlSrvStatement::NewLC(iDatabase->RawDbHandle(), ReadString8ZL(aMessage, 2, len), columnCount, paramCount);
  1.1326 +	TPckgBuf<TSqlIpcData> data;
  1.1327 +	data().iPrm1 = static_cast <TUint32> (columnCount);
  1.1328 +	data().iPrm2 = static_cast <TUint32> (paramCount);
  1.1329 +	aMessage.WriteL(0, data);
  1.1330 +	SQLPROFILER_REPORT_IPC(ESqlIpcWrite, sizeof(TSqlIpcData));
  1.1331 +	TInt stmtHandle = iStatements.Add(stmt);
  1.1332 +	__SQLPANIC_CLIENT(stmtHandle > 0, aMessage, ESqlPanicBadHandle);
  1.1333 +	CleanupStack::Pop(stmt);
  1.1334 +	return stmtHandle;
  1.1335 +	}
  1.1336 +
  1.1337 +/**
  1.1338 +Processes the request for executing the SQL statement.
  1.1339 +
  1.1340 +@param aFunction ESqlSrvStmtExec, ESqlSrvStmtAsyncExec, ESqlSrvStmtBindExec, ESqlSrvStmtBindExecRowId, ESqlSrvStmtAsyncBindExec
  1.1341 +
  1.1342 +Usage of the IPC call arguments:
  1.1343 +Arg 0: [in]    parameter buffer length in bytes (if aFunction == ESqlSrvStmtBindExec || aFunction == ESqlSrvStmtAsyncBindExec)
  1.1344 +Arg 1: [in]    parameter buffer 		(if aFunction == ESqlSrvStmtBindExec || aFunction == ESqlSrvStmtAsyncBindExec)
  1.1345 +*/
  1.1346 +TInt CSqlSrvSession::StmtExecL(const RMessage2& aMessage, TInt aStmtHandle, TSqlSrvFunction aFunction)
  1.1347 +	{	
  1.1348 +	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
  1.1349 +	if(aFunction == ESqlSrvStmtBindExec || aFunction == ESqlSrvStmtAsyncBindExec)
  1.1350 +		{
  1.1351 +		DoStmtBindL(aMessage, stmt);
  1.1352 +		}
  1.1353 +	__SQLLEAVE_IF_ERROR(stmt.Exec());
  1.1354 +	return iDatabase->LastChangesCount();
  1.1355 +	}
  1.1356 +
  1.1357 +/**
  1.1358 +Processes the request for moving the SQL statement on the next record.
  1.1359 +
  1.1360 +If the call does not fail, the only valid acceptable return codes should be KSqlAtRow and KSqlAtEnd.
  1.1361 +
  1.1362 +@panic SqlDb 7 In _DEBUG mode. The call completed with no error but the return code is not KSqlAtRow or KSqlAtEnd.
  1.1363 +
  1.1364 +Usage of the IPC call arguments:
  1.1365 +Arg 0: [in]    parameter buffer length in bytes (if aFunction == ESqlSrvStmtBindNext)
  1.1366 +Arg 1: [in]    parameter buffer 		(if aFunction == ESqlSrvStmtBindNext)
  1.1367 +Arg 2: [in]    client side column buffer length in bytes
  1.1368 +Arg 3: [out]   column buffer
  1.1369 +*/
  1.1370 +TInt CSqlSrvSession::StmtNextL(const RMessage2& aMessage, TInt aStmtHandle, TSqlSrvFunction aFunction)
  1.1371 +	{
  1.1372 +	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
  1.1373 +	if(aFunction == ESqlSrvStmtBindNext)
  1.1374 +		{
  1.1375 +		DoStmtBindL(aMessage, stmt);
  1.1376 +		}
  1.1377 +	TInt err = stmt.Next();
  1.1378 +	if(err == KSqlAtRow)
  1.1379 +		{
  1.1380 +		const RSqlBufFlat& bufFlat = stmt.ColumnValuesL();
  1.1381 +		TInt size = bufFlat.Size();
  1.1382 +		if(size > aMessage.Int2())
  1.1383 +			{
  1.1384 +			return size + KSqlClientBufOverflowCode;
  1.1385 +			}
  1.1386 +		aMessage.WriteL(3, bufFlat.BufDes());
  1.1387 +		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, size);
  1.1388 +		}
  1.1389 +	__SQLLEAVE_IF_ERROR(err);
  1.1390 +	__ASSERT_DEBUG(err == KSqlAtRow || err == KSqlAtEnd, __SQLPANIC(ESqlPanicInternalError));
  1.1391 +	return err;
  1.1392 +	}
  1.1393 +
  1.1394 +/**
  1.1395 +Processes the request for retrieving the statement column or parameter names.
  1.1396 +
  1.1397 +If the client side buffer size is not big enough, the function returns the size + KSqlClientBufOverflowCode.
  1.1398 +In this case the client must increase the buffer and try again to get the buffer only.
  1.1399 +
  1.1400 +Usage of the IPC call arguments:
  1.1401 +Arg 0: [in]		size of the client side buffer for the names (in bytes)
  1.1402 +Arg 1: [out]	ipc buffer, column or parameter names
  1.1403 +*/
  1.1404 +TInt CSqlSrvSession::StmtNamesL(const RMessage2& aMessage, TInt aStmtHandle, TSqlSrvFunction aFunction)
  1.1405 +	{
  1.1406 +	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
  1.1407 +	const RSqlBufFlat& namesBuf = aFunction == ESqlSrvStmtParamNames ? stmt.ParamNamesL() : stmt.ColumnNamesL();
  1.1408 +	TInt size = namesBuf.Size();
  1.1409 +	if(size <= aMessage.Int0())
  1.1410 +		{
  1.1411 +		aMessage.WriteL(1, namesBuf.BufDes());
  1.1412 +		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, size);
  1.1413 +		return 0;
  1.1414 +		}
  1.1415 +	return size + KSqlClientBufOverflowCode;
  1.1416 +	}
  1.1417 +
  1.1418 +/**
  1.1419 +Processes the request for accessing a large column value as a stream of bytes/characters.
  1.1420 +
  1.1421 +Usage of the IPC call arguments:
  1.1422 +Arg 0: [in]		column index (0 based)
  1.1423 +Arg 2: [out]	ipc buffer, column source
  1.1424 +*/
  1.1425 +TInt CSqlSrvSession::StmtColumnSourceL(const RMessage2& aMessage, TInt aStmtHandle)
  1.1426 +	{
  1.1427 +	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
  1.1428 +	TInt columnIndex = aMessage.Int0();
  1.1429 +	TPtrC8 columnSource;
  1.1430 +	TInt err = stmt.ColumnSource(columnIndex, columnSource);
  1.1431 +	__SQLLEAVE_IF_ERROR(err);
  1.1432 +	HIpcReadBuf* ipcBuf = HIpcReadBuf::NewL(columnSource);
  1.1433 +	return NewOutputStreamL(aMessage, ipcBuf);
  1.1434 +	}
  1.1435 +
  1.1436 +/**
  1.1437 +Processes the request for setting a large parameter value from a stream of bytes or 8/16-bit characters.
  1.1438 +
  1.1439 +@panic SqlDb 3 Client panic. Internal error - invalid stream handle.
  1.1440 +
  1.1441 +Usage of the IPC call arguments:
  1.1442 +Arg 0: [in]		parameter index (0 based)
  1.1443 +Arg 2: [out]	ipc buffer, parameter source
  1.1444 +*/
  1.1445 +TInt CSqlSrvSession::StmtParamSinkL(const RMessage2& aMessage, TInt aStmtHandle, TSqlSrvFunction aFunction)
  1.1446 +	{
  1.1447 +	iIpcStreams.AllocL();
  1.1448 +	TInt parameterIndex = aMessage.Int0();
  1.1449 +	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
  1.1450 +	HSqlSrvStmtParamBuf::TDataType dataType = aFunction == ESqlSrvStmtBinParamSink ? HSqlSrvStmtParamBuf::EBinary : HSqlSrvStmtParamBuf::EText16;
  1.1451 +	HSqlSrvStmtParamBuf* paramBuf = stmt.GetParamBufL(parameterIndex, dataType, HSqlSrvStmtParamBuf::EBufIpcStream);
  1.1452 +	HIpcStream* ipcStream = new (ELeave) HIpcStream(paramBuf, 0);
  1.1453 +	TInt strmHandle = iIpcStreams.Add(ipcStream);
  1.1454 +	__SQLPANIC_CLIENT(strmHandle > 0, aMessage, ESqlPanicBadHandle);
  1.1455 +	return strmHandle;
  1.1456 +	}
  1.1457 +
  1.1458 +/**
  1.1459 +Usage of the IPC call arguments:
  1.1460 +Arg 0: [in]		the client side buffer length in bytes
  1.1461 +Arg 1: [out]	refers to a place where the buffer data will be copied to.
  1.1462 +*/
  1.1463 +void CSqlSrvSession::StmtGetBufFlatL(const RMessage2& aMessage, TInt aStmtHandle)
  1.1464 +	{
  1.1465 +	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
  1.1466 +	const RSqlBufFlat& bufFlat = stmt.BufFlatL(static_cast <TSqlBufFlatType> (aMessage.Int0()));
  1.1467 +	aMessage.WriteL(1, bufFlat.BufDes());
  1.1468 +	SQLPROFILER_REPORT_IPC(ESqlIpcWrite, bufFlat.Size());
  1.1469 +	}
  1.1470 +
  1.1471 +/**
  1.1472 +Usage of the IPC call arguments:
  1.1473 +Arg 0: [in]		column index
  1.1474 +Arg 1: [in]		column buffer length in bytes
  1.1475 +Arg 2: [in/out]	column buffer
  1.1476 +*/
  1.1477 +void CSqlSrvSession::StmtColumnValueL(const RMessage2& aMessage, TInt aStmtHandle)
  1.1478 +	{
  1.1479 +	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
  1.1480 +	TPtrC8 columnSource;
  1.1481 +	TInt columnIndex = aMessage.Int0();
  1.1482 +	TInt err = stmt.ColumnSource(columnIndex, columnSource);
  1.1483 +	__SQLLEAVE_IF_ERROR(err);
  1.1484 +	TInt len = aMessage.Int1();
  1.1485 +	if(columnSource.Length() > len)
  1.1486 +		{
  1.1487 +		TPtr8 ptr(const_cast <TUint8*> (columnSource.Ptr()), columnSource.Length(), columnSource.Length());
  1.1488 +		ptr.SetLength(len);
  1.1489 +		aMessage.WriteL(2, ptr);
  1.1490 +		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, len);
  1.1491 +		__SQLLEAVE(KErrOverflow);	
  1.1492 +		}
  1.1493 +	else
  1.1494 +		{
  1.1495 +		aMessage.WriteL(2, columnSource);
  1.1496 +		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, len);
  1.1497 +		}
  1.1498 +	}
  1.1499 +
  1.1500 +/**
  1.1501 +Usage of the IPC call arguments:
  1.1502 +Arg 0: [in]    parameter buffer length in bytes
  1.1503 +Arg 1: [in]    parameter buffer
  1.1504 +*/
  1.1505 +void CSqlSrvSession::DoStmtBindL(const RMessage2& aMessage, CSqlSrvStatement& aStmt)
  1.1506 +	{
  1.1507 +	TInt prmLen = aMessage.Int0();
  1.1508 +	RSqlBufFlat& prmBuf = Server().GetFlatBufL(prmLen);
  1.1509 +	aMessage.ReadL(1, prmBuf.BufPtr());
  1.1510 +	SQLPROFILER_REPORT_IPC(ESqlIpcRead, prmLen);
  1.1511 +	aStmt.BindL(prmBuf);
  1.1512 +	}
  1.1513 +
  1.1514 +/**
  1.1515 +Processes the request for retrieving the statement declared column type names.
  1.1516 +
  1.1517 +If the client side buffer size is not big enough, the function returns the size + KSqlClientBufOverflowCode.
  1.1518 +In this case the client must increase the buffer and try again to get the buffer only
  1.1519 +
  1.1520 +Usage of the IPC call arguments:
  1.1521 +Arg 0: [in]    	input buffer max length in 16-bit characters
  1.1522 +Arg 1: [out]	ipc buffer, declared column type names
  1.1523 +*/
  1.1524 +TInt CSqlSrvSession::StmtDeclColumnTypesL(const RMessage2& aMessage, TInt aStmtHandle)
  1.1525 +	{	
  1.1526 +	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
  1.1527 +	const RSqlBufFlat& declColumnTypesBuf = stmt.GetDeclColumnTypesL();
  1.1528 +	TInt size = declColumnTypesBuf.Size();
  1.1529 +	if(size <= aMessage.Int0())
  1.1530 +		{
  1.1531 +		aMessage.WriteL(1, declColumnTypesBuf.BufDes());
  1.1532 +		return 0;
  1.1533 +		}
  1.1534 +	return size + KSqlClientBufOverflowCode;
  1.1535 +	}
  1.1536 +
  1.1537 +
  1.1538 +//////////////////////////////////////////////////////////////////////////////////////////////////////////	
  1.1539 +////////////////////////              Helper methods                     /////////////////////////////////
  1.1540 +//////////////////////////////////////////////////////////////////////////////////////////////////////////	
  1.1541 +
  1.1542 +/**
  1.1543 +Creates a new output IPC stream object using the aStreamBuf parameter as a stream buffer (stream data source).
  1.1544 +
  1.1545 +This method immediately pushes aStreamBuf onto the cleanup stack before creating a new output IPC 
  1.1546 +stream and so callers of this method should ensure that aStreamBuf is not already on the cleanup stack.
  1.1547 +
  1.1548 +Returns the handle of the created stream.
  1.1549 +
  1.1550 +@panic SqlDb 3 Client panic. Internal error - invalid stream handle.
  1.1551 +
  1.1552 +Usage of the IPC call arguments:
  1.1553 +Arg 2: [in/out]   IPC buffer
  1.1554 +*/
  1.1555 +TInt CSqlSrvSession::NewOutputStreamL(const RMessage2& aMessage, MStreamBuf* aStreamBuf)
  1.1556 +	{
  1.1557 +	aStreamBuf->PushL();
  1.1558 +	iIpcStreams.AllocL();
  1.1559 +	TInt size = aStreamBuf->SizeL();
  1.1560 +	__ASSERT_DEBUG(size >= 0, __SQLPANIC(ESqlPanicInternalError));
  1.1561 +	TPckgBuf<TIpcStreamBuf> ipcBuf;
  1.1562 +    // read the first buffer-full
  1.1563 +    TInt len = Min(size, KIpcBufSize);
  1.1564 +    aStreamBuf->ReadL(ipcBuf().iData, len);
  1.1565 +	TInt handle = 0;
  1.1566 +	if(size > KIpcBufSize)
  1.1567 +		{								// create the stream object
  1.1568 +		HIpcStream* ipcStream = new (ELeave) HIpcStream(aStreamBuf, KIpcBufSize);
  1.1569 +		handle = iIpcStreams.Add(ipcStream);
  1.1570 +		__SQLPANIC_CLIENT(handle > 0, aMessage, ESqlPanicBadHandle);
  1.1571 +		CleanupStack::Pop(aStreamBuf);
  1.1572 +		}
  1.1573 +	else								// no more data to send
  1.1574 +		{
  1.1575 +		CleanupStack::PopAndDestroy(aStreamBuf);
  1.1576 +		}
  1.1577 +    ipcBuf().iExt = size;
  1.1578 +    aMessage.WriteL(2, ipcBuf);
  1.1579 +    SQLPROFILER_REPORT_IPC(ESqlIpcWrite, size);
  1.1580 +	return handle;
  1.1581 +	}
  1.1582 +
  1.1583 +/**
  1.1584 +Reads a 8-bit string with "aByteLen" bytes length, which is in "aArgNum" argument of aMessage.
  1.1585 +The string will be zero terminated after the "read" operation.
  1.1586 +Returns TDes8 reference pointing to the zero-terminated string.
  1.1587 +
  1.1588 +@panic SqlDb 3 Client panic. The string length is not equal to aByteLen. If happens then it is an indication of a 
  1.1589 +                             problem inside client side sql library.
  1.1590 +@panic SqlDb 4 Client panic. Negative aByteLen value.
  1.1591 +*/
  1.1592 +TDes8& CSqlSrvSession::ReadString8ZL(const RMessage2& aMessage, TInt aArgNum, TInt aByteLen)
  1.1593 +	{
  1.1594 +	__SQLPANIC_CLIENT(aByteLen >= 0, aMessage, ESqlPanicBadArgument);
  1.1595 +	TDes8& buf = Server().GetBuf8L(aByteLen + 1);
  1.1596 +	aMessage.ReadL(aArgNum, buf);
  1.1597 +	SQLPROFILER_REPORT_IPC(ESqlIpcRead, aByteLen);
  1.1598 +    __SQLPANIC_CLIENT(buf.Length() == aByteLen, aMessage, ESqlPanicBadHandle);
  1.1599 +	buf.Append(TChar(0));
  1.1600 +	return buf;
  1.1601 +	}
  1.1602 +
  1.1603 +/**
  1.1604 +Reads a 16-bit string with "aCharLen" character length, which is in "aArgNum" argument of aMessage.
  1.1605 +The string will be zero terminated after the "read" operation.
  1.1606 +Returns TDes16 reference pointing to the zero-terminated string.
  1.1607 +
  1.1608 +@panic SqlDb 3 Client panic. The string length is not equal to aCharLen. If happens then it is an indication of a 
  1.1609 +                             problem inside client side sql library.
  1.1610 +@panic SqlDb 4 Client panic. Negative aCharLen value.
  1.1611 +*/
  1.1612 +TDes16& CSqlSrvSession::ReadString16ZL(const RMessage2& aMessage, TInt aArgNum, TInt aCharLen)
  1.1613 +	{
  1.1614 +	__SQLPANIC_CLIENT(aCharLen >= 0, aMessage, ESqlPanicBadArgument);
  1.1615 +	TDes16& buf = Server().GetBuf16L(aCharLen + 1);
  1.1616 +	aMessage.ReadL(aArgNum, buf);
  1.1617 +	SQLPROFILER_REPORT_IPC(ESqlIpcRead, (aCharLen * sizeof(TText)));
  1.1618 +    __SQLPANIC_CLIENT(buf.Length() == aCharLen, aMessage, ESqlPanicBadHandle);
  1.1619 +	buf.Append(TChar(0));
  1.1620 +	return buf;
  1.1621 +	}
  1.1622 +
  1.1623 +/**
  1.1624 +Reads a 16-bit string with "aCharLen" character length, which is in "aArgNum" argument of aMessage.
  1.1625 +Returns TDes16 reference pointing to the string.
  1.1626 +
  1.1627 +@panic SqlDb 3 Client panic. The string length is not equal to aCharLen. If happens then it is an indication of a 
  1.1628 +                             problem inside client side sql library.
  1.1629 +@panic SqlDb 4 Client panic. Negative aCharLen value.
  1.1630 +*/
  1.1631 +TDes16& CSqlSrvSession::ReadString16L(const RMessage2& aMessage, TInt aArgNum, TInt aCharLen)
  1.1632 +	{
  1.1633 +	__SQLPANIC_CLIENT(aCharLen >= 0, aMessage, ESqlPanicBadArgument);
  1.1634 +	TDes16& buf = Server().GetBuf16L(aCharLen);
  1.1635 +	aMessage.ReadL(aArgNum, buf);
  1.1636 +	SQLPROFILER_REPORT_IPC(ESqlIpcRead, (aCharLen * sizeof(TText)));
  1.1637 +    __SQLPANIC_CLIENT(buf.Length() == aCharLen, aMessage, ESqlPanicBadHandle);
  1.1638 +	return buf;
  1.1639 +	}
  1.1640 +
  1.1641 +/**
  1.1642 +The method constructs a CSqlSecurityPolicy object from the passed as an argument descriptor.
  1.1643 +
  1.1644 +@param aSecurityPolicyData A descriptor with the security policy data.
  1.1645 +
  1.1646 +@return A pointer to the created CSqlSecurityPolicy instance.
  1.1647 +
  1.1648 +@leave KErrNoMemory, out of memory condition has occured.
  1.1649 +*/
  1.1650 +CSqlSecurityPolicy* CSqlSrvSession::CreateSecurityPolicyL(const TDesC8& aSecurityPolicyData)
  1.1651 +	{
  1.1652 +	TSecurityPolicy defaultPolicy(TSecurityPolicy::EAlwaysFail);
  1.1653 +	CSqlSecurityPolicy* dbPolicy = CSqlSecurityPolicy::NewLC(defaultPolicy);
  1.1654 +	RSqlBufFlat& bufFlat = dbPolicy->BufFlat();
  1.1655 +    __SQLLEAVE_IF_ERROR(bufFlat.ReAlloc(aSecurityPolicyData.Length()));
  1.1656 +	bufFlat.BufPtr().Copy(aSecurityPolicyData);
  1.1657 +	CleanupStack::Pop(dbPolicy);
  1.1658 +	return dbPolicy;
  1.1659 +	}
  1.1660 +
  1.1661 +/**
  1.1662 +Reports how many objects are allocated by the client.
  1.1663 +If the database connection is not in a test mode, the allocated memory cells count will be ignored.
  1.1664 +*/
  1.1665 +TInt CSqlSrvSession::CountResources()
  1.1666 +	{
  1.1667 +	return iStatements.Count() + iIpcStreams.Count() + (iDbResourceTestMode ? User::CountAllocCells() : 0);
  1.1668 +	}
  1.1669 +
  1.1670 +/**
  1.1671 +Extracts from aMessage:
  1.1672 +- function code;
  1.1673 +- stream or statement handle;
  1.1674 +The function will panic the client if aMessage contains bad function code or bad handle encoded in it.
  1.1675 +*/
  1.1676 +void CSqlSrvSession::Extract(const RMessage2& aMessage, TSqlSrvFunction& aFunction, TInt& aHandle)
  1.1677 +	{
  1.1678 +	TInt msgCode = aMessage.Function();
  1.1679 +	aFunction = static_cast <TSqlSrvFunction> (KSqlSrvFunctionMask & msgCode);
  1.1680 +	//All operations with code > ESqlSrvDbDelete require valid iDatabase object.
  1.1681 +	if(aFunction > ESqlSrvDbDelete)
  1.1682 +		{
  1.1683 +		__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
  1.1684 +		}
  1.1685 +	if(aFunction >= ESqlSrvStmtClose)
  1.1686 +		{
  1.1687 +		//Extracting handle and handle type from the message code
  1.1688 +		TSqlSrvHandleType handleType = static_cast <TSqlSrvHandleType> (msgCode & KSqlSrvHandleTypeMask);
  1.1689 +		aHandle = (msgCode & KSqlSrvHandleMask) >> KSqlSrvHandleShiftBits;
  1.1690 +		__SQLPANIC_CLIENT(aHandle > 0, aMessage, ESqlPanicBadArgument);
  1.1691 +		if(aFunction < ESqlSrvStreamBase)
  1.1692 +			{
  1.1693 +			__SQLPANIC_CLIENT(handleType == ESqlSrvStatementHandle, aMessage, ESqlPanicBadArgument);
  1.1694 +			}
  1.1695 +		else
  1.1696 +			{
  1.1697 +			__SQLPANIC_CLIENT(handleType == ESqlSrvStreamHandle, aMessage, ESqlPanicBadArgument);
  1.1698 +			}
  1.1699 +		}
  1.1700 +	}
  1.1701 +
  1.1702 +/**
  1.1703 +The function reads aStmt column 0 value and copies it into the client buffer, accessed via aMessage argument.
  1.1704 +
  1.1705 +If an error occurs during the execution the function leaves with the error code.
  1.1706 +Possible non-leaving return values:
  1.1707 + - KErrNone              - the function has completed successfully;
  1.1708 + - Positive return value - the length of the column, which means - the destination buffer is too small.
  1.1709 +                           This return value is possible only with text or binary columns.
  1.1710 +
  1.1711 +Usage of the IPC call arguments: 
  1.1712 +Arg 0: [in]		(8/16-bit character length of SQL statement) | (expected column value type << 24).
  1.1713 +Arg 1: [in]		SQL statement.
  1.1714 +Arg 2: [in]		Byte max length of the receiving buffer
  1.1715 +Arg 3: [in/out]	The receiving buffer
  1.1716 +*/
  1.1717 +TInt CSqlSrvSession::GetColumnValueL(const RMessage2& aMessage, CSqlSrvStatement& aStmt, TSqlColumnType aColType)
  1.1718 +	{
  1.1719 +	TInt rc = KErrNone;
  1.1720 +	switch(aColType)
  1.1721 +		{
  1.1722 +		case ESqlInt:
  1.1723 +			{
  1.1724 +			TInt val = aStmt.ColumnInt(0);
  1.1725 +			aMessage.WriteL(3, TPtrC8(reinterpret_cast <const TUint8*> (&val), sizeof(val)));
  1.1726 +			SQLPROFILER_REPORT_IPC(ESqlIpcWrite, sizeof(val));
  1.1727 +			}
  1.1728 +			break;
  1.1729 +		case ESqlInt64:
  1.1730 +			{
  1.1731 +			TInt64 val = aStmt.ColumnInt64(0);
  1.1732 +			aMessage.WriteL(3, TPtrC8(reinterpret_cast <const TUint8*> (&val), sizeof(val)));
  1.1733 +			SQLPROFILER_REPORT_IPC(ESqlIpcWrite, sizeof(val));
  1.1734 +			}
  1.1735 +			break;
  1.1736 +		case ESqlReal:
  1.1737 +			{
  1.1738 +			TReal val = aStmt.ColumnReal(0);
  1.1739 +			aMessage.WriteL(3, TPtrC8(reinterpret_cast <const TUint8*> (&val), sizeof(val)));
  1.1740 +			SQLPROFILER_REPORT_IPC(ESqlIpcWrite, sizeof(val));
  1.1741 +			}
  1.1742 +			break;
  1.1743 +		case ESqlText:
  1.1744 +		case ESqlBinary:
  1.1745 +		default:
  1.1746 +			{
  1.1747 +			TPtrC8 val;
  1.1748 +			if(aColType == ESqlText)
  1.1749 +				{
  1.1750 +				TPtrC textVal = aStmt.ColumnTextL(0);
  1.1751 +				val.Set(reinterpret_cast <const TUint8*> (textVal.Ptr()), textVal.Length() * sizeof(TUint16));
  1.1752 +				}
  1.1753 +			else
  1.1754 +				{
  1.1755 +				val.Set(aStmt.ColumnBinary(0));
  1.1756 +				}
  1.1757 +			TInt len = val.Length();
  1.1758 +			if(len > aMessage.Int2())
  1.1759 +				{
  1.1760 +				rc = aColType == ESqlText ? (TUint)len / sizeof(TUint16) : len;
  1.1761 +				len = aMessage.Int2();
  1.1762 +				}
  1.1763 +			aMessage.WriteL(3, val.Left(len));
  1.1764 +			SQLPROFILER_REPORT_IPC(ESqlIpcWrite, len);
  1.1765 +			}
  1.1766 +			break;
  1.1767 +		}
  1.1768 +	return rc;
  1.1769 +	}