sysstatemgmt/systemstatemgr/cle/src/clesrv.cpp
changeset 0 4e1aa6a622a0
equal deleted inserted replaced
-1:000000000000 0:4e1aa6a622a0
       
     1 // Copyright (c) 2007-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 <e32debug.h>
       
    17 #include <e32math.h>
       
    18 #include <f32file.h>
       
    19 #include <s32file.h>
       
    20 
       
    21 #include "clesrv.h"
       
    22 #include "clesess.h"
       
    23 #include <ssm/ssmcmd.hrh>
       
    24 
       
    25 
       
    26 // This file is used to store the handles of the libraries which has unload option as ENeverUnload.
       
    27 // This is also defined in cmdcustomcommand.cpp and the handles are written to this file if 
       
    28 // the unload option is ENeverUnload.
       
    29 _LIT(KNeverUnloadLibHandleFile, ":\\private\\2000d75b\\temp\\unloadlibhandles.bin");
       
    30 
       
    31 // ------------------- Policy Server Security Setup ----------------------
       
    32 
       
    33 const TInt KSsmServerSid = 0x2000D75B; //UID3 of sysstatemgr.exe
       
    34 
       
    35 const TUint  KRangeCount = 3;
       
    36 const TInt   KRanges[KRangeCount] =
       
    37 	{
       
    38 	0,
       
    39 	ECleSrvExecuteCmdList,
       
    40 	EEndOfCleOpCodes
       
    41 	};
       
    42 
       
    43 /**
       
    44  Maps to index 0 in the array KPolicyElements
       
    45  */
       
    46 const TInt KSsmServerSidCheck = 0;
       
    47 
       
    48 /**
       
    49  Specifies the appropriate action for each range in KRanges.
       
    50  The nth element of KElementsIndex specifies the appropriate action for the nth range in KRanges.
       
    51  */
       
    52 const TUint8 KElementsIndex[KRangeCount] =
       
    53 	{
       
    54 	CPolicyServer::ENotSupported,
       
    55 	KSsmServerSidCheck,
       
    56 	CPolicyServer::ENotSupported,
       
    57 	};
       
    58 
       
    59 /**
       
    60  Array containing the different security checks performed by this server
       
    61  */
       
    62 const CPolicyServer::TPolicyElement KPolicyElements[] =
       
    63 	{
       
    64 	{_INIT_SECURITY_POLICY_S0(KSsmServerSid), CPolicyServer::EFailClient} //lint !e778 suppress Constant expression evaluates to 0 in operation '+'
       
    65 	};
       
    66 
       
    67 /**
       
    68  Setup a security policy which requires all caps to be used by the SsmServer for all requests
       
    69  including creating a connection. We do not yet have a usecase for anyone else other than
       
    70  SsmServer using SusUtilServer. The caller's SID is matched against SsmServer's
       
    71  SID in each ServiceL call
       
    72  */
       
    73 const CPolicyServer::TPolicy KCleServerPolicy =
       
    74 	{
       
    75 	KSsmServerSidCheck,	// map connection attempts as well to index [0] in KPolicyElements[]
       
    76 	KRangeCount,
       
    77 	KRanges,
       
    78 	KElementsIndex,
       
    79 	KPolicyElements
       
    80 	};
       
    81 
       
    82 
       
    83 
       
    84 void CCleServer::ExecuteCommandListL( CSsmCommandList* aCommandList, const RMessage2& aMessage, const TInt aSessionIndex )
       
    85 	{
       
    86 	__ASSERT_DEBUG( aCommandList->Count() > 0, User::Panic( KCleCmdListEmpty, KCleSrvBadCmdList) );
       
    87 	__ASSERT_DEBUG( __IN_RANGE(aSessionIndex, iSessionInfoArray.Count()), User::Panic( KCleSrvBadIdx, KCleSrvArrayIndexInvalid ) );
       
    88 			
       
    89 	if( (0 == aCommandList->Count()) || !__IN_RANGE(aSessionIndex, iSessionInfoArray.Count()) )
       
    90 		{
       
    91 		User::Leave( KErrArgument );
       
    92 		}
       
    93 	
       
    94 	CSsmCmdListExecutor* executor = CSsmCmdListExecutor::NewL( *this, aSessionIndex );
       
    95 	
       
    96 	iSessionInfoArray[ aSessionIndex ].iExecutor = executor;
       
    97 	iSessionInfoArray[ aSessionIndex ].iMessagePtr = aMessage;
       
    98 
       
    99 	executor->StartL( aCommandList );
       
   100 	}
       
   101 
       
   102 
       
   103 
       
   104 /**
       
   105  * Locate the CommandListExecutor associated with the session calling CommandListCancel.
       
   106  * Delete the Command list (which cancels its AO) then complete the client's RMessage with KErrCancel.
       
   107  */
       
   108 void CCleServer::ExecuteCommandListCancel( TInt aSessionIndex )
       
   109 	{
       
   110 	__ASSERT_DEBUG( __IN_RANGE( aSessionIndex, iSessionInfoArray.Count()), User::Panic( KCleSrvBadIdx, KCleSrvArrayIndexInvalid ) );
       
   111 	
       
   112 	if( iSessionInfoArray[ aSessionIndex ].iExecutor )
       
   113 		{
       
   114 		iSessionInfoArray[ aSessionIndex ].iMessagePtr.Complete( KErrCancel );
       
   115 		delete iSessionInfoArray[ aSessionIndex ].iExecutor;
       
   116 		iSessionInfoArray[ aSessionIndex ].iExecutor = NULL;
       
   117 		}
       
   118 	}
       
   119 
       
   120 	
       
   121 
       
   122 /**
       
   123  * This function is inherited from MCommandListExecutionObserver
       
   124  * and called from CSsmCmdListExecutor to signal the completion of command list processing.
       
   125  */
       
   126 void CCleServer::ListExecutionComplete( TInt aComplete, TInt aSessionIndex ,TCmdErrorSeverity /* aSeverity */ )
       
   127 	{
       
   128 	__ASSERT_DEBUG( __IN_RANGE(aSessionIndex, iSessionInfoArray.Count()), User::Panic( KCleSrvBadIdx, KCleSrvArrayIndexInvalid ) );
       
   129 	iSessionInfoArray[ aSessionIndex ].iMessagePtr.Complete( aComplete );
       
   130 	delete iSessionInfoArray[ aSessionIndex ].iExecutor;
       
   131 	iSessionInfoArray[ aSessionIndex ].iExecutor = NULL;
       
   132 	}
       
   133 
       
   134 
       
   135 
       
   136 /**
       
   137   Used to create a new server-side session.
       
   138  @return A pointer to the new instance of CSession2.
       
   139  @leave KErrNotSupported if versions are incompatible.
       
   140  @publishedPartner
       
   141  @released
       
   142 */
       
   143 EXPORT_C CSession2* CCleServer::NewSessionL( const TVersion& aVersion, const RMessage2& /*aMessage*/ ) const
       
   144 	{
       
   145 	if( !User::QueryVersionSupported(iVersion, aVersion) )
       
   146 		{
       
   147 		User::Leave( KErrNotSupported );
       
   148 		}
       
   149 	
       
   150 	CCleServer& mutatedSelf = const_cast< CCleServer& >( *this );
       
   151 	
       
   152 	return CCleSession::NewL( mutatedSelf ); 
       
   153 	}
       
   154 	
       
   155 
       
   156 
       
   157 /**
       
   158  Iterate through iSessionInfoArray to find an unused array element
       
   159  If found, use it. Otherwise, Append() a new SCleSessionInfo.
       
   160  This function is called during CSession construction.
       
   161 */
       
   162 void CCleServer::RegisterSessionL( TInt& aSessionIndex )
       
   163 	{
       
   164 	const TInt count = iSessionInfoArray.Count();
       
   165 	TBool slotFound = EFalse;
       
   166 	
       
   167 	for(TInt i = 0; i < count; i++ )
       
   168 		{
       
   169 		if( !iSessionInfoArray[ i ].iInUse )
       
   170 			{
       
   171 			iSessionInfoArray[ i ].iInUse = ETrue;
       
   172 			ASSERT( NULL == iSessionInfoArray[ i ].iExecutor );
       
   173 			aSessionIndex = i;
       
   174 			slotFound = ETrue;
       
   175 			iSessionCount++;			
       
   176 			break;
       
   177 			}
       
   178 		}
       
   179 	
       
   180 	if( !slotFound )
       
   181 		{
       
   182 		SCleSessionInfo sessionInfo;
       
   183 		sessionInfo.iExecutor = NULL;
       
   184 		sessionInfo.iInUse = ETrue;
       
   185 		iSessionInfoArray.AppendL( sessionInfo );
       
   186 		aSessionIndex = iSessionCount++;
       
   187 		}
       
   188 	
       
   189 	DEBUGPRINT2( _L("***** Registered in slot %d"), aSessionIndex );
       
   190 	}
       
   191 
       
   192 
       
   193 
       
   194 /**
       
   195  Called from CSession destructor.
       
   196 */
       
   197 void CCleServer::DeregisterSession( const TInt& aSessionIndex )
       
   198 	{
       
   199 	__ASSERT_DEBUG( __IN_RANGE(aSessionIndex, iSessionInfoArray.Count()), User::Panic(KCleSrvBadIdx, KCleSrvArrayIndexInvalid) );
       
   200 	
       
   201 	if( iSessionInfoArray[ aSessionIndex ].iExecutor )
       
   202 		{
       
   203 		delete iSessionInfoArray[ aSessionIndex ].iExecutor;
       
   204 		iSessionInfoArray[ aSessionIndex ].iExecutor = NULL;
       
   205 		}
       
   206 
       
   207 	iSessionInfoArray[ aSessionIndex ].iInUse = EFalse;
       
   208 	iSessionCount--;
       
   209 
       
   210    // Remove unused elements at the end of the array, so iSessionInfoArray can be (granular) shrunk
       
   211 	const TInt count = iSessionInfoArray.Count();
       
   212 	TBool slotRemoved = EFalse;
       
   213 	for(TInt i = count-1; i >= 0 ; i-- )
       
   214 		{
       
   215 		if( !iSessionInfoArray[ i ].iInUse )
       
   216 			{
       
   217       		iSessionInfoArray.Remove(i);
       
   218       		slotRemoved = ETrue;
       
   219 			}
       
   220 		else
       
   221 			{
       
   222 			break;
       
   223 			}
       
   224 		}
       
   225 	if (slotRemoved)
       
   226 		{
       
   227 		iSessionInfoArray.GranularCompress();
       
   228 		}
       
   229 
       
   230 	DEBUGPRINT2( _L("***** De-registered slot %d"), aSessionIndex );
       
   231  	}
       
   232 
       
   233 // Release the libraries loaded by custom commands which has the unload option set to 'ENeverUnload'
       
   234 TInt CCleServer::CloseNeverUnloadLibrariesL()
       
   235 	{
       
   236 	const TChar sysDrive = RFs::GetSystemDriveChar();
       
   237 	RBuf filename;
       
   238 	filename.CreateL(KNeverUnloadLibHandleFile().Length() + 1);
       
   239 	filename.Append(sysDrive);
       
   240 	filename.Append(KNeverUnloadLibHandleFile());
       
   241 	filename.CleanupClosePushL();
       
   242 	RFs fs;
       
   243 	User::LeaveIfError(fs.Connect());
       
   244 	CleanupClosePushL(fs);
       
   245 	RFile file;
       
   246 	CleanupClosePushL(file);
       
   247 	TInt libsReleased = 0;
       
   248 	const TInt error=file.Open(fs, filename, EFileShareReadersOnly|EFileStream|EFileRead);
       
   249 	if (error==KErrNone)
       
   250 		{
       
   251 		RFileReadStream readStream;
       
   252 		readStream.Attach(file);
       
   253 		CleanupClosePushL(readStream);
       
   254 		TInt handle=0;
       
   255 		RLibrary lib;
       
   256 		TRAPD(ret, handle = readStream.ReadInt32L());
       
   257 		while(ret != KErrEof && handle > 0)
       
   258 			{
       
   259 			lib.SetHandle(handle);
       
   260 			lib.Close();
       
   261 			libsReleased++;
       
   262 			TRAP(ret, handle = readStream.ReadInt32L());
       
   263 			}
       
   264 		CleanupStack::PopAndDestroy(&readStream);
       
   265 		}
       
   266 	fs.Delete(filename);//Ignore the error. Perhaps the file does not exist.
       
   267 	CleanupStack::PopAndDestroy(3);
       
   268 	return libsReleased;
       
   269 	}
       
   270 
       
   271 
       
   272 /**
       
   273  * Used to create a new CCleServer
       
   274  * @return A pointer to the CCleServer
       
   275  * @leave One of the system-wide error codes if construction fails.
       
   276  * @publishedPartner
       
   277  * @released
       
   278  */
       
   279 EXPORT_C CCleServer* CCleServer::NewL(const TDesC& aServerName)
       
   280 	{
       
   281 	CCleServer* self = NewLC(aServerName);
       
   282 	CleanupStack::Pop();
       
   283 	return self;	
       
   284 	}
       
   285 
       
   286 
       
   287 
       
   288 /**
       
   289  * Used to create a new CCleServer
       
   290  * @return A pointer to the CCleServer
       
   291  * @leave One of the system-wide error codes if construction fails.
       
   292  * @publishedPartner
       
   293  * @released
       
   294  */
       
   295 EXPORT_C CCleServer* CCleServer::NewLC(const TDesC& aServerName)
       
   296 	{
       
   297 	CCleServer* self = new(ELeave) CCleServer;	
       
   298 	CleanupStack::PushL( self );
       
   299 	self->ConstructL(aServerName);
       
   300 	return self;	
       
   301 	}
       
   302 	
       
   303 
       
   304 
       
   305 /**
       
   306  * Static function used to create and start CCleServer
       
   307  * 
       
   308  * @return KErrAlreadyExists if the server is already running
       
   309  * @publishedPartner
       
   310  * @released
       
   311  */
       
   312 EXPORT_C TInt CCleServer::StartCleSrv(const TDesC& aServerName)
       
   313 	{
       
   314 	TAny* threadParam = reinterpret_cast<TAny*>(const_cast<TDesC*>(&aServerName));
       
   315 	// Create a Unique name for the thread name
       
   316 	TName name(aServerName);
       
   317 	_LIT(KUnderScore, "_");
       
   318 	name.Append(KUnderScore);
       
   319 	name.AppendNum(Math::Random(), EHex);
       
   320 
       
   321 	const TInt KCleSrvMinHeapSize = 0x2000;
       
   322 	const TInt KCleSrvMaxHeapSize = 10 * KCleSrvMinHeapSize;
       
   323 	RThread srvThread;
       
   324 	TInt err = srvThread.Create( name, &CCleServer::CleSrvThreadFn, 
       
   325 								 KDefaultStackSize, KCleSrvMinHeapSize, KCleSrvMaxHeapSize, 
       
   326 								 threadParam, EOwnerProcess );
       
   327 
       
   328 	if( KErrNone == err )
       
   329 		{
       
   330 		TRequestStatus trs;
       
   331 		
       
   332 		srvThread.Rendezvous( trs );
       
   333 		srvThread.Resume();
       
   334 		srvThread.Close();
       
   335 		
       
   336 		User::WaitForRequest( trs );	
       
   337 		err = trs.Int();
       
   338 		}
       
   339 
       
   340 	return err;
       
   341 	}
       
   342 
       
   343 
       
   344 
       
   345 TInt CCleServer::CleSrvThreadFn( TAny* aAny )
       
   346 	{
       
   347 	const TDesC* serverName = const_cast<const TDesC*>(static_cast<TDesC*>(aAny));
       
   348 	TInt err = KErrNoMemory;
       
   349     CTrapCleanup* cleanup = CTrapCleanup::New();
       
   350     if( cleanup )
       
   351     	{
       
   352 	    TRAP( err,
       
   353 	        {
       
   354 	        CActiveScheduler* sched = new(ELeave) CActiveScheduler();
       
   355 	        CleanupStack::PushL( sched );
       
   356 	        CActiveScheduler::Install( sched );
       
   357 	
       
   358 	        CCleServer* cleSrv = CCleServer::NewLC(*serverName);
       
   359 	        RThread::Rendezvous( KErrNone );
       
   360 	    	// Must not use serverName after rendezvousing with client
       
   361 	        serverName = NULL;
       
   362 	        
       
   363 	        CActiveScheduler::Start();
       
   364 	
       
   365 	        CleanupStack::PopAndDestroy( cleSrv );
       
   366 	        CleanupStack::PopAndDestroy( sched );
       
   367 	        });
       
   368 
       
   369 	    delete cleanup;
       
   370     	}
       
   371  
       
   372     return err;
       
   373 	}
       
   374 
       
   375 
       
   376 /**
       
   377 
       
   378  */
       
   379 CCleServer::CCleServer()
       
   380 : CPolicyServer( EPriorityHigh, KCleServerPolicy, EUnsharableSessions ),
       
   381   iVersion( KCleSrvVersionMajor, KCleSrvVersionMinor, KCleSrvVersionBuild )
       
   382 	{
       
   383 	}
       
   384 	
       
   385 	
       
   386 	
       
   387 void CCleServer::ConstructL(const TDesC& aServerName)
       
   388 	{
       
   389 	//If the ENeverUnload file is left over, then it should be cleaned up.
       
   390 	//Ignore the error. We don't want the server to be stopped due to this error.
       
   391 	TRAP_IGNORE(CleanHandlesFileL());
       
   392 	
       
   393 	StartL( aServerName );
       
   394 	// The starting thread is signalled in the thread function.
       
   395 	}
       
   396 	
       
   397 
       
   398 // Delete the file which stores the handles of those libraries used by custom commands which has unload option set to ENeverUnload.
       
   399 // Generally it will be deleted from the destructor. If it could not be deleted for some reason from the destructor, 
       
   400 // then it should be deleted while starting the server.
       
   401 void CCleServer::CleanHandlesFileL()
       
   402 	{
       
   403 	const TChar sysDrive = RFs::GetSystemDriveChar();
       
   404 	RBuf filename;
       
   405 	filename.CreateL(KNeverUnloadLibHandleFile().Length() + 1);
       
   406 	filename.Append(sysDrive);
       
   407 	filename.Append(KNeverUnloadLibHandleFile());
       
   408 	filename.CleanupClosePushL();
       
   409 	RFs fs;
       
   410 	User::LeaveIfError(fs.Connect());
       
   411 	fs.Delete(filename);//Ignore the error. Perhaps the file does not exist.
       
   412 	fs.Close();
       
   413 	CleanupStack::PopAndDestroy();
       
   414 	}
       
   415 
       
   416 CCleServer::~CCleServer()
       
   417 	{
       
   418 	const TInt count = iSessionInfoArray.Count();	
       
   419 	for(TInt i = 0; i < count; i++ )
       
   420 		{
       
   421 		delete iSessionInfoArray[ i ].iExecutor;
       
   422 		iSessionInfoArray[ i ].iExecutor = NULL;
       
   423 		}
       
   424 	iSessionInfoArray.Close();
       
   425 
       
   426 	//Server is being destructed, so no need to leave from here.
       
   427 	TRAP_IGNORE(CloseNeverUnloadLibrariesL());
       
   428 	}
       
   429