Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "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:
// e32\euser\cbase\ub_polsvr.cpp
//
//
#include "ub_std.h"
_LIT(KPolicyServer, "CPolicyServer");
#include <e32debug.h>
#define __PSD(x) __PLATSEC_DIAGNOSTIC_STRING(x)
EXPORT_C CPolicyServer::CPolicyServer(TInt aPriority, const TPolicy& aPolicy, TServerType aType)
: CServer2(aPriority, aType), iPolicy(aPolicy)
{
#ifdef _DEBUG
TUint i;
TInt prev = iPolicy.iRanges[0];
//iPolicy.iRangeCount must be greater than 0. (ie you must have at least
//one policy
__ASSERT_DEBUG(iPolicy.iRangeCount > 0, Panic(EPolSvrIRangeCountInvalid));
//iRanges must start from request number 0.
__ASSERT_DEBUG(prev == 0, Panic(EPolSvr1stRangeNotZero));
__ASSERT_DEBUG((iPolicy.iElementsIndex[0] < ESpecialCaseHardLimit
|| iPolicy.iElementsIndex[0] > ESpecialCaseLimit),
Panic(EPolSvrElementsIndexValueInvalid) );
for(i=1; i<iPolicy.iRangeCount; i++)
{
TInt next = iPolicy.iRanges[i];
//iRanges must be in increasing order.
__ASSERT_DEBUG(next > prev, Panic(EPolSvrRangesNotIncreasing));
//iElementsIndex must not contain invalid values.
__ASSERT_DEBUG((iPolicy.iElementsIndex[i] < ESpecialCaseHardLimit
|| iPolicy.iElementsIndex[i] > ESpecialCaseLimit),
Panic(EPolSvrElementsIndexValueInvalid) );
prev = next;
}
//iOnConnect must not be an invalid value.
__ASSERT_DEBUG((iPolicy.iOnConnect < ESpecialCaseHardLimit
|| iPolicy.iOnConnect > ESpecialCaseLimit),
Panic(EPolSvrIOnConnectValueInvalid) );
#endif
}
EXPORT_C void CPolicyServer::RunL()
{
const RMessage2& msg = Message();
msg.ClearAuthorised();
TInt fn = msg.Function();
__ASSERT_COMPILE(-1 == RMessage2::EConnect);
if(fn >= RMessage2::EConnect)
//So this implies any "normal" message or Connect
//Now we have two steps to follow each having two mutually exculsive
//parts.
//Step 1: Find policy.
//Step 2: Apply policy.
{
const TPolicyElement* element = 0;
TUint specialCase = 0;
//1a: If its a normal message. Find the associate policy or special
//case action.
if(fn >= 0)
{
element = FindPolicyElement(fn, specialCase);
}
//1b: If its a connect message, there's a shortcut to the policy.
else
{
TUint8 i = iPolicy.iOnConnect;
if(i >= ESpecialCaseHardLimit)
specialCase = i;
else
element = &(iPolicy.iElements[i]);
}
//2a: We found a policy that we can automatically apply... Apply it!
if(element)
{
TSecurityInfo missing;
//If policy check succeeds, allow it through
if(element->iPolicy.CheckPolicy(msg, missing, __PSD("Checked by CPolicyServer::RunL")))
{
ProcessL(msg);
}
//Else see what failure action is required (return error code,
//panic client, ask user, etc...)
else
{
CheckFailedL(msg, element->iAction, missing);
}
}
//2b: The policy is a special case
else
{
switch(specialCase)
{
//If you change this you'll have to add to the switch statement
__ASSERT_COMPILE(ESpecialCaseLimit == 252u);
case ECustomCheck:
{
TInt action = EFailClient;
//The default action after failing a CustomSecurityCheck is
//to complete the message with KErrPermissionDenied. If
//you want a different action, then change the action
//parameter prior to returning from your derived
//implementation of CustomSecurityCheckL
TSecurityInfo missing;
__ASSERT_COMPILE(SCapabilitySet::ENCapW == 2);
memset(&missing, 0, sizeof(SSecurityInfo));
TCustomResult result = CustomSecurityCheckL(msg, action, missing);
if(result == EPass)
{
ProcessL(msg);
}
else if(result == EFail)
{
CheckFailedL(msg, action, missing);
}
else if(result == EAsync)
{
//Do Nothing. Derived CustomSecurityCheck is
//responsible for calling ProcessL/CheckFailedL
}
else
Panic(EPolSvrInvalidCustomResult);
}
break;
case ENotSupported:
msg.Complete(KErrNotSupported);
break;
case EAlwaysPass:
ProcessL(msg);
break;
default:
Panic(EPolSvrPolicyInvalid);
break;
}
}
}
//else it must be either Disconnect or bad message. Both are handled by
//ProcessL
else
{
ProcessL(msg);
}
// Queue reception of next message if it hasn't already been done
if(!IsActive())
ReStart();
}
EXPORT_C TInt CPolicyServer::RunError(TInt aError)
{
ProcessError(Message(), aError);
if (!IsActive())
ReStart();
return KErrNone;
}
EXPORT_C void CPolicyServer::ProcessL(const RMessage2& aMsg)
{
aMsg.SetAuthorised();
TInt fn = aMsg.Function();
if(fn >= 0)
{
CSession2* session=aMsg.Session();
if(session)
{
session->ServiceL(aMsg);
}
else
{
NotConnected(aMsg);
}
}
else if(fn==RMessage2::EConnect)
{
Connect(aMsg);
}
else if(fn==RMessage2::EDisConnect)
{
Disconnect(aMsg);
}
else
{
BadMessage(aMsg);
}
}
EXPORT_C void CPolicyServer::ProcessError(const RMessage2& aMsg, TInt aError)
{
__ASSERT_COMPILE(-1 == RMessage2::EConnect);
__ASSERT_ALWAYS(aMsg.Function() >= RMessage2::EConnect, User::Panic(KPolicyServer, 2));
if(aMsg.Authorised() && aMsg.Function() >= 0)
{
aMsg.Session()->ServiceError(aMsg, aError);
}
else //Either ServiceL hadn't been called yet (not (yet) authorised) or
//it's a Connect message
{
aMsg.Complete(aError);
}
}
EXPORT_C CPolicyServer::TCustomResult CPolicyServer::CustomSecurityCheckL(const RMessage2& /*aMsg*/, TInt& /*aAction*/, TSecurityInfo& /*aMissing*/)
{
Panic(EPolSvrCallingBaseImplementation);
return EFail;
}
EXPORT_C void CPolicyServer::CheckFailedL(const RMessage2& aMsg, TInt aAction, const TSecurityInfo& aMissing)
{
if(aAction < 0)
{
TCustomResult result = CustomFailureActionL(aMsg, aAction, aMissing);
if(result == EPass)
ProcessL(aMsg);
else if(result == EFail)
aMsg.Complete(KErrPermissionDenied);
else if(result == EAsync)
{}
//Do Nothing. Derived CustomFailureActionL is responsible for
//calling ProcessL/completing message with KErrPermissionDenied
else
Panic(EPolSvrInvalidCustomResult);
}
else if(aAction == EFailClient)
{
aMsg.Complete(KErrPermissionDenied);
}
else //if (aAction == EPanic) and all other +ve values
{
_LIT(KE32UserCBase, "E32USER-CBase");
aMsg.Panic(KE32UserCBase, EPolSvrActionPanicClient);
}
}
EXPORT_C CPolicyServer::TCustomResult CPolicyServer::CustomFailureActionL(const RMessage2& /*aMsg*/, TInt /*aAction*/, const TSecurityInfo& /*aMissing*/)
{
Panic(EPolSvrCallingBaseImplementation);
return EFail;
}
const CPolicyServer::TPolicyElement* CPolicyServer::FindPolicyElement(TInt aFn, TUint& aSpecialCase) const
{
//Connect (aFn == -1) is handled through iPolicy.iOnConnect. So aFn should
//always be greater than -1.
__ASSERT_DEBUG(aFn >= 0, User::Panic(KPolicyServer, 1));
TUint l = 0;
TUint u = iPolicy.iRangeCount;
TUint m = 0;
while(u > l)
{
m = (l+u) >> 1;
if(iPolicy.iRanges[m] > aFn)
u = m;
else
l = m + 1;
}
--l;
//the mth element of iElementsIndex tells us the index in iElements
//we want
TUint8 i = iPolicy.iElementsIndex[l];
//if the mth element of iElementsIndex is >= 250 -> Special Case
if(i >= ESpecialCaseHardLimit)
{
aSpecialCase = i;
return 0;
}
return &(iPolicy.iElements[i]);
}
/**
Extension function
*/
EXPORT_C TInt CPolicyServer::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1)
{
return CServer2::Extension_(aExtensionId, a0, a1);
}