diff -r 000000000000 -r 4e1aa6a622a0 sysstatemgmt/systemstatemgr/ssm/src/ssmswppolicysrv.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sysstatemgmt/systemstatemgr/ssm/src/ssmswppolicysrv.cpp Tue Feb 02 00:53:00 2010 +0200 @@ -0,0 +1,599 @@ +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// ssmpolicysrv.cpp +// +// + +#include +#include +#include +#include +#include + +#include "ssmswppolicysrv.h" +#include "ssmswppolicysess.h" +#include "ssmswppolicyconst.h" +#include "ssmdebug.h" +#include "ssmserverpanic.h" + +// ------------------- SsmSwpPolicy Server Security Setup ---------------------- + +const TInt KSsmServerSid = 0x2000D75B; //UID3 of sysstatemgr.exe + +const TUint KRangeCount = 3; +const TInt KRanges[KRangeCount] = + { + 0, + KFirstUsedOpCode, //range: 1...(EEndOfSsmSwpPolicySrvOpCodes-1) inclusive + EEndOfSsmSwpPolicySrvOpCodes + }; + +/** + Maps to index 0 in the array KPolicyElements + */ +const TInt KSsmServerSidCheck = 0; + +/** + Specifies the appropriate action for each range in KRanges. + The nth element of KElementsIndex specifies the appropriate action for the nth range in KRanges. + */ +const TUint8 KElementsIndex[KRangeCount] = + { + CPolicyServer::ENotSupported, + KSsmServerSidCheck, + CPolicyServer::ENotSupported, + }; + +/** + Array containing the different security checks performed by this server + */ +const CPolicyServer::TPolicyElement KPolicyElements[] = + { + {_INIT_SECURITY_POLICY_S0(KSsmServerSid), CPolicyServer::EFailClient} //lint !e778 suppress Constant expression evaluates to 0 in operation '+' + }; + +/** + Setup a security policy which requires all caps to be used by the SsmServer for all requests + including creating a connection. The caller's SID is matched against SsmServer's + SID in each ServiceL call + */ +const CPolicyServer::TPolicy KSsmSwpPolicyServerPolicy = + { + KSsmServerSidCheck, // map connection attempts as well to index [0] in KPolicyElements[] + KRangeCount, + KRanges, + KElementsIndex, + KPolicyElements + }; + +/** +CSsmSwpPolicyStepCompletion is an active object used for executing all the steps involved in +the swp transition. Initial state for the active object is set as EIdle. +*/ +CSsmSwpPolicyServer::CSsmSwpPolicyStepCompletion* CSsmSwpPolicyServer::CSsmSwpPolicyStepCompletion::NewL(MSsmSwpPolicy* aSwpPolicy, CSsmSwpPolicyServer& aServer, const TInt aSessionIndex) + { + CSsmSwpPolicyStepCompletion* self = new(ELeave)CSsmSwpPolicyStepCompletion(aSwpPolicy, aServer, aSessionIndex); + return self; + } + +CSsmSwpPolicyServer::CSsmSwpPolicyStepCompletion::CSsmSwpPolicyStepCompletion(MSsmSwpPolicy* aSwpPolicy, CSsmSwpPolicyServer& aServer, const TInt aSessionIndex) + : CActive(EPriorityStandard), iStep(EIdle), iSwpPolicy(aSwpPolicy), iSessionIndex(aSessionIndex), iServer(aServer) + { + CActiveScheduler::Add(this); + } + +CSsmSwpPolicyServer::CSsmSwpPolicyStepCompletion::~CSsmSwpPolicyStepCompletion() + { + Cancel(); + } + +/** +Calls Initialize of the SwpPolicy. Sets the active object state as EInitialize. +*/ +void CSsmSwpPolicyServer::CSsmSwpPolicyStepCompletion::StartInitialize(const RMessagePtr2& aMessagePtr2) + { + __ASSERT_DEBUG(!IsActive(), PanicNow(KSsmSwpPolicyServer, ESsmSwpPolicySrvStepError1)); + __ASSERT_DEBUG(iStep == EIdle, PanicNow(KSsmSwpPolicyServer, ESsmSwpPolicySrvStepError1)); + + // This message will be completed in RunL(). + iMessagePtr = aMessagePtr2; + + // Initialize is the first step in the process of swp transition. + // CSsmSwpPolicyFrame does all the step checking before giving the request to ssmswppolicyserver + // so no further checking is required here. + iStep = EInitialize; + iSwpPolicy->Initialize(iStatus); + SetActive(); + DEBUGPRINT2(_L("CSsmSwpPolicyStepCompletion: CSsmSwpPolicyStepCompletion State %d"), iStep); + } + +/** +Calls PrepareCommandList of the SwpPolicy. Sets the active object state as EPrepareCommandList. +*/ +void CSsmSwpPolicyServer::CSsmSwpPolicyStepCompletion::StartPrepareCommandList(const TSsmSwp& aSwp, const RMessagePtr2& aMessagePtr2) + { + __ASSERT_DEBUG(!IsActive(), PanicNow(KSsmSwpPolicyServer, ESsmSwpPolicySrvStepError2)); + __ASSERT_DEBUG(iStep == EInitialize, PanicNow(KSsmSwpPolicyServer, ESsmSwpPolicySrvStepError2)); + + // This message will be completed in RunL(). + iMessagePtr = aMessagePtr2; + + // PrepareCommandList should be called only after initializing the swp policy. + // CSsmSwpPolicyFrame does all the step checking before giving the request to ssmswppolicyserver + // so no further checking is required here. + iStep = EPrepareCommandList; + DEBUGPRINT2(_L("CSsmSwpPolicyStepCompletion: CSsmSwpPolicyStepCompletion State %d"), iStep); + iSwpPolicy->PrepareCommandList(aSwp, iStatus); + SetActive(); + } + +/** +Calls HandleCleReturnValue of the SwpPolicy. +*/ +void CSsmSwpPolicyServer::CSsmSwpPolicyStepCompletion::StartHandleCleReturnValue(const TSsmSwp& aSwp, TInt aError, TInt aSeverity, const RMessagePtr2& aMessagePtr2) + { + __ASSERT_DEBUG(!IsActive(), PanicNow(KSsmSwpPolicyServer, ESsmSwpPolicySrvStepError4)); + __ASSERT_DEBUG(iStep == ECallCommandList, PanicNow(KSsmSwpPolicyServer, ESsmSwpPolicySrvStepError4)); + + // This message will be completed in RunL(). + iMessagePtr = aMessagePtr2; + + // HandleCleReturnValue should be called only after executing the command list which is returned by swp policy. + // CSsmSwpPolicyFrame does all the step checking before giving the request to ssmswppolicyserver so no further checking is required here. + iStep = EHandleCleReturnValue; + DEBUGPRINT2(_L("CSsmSwpPolicyStepCompletion: CSsmSwpPolicyStepCompletion State %d"), iStep); + iSwpPolicy->HandleCleReturnValue(aSwp, aError, aSeverity, iStatus); + SetActive(); + } + +void CSsmSwpPolicyServer::CSsmSwpPolicyStepCompletion::RunL() + { + DEBUGPRINT2(_L("CSsmSwpPolicyStepCompletion: CSsmSwpPolicyStepCompletion State %d"), iStep); + // Completes the message + iMessagePtr.Complete(iStatus.Int()); + + // swp transition will be marked as complete only after the execution of HandleCleReturnValue method + if (iStep == EHandleCleReturnValue) + { + // In order to avoid the memory leak we have to delete the session info as this swp transition is cancelled, + // and the same session can be used for the next similar swp transition. + iServer.DeleteSSwpPolicySessionInfo(iSessionIndex); + } + } + +/** +Cancels any outstanding request, based on the state of the active object. +*/ +void CSsmSwpPolicyServer::CSsmSwpPolicyStepCompletion::DoCancel() + { + switch(iStep) + { + case EInitialize: + { + DEBUGPRINT1(_L("CSsmSwpPolicyStepCompletion: Cancelled the Initization of SwpPolicy")); + iSwpPolicy->InitializeCancel(); + iMessagePtr.Complete(KErrCancel); + break; + } + case EPrepareCommandList: + { + DEBUGPRINT1(_L("CSsmSwpPolicyStepCompletion: Cancelled the Preparation of the commandlist")); + iSwpPolicy->PrepareCommandListCancel(); + iMessagePtr.Complete(KErrCancel); + break; + } + case EHandleCleReturnValue: + { + DEBUGPRINT1(_L("CSsmSwpPolicyStepCompletion: Cancelled the HandleCleReturnValue")); + iSwpPolicy->HandleCleReturnValueCancel(); + iMessagePtr.Complete(KErrCancel); + break; + } + default: + { + break; + } + }; + } + +/** +Current RunL() implemenation doesn't leave, so RunError will never be called. +*/ +TInt CSsmSwpPolicyServer::CSsmSwpPolicyStepCompletion::RunError() + { + DEBUGPRINT1(_L("CSsmSwpPolicyStepCompletion: RunError")); + return KErrNone; + } + +/** +Gets the dll handle to SwpPolicy and initializes the SwpPolicy +*/ +void CSsmSwpPolicyServer::CallSetDllHandleAndInitializeL(const RMessage2& aMessage, const TInt aSessionIndex) + { + __ASSERT_DEBUG(IN_RANGE(aSessionIndex, iSessionInfoArray.Count()), PanicNow(KSsmSwpPolicyBadIdx, KSsmSwpPolicySrvArrayIndexInvalid)); + + RLibrary library; + // Sets the swp policy library handle. Library is owned by the CSsmSwpRequestHandler. + library.SetHandle(aMessage.Int0()); + + DEBUGPRINT1(_L("CSsmSwpPolicyServer: SwpPolicy handle is set")); + iSessionInfoArray[aSessionIndex].iSwpPolicy = reinterpret_cast(library.Lookup(1)()); + + DEBUGPRINT1(_L("CSsmSwpPolicyServer: Create CSsmSwpPolicyStepCompletion active object")); + iSessionInfoArray[aSessionIndex].iSsmSwpPolicyStepCompletion = CSsmSwpPolicyStepCompletion::NewL(iSessionInfoArray[aSessionIndex].iSwpPolicy, *this, aSessionIndex); + + // aMessage will be completed in CSsmSwpPolicyStepCompletion's RunL method, + // when the Initialization of the swp policy is completed. + iSessionInfoArray[aSessionIndex].iSsmSwpPolicyStepCompletion->StartInitialize(aMessage); + } + +/** +Cancels the Initialization of the swppolicy, if any Initialization request is pending. +*/ +void CSsmSwpPolicyServer::CallInitializeCancel(TInt aSessionIndex) + { + DEBUGPRINT1(_L("CSsmSwpPolicyServer: CallInitializeCancel")); + __ASSERT_DEBUG(IN_RANGE(aSessionIndex, iSessionInfoArray.Count()), PanicNow(KSsmSwpPolicyBadIdx, KSsmSwpPolicySrvArrayIndexInvalid)); + __ASSERT_DEBUG(iSessionInfoArray[aSessionIndex].iSsmSwpPolicyStepCompletion != NULL, PanicNow(KSsmSwpPolicyServer, ESsmSwpPolicyServerError1)); + + // CSsmSwpPolicyFrame checks whether initialize is called before cancelling the initialization, , so no need to check + // for valid iSsmSwpPolicyStepCompletion pointer. + // iSessionInfoArray[aSessionIndex].iMessagePtr will be completed in CSsmSwpPolicyStepCompletion's DoCancel method, + iSessionInfoArray[aSessionIndex].iSsmSwpPolicyStepCompletion->Cancel(); + + DEBUGPRINT1(_L("CSsmSwpPolicyServer: Deleted the session info as Initialize is cancelled")); + // In order to avoid the memory leak we have to delete the session info as this swp transition is cancelled, + // and the same session can be used for the next similar swp transition. + DeleteSSwpPolicySessionInfo(aSessionIndex); + } + +/** +Prepares the commandlist in swppolicy +*/ +void CSsmSwpPolicyServer::CallPrepareCommandListL(const RMessage2& aMessage, TInt aSessionIndex) + { + DEBUGPRINT1(_L("CSsmSwpPolicyServer: Call SwpPolicy's PrepareCommandList ")); + __ASSERT_DEBUG(IN_RANGE(aSessionIndex, iSessionInfoArray.Count()), PanicNow(KSsmSwpPolicyBadIdx, KSsmSwpPolicySrvArrayIndexInvalid)); + __ASSERT_DEBUG(iSessionInfoArray[aSessionIndex].iSsmSwpPolicyStepCompletion != NULL, PanicNow(KSsmSwpPolicyServer, ESsmSwpPolicyServerError2)); + + TSsmSwp ssmSwp(0,0); + TPckg swpBuf(ssmSwp); + aMessage.ReadL(0, swpBuf); + + // CSsmSwpPolicyFrame checks whether initialize is called before CallHandleCleReturnValue is called, so no need to check + // for valid iSsmSwpPolicyStepCompletion pointer. + + // aMessage will be completed in CSsmSwpPolicyStepCompletion's RunL method, + // when the preparation of the commandlist is completed. + iSessionInfoArray[aSessionIndex].iSsmSwpPolicyStepCompletion->StartPrepareCommandList(ssmSwp, aMessage); + } + +/** +Cancels the preparation of the commandlist, if any PrepareCommandList request is pending. +*/ +void CSsmSwpPolicyServer::CallPrepareCommandListCancel(TInt aSessionIndex) + { + DEBUGPRINT1(_L("CSsmSwpPolicyServer: CallPrepareCommandListCancel")); + __ASSERT_DEBUG(IN_RANGE(aSessionIndex, iSessionInfoArray.Count()), PanicNow(KSsmSwpPolicyBadIdx, KSsmSwpPolicySrvArrayIndexInvalid)); + __ASSERT_DEBUG(iSessionInfoArray[aSessionIndex].iSsmSwpPolicyStepCompletion != NULL, PanicNow(KSsmSwpPolicyServer, ESsmSwpPolicyServerError3)); + + // CSsmSwpPolicyFrame checks whether initialize is called before cancelling the initialization, so no need to check + // for valid iSsmSwpPolicyStepCompletion pointer. + // iSessionInfoArray[aSessionIndex].iMessagePtr will be completed in CSsmSwpPolicyStepCompletion's DoCancel method, + iSessionInfoArray[aSessionIndex].iSsmSwpPolicyStepCompletion->Cancel(); + + DEBUGPRINT1(_L("CSsmSwpPolicyServer: Deleted the session info as PrepareCommandList is cancelled")); + // In order to avoid the memory leak we have to delete the session info as this swp transition is cancelled, + // and the same session can be used for the next similar swp transition. + DeleteSSwpPolicySessionInfo(aSessionIndex); + } + +/** +Returns the commandlist to the client from swppolicy. +@return A pointer to commandlist. +*/ +void CSsmSwpPolicyServer::CallCommandListL(const RMessage2& aMessage, TInt aSessionIndex) + { + DEBUGPRINT1(_L("CSsmSwpPolicyServer: CallCommandListL")); + __ASSERT_DEBUG(IN_RANGE(aSessionIndex, iSessionInfoArray.Count()), PanicNow(KSsmSwpPolicyBadIdx, KSsmSwpPolicySrvArrayIndexInvalid)); + __ASSERT_DEBUG(iSessionInfoArray[aSessionIndex].iSsmSwpPolicyStepCompletion != NULL, PanicNow(KSsmSwpPolicyServer, ESsmSwpPolicyServerError4)); + // CommandList should be called only after preparing the command list, so the active object state should be EPrepareCommandList. + __ASSERT_DEBUG(iSessionInfoArray[aSessionIndex].iSsmSwpPolicyStepCompletion->CurrentStep() == CSsmSwpPolicyServer::CSsmSwpPolicyStepCompletion::EPrepareCommandList, + PanicNow(KSsmSwpPolicyServer, ESsmSwpPolicySrvStepError3)); + + // CSsmSwpPolicyFrame checks whether initialize is called before CallCommandList is called, so no need to check + // for valid iSsmSwpPolicyStepCompletion pointer. + // Sets the current step to CallCommandList + iSessionInfoArray[aSessionIndex].iSsmSwpPolicyStepCompletion->SetCurrentStep(CSsmSwpPolicyServer::CSsmSwpPolicyStepCompletion::ECallCommandList); + CSsmCommandList* ssmCmdList = (iSessionInfoArray[aSessionIndex].iSwpPolicy)->CommandList(); + CleanupStack::PushL(ssmCmdList); + CBufFlat* buf = CBufFlat::NewL(KSsmSwpPolicyStreamBufMaxSize); + CleanupStack::PushL(buf); + + RBufWriteStream writeStream(*buf); + CleanupClosePushL(writeStream); + + DEBUGPRINT1(_L("CSsmSwpPolicyServer: Externalizes the commandlist")); + ssmCmdList->ExternalizeL(writeStream); + + // Ensure any memory that might already have been allocated is disposed of. + // Transfer the streamed cmd list from the CBuf. + RBuf8 cmdListBuf; + cmdListBuf.CreateL(buf->Size()); + CleanupClosePushL(cmdListBuf); + buf->Read(0, cmdListBuf); + + aMessage.WriteL(0, cmdListBuf); + + aMessage.Complete(KErrNone); + CleanupStack::PopAndDestroy(4, ssmCmdList); // buf, writeStream and cmdListBuf + } + +/** +Handles the value returned by Cle. +*/ +void CSsmSwpPolicyServer::CallHandleCleReturnValueL(const RMessage2& aMessage, TInt aSessionIndex) + { + DEBUGPRINT1(_L("CSsmSwpPolicyServer: CallHandleCleReturnValueL")); + __ASSERT_DEBUG(IN_RANGE(aSessionIndex, iSessionInfoArray.Count()), PanicNow(KSsmSwpPolicyBadIdx, KSsmSwpPolicySrvArrayIndexInvalid)); + __ASSERT_DEBUG(iSessionInfoArray[aSessionIndex].iSsmSwpPolicyStepCompletion != NULL, PanicNow(KSsmSwpPolicyServer, ESsmSwpPolicyServerError5)); + + TSsmSwp ssmSwp(0,0); + TPckg swpBuf(ssmSwp); + aMessage.ReadL(0, swpBuf); + + const TInt error = aMessage.Int1(); + const TInt severity = aMessage.Int2(); + + // CSsmSwpPolicyFrame checks whether initialize is called before CallHandleCleReturnValue is called, so no need to check + // for valid iSsmSwpPolicyStepCompletion pointer. + + // aMessage will be completed in CSsmSwpPolicyStepCompletion's RunL method, + // when the cle's return value is handled by the swppolicy. + (iSessionInfoArray[aSessionIndex].iSsmSwpPolicyStepCompletion)->StartHandleCleReturnValue(ssmSwp, error, severity, aMessage); + } + +/** +Cancels the HandleCleReturnValue, if any HandleCleReturnValue request is pending. +*/ +void CSsmSwpPolicyServer::CallHandleCleReturnValueCancel(TInt aSessionIndex) + { + DEBUGPRINT1(_L("CSsmSwpPolicyServer: CallHandleCleReturnValueCancel")); + __ASSERT_DEBUG(IN_RANGE(aSessionIndex, iSessionInfoArray.Count()), PanicNow(KSsmSwpPolicyBadIdx, KSsmSwpPolicySrvArrayIndexInvalid)); + __ASSERT_DEBUG(iSessionInfoArray[aSessionIndex].iSsmSwpPolicyStepCompletion != NULL, PanicNow(KSsmSwpPolicyServer, ESsmSwpPolicyServerError6)); + + // CSsmSwpPolicyFrame checks whether initialize is called before cancelling the initialization, so no need to check + // for valid iSsmSwpPolicyStepCompletion pointer. + // iSessionInfoArray[aSessionIndex].iMessagePtr will be completed in CSsmSwpPolicyStepCompletion's DoCancel method. + iSessionInfoArray[aSessionIndex].iSsmSwpPolicyStepCompletion->Cancel(); + + DEBUGPRINT1(_L("CSsmSwpPolicyServer: Deleted the session info as HandleCleReturnValue is cancelled")); + // In order to avoid the memory leak we have to delete the session info as this swp transition is cancelled, + // and the same session can be used for the next similar swp transition. + DeleteSSwpPolicySessionInfo(aSessionIndex); + } + +/** +Iterate through iSessionInfoArray to find an unused array element +If found, use it. Otherwise, Append() a new SSwpPolicySessionInfo. +This function is called during CSession construction. +*/ +void CSsmSwpPolicyServer::RegisterSessionL(TInt& aSessionIndex) + { + const TInt count = iSessionInfoArray.Count(); + TBool slotFound = EFalse; + + for(TInt i = 0; i < count; ++i) + { + if(!iSessionInfoArray[i].iInUse) + { + DEBUGPRINT1(_L("CSsmSwpPolicyServer: Using the free slot of the sessionarray")); + iSessionInfoArray[i].iInUse = ETrue; + __ASSERT_ALWAYS(NULL, iSessionInfoArray[i].iSwpPolicy); + aSessionIndex = i; + slotFound = ETrue; + break; + } + } + + if(!slotFound) + { + DEBUGPRINT1(_L("CSsmSwpPolicyServer: No free slot found, so appending a new member to the sessionarray")); + SSwpPolicySessionInfo sessionInfo; + sessionInfo.iInUse = ETrue; + sessionInfo.iSwpPolicy = NULL; + sessionInfo.iSsmSwpPolicyStepCompletion = NULL; + iSessionInfoArray.AppendL(sessionInfo); + // using count instead of iSessionInfoArray.Count()-1 as it is set before appending the element to the array, + // and its value is equal to iSessionInfoArray.Count()-1 + aSessionIndex = count; + } + DEBUGPRINT2(_L("Registered SsmSwpPolicyCli in slot %d"), aSessionIndex); + } + +/** +This method is used to delete the session information once the swp transition is complete. +This is required as the same session can be used for more than one individual swp transition. +*/ +void CSsmSwpPolicyServer::DeleteSSwpPolicySessionInfo(TInt aSessionIndex) + { + __ASSERT_DEBUG(IN_RANGE(aSessionIndex, iSessionInfoArray.Count()), PanicNow(KSsmSwpPolicyBadIdx, KSsmSwpPolicySrvArrayIndexInvalid)); + + DEBUGPRINT1(_L("CSsmSwpPolicyServer: Deletes the SwpPolicySession information.")); + if(iSessionInfoArray[aSessionIndex].iSsmSwpPolicyStepCompletion) + { + delete iSessionInfoArray[aSessionIndex].iSsmSwpPolicyStepCompletion; + iSessionInfoArray[aSessionIndex].iSsmSwpPolicyStepCompletion = NULL; + } + + if(iSessionInfoArray[aSessionIndex].iSwpPolicy) + { + DEBUGPRINT1(_L("CSsmSwpPolicyServer: Releases the SwpPolicy")); + (iSessionInfoArray[aSessionIndex].iSwpPolicy)->Release(); + iSessionInfoArray[aSessionIndex].iSwpPolicy = NULL; + } + } + +/** +Called from CSession destructor. +*/ +void CSsmSwpPolicyServer::DeregisterSession(const TInt& aSessionIndex) + { + __ASSERT_DEBUG(IN_RANGE(aSessionIndex, iSessionInfoArray.Count()), PanicNow(KSsmSwpPolicyBadIdx, KSsmSwpPolicySrvArrayIndexInvalid)); + + DeleteSSwpPolicySessionInfo(aSessionIndex); + iSessionInfoArray[aSessionIndex].iInUse = EFalse; + + // Remove unused elements at the end of the array, so iSessionInfoArray can be (granular) shrunk + const TInt count = iSessionInfoArray.Count(); + TBool slotRemoved = EFalse; + for (TInt i = count-1; i >= 0 ; i--) + { + if (!iSessionInfoArray[i].iInUse) + { + iSessionInfoArray.Remove(i); + slotRemoved = ETrue; + } + else + { + break; + } + } + if (slotRemoved) + { + iSessionInfoArray.GranularCompress(); + } + DEBUGPRINT2(_L("De-registered SsmSwpPolicyCli slot %d"), aSessionIndex); + } + +/** +Used to create a new server-side session. +@return A pointer to the new instance of CSession2. +@leave KErrNotSupported if versions are incompatible. +*/ +EXPORT_C CSession2* CSsmSwpPolicyServer::NewSessionL(const TVersion& aVersion, const RMessage2& /*aMessage*/) const + { + TVersion version(KSsmSwpPolicySrvVersionMajor, KSsmSwpPolicySrvVersionMinor, KSsmSwpPolicySrvVersionBuild); + + if(!User::QueryVersionSupported(version, aVersion)) + { + DEBUGPRINT1(_L("CSsmSwpPolicyServer: Server version not supported")); + User::Leave(KErrNotSupported); + } + + CSsmSwpPolicyServer& mutatedSelf = const_cast< CSsmSwpPolicyServer& >(*this); + return CSsmSwpPolicySession::NewL(mutatedSelf); + } + +/** +Used to create a new CSsmSwpPolicyServer +@return A pointer to the CSsmSwpPolicyServer +*/ +CSsmSwpPolicyServer* CSsmSwpPolicyServer::NewLC(const TDesC& aServerName) + { + CSsmSwpPolicyServer* self = new(ELeave) CSsmSwpPolicyServer; + CleanupStack::PushL(self); + self->ConstructL(aServerName); + return self; + } + +/** +Static function used to create and start CSsmSwpPolicyServer +@return KErrAlreadyExists if the server is already running +*/ +EXPORT_C TInt CSsmSwpPolicyServer::StartSsmSwpPolicySrv(const TDesC& aServerName) + { + TAny* threadParam = reinterpret_cast(const_cast(&aServerName)); + + // Create a Unique name for the thread name + TName name(aServerName); + _LIT(KUnderScore, "_"); + name.Append(KUnderScore); + name.AppendNum(Math::Random(), EHex); + + const TInt KSsmPolicySrvMinHeapSize = 0x2000; // 8kB + const TInt KSsmPolicySrvMaxHeapSize = 10 * KSsmPolicySrvMinHeapSize; + RThread srvThread; + TInt err = srvThread.Create(name, &CSsmSwpPolicyServer::SsmSwpPolicySrvThreadFn, + KDefaultStackSize, KSsmPolicySrvMinHeapSize, KSsmPolicySrvMaxHeapSize, + threadParam, EOwnerProcess); + + DEBUGPRINT2(_L("CSsmSwpPolicyServer: SsmSwpPolicyServer created with %d") ,err); + if(KErrNone == err) + { + TRequestStatus trs; + + srvThread.Rendezvous(trs); + srvThread.Resume(); + + User::WaitForRequest(trs); + err = trs.Int(); + srvThread.Close(); + } + + return err; + } + +/** +Creates the ssmSwpPolicyServer +*/ +TInt CSsmSwpPolicyServer::SsmSwpPolicySrvThreadFn(TAny* aAny) + { + const TDesC* serverName = const_cast(static_cast(aAny)); + TInt err = KErrNoMemory; + CTrapCleanup* cleanup = CTrapCleanup::New(); + if(cleanup) + { + TRAP(err, + { + CActiveScheduler* sched = new(ELeave) CActiveScheduler(); + CleanupStack::PushL(sched); + CActiveScheduler::Install(sched); + + CSsmSwpPolicyServer* ssmSwpPolicySrv = CSsmSwpPolicyServer::NewLC(*serverName); + RThread::Rendezvous(KErrNone); + // Must not use serverName after rendezvousing with client + serverName = NULL; + + CActiveScheduler::Start(); + + CleanupStack::PopAndDestroy(ssmSwpPolicySrv); + CleanupStack::PopAndDestroy(sched); + }); + + delete cleanup; + } + + return err; + } + +CSsmSwpPolicyServer::CSsmSwpPolicyServer() + : CPolicyServer(EPriorityHigh, KSsmSwpPolicyServerPolicy, EUnsharableSessions) + { + } + +/** +Starts the ssmSwpPolicyServer +*/ +void CSsmSwpPolicyServer::ConstructL(const TDesC& aServerName) + { + StartL(aServerName); + // The starting thread is signalled in the thread function. + } + +CSsmSwpPolicyServer::~CSsmSwpPolicyServer() + { + iSessionInfoArray.Close(); + } +