sl@0: /* sl@0: * Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * RUpsSession implementation. See class and function definitions sl@0: * for more detail. sl@0: * sl@0: */ sl@0: sl@0: sl@0: /** sl@0: @file sl@0: */ sl@0: sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include "upscommon.h" sl@0: #include "upsclientconfig.h" sl@0: sl@0: namespace UserPromptService sl@0: { sl@0: sl@0: NONSHARABLE_CLASS(CPolicyChangeWatcher) : public CActive sl@0: { sl@0: public: sl@0: static CPolicyChangeWatcher *NewL(RUpsSession &aUpsSession); sl@0: ~CPolicyChangeWatcher(); sl@0: private: sl@0: CPolicyChangeWatcher(RUpsSession &aUpsSession); sl@0: void ConstructL(); sl@0: virtual void DoCancel(); sl@0: virtual void RunL(); sl@0: virtual TInt RunError(TInt aError); sl@0: sl@0: private: sl@0: RProperty iUpsPolicyChangeProperty; sl@0: RUpsSession &iUpsSession; sl@0: }; sl@0: sl@0: EXPORT_C RUpsSession::RUpsSession() sl@0: /** sl@0: This constructor provides a single point of definition from sl@0: which the superclass constructor is called. sl@0: */ sl@0: : RScsClientBase(), sl@0: iPolicyChangeWatcher(0), sl@0: iClientConfig(0) sl@0: { sl@0: // empty. sl@0: } sl@0: sl@0: EXPORT_C TInt RUpsSession::Connect() sl@0: /** sl@0: Connect to the UPS server. sl@0: sl@0: The thread which calls this function must be the same one which later calls Close(). sl@0: sl@0: Once connected, this session can be shared by multiple RUpsSubsession objects. sl@0: sl@0: The RUpsSubsession objects are allowed to be in different threads, in which case ShareAuto() must be called before they are created. sl@0: sl@0: @return Symbian OS error code where KErrNone indicates sl@0: success and any other value indicates failure. sl@0: */ sl@0: { sl@0: TVersion v = UserPromptService::Version(); sl@0: TUidType serverFullUid = UserPromptService::ServerImageFullUid(); sl@0: sl@0: TInt r = RScsClientBase::Connect( sl@0: UserPromptService::KUpsServerName, v, UserPromptService::KServerImageName, serverFullUid); sl@0: sl@0: if (r == KErrNone) sl@0: { sl@0: // preload the configuration sl@0: TRAP(r, RetrieveClientConfigL()); sl@0: } sl@0: sl@0: if((r == KErrNone) && (CActiveScheduler::Current() != 0)) sl@0: { sl@0: delete iPolicyChangeWatcher; sl@0: iPolicyChangeWatcher = 0; sl@0: TRAP(r, iPolicyChangeWatcher = CPolicyChangeWatcher::NewL(*this)); sl@0: } sl@0: sl@0: if(r != KErrNone) sl@0: { sl@0: Close(); sl@0: } sl@0: sl@0: return r; sl@0: } sl@0: sl@0: sl@0: static void deleteArrayOfTServiceConfig(TAny *aPtr) sl@0: { sl@0: TServiceConfig *array = reinterpret_cast(aPtr); sl@0: delete [] array; sl@0: } sl@0: sl@0: void RUpsSession::RetrieveClientConfigL() sl@0: { sl@0: // Query how many TServiceConfig entries there are. sl@0: TPckgBuf countBuf; sl@0: User::LeaveIfError(CallSessionFunction(EGetClientConfigLength, TIpcArgs(&countBuf))); sl@0: // Retrieve count from buffer sl@0: TInt count = countBuf(); sl@0: sl@0: // Create buffer to hold entries sl@0: TServiceConfig *rawServiceConfig = new(ELeave) TServiceConfig[count]; sl@0: CleanupStack::PushL(TCleanupItem(deleteArrayOfTServiceConfig, rawServiceConfig)); sl@0: sl@0: // Wrap array in a TPtr8 and use it to read array from server sl@0: TInt size = count * sizeof(TServiceConfig); sl@0: TPtr8 ptr((TUint8*)rawServiceConfig, size, size); sl@0: User::LeaveIfError(CallSessionFunction(EGetClientConfigData, TIpcArgs(&ptr))); sl@0: sl@0: CUpsClientConfig *tmp = CUpsClientConfig::NewL(count, rawServiceConfig); sl@0: delete iClientConfig; sl@0: iClientConfig = tmp; sl@0: sl@0: CleanupStack::PopAndDestroy(); // get rid of rawServiceConfig array sl@0: } sl@0: sl@0: sl@0: EXPORT_C void RUpsSession::Close() sl@0: /** sl@0: Frees the configuration object and calls RScsClientBase::Close sl@0: sl@0: This function MUST be called by the same thread which Connect(). sl@0: */ sl@0: { sl@0: delete iClientConfig; sl@0: iClientConfig = 0; sl@0: sl@0: if(iPolicyChangeWatcher) sl@0: { sl@0: iPolicyChangeWatcher->Cancel(); sl@0: } sl@0: delete iPolicyChangeWatcher; sl@0: iPolicyChangeWatcher = 0; sl@0: sl@0: RScsClientBase::Close(); sl@0: } sl@0: sl@0: void RUpsSession::NotifyPolicyFileChangedL() sl@0: /** sl@0: @internalComponent sl@0: @released sl@0: sl@0: Policy files have changed so update serviceconfig cache. sl@0: */ sl@0: { sl@0: RetrieveClientConfigL(); sl@0: } sl@0: sl@0: CUpsClientConfig::CUpsClientConfig() sl@0: : iServiceConfig(1 /* granularity */, 0 /* key offset */) sl@0: { sl@0: } sl@0: sl@0: CUpsClientConfig::~CUpsClientConfig() sl@0: { sl@0: iServiceConfig.Close(); sl@0: } sl@0: sl@0: CUpsClientConfig* CUpsClientConfig::NewL(TInt aCount, TServiceConfig *aRawServiceConfig) sl@0: /** sl@0: @param serviceConfig sl@0: sl@0: Takes ownership of the serviceConfig array via swap. Callers array will be cleared. sl@0: */ sl@0: { sl@0: CUpsClientConfig *self = new(ELeave) CUpsClientConfig(); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aCount, aRawServiceConfig); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: sl@0: void CUpsClientConfig::ConstructL(TInt aCount, TServiceConfig *aRawServiceConfig) sl@0: { sl@0: iServiceConfig.ReserveL(aCount); sl@0: for(TInt i=0; i < aCount; ++i) sl@0: { sl@0: iServiceConfig.InsertInUnsignedKeyOrderL(aRawServiceConfig[i]); sl@0: } sl@0: } sl@0: sl@0: CUpsClientConfig::TQueryUpsResult sl@0: CUpsClientConfig::QueryUps(TBool aServerChecksPassed, sl@0: const TServiceId &aServiceId, sl@0: const TSecureId &aClientSid, sl@0: const TProcessId &aClientProcessId) const sl@0: { sl@0: TServiceConfig sc = {0}; sl@0: sc.iServiceId = aServiceId.iUid; /* Only service id is used in lookup */ sl@0: TInt i = iServiceConfig.FindInUnsignedKeyOrder(sc); sl@0: if(i == KErrNotFound) sl@0: { sl@0: // Must be no policy file for this service so no point in querying UPS sl@0: return aServerChecksPassed ? EAllow: EReject; sl@0: } sl@0: sl@0: sl@0: // Read entry sl@0: sc = iServiceConfig[i]; sl@0: sl@0: switch(sc.iPolicy) sl@0: { sl@0: case EAlwaysCheck: sl@0: return EQueryUps; sl@0: sl@0: case ECheckPostManufacture: sl@0: { sl@0: TBool isProtected = (TUint(aClientSid) & 0x80000000) == 0; sl@0: if(! isProtected) sl@0: { sl@0: return EQueryUps; sl@0: } sl@0: sl@0: // Need to obtain the drive letter for the exe sl@0: // sl@0: // This requires opening the RProcess and two copies of a full filename (one 8 bit the other unicode)...... sl@0: // We could optimse this by doing it when Initialise() is called, but that then slows down all Initialise calls even ones sl@0: // not doing the ECheckPostManufacture check. sl@0: RProcess clientProcess; sl@0: if(clientProcess.Open(aClientProcessId) != KErrNone) sl@0: { sl@0: return EReject; // Presumably it exited... sl@0: } sl@0: sl@0: TFileName clientExeName = clientProcess.FileName(); sl@0: clientProcess.Close(); sl@0: TChar driveChar= clientExeName[0]; sl@0: sl@0: if(aServerChecksPassed && sl@0: (driveChar == 'z' || driveChar == 'Z')) sl@0: { sl@0: return EAllow; sl@0: } sl@0: sl@0: return EQueryUps; sl@0: } sl@0: sl@0: case ECheckUnprotectedSids: sl@0: { sl@0: TBool isProtected = (TUint(aClientSid) & 0x80000000) == 0; sl@0: sl@0: if(aServerChecksPassed && isProtected) sl@0: { sl@0: return EAllow; sl@0: } sl@0: sl@0: return EQueryUps; sl@0: } sl@0: sl@0: case ECheckIfFailed: sl@0: return aServerChecksPassed ? EAllow : EQueryUps; sl@0: sl@0: BULLSEYE_OFF sl@0: default: sl@0: BULLSEYE_RESTORE sl@0: case ENeverCheck: sl@0: return aServerChecksPassed ? EAllow: EReject; sl@0: } sl@0: // Never gets here sl@0: } sl@0: sl@0: // sl@0: // CPolicyChangeWatcher member functions sl@0: // sl@0: CPolicyChangeWatcher *CPolicyChangeWatcher::NewL(RUpsSession &aUpsSession) sl@0: { sl@0: CPolicyChangeWatcher *self = new(ELeave) CPolicyChangeWatcher(aUpsSession); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: CPolicyChangeWatcher::CPolicyChangeWatcher(RUpsSession &aUpsSession) sl@0: : CActive(CActive::EPriorityStandard+1), sl@0: iUpsSession(aUpsSession) sl@0: { sl@0: CActiveScheduler::Add(this); sl@0: } sl@0: sl@0: void CPolicyChangeWatcher::ConstructL() sl@0: { sl@0: User::LeaveIfError(iUpsPolicyChangeProperty.Attach(KUpsServerUid, KUpsServiceConfigProperty, EOwnerThread)); sl@0: iUpsPolicyChangeProperty.Subscribe(iStatus); sl@0: SetActive(); sl@0: } sl@0: sl@0: CPolicyChangeWatcher::~CPolicyChangeWatcher() sl@0: { sl@0: Cancel(); sl@0: iUpsPolicyChangeProperty.Close(); sl@0: } sl@0: sl@0: void CPolicyChangeWatcher::DoCancel() sl@0: { sl@0: iUpsPolicyChangeProperty.Cancel(); sl@0: } sl@0: sl@0: void CPolicyChangeWatcher::RunL() sl@0: { sl@0: // Re-subscribe for policy file change notifications sl@0: iUpsPolicyChangeProperty.Subscribe(iStatus); sl@0: SetActive(); sl@0: sl@0: // Tell session to update its cache. sl@0: iUpsSession.NotifyPolicyFileChangedL(); sl@0: } sl@0: sl@0: TInt CPolicyChangeWatcher::RunError(TInt /* aError */) sl@0: { sl@0: // Ignore all errors sl@0: //RDebug::Printf("CPolicyChangeWatcher::RunError(%d)\n", aError); sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: } // End of namespace UserPromptService sl@0: sl@0: // End of file sl@0: