persistentstorage/sql/SRC/Server/SqlSrvSession.cpp
changeset 0 08ec8eefde2f
child 8 fa9941cf3867
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "SqlSrvMain.h"			//CSqlServer
       
    17 #include "SqlSrvSession.h"		//CSqlSrvSession
       
    18 #include "SqlSrvStatement.h"	//CSqlSrvStatement, HSqlSrvStmtParamBuf
       
    19 #include "SqlSecurityImpl.h"	//CSqlSecurityPolicy
       
    20 #include "SqlSrvUtil.h"			//Global server functions
       
    21 #include "SqlUtil.h"			// config length
       
    22 #include "SqlSrvDriveSpace.h"	//CSqlDriveSpace, RSqlDriveSpaceCol
       
    23 #include "SqlSrvBlob.h"
       
    24 #include "SqlResourceProfiler.h"
       
    25 #include "SqlCompact.h"
       
    26 #include "UTraceSql.h"
       
    27 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    28 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
    29 
       
    30 #ifdef _DEBUG
       
    31 
       
    32 const TInt KDelayedDbHeapFailureMask = 0x1000;
       
    33 
       
    34 //Puts the database connection in a test mode
       
    35 //Returns true if the heap failure simulation has to be delayed untill the database is opened
       
    36 //Initialises iDbResourceTestMode and iFailedAllocNumber (if delayed simulation) data members
       
    37 inline TBool CSqlSrvSession::ActivateDbTestMode(TInt aHeapFailureMode, TInt aFailedAllocNumber)
       
    38 	{
       
    39 	iDbResourceTestMode = aHeapFailureMode;
       
    40 	if(aHeapFailureMode & KDelayedDbHeapFailureMask)
       
    41 		{
       
    42 		iFailedAllocNumber = aFailedAllocNumber;
       
    43 		return ETrue;
       
    44 		}
       
    45 	return EFalse;
       
    46 	}
       
    47 
       
    48 //If the database connection is in a test mode then the macro will reset the heap allocation failure type.
       
    49 //and stop the test mode.
       
    50 inline void CSqlSrvSession::StopDbTestMode()
       
    51 	{
       
    52 	if(iDbResourceTestMode)
       
    53 		{
       
    54 		iDbResourceTestMode = 0;
       
    55 		User::__DbgSetAllocFail(RHeap::EUser, RHeap::ENone, 0);
       
    56 		}
       
    57 	}
       
    58 
       
    59 //If the database connection is in a test mode then the function will mark the allocated by the 
       
    60 //server resources.
       
    61 inline void CSqlSrvSession::DbResourceMark()
       
    62 	{
       
    63 	if(iDbResourceTestMode)
       
    64 		{
       
    65 		ResourceCountMarkStart();
       
    66 		}
       
    67 	}
       
    68 
       
    69 //If the database connection is in a test mode then the macro will check the allocated by the server resources,
       
    70 //comparing their count with the resource count at the moment DbResourceMark() has been called.
       
    71 //The client will be panicked if the resource count now is different.
       
    72 inline void CSqlSrvSession::DbResourceEnd(const RMessage2& aMessage)
       
    73 	{
       
    74 	if(iDbResourceTestMode)
       
    75 		{
       
    76 		ResourceCountMarkEnd(aMessage);
       
    77 		}
       
    78 	}
       
    79 
       
    80 //Executes the heap simulation failure.
       
    81 inline void CSqlSrvSession::DbSetAllocFail(TInt aHeapFailureMode, TInt aFailedAllocNumber)
       
    82 	{
       
    83 	User::__DbgSetAllocFail(RHeap::EUser, 
       
    84 							static_cast <RHeap::TAllocFail> (aHeapFailureMode & (KDelayedDbHeapFailureMask - 1)), 
       
    85 							aFailedAllocNumber);
       
    86 	}
       
    87 	
       
    88 //Executes the delayed heap simulation failure, if the connection is in test mode
       
    89 inline void CSqlSrvSession::DbSetDelayedAllocFail()
       
    90 	{
       
    91 	if(iDbResourceTestMode & KDelayedDbHeapFailureMask)
       
    92 		{
       
    93 		User::__DbgSetAllocFail(RHeap::EUser, 
       
    94 								static_cast <RHeap::TAllocFail> (iDbResourceTestMode & (KDelayedDbHeapFailureMask - 1)), 
       
    95 								iFailedAllocNumber);
       
    96 		}
       
    97 	}
       
    98 	
       
    99 #else //_DEBUG
       
   100 
       
   101 inline TBool CSqlSrvSession::ActivateDbTestMode(TInt, TInt)
       
   102 	{
       
   103 	return EFalse;
       
   104 	}
       
   105 
       
   106 inline void CSqlSrvSession::StopDbTestMode()
       
   107 	{
       
   108 	}
       
   109 
       
   110 inline void CSqlSrvSession::DbResourceMark()
       
   111 	{
       
   112 	}
       
   113 
       
   114 inline void CSqlSrvSession::DbResourceEnd(const RMessage2&)
       
   115 	{
       
   116 	}
       
   117 
       
   118 inline void CSqlSrvSession::DbSetAllocFail(TInt, TInt)
       
   119 	{
       
   120 	}
       
   121 	
       
   122 inline void CSqlSrvSession::DbSetDelayedAllocFail()
       
   123 	{
       
   124 	}
       
   125 
       
   126 #endif//_DEBUG
       
   127 
       
   128 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   129 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   130 
       
   131 /**
       
   132 Searches aContainer for an object identified by aHandle.
       
   133 If such object exists, a reference to it is returned.
       
   134 If there is no object, the client gets a panic.
       
   135 
       
   136 @panic SqlDb 4 Client panic. Invalid aHandle parameter value (zero, negative or out of range).
       
   137 
       
   138 @internalComponent
       
   139 */
       
   140 template <class T> T& SqlSessObjFind(RDbObjContainer<T>& aContainer, TInt aHandle, const RMessage2& aMessage)
       
   141 	{
       
   142 	T* obj = aContainer.Find(aHandle);
       
   143 	__SQLPANIC_CLIENT(obj != NULL, aMessage, ESqlPanicBadArgument);
       
   144 	return *obj;
       
   145 	}
       
   146 
       
   147 //This function return true, if there is free disk space on drive where the main database file is.
       
   148 static TBool HasFreeDiskSpace(RFs& aFs, TDriveNumber aDrive)
       
   149 	{
       
   150 	TVolumeInfo volInfo;
       
   151 	TInt err = aFs.Volume(volInfo, aDrive);
       
   152 	if(err == KErrNone)
       
   153 		{
       
   154 		const TInt64 KDiskSpaceThreshold = 1024 * 4;
       
   155 		return volInfo.iFree > KDiskSpaceThreshold;
       
   156 		}
       
   157 	return ETrue;
       
   158 	}
       
   159 	
       
   160 //If aError is KSqlErrFull and  there is no free disk space, then KSqlErrFull is converted to KErrDiskFull
       
   161 //and returned.
       
   162 static TInt ConvertSqlFull2DiskFullErr(TInt aError, RFs& aFs, TDriveNumber aDrive)
       
   163 	{
       
   164 	if(aError == KSqlErrFull && !HasFreeDiskSpace(aFs, aDrive))
       
   165 		{
       
   166 		aError = KErrDiskFull;
       
   167 		}
       
   168 	return aError;
       
   169 	}
       
   170 
       
   171 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   172 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
       
   173 
       
   174 /**
       
   175 Creates a new instance of CSqlSrvSession class.
       
   176 
       
   177 This function shall never be called directly.
       
   178 It is CSqlServer responsibility to create a new server side session object as a responce to the criation of a
       
   179 client side session instance.
       
   180 
       
   181 @return A pointer to the created CSqlSrvSession instance.
       
   182 
       
   183 @leave KErrNoMemory, an out of memory condition has occurred;
       
   184 
       
   185 @see CSqlServer
       
   186 @see CSqlServer::NewSessionL()
       
   187 */
       
   188 CSqlSrvSession* CSqlSrvSession::NewL()
       
   189 	{
       
   190 	CSqlSrvSession* self = new (ELeave)	CSqlSrvSession;
       
   191 	CleanupStack::PushL(self);
       
   192 	self->ConstructL();
       
   193 	CleanupStack::Pop(self);
       
   194 	return self;
       
   195 	}
       
   196 
       
   197 /**
       
   198 Frees the allocated by CSqlSrvSession instance resources and memory.
       
   199 */
       
   200 CSqlSrvSession::~CSqlSrvSession()
       
   201 	{
       
   202 	StopDbTestMode();
       
   203 	DbFreeReservedSpace();
       
   204 	iIpcStreams.Close();
       
   205 	iStatements.Close();
       
   206 	delete iDatabase;
       
   207 	}
       
   208 
       
   209 /**
       
   210 Receives and dispatches all client side requests.
       
   211 
       
   212 CSession2::ServiceL() implementation.
       
   213 
       
   214 @param aMessage Client message containing the request (function code and data)
       
   215 
       
   216 @leave The function may leave with some database specific 
       
   217 	   errors categorised as ESqlDbError or system-wide error codes.
       
   218 
       
   219 @see CSession2::ServiceL()
       
   220 */
       
   221 void CSqlSrvSession::ServiceL(const RMessage2& aMessage)
       
   222 	{
       
   223 	TSqlSrvFunction funcCode = ESqlSrvTestBase;
       
   224 	TInt handle = 0;
       
   225 	Extract(aMessage, funcCode, handle);
       
   226 	TInt retCode = KErrNone;
       
   227 	if(funcCode >= ESqlSrvDbBase)
       
   228 		{
       
   229 		SQLPROFILER_REPORT_IPC(ESqlIpcRq, 0);
       
   230 		}
       
   231 	SYMBIAN_TRACE_SQL_EVENTS_ONLY(TPtrC8 funcName = GetIPCFuncStr(funcCode));
       
   232 	SYMBIAN_TRACE_SQL_EVENTS_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EBorder), KSrvMsgStr, &funcName));
       
   233 	
       
   234 	SQLPROFILER_IPC_START(iIpcCounter, iDatabase ? (TUint)iDatabase->RawDbHandle() : 0);
       
   235 	
       
   236 	switch(funcCode)
       
   237 		{
       
   238 		//////////////////////  resource check operations  ///////////////////////////
       
   239 		case ESqlSrvResourceMark:
       
   240 			ResourceCountMarkStart();
       
   241 			break;
       
   242 		case ESqlSrvResourceCheck:
       
   243 			ResourceCountMarkEnd(aMessage);
       
   244 			break;
       
   245 		case ESqlSrvResourceCount:
       
   246 			retCode = CountResources();					//Returns the recourse count
       
   247 			break;
       
   248 		case ESqlSrvSetDbHeapFailure:
       
   249 			if(ActivateDbTestMode(aMessage.Int0(), aMessage.Int1()))
       
   250 				{
       
   251 				break;	
       
   252 				}
       
   253 		case ESqlSrvSetHeapFailure:
       
   254 			DbSetAllocFail(aMessage.Int0(), aMessage.Int1());
       
   255 			break;
       
   256 		//////////////////////   profiling operations  //////////////////////////////////
       
   257 		case ESqlSrvProfilerStart:
       
   258 			TSqlSrvResourceProfiler::StartL(aMessage);
       
   259 			break;
       
   260 		case ESqlSrvProfilerStop:
       
   261 			TSqlSrvResourceProfiler::StopL(aMessage);
       
   262 			break;
       
   263 		case ESqlSrvProfilerReset:
       
   264 			TSqlSrvResourceProfiler::ResetL(aMessage);
       
   265 			break;
       
   266 		case ESqlSrvProfilerQuery:
       
   267 			ProfilerQueryL(aMessage);
       
   268 			break;
       
   269 		//////////////////////   database operations //////////////////////////////////
       
   270 		case ESqlSrvDbCreate:
       
   271 		case ESqlSrvDbCreateSecure:
       
   272 		case ESqlSrvDbOpen:
       
   273 			DbResourceMark();
       
   274 			DbCreateObjectL(aMessage, funcCode);
       
   275 			DbSetDelayedAllocFail();
       
   276 			break;
       
   277 		case ESqlSrvDbOpenFromHandle:
       
   278 			DbResourceMark();
       
   279 			DbCreateObjectFromHandleL(aMessage);
       
   280 			DbSetDelayedAllocFail();
       
   281 			break;
       
   282 		case ESqlSrvDbAttach:
       
   283 			DbAttachL(aMessage);
       
   284 			break;
       
   285 		case ESqlSrvDbAttachFromHandle:
       
   286 			DbAttachFromHandleL(aMessage);
       
   287 			break;
       
   288 		case ESqlSrvDbDetach:
       
   289 			DbDetachL(aMessage);
       
   290 			break;
       
   291 		case ESqlSrvDbClose:
       
   292 			DbDestroyObject();
       
   293 			DbResourceEnd(aMessage);
       
   294 			StopDbTestMode();
       
   295 			break;
       
   296 		case ESqlSrvDbCopy:
       
   297 			DbResourceMark();
       
   298 			DbCopyFileL(aMessage);
       
   299 			break;
       
   300 		case ESqlSrvDbDelete:
       
   301 			DbResourceMark();
       
   302 			DbDeleteFileL(aMessage);
       
   303 			break;
       
   304 		case ESqlSrvLastErrorMsg:
       
   305 			retCode = DbLastErrorMessageL(aMessage);//may return that the client buffer is not big enough for the message
       
   306 			break;
       
   307 		case ESqlSrvDbLastInsertedRowId:
       
   308 			DbLastInsertedRowIdL(aMessage);
       
   309 			break;
       
   310 		case ESqlSrvDbExec8:
       
   311 			retCode = DbExecSql8L(aMessage);		//returns the count of affected records
       
   312 			break;
       
   313 		case ESqlSrvDbExec16:
       
   314 			retCode = DbExecSql16L(aMessage);	//returns the count of affected records
       
   315 			break;
       
   316 		case ESqlSrvDbSetIsolationLevel:
       
   317 			DbSetIsolationLevelL(aMessage);
       
   318 			break;
       
   319 		case ESqlSrvDbGetSecurityPolicy:
       
   320 			retCode = DbGetSecurityPolicyL(aMessage);//may return that the client buffer is not big enough for the security policy
       
   321 			break;
       
   322 		case ESqlSrvDbScalarFullSelect8:
       
   323 			retCode = DbScalarFullSelectL(aMessage, EFalse);//may return that the client buffer is not big enough for the column value
       
   324 			break;
       
   325 		case ESqlSrvDbScalarFullSelect16:
       
   326 			retCode = DbScalarFullSelectL(aMessage, ETrue);//may return that the client buffer is not big enough for the column value
       
   327 			break;
       
   328 		case ESqlSrvDbInTransaction:
       
   329 			retCode = DbInTransaction(aMessage);	//Returns whether the database in in transaction or not - true/false
       
   330 			break;
       
   331 		case ESqlSrvDbSize:
       
   332 			retCode = DbSizeL(aMessage);			//Returns the database size
       
   333 			break;
       
   334 		case ESqlSrvDbSize2:
       
   335 			DbSize2L(aMessage);
       
   336 			break;
       
   337 		case ESqlSrvDbCompact:
       
   338 			retCode = DbCompactL(aMessage);			//Returns the amount of the removed free database space
       
   339 			break;
       
   340 		//////////////////////   reserved drive space management ////////////////////////
       
   341 		case ESqlSrvDbReserveDriveSpace:
       
   342 			__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
   343 			DbReserveDriveSpaceL();
       
   344 			break;
       
   345 		case ESqlSrvDbFreeReservedSpace:
       
   346 			__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
   347 			DbFreeReservedSpace();
       
   348 			break;
       
   349 		case ESqlSrvDbGetReserveAccess:
       
   350 			__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
   351 			DbGetReserveAccessL();
       
   352 			break;
       
   353 		case ESqlSrvDbReleaseReserveAccess:
       
   354 			__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
   355 			DbReleaseReserveAccess();
       
   356 			break;
       
   357 		//////////////////////   BLOB source ///////////////////////////////////////////
       
   358 		case ESqlSrvDbBlobSource:
       
   359 			retCode = DbBlobSourceL(aMessage);		//Returns the BLOB handle
       
   360 			break;
       
   361 		//////////////////////   statement operations //////////////////////////////////
       
   362 		case ESqlSrvStmtPrepare8:
       
   363 			retCode = StmtPrepareL(aMessage, EFalse);//returns the statement handle
       
   364 			break;
       
   365 		case ESqlSrvStmtPrepare16:
       
   366 			retCode = StmtPrepareL(aMessage, ETrue);//returns the statement handle
       
   367 			break;
       
   368 		case ESqlSrvStmtClose:
       
   369 			iStatements.Remove(handle);
       
   370 			break;
       
   371 		case ESqlSrvStmtReset:
       
   372 			retCode = ::SqlSessObjFind(iStatements, handle, aMessage).Reset();//May return that the statement has expired
       
   373 			break;
       
   374 		case ESqlSrvStmtExec:
       
   375 		case ESqlSrvStmtAsyncExec:
       
   376 		case ESqlSrvStmtBindExec:
       
   377 		case ESqlSrvStmtAsyncBindExec:
       
   378 			retCode = StmtExecL(aMessage, handle, funcCode);//returns the count of affected records
       
   379 			break;
       
   380 		case ESqlSrvStmtNext:
       
   381 		case ESqlSrvStmtBindNext:
       
   382 			retCode = StmtNextL(aMessage, handle, funcCode);//returns a non-negative number if the client side buffer is too small
       
   383 			break;
       
   384 		case ESqlSrvStmtColumnNames:
       
   385 		case ESqlSrvStmtParamNames:
       
   386 			retCode = StmtNamesL(aMessage, handle, funcCode);//returns a non-negative number if the client side buffer is too small
       
   387 			break;
       
   388 		case ESqlSrvStmtColumnSource:
       
   389 			retCode = StmtColumnSourceL(aMessage, handle);//returns an IPC stream handle
       
   390 			break;
       
   391 		case ESqlSrvStmtBinParamSink:
       
   392 		case ESqlSrvStmtTxtParamSink16:
       
   393 			retCode = StmtParamSinkL(aMessage, handle, funcCode);//returns an IPC stream handle
       
   394 			break;
       
   395 		case ESqlSrvStmtBufFlat:
       
   396 			StmtGetBufFlatL(aMessage, handle);
       
   397 			break;
       
   398 		case ESqlSrvStmtColumnValue:
       
   399 			StmtColumnValueL(aMessage, handle);
       
   400 			break;
       
   401 		case ESqlSrvStmtDeclColumnTypes:
       
   402 			StmtDeclColumnTypesL(aMessage, handle);
       
   403 			break;
       
   404 		//////////////////////   stream operations //////////////////////////////////
       
   405 		case ESqlSrvStreamRead:
       
   406 			retCode = ::SqlSessObjFind(iIpcStreams, handle, aMessage).ReadL(aMessage);
       
   407 			break;
       
   408 		case ESqlSrvStreamWrite:
       
   409 			::SqlSessObjFind(iIpcStreams, handle, aMessage).WriteL(aMessage);
       
   410 			break;
       
   411 		case ESqlSrvStreamSize:
       
   412 			retCode = ::SqlSessObjFind(iIpcStreams, handle, aMessage).SizeL();
       
   413 			break;
       
   414 		case ESqlSrvStreamSynch:
       
   415 			::SqlSessObjFind(iIpcStreams, handle, aMessage).SynchL();
       
   416 			break;
       
   417 		case ESqlSrvStreamClose:
       
   418 			iIpcStreams.Remove(handle);
       
   419 			break;
       
   420 		//////////////////////                     //////////////////////////////////
       
   421 		default:	
       
   422 			retCode = KErrNotSupported;
       
   423 			break;
       
   424 		}
       
   425 	Server().Compactor().RestartTimer();
       
   426 	Server().MinimizeBuffers();		
       
   427 	if(!aMessage.IsNull())
       
   428 		{
       
   429 		aMessage.Complete(retCode);
       
   430 		}
       
   431     SQLPROFILER_IPC_END(iIpcCounter, funcCode, iDatabase ? (TUint)iDatabase->RawDbHandle() : 0, iIpcTraceData, retCode);
       
   432 	}
       
   433 
       
   434 /**
       
   435 If aError is KErrBadDescriptor, then panic the client, else - default error handling.
       
   436 KErrBadDescriptor error may be thrown from "message write" operations, if the client supplied a bad
       
   437 descriptor to the server.
       
   438 */
       
   439 void CSqlSrvSession::ServiceError(const RMessage2& aMessage, TInt aError)
       
   440  	{
       
   441 	Server().MinimizeBuffers();		
       
   442 	aError = ::ConvertSqlFull2DiskFullErr(aError, Server().FileData().Fs(), iDrive);
       
   443  	if(aError == KErrBadDescriptor)
       
   444  		{
       
   445 		//The __SQLPANIC_CLIENT() macro cannot be used here because it calls a leaving function. A leaving call
       
   446 		//from a leaving call will terminate the server.
       
   447 		_LIT(KPanicCategory, "SqlDb");
       
   448 		
       
   449 		SYMBIAN_TRACE_SQL_ERR_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EError), KSqlSrvPanicClient, aError));
       
   450 		aMessage.Panic(KPanicCategory, ESqlPanicBadDescriptor);
       
   451  		}
       
   452  	
       
   453  	SYMBIAN_TRACE_SQL_ERR_ONLY(UTF::Printf(UTF::TTraceContext(UTF::EError), KSqlSrvError, aError));
       
   454  	SQLPROFILER_IPC_ERROR(iIpcCounter, static_cast <TSqlSrvFunction> (KSqlSrvFunctionMask & aMessage.Function()), 
       
   455  	       iDatabase ? (TUint)iDatabase->RawDbHandle() : 0, aError);
       
   456  	CSession2::ServiceError(aMessage, aError);
       
   457    	}
       
   458 
       
   459 ///////////////////////////////////////////////////////////////////////////////////////////////////////
       
   460 ////////////////////////////          Profiler  operations           ///////////////////////////////////
       
   461 ///////////////////////////////////////////////////////////////////////////////////////////////////////
       
   462 
       
   463 /**
       
   464 Retrieves the counter values for the specified profiling counter.
       
   465 
       
   466 @leave  KErrNone, the operation completed successfully,
       
   467         KErrOverflow, the receiving buffer size is too small;
       
   468                   One of the other system-wide error codes may also be returned.
       
   469 
       
   470 @see TSqlResourceProfiler
       
   471 
       
   472 Usage of the IPC call arguments:
       
   473  - Arg 0: [in]  profiling counter type, one of the TSqlResourceProfiler::TSqlCounter enum item values.
       
   474  - Arg 1: [in]  the size of the buffer for the profiling counter values.
       
   475  - Arg 2: [out] the buffer for the profiling counter values.
       
   476 
       
   477 @panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
       
   478 */
       
   479 void CSqlSrvSession::ProfilerQueryL(const RMessage2& aMessage)
       
   480 	{
       
   481 	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
   482 	if(aMessage.Int0() == TSqlResourceProfiler::ESqlCounterConfig)
       
   483 		{
       
   484 		const TInt KConfigBufLen = 128;
       
   485 		if(aMessage.Int1() < KConfigBufLen)
       
   486 			{
       
   487 			__SQLLEAVE(KErrOverflow);	
       
   488 			}
       
   489 		TBuf8<KConfigBufLen> res;
       
   490 		iDatabase->QueryConfigL(res);
       
   491 		aMessage.WriteL(2, res);
       
   492 		}
       
   493 	else
       
   494 		{
       
   495 		TSqlSrvResourceProfiler::QueryL(aMessage);
       
   496 		}				
       
   497 	}
       
   498 
       
   499 ///////////////////////////////////////////////////////////////////////////////////////////////////////
       
   500 ////////////////////////////          Database operations           ///////////////////////////////////
       
   501 ///////////////////////////////////////////////////////////////////////////////////////////////////////
       
   502 
       
   503 /**
       
   504 Processes the request for creating/opening a database.
       
   505 
       
   506 The function initializes iDatabase and iDrive data members.
       
   507 
       
   508 Usage of the IPC call arguments:
       
   509 Arg 0: [in]  database file name length in 16-bit characters
       
   510 Arg 1: [in]  database file name
       
   511 Arg 2: [in]  PPPPCCCC, where PPPP is the security policy length, CCCC is the config string length.
       
   512 Arg 3: [in]  security policies buffer | config string
       
   513 
       
   514 @leave KErrArgument If config string length or security policy length is invalid (negative length or too big length)
       
   515 @panic SqlDb 1 Client panic. iDatabase is not NULL (it has been created already)
       
   516 */
       
   517 void CSqlSrvSession::DbCreateObjectL(const RMessage2& aMessage, TSqlSrvFunction aFunction)
       
   518 	{
       
   519 	__SQLPANIC_CLIENT(!iDatabase, aMessage, ESqlPanicObjExists);
       
   520 	const TInt KSecurityPolicyLen = (aMessage.Int2() & 0x7fff0000) >> 16;
       
   521 	const TInt KConfigStringLen = aMessage.Int2() & 0xffff;
       
   522 	if(KSecurityPolicyLen < 0 || KConfigStringLen < 0 || KConfigStringLen > KSqlSrvMaxConfigStrLen)
       
   523 		{
       
   524 		__SQLLEAVE(KErrArgument);	
       
   525 		}
       
   526 	TBuf8<KSqlSrvMaxConfigStrLen> configStr;
       
   527 	if(KConfigStringLen > 0)
       
   528 		{
       
   529 		aMessage.ReadL(3, configStr, KSecurityPolicyLen);
       
   530 		SQLPROFILER_REPORT_IPC(ESqlIpcRead, KConfigStringLen);
       
   531 		}
       
   532 	TSqlSrvFileData& fileData = Server().FileData();
       
   533 	fileData.SetL(aMessage, aMessage.Int0(), 1, &configStr);
       
   534 	iDrive = fileData.Drive();
       
   535 	switch(aFunction)
       
   536 		{
       
   537 		case ESqlSrvDbCreate:
       
   538 			if(fileData.IsSecureFileNameFmt())
       
   539 				{
       
   540 				__SQLLEAVE(KErrArgument);	
       
   541 				}
       
   542 			iDatabase = CSqlSrvDatabase::CreateL(fileData);
       
   543 			break;
       
   544 		case ESqlSrvDbCreateSecure:
       
   545 			{
       
   546 			if(!fileData.IsSecureFileNameFmt())
       
   547 				{
       
   548 				__SQLLEAVE(KErrArgument);	
       
   549 				}
       
   550 			//The caller can create a secure database which secure UID matches his secure UID.
       
   551 			if(fileData.SecureUid() != aMessage.SecureId())
       
   552 				{
       
   553 				__SQLLEAVE(KErrPermissionDenied);	
       
   554 				}
       
   555 			CSqlSecurityPolicy* policy = InternalizeSecurityPolicyL(aMessage);
       
   556 			iDatabase = CSqlSrvDatabase::CreateSecureL(fileData, policy);
       
   557 			}
       
   558 			break;
       
   559 		case ESqlSrvDbOpen:
       
   560 			iDatabase = CSqlSrvDatabase::OpenL(fileData);
       
   561 			break;
       
   562 		default:
       
   563 			__SQLLEAVE(KErrArgument);	
       
   564 			break;
       
   565 		}
       
   566 	}
       
   567 
       
   568 /**
       
   569 Processes the request for opening a database from file handle.
       
   570 The server expects that the database to be opened/created is in the applicatio's private data cage.
       
   571 
       
   572 Usage of the IPC call arguments:
       
   573  - Arg 0: [in]  The 32 bits of the argument are used as follow:
       
   574  @code
       
   575  MSB                                                                                 LSB
       
   576  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
       
   577  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 
       
   578  @endcode
       
   579  Where:
       
   580  @code
       
   581   - "Ro" - read-only flag, true if the file is read-only;
       
   582   - "Cr" - create/open flag, true if the file was created, false if the file was opened;
       
   583   - "C"  - config string length in 16-bit characters;
       
   584   - "F"  - database file name length in 16-bit characters;
       
   585  @endcode
       
   586  - Arg 1: [in]  database file name | config string
       
   587  - Arg 2: [in]  file session handle
       
   588  - Arg 3: [in]  database file handle
       
   589 
       
   590 @panic SqlDb 1 Client panic. iDatabase is not NULL (it has been created already)
       
   591 */
       
   592 void CSqlSrvSession::DbCreateObjectFromHandleL(const RMessage2& aMessage)
       
   593 	{
       
   594 	__SQLPANIC_CLIENT(!iDatabase, aMessage, ESqlPanicObjExists);
       
   595 	const TBool KReadOnly = (aMessage.Int0() & 0x80000000) != 0;
       
   596 	const TBool KCreated = (aMessage.Int0() & 0x40000000) != 0;
       
   597 	const TInt KDbFileNameLen = aMessage.Int0() & 0x0000FFFF;
       
   598 	const TInt KConfigStringLen = (aMessage.Int0() & 0x3FFF0000) >> 16;
       
   599 	if(KConfigStringLen < 0 || KConfigStringLen > KSqlSrvMaxConfigStrLen)
       
   600 		{
       
   601 		__SQLLEAVE(KErrArgument);	
       
   602 		}
       
   603 	if(KDbFileNameLen < 1 || KDbFileNameLen > KMaxFileName)
       
   604 		{
       
   605 		__SQLLEAVE(KErrBadName);
       
   606 		}
       
   607 	TDes16& buffer = Server().GetBuf16L(KDbFileNameLen + KConfigStringLen);
       
   608 	aMessage.ReadL(1, buffer);
       
   609 	SQLPROFILER_REPORT_IPC(ESqlIpcRead, ((KDbFileNameLen + KConfigStringLen) * sizeof(TText)));
       
   610 	TFileName dbFileName;
       
   611 	dbFileName.Copy(buffer.LeftTPtr(KDbFileNameLen));
       
   612 	TBuf8<KSqlSrvMaxConfigStrLen> configStr;
       
   613 	if(KConfigStringLen > 0)
       
   614 		{
       
   615 		configStr.Copy(buffer.MidTPtr(KDbFileNameLen, KConfigStringLen));
       
   616 		}
       
   617 	TSqlSrvFileData& fileData = Server().FileData();
       
   618 	fileData.SetFromHandleL(aMessage, dbFileName, KCreated, KReadOnly, &configStr);
       
   619 	iDrive = fileData.Drive();
       
   620 	iDatabase = CSqlSrvDatabase::OpenL(fileData);
       
   621 	}
       
   622 
       
   623 /**
       
   624 Processes the request for copying a database.
       
   625 
       
   626 Only the database creator can copy the database if the database is a secure database.
       
   627 
       
   628 Usage of the IPC call arguments:
       
   629 Arg 0: [in]  source database file name length
       
   630 Arg 1: [in]  source database file name
       
   631 Arg 2: [in]  destination database file name length
       
   632 Arg 3: [in]  destination database file name
       
   633 */
       
   634 void CSqlSrvSession::DbCopyFileL(const RMessage2& aMessage)
       
   635 	{
       
   636 	const TInt KDbCnt = 2;											//"2" - because we have 2 dbases: src and dest
       
   637 	const TInt KSrcDbIdx = 0;
       
   638 	const TInt KDestDbIdx = 1;
       
   639 	TInt fileNameLen[KDbCnt] = {aMessage.Int0(), aMessage.Int2()};
       
   640 	TSqlSrvFileData& fileData = Server().FileData();
       
   641 	TUint dbSecureFlag[KDbCnt];
       
   642 	TUid  dbSID[KDbCnt] = {KNullUid, KNullUid};
       
   643 	TFileName dbFileName[KDbCnt];
       
   644 	//Initialize dbSecureFlag[], dbSID[] and dbFileName[] array elements
       
   645 	for(TInt i=0;i<KDbCnt;++i)									
       
   646 		{
       
   647 		fileData.SetL(aMessage, fileNameLen[i], i * KDbCnt + 1);	//"i * KDbCnt + 1" is the RMessage2 parameter number: 1 for src db, 3 for dest db
       
   648 		dbSecureFlag[i] = fileData.IsSecureFileNameFmt() ? 1 : 0;
       
   649 		if(dbSecureFlag[i])
       
   650 			{
       
   651 			dbSID[i] = fileData.SecureUid();
       
   652 			}
       
   653 		dbFileName[i].Copy(fileData.FileName());
       
   654 		}
       
   655 	//It is not allowed to copy non-secure to a secure or secure to a non-secure database.
       
   656 	if(dbSecureFlag[KSrcDbIdx] ^ dbSecureFlag[KDestDbIdx])
       
   657 		{
       
   658 		__SQLLEAVE(KErrPermissionDenied);	
       
   659 		}
       
   660 	//If this is a secure database "copy" operation, then...
       
   661 	if(dbSecureFlag[KSrcDbIdx])
       
   662 		{
       
   663 		TUid callerSid = aMessage.SecureId();
       
   664 		//A secure database can be copied only by its owner (database SID matches caller SID).
       
   665 		if(callerSid != dbSID[KSrcDbIdx] || callerSid != dbSID[KDestDbIdx])
       
   666 			{
       
   667 			__SQLLEAVE(KErrPermissionDenied);	
       
   668 			}
       
   669 		}
       
   670 	//Copy the database
       
   671 	CFileMan* fileMan = CFileMan::NewL(fileData.Fs());
       
   672 	CleanupStack::PushL(fileMan);
       
   673 	__SQLLEAVE_IF_ERROR(fileMan->Copy(dbFileName[KSrcDbIdx], dbFileName[KDestDbIdx]));
       
   674 	//"Copy" operation executed without errors. Now it is a time to turn off the read-only
       
   675 	//flag of the target file (which may be on if the source file is on a read-only drive)
       
   676 	__SQLLEAVE_IF_ERROR(fileData.Fs().SetAtt(dbFileName[KDestDbIdx], 0, KEntryAttReadOnly));
       
   677 	CleanupStack::PopAndDestroy(fileMan);
       
   678 	}
       
   679 
       
   680 /**
       
   681 Processes the request for deleting a database.
       
   682 
       
   683 Only the database creator can delete the database if the database is a secure database.
       
   684 
       
   685 Usage of the IPC call arguments:
       
   686 Arg 0: [in]  database file name length
       
   687 Arg 1: [in]  database file name
       
   688 */
       
   689 void CSqlSrvSession::DbDeleteFileL(const RMessage2& aMessage)
       
   690 	{	
       
   691 	TSqlSrvFileData& fileData = Server().FileData();
       
   692 	fileData.SetL(aMessage, aMessage.Int0(), 1);
       
   693 	if(fileData.IsSecureFileNameFmt())
       
   694 		{
       
   695 		//A secure database can be deleted only by its owner (database SID matches caller SID).
       
   696 		if(fileData.SecureUid() != aMessage.SecureId())
       
   697 			{
       
   698 			__SQLLEAVE(KErrPermissionDenied);	
       
   699 			}
       
   700 		}
       
   701 	#ifdef _NOTIFY
       
   702 	TPtrC fname = fileData.FileName();
       
   703 	RDebug::Print(_L("--SrvSess, delete, fname=\"%S\"\r\n"), &fname);
       
   704 	#endif		
       
   705 	__SQLLEAVE_IF_ERROR(fileData.Fs().Delete(fileData.FileName()));
       
   706 	}
       
   707 
       
   708 /**
       
   709 Processes the request for retrieving the last error message.
       
   710 
       
   711 If the client side buffer size is not big enough, the function returns the needed 
       
   712 buffer size + KSqlClientBufOverflowCode.
       
   713 In this case the client must increase the buffer and try again to get the message.
       
   714 
       
   715 Usage of the IPC call arguments:
       
   716 Arg 0: [in]		Message buffer length in 16-bit characters
       
   717 Arg 1: [in/out]	Message buffer
       
   718 
       
   719 @panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
       
   720 @panic SqlDb 4 Client panic. Negative client message buffer length (Arg 0).
       
   721 */
       
   722 TInt CSqlSrvSession::DbLastErrorMessageL(const RMessage2& aMessage)
       
   723 	{
       
   724 	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
   725 	TPtrC msg = iDatabase->LastErrorMessage();
       
   726 	TInt msgLen = msg.Length();
       
   727 	TInt bufSize = aMessage.Int0();
       
   728 	__SQLPANIC_CLIENT(bufSize >= 0, aMessage, ESqlPanicBadArgument);
       
   729 	if(msgLen <= bufSize)
       
   730 		{
       
   731 		aMessage.WriteL(1, msg);
       
   732 		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, (msgLen * sizeof(TText)));
       
   733 		return 0;
       
   734 		}
       
   735 	return msgLen + KSqlClientBufOverflowCode;
       
   736 	}
       
   737 	
       
   738 /**
       
   739 Processes the request for retrieving the last inserted ROWID of this database connection.
       
   740 
       
   741 Usage of the IPC call arguments:
       
   742 Arg 0: [in/out]	Receiving buffer
       
   743 
       
   744 @panic SqlDb 2 Client panic. The database object is not yet created yet (iDatabase is NULL).
       
   745 */
       
   746 void CSqlSrvSession::DbLastInsertedRowIdL(const RMessage2& aMessage)
       
   747 	{
       
   748 	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
   749 	TInt64 rowid = iDatabase->LastInsertedRowId();
       
   750 	aMessage.WriteL(0, TPtrC8(reinterpret_cast <const TUint8*> (&rowid), sizeof(rowid)));
       
   751 	SQLPROFILER_REPORT_IPC(ESqlIpcWrite, sizeof(rowid));
       
   752 	}
       
   753 
       
   754 /**
       
   755 Processes the request for retrieving the database security policies.
       
   756 
       
   757 The method leaves with KErrNotSupported if the database is not a secure database.
       
   758 
       
   759 If the client side buffer size is not big enough, the function returns the needed 
       
   760 buffer size + KSqlClientBufOverflowCode.
       
   761 In this case the client must increase the buffer and try again to get the database security policy.
       
   762 
       
   763 Usage of the IPC call arguments:
       
   764 Arg 0: [in]		security policy buffer length in bytes
       
   765 Arg 1: [in/out]	buffer for the database security policies
       
   766 
       
   767 @panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
       
   768 */
       
   769 TInt CSqlSrvSession::DbGetSecurityPolicyL(const RMessage2& aMessage)
       
   770 	{
       
   771 	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
   772 	const CSqlSecurityPolicy* securityPolicy = iDatabase->SecurityPolicy();
       
   773 	if(!securityPolicy)
       
   774 		{
       
   775 		__SQLLEAVE(KErrNotSupported);
       
   776 		}
       
   777 	const RSqlBufFlat& bufFlat = securityPolicy->BufFlat();
       
   778 	TInt size = bufFlat.Size();
       
   779 	if(size <= aMessage.Int0())
       
   780 		{
       
   781 		aMessage.WriteL(1, bufFlat.BufDes());
       
   782 		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, size);
       
   783 		return 0;
       
   784 		}
       
   785 	return size + KSqlClientBufOverflowCode;
       
   786 	}
       
   787 
       
   788 /**
       
   789 If an error occurs during the execution the function leaves with the error code.
       
   790 Possible non-leaving return values:
       
   791  - KErrNone              - the function has completed successfully;
       
   792  - Positive return value - the length of the column, which means - the destination buffer is too small.
       
   793                            This return value is possible only with text or binary columns.
       
   794 
       
   795 @panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
       
   796 
       
   797 Usage of the IPC call arguments: 
       
   798 Arg 0: [in]		(8/16-bit character length of SQL statement) | (expected column value type << 24).
       
   799 Arg 1: [in]		SQL statement.
       
   800 Arg 2: [in]		Byte max length of the receiving buffer
       
   801 Arg 3: [in/out]	The receiving buffer
       
   802 */
       
   803 TInt CSqlSrvSession::DbScalarFullSelectL(const RMessage2& aMessage, TBool aIsText16)
       
   804 	{
       
   805 	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
   806 	TUint sqlLen = static_cast <TUint> (aMessage.Int0()) & 0x00FFFFFF;
       
   807 	TSqlColumnType  colType = static_cast <TSqlColumnType> ((static_cast <TUint> (aMessage.Int0()) & 0xFF000000) >> 24);
       
   808 	TInt columnCount = -1;
       
   809 	TInt paramCount = -1;
       
   810 	CSqlSrvStatement*  stmt = aIsText16 ? 
       
   811 								CSqlSrvStatement::NewLC(iDatabase->RawDbHandle(), ReadString16ZL(aMessage, 1, sqlLen), columnCount, paramCount) :
       
   812 								CSqlSrvStatement::NewLC(iDatabase->RawDbHandle(), ReadString8ZL(aMessage, 1, sqlLen), columnCount, paramCount);
       
   813 	if(columnCount != 1 || paramCount != 0)
       
   814 		{
       
   815 		__SQLLEAVE(KErrArgument);	
       
   816 		}
       
   817 	TInt err = stmt->Next();
       
   818 	if(err == KSqlAtRow)
       
   819 		{
       
   820 		err = GetColumnValueL(aMessage, *stmt, colType);
       
   821 		}
       
   822 	else
       
   823 		{
       
   824 		__SQLLEAVE(err == KSqlAtEnd ? KErrNotFound : err);
       
   825 		}
       
   826 	CleanupStack::PopAndDestroy(stmt);
       
   827 	return err;
       
   828 	}
       
   829 
       
   830 /**
       
   831 @return True, if the database is in transaction, false otherwise.
       
   832 
       
   833 @panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
       
   834 */
       
   835 TBool CSqlSrvSession::DbInTransaction(const RMessage2& aMessage)
       
   836 	{
       
   837 	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
   838 	return iDatabase->InTransaction();
       
   839 	}
       
   840 
       
   841 /**
       
   842 Main database size in bytes.
       
   843 
       
   844 @return Main database size in bytes.
       
   845 
       
   846 @leave KErrNoMemory, an out of memory condition has occurred,
       
   847                      Note that the function may also leave with some other system wide errors or 
       
   848                      database specific errors categorised as ESqlDbError,
       
   849 	   KErrTooBig,   The database is very big and the size cannot fit in a 32-bit signed integer.
       
   850 
       
   851 @panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
       
   852 */
       
   853 TInt CSqlSrvSession::DbSizeL(const RMessage2& aMessage)
       
   854 	{
       
   855 	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
   856 	TInt64 size = iDatabase->SizeL();
       
   857 	if(size > KMaxTInt)
       
   858 		{
       
   859 		__SQLLEAVE(KErrTooBig);
       
   860 		}
       
   861 	return size;
       
   862 	}
       
   863 
       
   864 /**
       
   865 Retrieves the database size and free space.
       
   866 
       
   867 Usage of the IPC call arguments:
       
   868 Arg 0: [in/out]	Points to a RSqlDatabase::TSize object, where the database size and free space values
       
   869 			    will be copied.
       
   870 Arg 1: [in]		The database name length in 16-bit characters
       
   871 Arg 2: [in]		The attached database name or KNullDesC for the main database
       
   872 
       
   873 @leave KErrNoMemory, an out of memory condition has occurred,
       
   874                      Note that the function may also leave with some other system wide errors or 
       
   875                      database specific errors categorised as ESqlDbError.
       
   876        KErrBadName, Invalid database name
       
   877 
       
   878 @panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
       
   879 */
       
   880 void CSqlSrvSession::DbSize2L(const RMessage2& aMessage)
       
   881 	{
       
   882 	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
   883 	const TInt KDbNameLen = aMessage.Int1();
       
   884 	if(KDbNameLen < 0 || KDbNameLen > KMaxFileName)
       
   885 		{
       
   886 		__SQLLEAVE(KErrBadName);
       
   887 		}
       
   888 	TPtrC dbName(KNullDesC);
       
   889 	if(KDbNameLen > 0)
       
   890 		{
       
   891 		dbName.Set(ReadString16L(aMessage, 2, KDbNameLen));
       
   892 		}
       
   893 	TPckgBuf<RSqlDatabase::TSize> data;
       
   894 	data().iSize = iDatabase->SizeL(dbName);
       
   895 	data().iFree = iDatabase->FreeSpaceL(dbName);
       
   896 	aMessage.WriteL(0, data);
       
   897 	SQLPROFILER_REPORT_IPC(ESqlIpcWrite, sizeof(RSqlDatabase::TSize));
       
   898 	}
       
   899 
       
   900 /**
       
   901 Runs database compaction.
       
   902 
       
   903 Usage of the IPC call arguments:
       
   904 Arg 0: [in]	    How much space in bytes should be compacted, all free pages should be removed if the
       
   905 				parameter value is RSqlDatabase::EMaxCompaction.
       
   906 				Note that the requested space to be compacted will be rounded up to the nearest page count,
       
   907 				e.g. request for removing 1 byte will remove one free page from the database file. 
       
   908 Arg 1: [in]		The database name length in characters
       
   909 Arg 2: [in]		The attached database name or KNullDesC for the main database
       
   910 
       
   911 @return The size of the removed free space
       
   912 
       
   913 @panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
       
   914 */
       
   915 TInt CSqlSrvSession::DbCompactL(const RMessage2& aMessage)
       
   916 	{
       
   917 	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
   918 	const TInt KSize = aMessage.Int0();
       
   919 	if(KSize < 0)
       
   920 		{
       
   921 		if(KSize != RSqlDatabase::EMaxCompaction)
       
   922 			{
       
   923 			__SQLLEAVE(KErrArgument);
       
   924 			}
       
   925 		}
       
   926 	if(KSize == 0)
       
   927 		{
       
   928 		return 0;	
       
   929 		}
       
   930 	const TInt KDbNameLen = aMessage.Int1();
       
   931 	if(KDbNameLen < 0 || KDbNameLen > KMaxFileName)
       
   932 		{
       
   933 		__SQLLEAVE(KErrBadName);
       
   934 		}
       
   935 	TPtrC dbName(KNullDesC);
       
   936 	if(KDbNameLen > 0)
       
   937 		{
       
   938 		dbName.Set(ReadString16L(aMessage, 2, KDbNameLen));
       
   939 		}
       
   940 	return iDatabase->CompactL(KSize, dbName);
       
   941 	}
       
   942 	
       
   943 /**
       
   944 Usage of the IPC call arguments:
       
   945 Arg 0: [in]		requested size of the space to be reserved - not used
       
   946 
       
   947 The function leaves with KErrAlreadyExists if a drive space has been reserved already by this session.
       
   948 */
       
   949 void CSqlSrvSession::DbReserveDriveSpaceL()
       
   950 	{
       
   951 	if(iDriveSpaceReserved)
       
   952 		{
       
   953 		__SQLLEAVE(KErrAlreadyExists);
       
   954 		}
       
   955 	RSqlDriveSpaceCol& driveSpaceCol = Server().DriveSpaceCol();
       
   956     if(!driveSpaceCol.Find(iDrive))
       
   957     	{
       
   958     	(void)driveSpaceCol.AddL(iDrive);
       
   959     	}
       
   960 	
       
   961 	iDriveSpaceReserved = ETrue;
       
   962 	//Only iDriveSpaceReserved is set, nothing more needs to be done, because RSqlDriveSpaceCol::AddL() will
       
   963 	//reserve a drive space on the specified drive.
       
   964 	//Although it looks like that the implementation can ommit "iDriveSpaceReserved" flag, this flag plays important
       
   965 	//role, because it is used to ensure that every "reserve drive space" request is matched by a "free drive space"
       
   966 	//call.
       
   967 	}
       
   968 	
       
   969 /**
       
   970 If the client has been given an access to the reserved drive space, that access will be released.
       
   971 */
       
   972 void CSqlSrvSession::DbFreeReservedSpace()
       
   973 	{
       
   974 	DbReleaseReserveAccess();
       
   975 	iDriveSpaceReserved = EFalse;
       
   976 	}
       
   977 	
       
   978 /**
       
   979 The function leaves with KErrInUse if an access to the reserved drive space has been given to the client.
       
   980 The function leaves with KErrNotFound if no drive space has been reserved for the drive, where the database file is.
       
   981 */
       
   982 void CSqlSrvSession::DbGetReserveAccessL()
       
   983 	{
       
   984 	if(iDriveSpaceInUse)
       
   985 		{
       
   986 		__SQLLEAVE(KErrInUse);	
       
   987 		}
       
   988 	if(!iDriveSpaceReserved)
       
   989 		{
       
   990 		__SQLLEAVE(KErrNotFound);
       
   991 		}
       
   992 	CSqlDriveSpace* driveSpace = Server().DriveSpaceCol().Find(iDrive);
       
   993    	if(!driveSpace)
       
   994    		{
       
   995 		__SQLLEAVE(KErrNotFound);
       
   996    		}
       
   997    	driveSpace->GetAccessL();
       
   998    	iDriveSpaceInUse = ETrue;
       
   999 	}
       
  1000 	
       
  1001 /**
       
  1002 Releases the drive space reserve if it has been in use by this session (resp. client).
       
  1003 */
       
  1004 void CSqlSrvSession::DbReleaseReserveAccess()
       
  1005 	{
       
  1006 	if(iDriveSpaceInUse)
       
  1007 		{
       
  1008 		CSqlDriveSpace* driveSpace = Server().DriveSpaceCol().Find(iDrive);
       
  1009 		if(driveSpace)
       
  1010 			{
       
  1011    			driveSpace->ReleaseAccess();
       
  1012 			}
       
  1013    		iDriveSpaceInUse = EFalse;
       
  1014 		}
       
  1015 	}
       
  1016 
       
  1017 /**
       
  1018 Processes the request for attaching a secure or non-secure database.
       
  1019 
       
  1020 Usage of the IPC call arguments: 
       
  1021 Arg 0: [in]	Database file name length (counted in 16-bit characters).
       
  1022 Arg 1: [in]	Database file name.
       
  1023 Arg 2: [in]	Logical database name length (counted in 16-bit characters).
       
  1024 Arg 3: [in]	Logical database name.
       
  1025 
       
  1026 @panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
       
  1027 */
       
  1028 void CSqlSrvSession::DbAttachL(const RMessage2& aMessage)
       
  1029 	{
       
  1030 	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
  1031 	TSqlSrvFileData& fileData = Server().FileData();
       
  1032 	fileData.SetL(aMessage, aMessage.Int0(), 1);
       
  1033 	TInt logicalDbNameLen = aMessage.Int2();
       
  1034 	if(logicalDbNameLen < 1 || logicalDbNameLen > KMaxFileName)
       
  1035 		{
       
  1036 		__SQLLEAVE(KErrBadName);
       
  1037 		}
       
  1038 	iDatabase->AttachDbL(fileData, ReadString16L(aMessage, 3, logicalDbNameLen));
       
  1039 	}
       
  1040 
       
  1041 /**
       
  1042 Processes the request for attaching a database using file session and file handles sent by the client.
       
  1043 
       
  1044 Usage of the IPC call arguments:
       
  1045  - Arg 0: [in]  The 32 bits of the argument are used as follow:
       
  1046  @code
       
  1047  MSB                                                                                 LSB
       
  1048  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
       
  1049  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
       
  1050  @endcode
       
  1051  Where:
       
  1052  @code
       
  1053   - "Ro" - read-only flag, true if the file is read-only;
       
  1054   - "F"  - database file name length in 16-bit characters;
       
  1055  @endcode
       
  1056 Arg 1: [in]  db names buffer
       
  1057 Arg 2: [in]  file session handle
       
  1058 Arg 3: [in]  database file handle
       
  1059 
       
  1060 @panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
       
  1061 */
       
  1062 void CSqlSrvSession::DbAttachFromHandleL(const RMessage2& aMessage)
       
  1063 	{
       
  1064 	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
  1065 	//Read-only flag, buffer length, buffer allocation
       
  1066 	TBool readOnly = (aMessage.Int0() & 0x80000000) != 0;
       
  1067 	const TInt KBufLen = aMessage.Int0() & 0x7FFFFFFF;
       
  1068 	if(KBufLen <= 0)
       
  1069 		{
       
  1070 		__SQLLEAVE(KErrArgument);
       
  1071 		}
       
  1072 	HBufC8* buf = HBufC8::NewLC(KBufLen);
       
  1073 	TPtr8 bufPtr = buf->Des();
       
  1074 	aMessage.ReadL(1, bufPtr);
       
  1075 	SQLPROFILER_REPORT_IPC(ESqlIpcRead, KBufLen);
       
  1076 	if(KBufLen != bufPtr.Length())
       
  1077 		{
       
  1078 		__SQLLEAVE(KErrArgument);
       
  1079 		}
       
  1080 	RDesReadStream in(bufPtr);
       
  1081 	TDes& dbFileName = Server().FileNameBuf();
       
  1082 	TDes16& dbName = Server().GetBuf16L(KMaxFileName);
       
  1083 	in >> dbFileName;
       
  1084 	in >> dbName;
       
  1085 	CleanupStack::PopAndDestroy(buf);
       
  1086 	TSqlSrvFileData& fileData = Server().FileData();
       
  1087 	fileData.SetFromHandleL(aMessage, dbFileName, EFalse, readOnly);
       
  1088 	iDatabase->AttachDbL(fileData, dbName);
       
  1089 	}
       
  1090 	
       
  1091 /**
       
  1092 Processes the request for detaching a secure or non-secure database.
       
  1093 
       
  1094 Usage of the IPC call arguments: 
       
  1095 Arg 0: [in]	Logical database name length (counted in 16-bit characters).
       
  1096 Arg 1: [in]	Logical database name.
       
  1097 
       
  1098 @panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
       
  1099 */
       
  1100 void CSqlSrvSession::DbDetachL(const RMessage2& aMessage)
       
  1101 	{
       
  1102 	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
  1103 	TInt logicalDbNameLen = aMessage.Int0();
       
  1104 	if(logicalDbNameLen < 1 || logicalDbNameLen > KMaxFileName)
       
  1105 		{
       
  1106 		__SQLLEAVE(KErrBadName);
       
  1107 		}
       
  1108 	iDatabase->DetachDbL(ReadString16L(aMessage, 1, logicalDbNameLen));
       
  1109 	}
       
  1110 
       
  1111 /**
       
  1112 Reads a 16-bit string from the specified stream and returns it in zero-terminated
       
  1113 8-bit format in aNameOut.
       
  1114 If the string is of zero length then the substitute string provided will be used instead.
       
  1115 
       
  1116 @param aStrm 				The read stream
       
  1117 @param aNameOut 			The output parameter that will contain the string read
       
  1118 @param aEmptyNameSubstitute The substitute string to use if the string to be read from
       
  1119 							the stream is zero length
       
  1120 
       
  1121 @leave KErrNoMemory, 		 An out of memory condition has occurred;
       
  1122 	   KErrArgument, 		 The UTF-16 to UTF-8 string conversion failed;	
       
  1123 	   KErrBadName,	 		 The string has an invalid length;
       
  1124 */
       
  1125 void CSqlSrvSession::ExtractNameL(RDesReadStream& aStrm, TDes8& aNameOut, const TDesC& aEmptyNameSubstitute)
       
  1126 	{
       
  1127 	 TBool replace = EFalse;
       
  1128 	 TInt32 len;
       
  1129 	 aStrm >> len;
       
  1130 
       
  1131 	 if(len == 0)
       
  1132 	 	{
       
  1133 	   	if(aEmptyNameSubstitute.Length() > 0)
       
  1134 			{
       
  1135 		 	len = aEmptyNameSubstitute.Length();
       
  1136 	 	 	replace = ETrue;
       
  1137 			}
       
  1138 	 	else
       
  1139 			{
       
  1140 			__SQLLEAVE(KErrBadName);
       
  1141 			}
       
  1142 	  	}
       
  1143 
       
  1144 	 if(len < 1 || len > KMaxFileName)
       
  1145 	  {
       
  1146 	  __SQLLEAVE(KErrBadName);
       
  1147 	  }
       
  1148 
       
  1149 	 HBufC* buf = HBufC::NewLC(len + 1);
       
  1150 	 TPtr ptr = buf->Des();
       
  1151 	 if(replace)
       
  1152 	 	{
       
  1153 	  	ptr.Copy(aEmptyNameSubstitute);
       
  1154 	  	}
       
  1155 	 else
       
  1156 	 	{
       
  1157 	  	aStrm >> ptr;
       
  1158 	 	}
       
  1159 	 ptr.Append(0);
       
  1160 	 
       
  1161 	 if(!::UTF16ZToUTF8Z(ptr, aNameOut))
       
  1162 	  {
       
  1163 	  __SQLLEAVE(KErrArgument);
       
  1164 	  }
       
  1165 	  
       
  1166 	 CleanupStack::PopAndDestroy(buf);
       
  1167 	 }
       
  1168 
       
  1169 /**
       
  1170 Processes the request for creating an IPC stream for accessing the content of a blob column.
       
  1171 
       
  1172 @param aMessage The client request wrapped in an IPC message
       
  1173 
       
  1174 @return The blob stream handle
       
  1175 
       
  1176 @leave KErrNoMemory, 		 An out of memory condition has occurred;
       
  1177 	   KErrArgument, 		 The IPC data buffer length is invalid, or the ROWID is invalid,
       
  1178 	   				 		 or UTF-16 to UTF-8 string conversion failed;	
       
  1179 	   KErrBadDescriptor 	 The transferred data is bigger than the specified length;
       
  1180 	   KErrBadName,	 		 The table name, column name or database name has an invalid length;
       
  1181        KErrPermissionDenied, The client does not have the required security capabilites for this operation; 						 
       
  1182        						 Note that the function may also leave with some other system wide errors or 
       
  1183                      		 database specific errors categorised as ESqlDbError.
       
  1184 
       
  1185 @panic SqlDb 2 Client panic. The database object is not yet created (iDatabase is NULL)
       
  1186 @panic SqlDb 3 Client panic. Failed to create a blob stream handle
       
  1187 
       
  1188 Usage of the IPC call arguments:
       
  1189 Arg 0: [in]	    The length of the IPC data buffer
       
  1190 Arg 1: [in]	    IPC data buffer containing blob parameters: table name, column name, rowid, mode, database name.
       
  1191 Arg 2: [out]	IPC buffer containing the blob stream handle
       
  1192 */
       
  1193 TInt CSqlSrvSession::DbBlobSourceL(const RMessage2& aMessage)
       
  1194 	{	
       
  1195 	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
  1196 	
       
  1197 	iIpcStreams.AllocL();
       
  1198 	
       
  1199 	TInt ipcPrmLen = aMessage.Int0();
       
  1200 	if(ipcPrmLen < 1)
       
  1201 		{
       
  1202 		__SQLLEAVE(KErrArgument);
       
  1203 		}
       
  1204 	TDes8& ipcPrmDes = ReadString8ZL(aMessage, 1, ipcPrmLen);
       
  1205 	RDesReadStream strm(ipcPrmDes);
       
  1206 	
       
  1207 	TBuf8<KMaxFileName + 1> tblName;
       
  1208 	ExtractNameL(strm, tblName);
       
  1209 	
       
  1210 	TBuf8<KMaxFileName + 1> colName;
       
  1211 	ExtractNameL(strm, colName);
       
  1212 	
       
  1213 	TInt64 rowId;
       
  1214 	strm >> rowId;
       
  1215 	if(rowId == -1)
       
  1216 		{
       
  1217 		rowId = iDatabase->LastInsertedRowId();
       
  1218 		}
       
  1219 	if(rowId <= 0)
       
  1220 		{
       
  1221 		__SQLLEAVE(KErrArgument);
       
  1222 		}
       
  1223 
       
  1224 	TInt32 tmp;	
       
  1225 	strm >> tmp;
       
  1226 	TBool isReadOnly = tmp != 0;
       
  1227 	
       
  1228 	TBuf8<KMaxFileName + 1> dbName;
       
  1229 	ExtractNameL(strm, dbName, KMainDb16);
       
  1230 						
       
  1231 	strm.Close();
       
  1232 			 		
       
  1233 	// If the database is secure then check that the client has the required capabilities for the operation
       
  1234 	TInt dbOpType = isReadOnly ? SQLITE_READ : SQLITE_UPDATE;
       
  1235 	if(CSqlSrvDatabase::AuthorizeCallback(iDatabase, dbOpType, (char*)tblName.Ptr(), (char*)colName.Ptr(), (char*)dbName.Ptr(), '\0') != SQLITE_OK)	
       
  1236 		{
       
  1237 		__SQLLEAVE(KErrPermissionDenied);	
       
  1238 		}
       
  1239 
       
  1240 	// Create the stream buffer
       
  1241 	HBlobBuf* blobBuf = HBlobBuf::NewL(iDatabase->RawDbHandle(), dbName, tblName, colName, rowId, isReadOnly ? HBlobBuf::EReadOnly : HBlobBuf::EReadWrite);
       
  1242 	blobBuf->PushL();
       
  1243 		
       
  1244 	// Return the blob size to the client
       
  1245 	TPckgBuf<TIpcStreamBuf> ipcBuf;
       
  1246 	TInt size = blobBuf->SizeL();
       
  1247 	ipcBuf().iExt = size;
       
  1248 	
       
  1249 	// If this is a read stream then return the first client buffer-full of data
       
  1250 	TInt len = 0;
       
  1251 	if(isReadOnly && (size > 0))
       
  1252 		{
       
  1253 		len = Min(size, KIpcBufSize);
       
  1254 		blobBuf->ReadL(ipcBuf().iData, len);	
       
  1255 		}
       
  1256 	
       
  1257 	// Create the stream object
       
  1258 	HIpcStream* ipcStream = new (ELeave) HIpcStream(blobBuf, len);
       
  1259 	TInt strmHandle = iIpcStreams.Add(ipcStream);
       
  1260 	__SQLPANIC_CLIENT(strmHandle > 0, aMessage, ESqlPanicBadHandle);
       
  1261 	CleanupStack::Pop(blobBuf);
       
  1262 
       
  1263 	// Send the size and data to the client
       
  1264 	aMessage.WriteL(2, ipcBuf);
       
  1265 	SQLPROFILER_REPORT_IPC(ESqlIpcWrite, size);
       
  1266 
       
  1267 	return strmHandle;
       
  1268 	}
       
  1269 	
       
  1270 ///////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1271 ////////////////////////////          Statement operations           //////////////////////////////////
       
  1272 ///////////////////////////////////////////////////////////////////////////////////////////////////////
       
  1273 
       
  1274 /**
       
  1275 Processes the request for preparing a 8/16-bit SQL statement.
       
  1276 
       
  1277 @panic SqlDb 2 Client panic. iDatabase is NULL (the database object is not created yet).
       
  1278 @panic SqlDb 3 Client panic. Internal error - invalid statement handle.
       
  1279 
       
  1280 Usage of the IPC call arguments:
       
  1281 Arg 0: [out]	Column count and parameter count
       
  1282 Arg 1: [in]		8/16-bit character length of SQL statement
       
  1283 Arg 2: [in]		SQL statement
       
  1284 */
       
  1285 TInt CSqlSrvSession::StmtPrepareL(const RMessage2& aMessage, TBool aIsText16)
       
  1286 	{
       
  1287 	__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
  1288 	iStatements.AllocL();
       
  1289 	TInt columnCount = -1;
       
  1290 	TInt paramCount = -1;
       
  1291 	TUint len = static_cast <TUint> (aMessage.Int1());
       
  1292 	CSqlSrvStatement*  stmt = aIsText16 ? 
       
  1293 						CSqlSrvStatement::NewLC(iDatabase->RawDbHandle(), ReadString16ZL(aMessage, 2, len), columnCount, paramCount) :
       
  1294 						CSqlSrvStatement::NewLC(iDatabase->RawDbHandle(), ReadString8ZL(aMessage, 2, len), columnCount, paramCount);
       
  1295 	TPckgBuf<TSqlIpcData> data;
       
  1296 	data().iPrm1 = static_cast <TUint32> (columnCount);
       
  1297 	data().iPrm2 = static_cast <TUint32> (paramCount);
       
  1298 	aMessage.WriteL(0, data);
       
  1299 	SQLPROFILER_REPORT_IPC(ESqlIpcWrite, sizeof(TSqlIpcData));
       
  1300 	TInt stmtHandle = iStatements.Add(stmt);
       
  1301 	__SQLPANIC_CLIENT(stmtHandle > 0, aMessage, ESqlPanicBadHandle);
       
  1302 	CleanupStack::Pop(stmt);
       
  1303 	return stmtHandle;
       
  1304 	}
       
  1305 
       
  1306 /**
       
  1307 Processes the request for executing the SQL statement.
       
  1308 
       
  1309 @param aFunction ESqlSrvStmtExec, ESqlSrvStmtAsyncExec, ESqlSrvStmtBindExec, ESqlSrvStmtBindExecRowId, ESqlSrvStmtAsyncBindExec
       
  1310 
       
  1311 Usage of the IPC call arguments:
       
  1312 Arg 0: [in]    parameter buffer length in bytes (if aFunction == ESqlSrvStmtBindExec || aFunction == ESqlSrvStmtAsyncBindExec)
       
  1313 Arg 1: [in]    parameter buffer 		(if aFunction == ESqlSrvStmtBindExec || aFunction == ESqlSrvStmtAsyncBindExec)
       
  1314 */
       
  1315 TInt CSqlSrvSession::StmtExecL(const RMessage2& aMessage, TInt aStmtHandle, TSqlSrvFunction aFunction)
       
  1316 	{	
       
  1317 	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
       
  1318 	if(aFunction == ESqlSrvStmtBindExec || aFunction == ESqlSrvStmtAsyncBindExec)
       
  1319 		{
       
  1320 		DoStmtBindL(aMessage, stmt);
       
  1321 		}
       
  1322 	__SQLLEAVE_IF_ERROR(stmt.Exec());
       
  1323 	return iDatabase->LastChangesCount();
       
  1324 	}
       
  1325 
       
  1326 /**
       
  1327 Processes the request for moving the SQL statement on the next record.
       
  1328 
       
  1329 If the call does not fail, the only valid acceptable return codes should be KSqlAtRow and KSqlAtEnd.
       
  1330 
       
  1331 @panic SqlDb 7 In _DEBUG mode. The call completed with no error but the return code is not KSqlAtRow or KSqlAtEnd.
       
  1332 
       
  1333 Usage of the IPC call arguments:
       
  1334 Arg 0: [in]    parameter buffer length in bytes (if aFunction == ESqlSrvStmtBindNext)
       
  1335 Arg 1: [in]    parameter buffer 		(if aFunction == ESqlSrvStmtBindNext)
       
  1336 Arg 2: [in]    client side column buffer length in bytes
       
  1337 Arg 3: [out]   column buffer
       
  1338 */
       
  1339 TInt CSqlSrvSession::StmtNextL(const RMessage2& aMessage, TInt aStmtHandle, TSqlSrvFunction aFunction)
       
  1340 	{
       
  1341 	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
       
  1342 	if(aFunction == ESqlSrvStmtBindNext)
       
  1343 		{
       
  1344 		DoStmtBindL(aMessage, stmt);
       
  1345 		}
       
  1346 	TInt err = stmt.Next();
       
  1347 	if(err == KSqlAtRow)
       
  1348 		{
       
  1349 		const RSqlBufFlat& bufFlat = stmt.ColumnValuesL();
       
  1350 		TInt size = bufFlat.Size();
       
  1351 		if(size > aMessage.Int2())
       
  1352 			{
       
  1353 			return size + KSqlClientBufOverflowCode;
       
  1354 			}
       
  1355 		aMessage.WriteL(3, bufFlat.BufDes());
       
  1356 		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, size);
       
  1357 		}
       
  1358 	__SQLLEAVE_IF_ERROR(err);
       
  1359 	__SQLASSERT(err == KSqlAtRow || err == KSqlAtEnd, ESqlPanicInternalError);
       
  1360 	return err;
       
  1361 	}
       
  1362 
       
  1363 /**
       
  1364 Processes the request for retrieving the statement column or parameter names.
       
  1365 
       
  1366 If the client side buffer size is not big enough, the function returns the size + KSqlClientBufOverflowCode.
       
  1367 In this case the client must increase the buffer and try again to get the buffer only.
       
  1368 
       
  1369 Usage of the IPC call arguments:
       
  1370 Arg 0: [in]		size of the client side buffer for the names (in bytes)
       
  1371 Arg 1: [out]	ipc buffer, column or parameter names
       
  1372 */
       
  1373 TInt CSqlSrvSession::StmtNamesL(const RMessage2& aMessage, TInt aStmtHandle, TSqlSrvFunction aFunction)
       
  1374 	{
       
  1375 	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
       
  1376 	const RSqlBufFlat& namesBuf = aFunction == ESqlSrvStmtParamNames ? stmt.ParamNamesL() : stmt.ColumnNamesL();
       
  1377 	TInt size = namesBuf.Size();
       
  1378 	if(size <= aMessage.Int0())
       
  1379 		{
       
  1380 		aMessage.WriteL(1, namesBuf.BufDes());
       
  1381 		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, size);
       
  1382 		return 0;
       
  1383 		}
       
  1384 	return size + KSqlClientBufOverflowCode;
       
  1385 	}
       
  1386 
       
  1387 /**
       
  1388 Processes the request for accessing a large column value as a stream of bytes/characters.
       
  1389 
       
  1390 Usage of the IPC call arguments:
       
  1391 Arg 0: [in]		column index (0 based)
       
  1392 Arg 2: [out]	ipc buffer, column source
       
  1393 */
       
  1394 TInt CSqlSrvSession::StmtColumnSourceL(const RMessage2& aMessage, TInt aStmtHandle)
       
  1395 	{
       
  1396 	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
       
  1397 	TInt columnIndex = aMessage.Int0();
       
  1398 	TPtrC8 columnSource;
       
  1399 	TInt err = stmt.ColumnSource(columnIndex, columnSource);
       
  1400 	__SQLLEAVE_IF_ERROR(err);
       
  1401 	HIpcReadBuf* ipcBuf = HIpcReadBuf::NewL(columnSource);
       
  1402 	return NewOutputStreamL(aMessage, ipcBuf);
       
  1403 	}
       
  1404 
       
  1405 /**
       
  1406 Processes the request for setting a large parameter value from a stream of bytes or 8/16-bit characters.
       
  1407 
       
  1408 @panic SqlDb 3 Client panic. Internal error - invalid stream handle.
       
  1409 
       
  1410 Usage of the IPC call arguments:
       
  1411 Arg 0: [in]		parameter index (0 based)
       
  1412 Arg 2: [out]	ipc buffer, parameter source
       
  1413 */
       
  1414 TInt CSqlSrvSession::StmtParamSinkL(const RMessage2& aMessage, TInt aStmtHandle, TSqlSrvFunction aFunction)
       
  1415 	{
       
  1416 	iIpcStreams.AllocL();
       
  1417 	TInt parameterIndex = aMessage.Int0();
       
  1418 	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
       
  1419 	HSqlSrvStmtParamBuf::TDataType dataType = aFunction == ESqlSrvStmtBinParamSink ? HSqlSrvStmtParamBuf::EBinary : HSqlSrvStmtParamBuf::EText16;
       
  1420 	HSqlSrvStmtParamBuf* paramBuf = stmt.GetParamBufL(parameterIndex, dataType, HSqlSrvStmtParamBuf::EBufIpcStream);
       
  1421 	HIpcStream* ipcStream = new (ELeave) HIpcStream(paramBuf, 0);
       
  1422 	TInt strmHandle = iIpcStreams.Add(ipcStream);
       
  1423 	__SQLPANIC_CLIENT(strmHandle > 0, aMessage, ESqlPanicBadHandle);
       
  1424 	return strmHandle;
       
  1425 	}
       
  1426 
       
  1427 /**
       
  1428 Usage of the IPC call arguments:
       
  1429 Arg 0: [in]		the client side buffer length in bytes
       
  1430 Arg 1: [out]	refers to a place where the buffer data will be copied to.
       
  1431 */
       
  1432 void CSqlSrvSession::StmtGetBufFlatL(const RMessage2& aMessage, TInt aStmtHandle)
       
  1433 	{
       
  1434 	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
       
  1435 	const RSqlBufFlat& bufFlat = stmt.BufFlatL(static_cast <TSqlBufFlatType> (aMessage.Int0()));
       
  1436 	aMessage.WriteL(1, bufFlat.BufDes());
       
  1437 	SQLPROFILER_REPORT_IPC(ESqlIpcWrite, bufFlat.Size());
       
  1438 	}
       
  1439 
       
  1440 /**
       
  1441 Usage of the IPC call arguments:
       
  1442 Arg 0: [in]		column index
       
  1443 Arg 1: [in]		column buffer length in bytes
       
  1444 Arg 2: [in/out]	column buffer
       
  1445 */
       
  1446 void CSqlSrvSession::StmtColumnValueL(const RMessage2& aMessage, TInt aStmtHandle)
       
  1447 	{
       
  1448 	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
       
  1449 	TPtrC8 columnSource;
       
  1450 	TInt columnIndex = aMessage.Int0();
       
  1451 	TInt err = stmt.ColumnSource(columnIndex, columnSource);
       
  1452 	__SQLLEAVE_IF_ERROR(err);
       
  1453 	TInt len = aMessage.Int1();
       
  1454 	if(columnSource.Length() > len)
       
  1455 		{
       
  1456 		TPtr8 ptr(const_cast <TUint8*> (columnSource.Ptr()), columnSource.Length(), columnSource.Length());
       
  1457 		ptr.SetLength(len);
       
  1458 		aMessage.WriteL(2, ptr);
       
  1459 		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, len);
       
  1460 		__SQLLEAVE(KErrOverflow);	
       
  1461 		}
       
  1462 	else
       
  1463 		{
       
  1464 		aMessage.WriteL(2, columnSource);
       
  1465 		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, len);
       
  1466 		}
       
  1467 	}
       
  1468 
       
  1469 /**
       
  1470 Usage of the IPC call arguments:
       
  1471 Arg 0: [in]    parameter buffer length in bytes
       
  1472 Arg 1: [in]    parameter buffer
       
  1473 */
       
  1474 void CSqlSrvSession::DoStmtBindL(const RMessage2& aMessage, CSqlSrvStatement& aStmt)
       
  1475 	{
       
  1476 	TInt prmLen = aMessage.Int0();
       
  1477 	RSqlBufFlat& prmBuf = Server().GetFlatBufL(prmLen);
       
  1478 	aMessage.ReadL(1, prmBuf.BufPtr());
       
  1479 	SQLPROFILER_REPORT_IPC(ESqlIpcRead, prmLen);
       
  1480 	aStmt.BindL(prmBuf);
       
  1481 	}
       
  1482 
       
  1483 /**
       
  1484 Usage of the IPC call arguments:
       
  1485 Arg 0: [in]    	input buffer max length in 16-bit characters
       
  1486 Arg 1: [in/out]	buffer
       
  1487 */
       
  1488 void CSqlSrvSession::StmtDeclColumnTypesL(const RMessage2& aMessage, TInt aStmtHandle)
       
  1489 	{
       
  1490 	CSqlSrvStatement& stmt = ::SqlSessObjFind(iStatements, aStmtHandle, aMessage);
       
  1491 	HBufC* colTypesBuf = stmt.GetDeclColumnTypesL();
       
  1492 	CleanupStack::PushL(colTypesBuf);
       
  1493 	if(colTypesBuf->Des().Length() > aMessage.Int0())
       
  1494 		{
       
  1495 		__SQLLEAVE(KErrOverflow);
       
  1496 		}
       
  1497 	aMessage.WriteL(1, colTypesBuf->Des());
       
  1498 	SQLPROFILER_REPORT_IPC(ESqlIpcWrite, (colTypesBuf->Des().Length() * sizeof(TText)));
       
  1499 	CleanupStack::PopAndDestroy(colTypesBuf);
       
  1500 	}
       
  1501 
       
  1502 
       
  1503 //////////////////////////////////////////////////////////////////////////////////////////////////////////	
       
  1504 ////////////////////////              Helper methods                     /////////////////////////////////
       
  1505 //////////////////////////////////////////////////////////////////////////////////////////////////////////	
       
  1506 
       
  1507 /**
       
  1508 Creates a new output IPC stream object using the aStreamBuf parameter as a stream buffer (stream data source).
       
  1509 
       
  1510 This method immediately pushes aStreamBuf onto the cleanup stack before creating a new output IPC 
       
  1511 stream and so callers of this method should ensure that aStreamBuf is not already on the cleanup stack.
       
  1512 
       
  1513 Returns the handle of the created stream.
       
  1514 
       
  1515 @panic SqlDb 3 Client panic. Internal error - invalid stream handle.
       
  1516 
       
  1517 Usage of the IPC call arguments:
       
  1518 Arg 2: [in/out]   IPC buffer
       
  1519 */
       
  1520 TInt CSqlSrvSession::NewOutputStreamL(const RMessage2& aMessage, MStreamBuf* aStreamBuf)
       
  1521 	{
       
  1522 	aStreamBuf->PushL();
       
  1523 	iIpcStreams.AllocL();
       
  1524 	TInt size = aStreamBuf->SizeL();
       
  1525 	TPckgBuf<TIpcStreamBuf> ipcBuf;
       
  1526 	if(size > 0)						// read the first buffer-full
       
  1527 		{
       
  1528 		TInt len = Min(size, KIpcBufSize);
       
  1529 		aStreamBuf->ReadL(ipcBuf().iData, len);
       
  1530 		}
       
  1531 	TInt handle = 0;
       
  1532 	if(size < 0 || size > KIpcBufSize)
       
  1533 		{								// create the stream object
       
  1534 		HIpcStream* ipcStream = new (ELeave) HIpcStream(aStreamBuf, KIpcBufSize);
       
  1535 		handle = iIpcStreams.Add(ipcStream);
       
  1536 		__SQLPANIC_CLIENT(handle > 0, aMessage, ESqlPanicBadHandle);
       
  1537 		CleanupStack::Pop(aStreamBuf);
       
  1538 		}
       
  1539 	else								// no more data to send
       
  1540 		{
       
  1541 		CleanupStack::PopAndDestroy(aStreamBuf);
       
  1542 		}
       
  1543 	if(size >= 0)
       
  1544 		{
       
  1545 		ipcBuf().iExt = size;
       
  1546 		aMessage.WriteL(2, ipcBuf);
       
  1547 		SQLPROFILER_REPORT_IPC(ESqlIpcWrite, size);
       
  1548 		}
       
  1549 	return handle;
       
  1550 	}
       
  1551 
       
  1552 /**
       
  1553 Reads a 8-bit string with "aByteLen" bytes length, which is in "aArgNum" argument of aMessage.
       
  1554 The string will be zero terminated after the "read" operation.
       
  1555 Returns TDes8 reference pointing to the zero-terminated string.
       
  1556 
       
  1557 @leave KErrBadDescriptor The transferred data length is bigger than the aByteLen value 
       
  1558 
       
  1559 @panic SqlDb 4 Client panic. Negative aByteLen value.
       
  1560 */
       
  1561 TDes8& CSqlSrvSession::ReadString8ZL(const RMessage2& aMessage, TInt aArgNum, TInt aByteLen)
       
  1562 	{
       
  1563 	__SQLPANIC_CLIENT(aByteLen >= 0, aMessage, ESqlPanicBadArgument);
       
  1564 	TDes8& buf = Server().GetBuf8L(aByteLen + 1);
       
  1565 	aMessage.ReadL(aArgNum, buf);
       
  1566 	SQLPROFILER_REPORT_IPC(ESqlIpcRead, aByteLen);
       
  1567 	if(buf.Length() > aByteLen)
       
  1568 		{
       
  1569 		__SQLLEAVE(KErrBadDescriptor);
       
  1570 		}
       
  1571 	buf.Append(TChar(0));
       
  1572 	return buf;
       
  1573 	}
       
  1574 
       
  1575 /**
       
  1576 Reads a 16-bit string with "aCharLen" character length, which is in "aArgNum" argument of aMessage.
       
  1577 The string will be zero terminated after the "read" operation.
       
  1578 Returns TDes16 reference pointing to the zero-terminated string.
       
  1579 
       
  1580 @leave KErrBadDescriptor The transferred data length is bigger than the aCharLen value
       
  1581 
       
  1582 @panic SqlDb 4 Client panic. Negative aCharLen value.
       
  1583 */
       
  1584 TDes16& CSqlSrvSession::ReadString16ZL(const RMessage2& aMessage, TInt aArgNum, TInt aCharLen)
       
  1585 	{
       
  1586 	__SQLPANIC_CLIENT(aCharLen >= 0, aMessage, ESqlPanicBadArgument);
       
  1587 	TDes16& buf = Server().GetBuf16L(aCharLen + 1);
       
  1588 	aMessage.ReadL(aArgNum, buf);
       
  1589 	SQLPROFILER_REPORT_IPC(ESqlIpcRead, (aCharLen * sizeof(TText)));
       
  1590 	if(buf.Length() > aCharLen)
       
  1591 		{
       
  1592 		__SQLLEAVE(KErrBadDescriptor);
       
  1593 		}
       
  1594 	buf.Append(TChar(0));
       
  1595 	return buf;
       
  1596 	}
       
  1597 
       
  1598 /**
       
  1599 Reads a 16-bit string with "aCharLen" character length, which is in "aArgNum" argument of aMessage.
       
  1600 Returns TDes16 reference pointing to the string.
       
  1601 
       
  1602 @leave KErrBadDescriptor The transferred data length is bigger than the aCharLen value
       
  1603 
       
  1604 @panic SqlDb 4 Client panic. Negative aCharLen value.
       
  1605 */
       
  1606 TDes16& CSqlSrvSession::ReadString16L(const RMessage2& aMessage, TInt aArgNum, TInt aCharLen)
       
  1607 	{
       
  1608 	__SQLPANIC_CLIENT(aCharLen >= 0, aMessage, ESqlPanicBadArgument);
       
  1609 	TDes16& buf = Server().GetBuf16L(aCharLen);
       
  1610 	aMessage.ReadL(aArgNum, buf);
       
  1611 	SQLPROFILER_REPORT_IPC(ESqlIpcRead, (aCharLen * sizeof(TText)));
       
  1612 	if(buf.Length() > aCharLen)
       
  1613 		{
       
  1614 		__SQLLEAVE(KErrBadDescriptor);
       
  1615 		}
       
  1616 	return buf;
       
  1617 	}
       
  1618 
       
  1619 /**
       
  1620 The method reads the message argument 1 data and constructs a CSqlSecurityPolicy object from the data.
       
  1621 
       
  1622 @param aMessage Client request encapsulated in RMessage2 object.
       
  1623 
       
  1624 @return A pointer to the created CSqlSecurityPolicy instance.
       
  1625 
       
  1626 @leave KErrArgument, if aMessage argument 0 length is 0 or negative (no security data);
       
  1627        KErrNoMemory, out of memory condition has occured.
       
  1628 
       
  1629 Usage of the IPC call arguments:
       
  1630 Arg 2: [in]  security policies buffer length in bytes if aFunction is ESqlSrvDbCreateSecure
       
  1631 Arg 3: [in]  security policies buffer if aFunction is ESqlSrvDbCreateSecure
       
  1632 */
       
  1633 CSqlSecurityPolicy* CSqlSrvSession::InternalizeSecurityPolicyL(const RMessage2& aMessage)
       
  1634 	{
       
  1635 	// Leave if there is no security policy data
       
  1636 	// The format of arg[2] is an unsigned int
       
  1637 	// with the policy length shifted and concated to the config length
       
  1638 	// the policy data is the first part of arg[3]
       
  1639 	const TUint KConfigStrLenBitWidth = 16;
       
  1640 	TInt securityPolicyLen = aMessage.Int2() >> KConfigStrLenBitWidth;
       
  1641 	if(securityPolicyLen < 1)
       
  1642 		{
       
  1643 		__SQLLEAVE(KErrArgument);
       
  1644 		}
       
  1645 	TSecurityPolicy defaultPolicy(TSecurityPolicy::EAlwaysFail);
       
  1646 	CSqlSecurityPolicy* dbPolicy = CSqlSecurityPolicy::NewLC(defaultPolicy);
       
  1647 	RSqlBufFlat& bufFlat = dbPolicy->BufFlat();
       
  1648 	if(securityPolicyLen > bufFlat.MaxSize())
       
  1649 		{
       
  1650 		__SQLLEAVE_IF_ERROR(bufFlat.ReAlloc(securityPolicyLen));
       
  1651 		}
       
  1652 	TPtr8& ptr = bufFlat.BufPtr();
       
  1653 	aMessage.ReadL(3, ptr);
       
  1654 	SQLPROFILER_REPORT_IPC(ESqlIpcRead, securityPolicyLen);
       
  1655 	// trim off config data if any
       
  1656 	TInt extraBytes = ptr.Length() - securityPolicyLen;
       
  1657 	if(extraBytes > 0)
       
  1658 		{
       
  1659 		ptr.Delete(securityPolicyLen, extraBytes);
       
  1660 		}
       
  1661 	CleanupStack::Pop(dbPolicy);
       
  1662 	return dbPolicy;
       
  1663 	}
       
  1664 
       
  1665 /**
       
  1666 Reports how many objects are allocated by the client.
       
  1667 If the database connection is not in a test mode, the allocated memory cells count will be ignored.
       
  1668 */
       
  1669 TInt CSqlSrvSession::CountResources()
       
  1670 	{
       
  1671 	return iStatements.Count() + iIpcStreams.Count() + (iDbResourceTestMode ? User::CountAllocCells() : 0);
       
  1672 	}
       
  1673 
       
  1674 /**
       
  1675 Extracts from aMessage:
       
  1676 - function code;
       
  1677 - stream or statement handle;
       
  1678 The function will panic the client if aMessage contains bad function code or bad handle encoded in it.
       
  1679 */
       
  1680 void CSqlSrvSession::Extract(const RMessage2& aMessage, TSqlSrvFunction& aFunction, TInt& aHandle)
       
  1681 	{
       
  1682 	TInt msgCode = aMessage.Function();
       
  1683 	aFunction = static_cast <TSqlSrvFunction> (KSqlSrvFunctionMask & msgCode);
       
  1684 	//All operations with code > ESqlSrvDbDelete require valid iDatabase object.
       
  1685 	if(aFunction > ESqlSrvDbDelete)
       
  1686 		{
       
  1687 		__SQLPANIC_CLIENT(iDatabase != NULL, aMessage, ESqlPanicInvalidObj);
       
  1688 		}
       
  1689 	if(aFunction >= ESqlSrvStmtClose)
       
  1690 		{
       
  1691 		//Extracting handle and handle type from the message code
       
  1692 		TSqlSrvHandleType handleType = static_cast <TSqlSrvHandleType> (msgCode & KSqlSrvHandleTypeMask);
       
  1693 		aHandle = (msgCode & KSqlSrvHandleMask) >> KSqlSrvHandleShiftBits;
       
  1694 		__SQLPANIC_CLIENT(aHandle > 0, aMessage, ESqlPanicBadArgument);
       
  1695 		if(aFunction >= ESqlSrvStmtClose && aFunction < ESqlSrvStreamBase)
       
  1696 			{
       
  1697 			__SQLPANIC_CLIENT(handleType == ESqlSrvStatementHandle, aMessage, ESqlPanicBadArgument);
       
  1698 			}
       
  1699 		else if(aFunction > ESqlSrvStreamBase)
       
  1700 			{
       
  1701 			__SQLPANIC_CLIENT(handleType == ESqlSrvStreamHandle, aMessage, ESqlPanicBadArgument);
       
  1702 			}
       
  1703 		}
       
  1704 	}
       
  1705 
       
  1706 /**
       
  1707 The function reads aStmt column 0 value and copies it into the client buffer, accessed via aMessage argument.
       
  1708 
       
  1709 If an error occurs during the execution the function leaves with the error code.
       
  1710 Possible non-leaving return values:
       
  1711  - KErrNone              - the function has completed successfully;
       
  1712  - Positive return value - the length of the column, which means - the destination buffer is too small.
       
  1713                            This return value is possible only with text or binary columns.
       
  1714 
       
  1715 Usage of the IPC call arguments: 
       
  1716 Arg 0: [in]		(8/16-bit character length of SQL statement) | (expected column value type << 24).
       
  1717 Arg 1: [in]		SQL statement.
       
  1718 Arg 2: [in]		Byte max length of the receiving buffer
       
  1719 Arg 3: [in/out]	The receiving buffer
       
  1720 */
       
  1721 TInt CSqlSrvSession::GetColumnValueL(const RMessage2& aMessage, CSqlSrvStatement& aStmt, TSqlColumnType aColType)
       
  1722 	{
       
  1723 	TInt rc = KErrNone;
       
  1724 	switch(aColType)
       
  1725 		{
       
  1726 		case ESqlInt:
       
  1727 			{
       
  1728 			TInt val = aStmt.ColumnInt(0);
       
  1729 			aMessage.WriteL(3, TPtrC8(reinterpret_cast <const TUint8*> (&val), sizeof(val)));
       
  1730 			SQLPROFILER_REPORT_IPC(ESqlIpcWrite, sizeof(val));
       
  1731 			}
       
  1732 			break;
       
  1733 		case ESqlInt64:
       
  1734 			{
       
  1735 			TInt64 val = aStmt.ColumnInt64(0);
       
  1736 			aMessage.WriteL(3, TPtrC8(reinterpret_cast <const TUint8*> (&val), sizeof(val)));
       
  1737 			SQLPROFILER_REPORT_IPC(ESqlIpcWrite, sizeof(val));
       
  1738 			}
       
  1739 			break;
       
  1740 		case ESqlReal:
       
  1741 			{
       
  1742 			TReal val = aStmt.ColumnReal(0);
       
  1743 			aMessage.WriteL(3, TPtrC8(reinterpret_cast <const TUint8*> (&val), sizeof(val)));
       
  1744 			SQLPROFILER_REPORT_IPC(ESqlIpcWrite, sizeof(val));
       
  1745 			}
       
  1746 			break;
       
  1747 		case ESqlText:
       
  1748 		case ESqlBinary:
       
  1749 		default:
       
  1750 			{
       
  1751 			TPtrC8 val;
       
  1752 			if(aColType == ESqlText)
       
  1753 				{
       
  1754 				TPtrC textVal = aStmt.ColumnText(0);
       
  1755 				val.Set(reinterpret_cast <const TUint8*> (textVal.Ptr()), textVal.Length() * sizeof(TUint16));
       
  1756 				}
       
  1757 			else
       
  1758 				{
       
  1759 				val.Set(aStmt.ColumnBinary(0));
       
  1760 				}
       
  1761 			TInt len = val.Length();
       
  1762 			if(len > aMessage.Int2())
       
  1763 				{
       
  1764 				rc = aColType == ESqlText ? (TUint)len / sizeof(TUint16) : len;
       
  1765 				len = aMessage.Int2();
       
  1766 				}
       
  1767 			aMessage.WriteL(3, val.Left(len));
       
  1768 			SQLPROFILER_REPORT_IPC(ESqlIpcWrite, len);
       
  1769 			}
       
  1770 			break;
       
  1771 		}
       
  1772 	return rc;
       
  1773 	}