omadrm/drmengine/server/src/DRMDbSession.cpp
changeset 0 95b198f216e5
child 18 8a03a285ab14
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/omadrm/drmengine/server/src/DRMDbSession.cpp	Thu Dec 17 08:52:27 2009 +0200
@@ -0,0 +1,4928 @@
+/*
+* Copyright (c) 2003-2008 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:  This class handles all client requests.
+*
+*/
+
+
+// INCLUDE FILES
+#include <s32file.h>
+#include <f32file.h>
+#include <symmetric.h>
+#include <rijndael.h>
+#include <caf/caf.h>
+#include <x509keys.h>
+#include <asn1dec.h>
+#include <dcfrep.h>
+
+#include <e32math.h>
+#include <utf.h>
+
+#include <SysUtil.h>    // Disk space checking
+
+#ifdef RD_MULTIPLE_DRIVE
+#include <DriveInfo.h>
+#endif
+
+#include "Oma2Agent.h"
+#include "DRMPermission.h"
+#include "DRMDbSession.h"
+#include "drmengineclientserver.h"
+#include "DRMRightsServer.h"
+#include "RoapStorageClient.h"
+#include "OmaCrypto.h"
+#include "CmlaCrypto.h"
+#include "DrmKeyStorage.h"
+#include "drmrightsdb.h"
+#include "drmparentstorage.h"
+#include "DrmDomainContext.h"
+#include "DrmRiContext.h"
+#include "drmenginetypedefs.h"
+#include "DRMXOma.h"
+
+#include "DRMNotifier.h"
+#include "DRMEventAddRemove.h"
+#include "DRMEventModify.h"
+#include "DRMRightsCleaner.h"
+#include "DRMActiveOperation.h"
+#include "drmconsume.h"
+#include "drmlog.h"
+#include "drmpointerarray.h"
+#include "base64.h"
+
+#ifdef RD_DRM_METERING
+#include "drmmeteringdbdata.h"
+#endif
+
+// NAMESPACES
+using namespace DRMEngine;
+
+// EXTERNAL DATA STRUCTURES
+// EXTERNAL FUNCTION PROTOTYPES
+// CONSTANTS
+
+// MACROS
+#define REPLAYCACHE reinterpret_cast< CDRMRightsServer* >\
+    (const_cast<CServer2*>(Server()))->ReplayCache()
+#define DRMDB ( ( CDRMRightsServer* )( Server() ) )->Database()
+#ifdef RD_DRM_METERING
+#define METERINGDB reinterpret_cast< CDRMRightsServer* >\
+    (const_cast<CServer2*>(Server()))->MeteringDatabase()
+#endif
+#define RFSSESSION ( ( CDRMRightsServer* )( Server() ) )->FileServerSession()
+#define DRMNOTIFIER ( ( CDRMRightsServer* )( Server() ) )->Notifier()
+#define XOMAHEADER ( ( CDRMRightsServer* )( Server() ) )->XOmaHeaders()
+#define IMEI ( ( CDRMRightsServer* )( Server() ) )->GetIMEIL()
+#define IMSI ( ( CDRMRightsServer* )( Server() ) )->GetIMSIL()
+#define SERVER reinterpret_cast< CDRMRightsServer* >\
+    (const_cast<CServer2*>(Server()))
+
+#define IPCREAD0L( a ) aMessage.ReadL( 0, a )
+#define IPCREAD1L( a ) aMessage.ReadL( 1, a )
+#define IPCREAD2L( a ) aMessage.ReadL( 2, a )
+#define IPCREAD3L( a ) aMessage.ReadL( 3, a )
+#define IPCWRITE0L( a ) aMessage.WriteL( 0, a )
+#define IPCWRITE1L( a ) aMessage.WriteL( 1, a )
+#define IPCWRITE2L( a ) aMessage.WriteL( 2, a )
+#define IPCWRITE3L( a ) aMessage.WriteL( 3, a )
+#define IPCGETDESLEN0 aMessage.GetDesLength( 0 )
+#define IPCGETDESLEN1 aMessage.GetDesLength( 1 )
+#define IPCGETDESLEN2 aMessage.GetDesLength( 2 )
+#define IPCGETDESLEN3 aMessage.GetDesLength( 3 )
+#define IPCGETDESMAXLEN0 aMessage.GetDesMaxLength( 0 )
+#define IPCGETDESMAXLEN1 aMessage.GetDesMaxLength( 1 )
+#define IPCGETDESMAXLEN2 aMessage.GetDesMaxLength( 2 )
+#define IPCGETDESMAXLEN3 aMessage.GetDesMaxLength( 3 )
+
+// LOCAL CONSTANTS AND MACROS
+
+#ifdef RD_MULTIPLE_DRIVE
+
+_LIT( KDbTempPath, "%c:\\system\\temp\\" );
+_LIT( KTimedReplayCacheFile, "%c:\\private\\101F51F2\\timererc.dat" );
+_LIT( KPlainReplayCacheFile, "%c:\\private\\101F51F2\\plainrc.dat" );
+#ifdef RD_DRM_METERING
+_LIT( KMeteringDataBaseFile, "%c:\\private\\101F51F2\\meterdb.dat" );
+#endif
+
+#else
+
+_LIT( KTimedReplayCacheFile, "c:\\private\\101F51F2\\timererc.dat" );
+_LIT( KPlainReplayCacheFile, "c:\\private\\101F51F2\\plainrc.dat" );
+#ifdef RD_DRM_METERING
+_LIT( KMeteringDataBaseFile, "c:\\private\\101F51F2\\meterdb.dat" );
+#endif
+
+#endif
+
+
+const TInt KMicrosecondsToSecond = 1000000;
+_LIT8( KFLPrefix, "flk" );
+_LIT8( KFLLongPrefix, "flk:flk" );
+
+_LIT8( KFLSuffix, "@localhost" );
+
+// These need to be updated if the DRM Filter / Oma1DcfCreator URI's change
+// IMPORTANT IMPORTANT IMPORTANT
+_LIT8( KDCMUri, "ldf:31415926535@localhost");
+_LIT8( KLDFUri, "flk:flkS60_3_0_Hutchinson_2005");
+
+_LIT8(KTimeStamp, "timeStamp");
+#ifdef RD_DRM_METERING
+_LIT8(KMeteringDelimiter, ":");
+_LIT8(KCRLF, "\r\n" );
+#endif
+
+LOCAL_C const TUint8 KFLPrefixLength = 3;
+const TUint32 KTrustedShutdownClient = 0x10205CB5;
+const TUint32 KAppInstSrv = 0x101F875A;
+
+
+const TInt KSanityDataLengthLow = 0;
+const TInt KSanityDataLengthHigh = 32768;
+
+// MODULE DATA STRUCTURES
+NONSHARABLE_STRUCT( TDeleteFile )
+    {
+    RFs* iFs;
+    TFileName* iFileName;
+    };
+
+// ============================ auto_handde helper class =======================
+//Auto handle for easening handle release on exceptional exit situations
+template<class T> class auto_handle
+    {
+public:
+
+    auto_handle() {}
+    auto_handle(T aHandle) : iHandle( aHandle ) {}
+    auto_handle( auto_handle<T>& aHandle) : iHandle( aHandle.release() ) {}
+    ~auto_handle() { iHandle.Close(); }
+    const T& operator()() const { return iHandle; }
+    T& operator()() { return iHandle; }
+    T get() const { return iHandle; }
+    T release() { T temp = iHandle; iHandle = 0; return temp; }
+
+private:
+    T iHandle;
+    };
+
+// DATA TYPES
+// LOCAL FUNCTION PROTOTYPES
+LOCAL_C void DeleteFile( TAny* aHandle );
+LOCAL_C void DeleteObject( TAny* aObject );
+LOCAL_C TTime EndTime( const TTime& aTime1, const TTime& aTime2 );
+
+// FORWARD DECLARATIONS
+LOCAL_C void ModifyRightsObjectByTimeL( CDRMPermission* aRights,
+                                        TTimeIntervalMicroSeconds& aChange,
+                                        TBool aModifyInsertionTime );
+LOCAL_C void ModifyTimesInListL( CDRMPermissionList* aList,
+                                 TTimeIntervalMicroSeconds& aChange,
+                                 TBool aModifyInsertionTime );
+
+LOCAL_C void ModifyConstraintByTime( CDRMConstraint* aConstraint,
+                                     TTimeIntervalMicroSeconds& aChange );
+
+LOCAL_C TPtrC8 ExtractElement( const TDesC8& aRights, const TDesC8& aElement,
+                               TInt& aOffset );
+
+LOCAL_C TTime Iso8601ToTime( TDesC8& aTimeString );
+
+// ============================= LOCAL FUNCTIONS ==============================
+
+// -----------------------------------------------------------------------------
+// SanitizeL
+// Performs a sanity check on length parameters
+// -----------------------------------------------------------------------------
+//
+LOCAL_C void SanitizeL( TInt aParam )
+    {
+    if( aParam <= KSanityDataLengthLow || aParam > KSanityDataLengthHigh )
+        {
+        User::Leave(KErrArgument);
+        }
+    }
+
+
+LOCAL_C void ModifyTimesInListL( CDRMPermissionList* aList,
+    TTimeIntervalMicroSeconds& aChange,
+    TBool aModifyInsertionTime )
+    {
+    TInt i = 0;
+
+    // Go through the whole list and run the modification for all objects
+    for( i = 0; i < aList->Count(); i++ )
+        {
+        // Call modification for each rights object in the list
+        ModifyRightsObjectByTimeL( (*aList)[i], aChange, aModifyInsertionTime );
+        }
+    };
+
+LOCAL_C void ModifyRightsObjectByTimeL( CDRMPermission* aRights,
+    TTimeIntervalMicroSeconds& aChange,
+    TBool aModifyInsertionTime )
+    {
+
+    // If original insertion time exists and we want to change it, change it
+    if ( aModifyInsertionTime && aRights->iOriginalInsertTime != Time::NullTTime() )
+        {
+        aRights->iOriginalInsertTime += aChange;
+        }
+
+    if ( aRights->iAvailableRights & ERightsTopLevel )
+        {
+        ModifyConstraintByTime( aRights->iTopLevel, aChange );
+        }
+
+    // If play rights are available, check if they need to be changed
+    if ( aRights->iAvailableRights & ERightsPlay )
+        {
+        ModifyConstraintByTime( aRights->iPlay, aChange );
+        }
+
+    // If display rights are available, check if they need to be changed
+    if ( aRights->iAvailableRights & ERightsDisplay )
+        {
+        ModifyConstraintByTime( aRights->iDisplay, aChange );
+        }
+
+    // If execute rights are available, check if they need to be changed
+    if ( aRights->iAvailableRights & ERightsExecute )
+        {
+        ModifyConstraintByTime( aRights->iExecute, aChange );
+        }
+
+    // If print rights are available, check if they need to be changed
+    if ( aRights->iAvailableRights & ERightsPrint )
+        {
+        ModifyConstraintByTime( aRights->iPrint, aChange );
+        }
+
+    };
+
+LOCAL_C void ModifyConstraintByTime(
+    CDRMConstraint* aConstraint,
+    TTimeIntervalMicroSeconds& aChange )
+    {
+    // if start time exists, modify it
+    if ( aConstraint->iActiveConstraints & EConstraintStartTime )
+        {
+        aConstraint->iStartTime += aChange;
+        }
+
+    // if end time exists, modify it
+    if ( aConstraint->iActiveConstraints & EConstraintEndTime )
+        {
+        aConstraint->iEndTime += aChange;
+        }
+
+    // if activated interval exists, modify it
+    if ( aConstraint->iActiveConstraints & EConstraintInterval &&
+         aConstraint->iIntervalStart != Time::NullTTime() )
+        {
+        aConstraint->iIntervalStart += aChange;
+        }
+    };
+
+LOCAL_C TPtrC8 ExtractElement( const TDesC8& aRights,
+                               const TDesC8& aElement,
+                               TInt& aOffset )
+    {
+    DRMLOG( _L("CDRMDbSession::ExtractElement") );
+
+    TPtrC8 temp( KNullDesC8 );
+    TInt startPos = ( 0 );
+    TInt endPos = ( 0 );
+    TInt ret( 0 );
+    TInt startLength ( 0 );
+
+    auto_handle< RBuf8 > tagToBeFound;
+    // Must be nonleaving since this function is nonleaving
+    ret = tagToBeFound().Create( aElement.Length() + 3 ); // max "</" aElement ">"
+    if ( ret != KErrNone )
+        {
+        aOffset = -1;
+        return KNullDesC8();
+        }
+
+    // First we try to find the start tag (as localname)
+    tagToBeFound().SetLength( 0 );
+    tagToBeFound().AppendFormat( _L8( "<%S" ), &aElement );
+
+    temp.Set( aRights.Mid( aOffset ) );
+
+    startPos = temp.Find( tagToBeFound() );
+
+    startLength = tagToBeFound().Length();
+    startPos += aOffset;
+    temp.Set( aRights.Mid( startPos + startLength ) );
+
+    // Now find the end of the start tag
+    tagToBeFound().SetLength( 0 );
+    tagToBeFound().Append( _L8( ">" ) ); // '>' as last
+
+    // Define the starting point of the data after the start tag
+    // and skip the '>' mark.
+    startPos = startPos + startLength + temp.Find( tagToBeFound() ) + 1;
+
+    temp.Set( aRights.Mid( startPos ) );
+
+    // Finally find the start of the end tag
+    tagToBeFound().SetLength( 0 );
+    tagToBeFound().AppendFormat( _L8( "</%S" ), &aElement );
+
+    endPos = startPos + temp.Find(tagToBeFound() );
+
+    if ( endPos < startPos )
+        {
+        aOffset = -1;
+        return KNullDesC8();
+        }
+
+    temp.Set( aRights.Mid(startPos, endPos - startPos) );
+
+    aOffset = endPos;
+    DRMLOG2( _L( "Calculated length %d" ), endPos - startPos);
+    DRMLOG( _L( "Extracted element" ) );
+
+    //auto_handle closes and frees allocated resources
+    return temp;
+    };
+
+LOCAL_C TTime Iso8601ToTime( TDesC8& aTimeString )
+    {
+
+    DRMLOG( _L("CDRMDbSession::Iso8601ToTime") );
+
+    TLex8 lex;
+    TInt year = 0;
+    TInt month = 0;
+    TInt day = 0;
+    TInt hour = 0;
+    TInt minute = 0;
+    TInt second = 0;
+    TTime r = Time::NullTTime();
+    TLocale l;
+    TTimeIntervalSeconds offset(l.UniversalTimeOffset());
+
+    if (aTimeString.Length() > 0)
+        {
+        lex = aTimeString;
+        lex.Val(year);
+        lex.Inc();
+        lex.Val(month);
+        lex.Inc();
+        lex.Val(day);
+        lex.Inc();
+        lex.Val(hour);
+        lex.Inc();
+        lex.Val(minute);
+        lex.Inc();
+        lex.Val(second);
+        r = TTime(TDateTime(year, static_cast<TMonth>(month - 1), day - 1,
+                hour, minute, second, 0));
+        if (lex.Get() != 'Z')
+            {
+            r += offset;
+            }
+        }
+    return r;
+    }
+
+#ifdef RD_DRM_METERING
+LOCAL_C HBufC8* CreateMeteringDataL( CDRMPointerArray<CDrmMeteringDbData>* meteringArray )
+    {
+    // Calculate buffer size of cipher data
+    TInt size( sizeof( KCRLF ) );
+    HBufC8* cipherData = NULL;
+    TPtr8 ptr( NULL, 0 );
+
+    _LIT8( KElementStart, "<rawMeteringReportData>");
+    _LIT8( KElementEnd, "</rawMeteringReportData>");
+
+    size = KElementStart().Size() + KElementEnd().Size();
+
+    for( TUint i(0); i < meteringArray->Count(); i++ )
+        {
+        size += sizeof( ( *meteringArray)[i]->iContentId );
+        if ( (*meteringArray)[i]->iParentUid &&
+             (*meteringArray)[i]->iParentUid->Size() )
+            {
+            size += (*meteringArray)[i]->iParentUid->Size() + 1;
+            }
+        switch( (*meteringArray)[i]->iPermission )
+            {
+            case EPlay:
+                size += 4;
+                break;
+            case EView:
+            case EExecute:
+                size += 7;
+                break;
+            case EPrint:
+                size+= 5;
+                break;
+            default:
+                break; // Not a valid permission
+            }
+        size += (*meteringArray)[i]->iContentId->Size();
+        size += sizeof( (*meteringArray)[i]->iAccumulatedTime.Int() / 60 );
+        size += sizeof( (*meteringArray)[i]->iAccumulatedTime.Int() % 60 );
+        if( ( ( *meteringArray)[i]->iAccumulatedTime.Int() % 60 ) < 10 )
+            {
+            size++; //for precending zero for seconds..
+            }
+        size += sizeof( ( *meteringArray)[i]->iCount );
+        size += 4 * sizeof( KMeteringDelimiter ); // ":" -delimiter
+        size += sizeof( KCRLF );
+        }
+
+    cipherData = HBufC8::NewLC( size );
+    ptr.Set( cipherData->Des() );
+    ptr.Append( KElementStart );
+
+    for( TUint i(0); i < meteringArray->Count(); i++ )
+        {
+        ptr.Append( KCRLF );
+        if ( (*meteringArray)[i]->iParentUid &&
+             (*meteringArray)[i]->iParentUid->Size() )
+            {
+            ptr.Append( *(*meteringArray)[i]->iParentUid );
+            ptr.Append( _L(";") );
+            }
+        ptr.Append( *(*meteringArray)[i]->iContentId );
+        ptr.Append( KMeteringDelimiter );
+        switch( (*meteringArray)[i]->iPermission )
+            {
+            case EPlay:
+                ptr.Append( _L("play") );
+                break;
+            case EView:
+                ptr.Append( _L("display") );
+                break;
+            case EExecute:
+                ptr.Append( _L("execute") );
+                break;
+            case EPrint:
+                ptr.Append( _L("print") );
+                break;
+            default:
+                break; // Not a valid permission
+            }          // export not supported
+        ptr.Append( KMeteringDelimiter );
+        ptr.AppendNum( (*meteringArray)[i]->iCount );
+        ptr.Append( KMeteringDelimiter );
+        ptr.AppendNum( (*meteringArray)[i]->iAccumulatedTime.Int() / 60 );
+        ptr.Append( KMeteringDelimiter );
+        if( ( ( *meteringArray)[i]->iAccumulatedTime.Int() % 60 ) < 10 )
+            {
+            ptr.AppendNum( 0 ); //precending zero for seconds..
+            }
+        ptr.AppendNum( (*meteringArray)[i]->iAccumulatedTime.Int() % 60 );
+        }
+    ptr.Append( KCRLF );
+    ptr.Append( KElementEnd );
+    CleanupStack::Pop( cipherData );
+    return cipherData;
+    }
+#endif
+
+// ----------------------------------------------------------------------------
+// DeleteFile
+// Deletes the file by TFileName presented by aHandle
+// ----------------------------------------------------------------------------
+//
+void DeleteFile( TAny* aHandle )
+    {
+    __ASSERT_DEBUG( aHandle, User::Panic( _L( "DeleteFile" ), KErrArgument ) );
+    TDeleteFile* handle = reinterpret_cast< TDeleteFile* >( aHandle );
+
+    handle->iFs->Delete( *( handle->iFileName ) );
+    }
+
+// ----------------------------------------------------------------------------
+// DeleteObject
+// Deletes the file by TFileName presented by aHandle
+// ----------------------------------------------------------------------------
+//
+void DeleteObject( TAny* aObject )
+    {
+    __ASSERT_DEBUG( aObject, User::Panic( _L( "DeleteObject" ), KErrArgument ) );
+    MDrmKeyStorage* object = reinterpret_cast< MDrmKeyStorage* >( aObject );
+    delete object;
+    object = NULL;
+    }
+
+
+// ----------------------------------------------------------------------------
+// EndTime
+// Calculate the true end time: pick the smaller one of aTime1 & aTime2,
+// but ignore Time::NullTTime anyhow.
+// ----------------------------------------------------------------------------
+//
+TTime EndTime( const TTime& aTime1, const TTime& aTime2 )
+    {
+    TTime nullTime = Time::NullTTime();
+
+    if ( aTime1 == nullTime )
+        {
+        return aTime2;
+        }
+
+    if ( aTime2 == nullTime )
+        {
+        return aTime1;
+        }
+
+    return Min( aTime1, aTime2 );
+    }
+
+// ============================ MEMBER FUNCTIONS ==============================
+// ----------------------------------------------------------------------------
+// CDRMRightsServer::NewLC
+// Two-phased constructor.
+// ----------------------------------------------------------------------------
+//
+CDRMDbSession* CDRMDbSession::NewL()
+    {
+    CDRMDbSession* self = new( ELeave ) CDRMDbSession();
+
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMRightsServer::~CDRMDbSession
+// Destructor.
+// ----------------------------------------------------------------------------
+//
+CDRMDbSession::~CDRMDbSession()
+    {
+    DRMLOG( _L( "CDRMDbSession::~" ) );
+    delete iPreparedData;
+    iPreparedData = NULL;
+
+    delete iWidePreparedData;
+    iWidePreparedData = NULL;
+
+    delete iFileName;
+    iFileName = NULL;
+
+    if ( iPendingRequest )
+        {
+        delete iPendingRequest;
+        }
+
+    delete iContentId;
+    iContentId = NULL;
+
+    iClient.Close();
+
+    iCek = KNullDesC8;
+    iCek.FillZ();
+
+    delete iConsume;
+    iRoapClient.Close();
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMRightsServer::CDRMDbSession
+// Default constructor.
+// ----------------------------------------------------------------------------
+//
+CDRMDbSession::CDRMDbSession():
+    iCredentialsChecked(ENotChecked),
+    iContentId(NULL)
+    {
+    iRek.SetLength( 0 );
+    }
+
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::RoapClient
+// Returns a handle to the Roap client
+// ----------------------------------------------------------------------------
+Roap::RRoapStorageClient& CDRMDbSession::RoapClient()
+    {
+    return iRoapClient;
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMRightsServer::ServiceL
+// Forwards requests from clients to helper methods.
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::ServiceL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::ServiceL" ) );
+    DRMLOG2( _L( "Message Handle: %08x"), aMessage.Handle() );
+
+    // Close the client before opening a new connection over it to avoid
+    // leaking memory in the kernel side
+    iClient.Close();
+
+    aMessage.ClientL( iClient );
+
+    // This function call is TRAPped by framework, and message is completed
+    // with the error in case of leaving operation.
+    switch ( aMessage.Function() )
+        {
+        case EAddRecord:
+            AddRecordL( aMessage, ENoProtection );
+            break;
+
+        case EAddProtectedRecord:
+            AddRecordL( aMessage, EPublicKey );
+            break;
+
+        case EAddDomainRecord:
+            AddRecordL( aMessage, EDomainKey );
+            break;
+
+        case EGetDbEntry:
+            GetRecordL( aMessage );
+            break;
+
+        case EGetEntryList:
+            GetEntryListL( aMessage );
+            break;
+
+        case EDeleteWithCID:
+            DeleteL( aMessage );
+            break;
+
+        case EDeleteRO:
+            DeleteRecordL( aMessage );
+            break;
+
+        case EExportCIDs:
+            ExportCIDsL( aMessage );
+            break;
+
+        case EGetKey:
+            GetKeyL( aMessage );
+            break;
+
+        case ECheckRights:
+            CheckRightsL( aMessage );
+            break;
+
+        case ECount:
+            CountL( aMessage );
+            break;
+
+        case EDeleteAll:
+            DeleteAllL( aMessage );
+            break;
+
+        case EConsume:
+            ConsumeL( aMessage );
+            break;
+
+        case ECheckConsume:
+            CheckConsumeL( aMessage );
+            break;
+
+        case ECalculatePadding:
+            CalculatePaddingL( aMessage);
+            break;
+
+        case ESecureTime:
+            SecureTimeL( aMessage );
+            break;
+
+        case EGetPreparedData:
+            GetPreparedDataL( aMessage );
+            break;
+
+        case EAddDomainRO:
+            AddDomainROL( aMessage );
+            break;
+
+        case EGetDomainRO:
+            GetDomainROL( aMessage );
+            break;
+
+        case EDeleteDomainRO:
+            DeleteDomainROL( aMessage );
+            break;
+
+        case EIsInCache:
+            IsInCacheL( aMessage );
+            break;
+
+        case EAddToCache:
+            AddToCacheL( aMessage );
+            break;
+
+        case EDecrypt:
+            DecryptL( aMessage );
+            break;
+
+        case EEncrypt:
+            EncryptL( aMessage );
+            break;
+
+        case EInitializeKey:
+            InitializeKeyL( aMessage );
+            break;
+
+        case EInitializeGroupKey:
+            InitializeGroupKeyL( aMessage );
+            break;
+
+        case EGetDomainRoForCid:
+            GetDomainRosForCidL( aMessage );
+            break;
+
+        case EDeleteExpired:
+            DeleteExpiredPermissionsL( aMessage );
+            break;
+
+        case ESetEstimatedArrival:
+            SetEstimatedArrivalL( aMessage );
+            break;
+
+        case EGetEstimatedArrival:
+            GetEstimatedArrivalL( aMessage );
+            break;
+
+        case ESetName:
+            SetNameL( aMessage );
+            break;
+
+        case EGetName:
+            GetNameL( aMessage );
+            break;
+
+        case EGetWideData:
+            GetWideDataL( aMessage );
+            break;
+
+        case ECancel:
+            Cancel( aMessage );
+            break;
+
+        case EGetUdtData:
+            GetUdtDataL( aMessage );
+            break;
+
+        case EInitiateUdt:
+            InitiateUdtL( aMessage );
+            break;
+
+        case EInitOrphanedList:
+            InitExportOrphanedCIDsL( aMessage );
+            break;
+
+        case EGetOrphanedList:
+            ExportOrphanedCIDsL( aMessage );
+            break;
+
+        case EGetFLUri:
+            GetFLUriL( aMessage );
+            break;
+
+        case EEncodeRightsIssuerField:
+            EncodeRightsIssuerL( aMessage );
+            break;
+
+        case EDecodeRightsIssuerField:
+            DecodeRightsIssuerL( aMessage );
+            break;
+
+        case ESetAuthenticationSeed:
+            SetAuthenticationSeedL( aMessage );
+            break;
+
+        case EGetAuthenticationSeed:
+            GetAuthenticationSeedL( aMessage );
+            break;
+
+        case EVerifyMac:
+            VerifyMacL( aMessage );
+            break;
+
+        case EGetSupportedIndividuals:
+            GetSupportedIndividualsL( aMessage );
+            break;
+
+        case EStopWatching:
+            StopWatchingL( aMessage );
+            break;
+
+        case EUnwrapDeviceMacAndRek:
+            UnwrapMacAndRekL( aMessage, EFalse );
+            break;
+
+        case EUnwrapDomainMacAndRek:
+            UnwrapMacAndRekL( aMessage, ETrue );
+            break;
+
+        case EGetRandomData:
+            GetRandomDataL( aMessage );
+            break;
+
+        case EGetMeteringData:
+            GetMeteringDataL( aMessage );
+            break;
+
+        case EDeleteMeteringData:
+            DeleteMeteringDataL( aMessage );
+            break;
+
+        default:
+            DRMLOG( _L( "CDRMDbSession::DispatchL: Invalid command" ) );
+            User::Leave( KErrNotSupported );
+        }
+
+    // The message has already completed successfully.
+    DRMLOG2( _L( "CDRMDbSession::ServiceL ok (%08x)"), aMessage.Handle() );
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMRightsServer::ServiceError
+// Completes the request with given error code if the request is still pending.
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::ServiceError( const RMessage2& aMessage, TInt aError )
+    {
+    DRMLOG2( _L( "CDRMDbSession::ServiceError: error %d" ), aError );
+
+    if ( !aMessage.IsNull() )
+        {
+        aMessage.Complete( aError );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::ConstructL
+// Second phase constructor.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::ConstructL()
+    {
+    iRoapClientConnected = EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::AddRecord
+// Get the information from the client, construct a rights object, and add
+// it to the database.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::AddRecordL(
+    const RMessage2& aMessage,
+    TProtectionType aProtection )
+    {
+    DRMLOG( _L( "CDRMDbSession::AddRecordL" ) );
+    //__UHEAP_MARK;
+
+    CDRMPermission* permission = NULL;
+    HBufC8* wrappedcek = NULL;
+    HBufC8* cek = NULL;
+    HBufC8* CID = NULL;
+    HBufC8* rightsData = NULL;
+    TInt size = 0;
+    TPtr8 data( NULL, 0 );
+    TDRMUniqueID UID;
+
+
+    CDRMEventAddRemove* event = CDRMEventAddRemove::NewLC( ERightsObjectRecieved );
+    TRequestStatus status;
+
+    SanitizeL( aMessage.GetDesLength(0) );
+    SanitizeL( aMessage.GetDesLength(1) );
+
+    size = User::LeaveIfError( IPCGETDESLEN1 );
+    rightsData = HBufC8::NewMaxLC( size );
+    data.Set( const_cast< TUint8* >( rightsData->Ptr() ), 0, size );
+    IPCREAD1L( data );
+    permission = CDRMPermission::NewLC();
+    permission->ImportL( data );
+
+    UpdateSecureTime();
+
+    // Determine whether the RO is legal.
+    if ( ( ( permission->iAvailableRights & ERightsPlay ) &&
+           ( Invalid( *permission->iPlay ) ) ) ||
+         ( ( permission->iAvailableRights & ERightsDisplay ) &&
+           ( Invalid( *permission->iDisplay ) ) ) ||
+         ( ( permission->iAvailableRights & ERightsExecute ) &&
+           ( Invalid( *permission->iExecute ) ) ) ||
+         ( ( permission->iAvailableRights & ERightsPrint ) &&
+           ( Invalid( *permission->iPrint ) ) ) ||
+         ( ( permission->iAvailableRights & ERightsTopLevel ) &&
+           ( Invalid( *permission->iTopLevel ) ) ) )
+        {
+        User::Leave( ENoRights );
+        }
+
+    size = User::LeaveIfError( IPCGETDESLEN0 );
+    CID = HBufC8::NewLC( size );
+
+    size = User::LeaveIfError( IPCGETDESLEN2 );
+
+    // Always reserve enough space for a key, if it's 0 then it is, length will be as well.
+    size = size > KDCFKeySize ? size : KDCFKeySize;
+    if( size > KSanityDataLengthHigh )
+        {
+        User::Leave(KErrArgument);
+        }
+    wrappedcek = HBufC8::NewLC( size );
+
+    data.Set( CID->Des() );
+    IPCREAD0L( data );
+
+    data.Set( wrappedcek->Des() );
+    IPCREAD2L( data );
+
+
+    if ( aProtection != ENoProtection )
+        {
+        if(!iRek.Length())
+            {
+            User::Leave(KErrNotReady);
+            }
+
+        cek = OmaCrypto::AesUnwrapL(iRek, *wrappedcek);
+        CleanupStack::PopAndDestroy( wrappedcek );
+        CleanupStack::PushL( cek );
+        }
+    else
+        {
+        cek = wrappedcek;
+        }
+
+    DRMLOG(_L("CEK:"));
+    DRMLOGHEX(( *cek ));
+
+    if ( permission->iOriginalInsertTime == Time::NullTTime() )
+        {
+        permission->iOriginalInsertTime = iTrustedTime;
+        }
+
+    DRMDB.AddDBEntryL( *CID, *permission, *cek, UID );
+
+    // Remove a rights object from the xoma list if it is there
+    RPointerArray<CDRMXOma>& array = XOMAHEADER;
+    TInt i = 0;
+
+    for( ; i < array.Count(); i++ )
+        {
+        // if the content id is found, remove it from the list
+        if( !CID->Compare( array[i]->ContentID() ) )
+            {
+            delete array[i];
+            array.Remove( i );
+            break;
+            }
+        }
+
+    // Write the UID back to the client.
+    data.Set( reinterpret_cast< TUint8* >( &UID ), sizeof( UID ),
+        sizeof( UID ) );
+    IPCWRITE3L( data );
+
+    // Notify clients
+    event->SetContentIDL(CID->Des());
+
+    DRMNOTIFIER.SendEventL(*event,status);
+    User::WaitForRequest(status);
+
+    CleanupStack::PopAndDestroy( 5 ); // cek, CID, permission, data, event
+
+    aMessage.Complete( KErrNone );
+
+    //__UHEAP_MARKEND;
+    DRMLOG( _L( "CDRMDbSession::AddRecordL done" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::GetRecordL
+// Get record.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetRecordL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::GetRecordL" ) );
+
+    CDRMPermission* object = NULL;
+    TInt size = 0;
+    TPckg< TInt > package( size );
+    TDRMUniqueID id;
+    HBufC8* CID = NULL;
+    TPtr8 data( reinterpret_cast< TUint8* >( &id ), 0, sizeof( id ) );
+
+    // Cleanup.
+    if ( iPreparedData )
+        {
+        delete iPreparedData;
+        iPreparedData = NULL;
+        }
+
+    IPCREAD2L( data );
+
+    SanitizeL( aMessage.GetDesLength(3) );
+    CID = HBufC8::NewLC( IPCGETDESLEN3 );
+
+    data.Set( CID->Des() );
+    IPCREAD3L( data );
+
+    object = DRMDB.GetDBEntryByContentIDL( *CID, id );
+    CleanupStack::PushL( object );
+
+    // modify the times in the rights object to UI time
+    UpdateSecureTime();
+    TTime currentTime;
+    currentTime.HomeTime();
+    TTimeIntervalMicroSeconds change = currentTime.Int64() - iTrustedTime.Int64();
+    ModifyRightsObjectByTimeL( object, change, ETrue );
+
+    iPreparedData = object->ExportL();
+    size = iPreparedData->Length();
+
+    IPCWRITE0L( package );
+
+    CleanupStack::PopAndDestroy( object );
+    CleanupStack::PopAndDestroy( CID );
+
+    aMessage.Complete( KErrNone );
+
+    DRMLOG( _L( "CDRMDbSession::GetRecordL ok" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::GetEntryListL
+// Create a temporary file from RPointerArray list the database created.
+// Return the file name to the client. In case of an error, the temporary file
+// is deleted.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetEntryListL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::GetEntryListL" ) );
+    __UHEAP_MARK;
+
+    TFileName tmpFile( KNullDesC );
+    HBufC8* CID = NULL;
+    TPtr8 data( NULL, 0 );
+
+    SanitizeL( aMessage.GetDesLength(1));
+
+    CID = HBufC8::NewLC( IPCGETDESLEN1 );
+
+
+    TDeleteFile dodeletefile =
+        {
+        &RFSSESSION,
+        &tmpFile
+        };
+
+    CDRMPermissionList* list = CDRMPermissionList::NewLC();
+    list->SetAutoCleanup( ETrue );
+
+    data.Set( CID->Des() );
+    IPCREAD1L( data );
+
+    DRMDB.GetDBEntryByContentIDL( *CID, *list );
+
+    // Exclude domain rights where we are not part of the domain
+    RemoveInvalidPermissionsL( list );
+    if ( list->Count() == 0 )
+        {
+        User::Leave( KErrCANoRights );
+        }
+
+    // modify the times in the rights object to UI time
+    UpdateSecureTime();
+    TTime currentTime;
+    currentTime.HomeTime();
+    TTimeIntervalMicroSeconds change = currentTime.Int64() - iTrustedTime.Int64();
+    ModifyTimesInListL( list, change, ETrue );
+
+    // Delete the file if something goes wrong.
+    TCleanupItem fileCleanup( DeleteFile, &dodeletefile );
+    CleanupStack::PushL( fileCleanup );
+
+    // Convert the list to a permanent file store.
+    ListToFileL( *list, tmpFile );
+
+    // It is virtually impossible to make WriteL to leave in this case,
+    // but anything is still possible...
+    IPCWRITE0L( tmpFile );
+
+    CleanupStack::Pop( &dodeletefile );
+    CleanupStack::PopAndDestroy( 2 ); // list, CID
+
+    __UHEAP_MARKEND;
+
+    // All done
+    aMessage.Complete( KErrNone );
+
+    DRMLOG( _L( "CDRMDbSession::GetEntryListL: ok" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::DeleteL
+// Delete all rights objects with a certain CID.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::DeleteL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::DeleteL" ) );
+    __UHEAP_MARK;
+    TPtr8 data( NULL, 0 );
+
+    // Check for VendorId
+
+    _LIT_SECURITY_POLICY_V0(vidCheck, VID_DEFAULT); // Check Default VID
+    if ( !vidCheck().CheckPolicy(iClient) )
+        {
+        User::Leave( KErrAccessDenied );
+        }
+
+    CDRMEventAddRemove* event = CDRMEventAddRemove::NewLC( ERightsObjectDeletedAll );
+    TRequestStatus status;
+
+    HBufC8* CID = HBufC8::NewLC(
+        User::LeaveIfError( IPCGETDESLEN2 ) );
+
+    data.Set( CID->Des() );
+
+    IPCREAD2L( data );
+
+
+    // Check if deletion is allowed:
+    if( DeleteAllowedL( *CID ) )
+        {
+        DRMDB.DeleteDBEntryL( *CID );
+
+        // Notify
+        event->SetContentIDL(CID->Des());
+
+        DRMNOTIFIER.SendEventL(*event,status);
+        User::WaitForRequest(status);
+        }
+    CleanupStack::PopAndDestroy( 2 ); // CID, event
+    aMessage.Complete( KErrNone );
+    __UHEAP_MARKEND;
+    DRMLOG( _L( "CDRMDbSession::DeleteL ok" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::DeleteRecordL
+// Delete a single RO.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::DeleteRecordL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::DeleteRecordL" ) );
+    __UHEAP_MARK;
+    TDRMUniqueID id;
+
+    _LIT_SECURITY_POLICY_V0(vidCheck, VID_DEFAULT); // Check Default VID
+    if ( !vidCheck().CheckPolicy(iClient) )
+        {
+        User::Leave( KErrAccessDenied );
+        }
+
+    CDRMEventAddRemove* event = CDRMEventAddRemove::NewLC( ERightsObjectDeleted );
+    TRequestStatus status;
+
+    TPtr8 data(
+        reinterpret_cast< TUint8* >( &id ), 0, sizeof( TDRMUniqueID ) );
+
+    HBufC8* CID = HBufC8::NewLC(
+        User::LeaveIfError( IPCGETDESLEN3 ) );
+
+    IPCREAD0L( data );
+
+    data.Set( CID->Des() );
+    IPCREAD3L( data );
+
+    // Check if deletion is allowed:
+    if( DeleteAllowedL( *CID ) )
+        {
+        DRMDB.DeleteDBEntryL( *CID, id );
+
+        event->SetContentIDL( CID->Des() );
+
+        DRMNOTIFIER.SendEventL( *event, status );
+        User::WaitForRequest( status );
+        }
+
+    CleanupStack::PopAndDestroy( 2 ); // CID, event
+
+    aMessage.Complete( KErrNone );
+    __UHEAP_MARKEND;
+    DRMLOG( _L( "CDRMDbSession::DeleteRecordL ok" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::ExportCIDsL
+// Create a temporary file for rights database to export the CIDs,
+// and write the file name to the client.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::ExportCIDsL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::ExportCIDsL" ) );
+    __UHEAP_MARK;
+
+    TFileName fileName( KNullDesC );
+    TDeleteFile deletefile =
+        {
+        &RFSSESSION,
+        &fileName
+        };
+
+    TCleanupItem item( DeleteFile, &deletefile );
+    CleanupStack::PushL( item );
+
+    DRMDB.ExportContentIDListL( fileName );
+
+    IPCWRITE0L( fileName );
+
+    CleanupStack::Pop( &deletefile );
+
+    aMessage.Complete( KErrNone );
+    __UHEAP_MARKEND;
+    DRMLOG( _L( "CDRMDbSession::ExportCIDsL: ok" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::GetKeyL
+// Ask for a list of rights object based on the given CID.
+// If there is even one rights object which allows the required consuming
+// operation, get the key from database updating the RO if necessary.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetKeyL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::GetKeyL" ) );
+    __UHEAP_MARK;
+    // If credentials haven't been checked, don't return the key
+    if (iCredentialsChecked == ECheckedAndAllowed)
+        {
+        if (iCek.Length() > 0)
+            {
+            aMessage.Write(2, iCek);
+            aMessage.Complete(KErrNone);
+            }
+        else
+            {
+            aMessage.Complete(KErrCANoRights);
+            }
+        }
+    else
+        {
+        aMessage.Complete(KErrAccessDenied);
+        }
+    __UHEAP_MARKEND;
+    DRMLOG( _L( "CDRMDbSession::GetKeyL: Ok" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::CheckRightsL
+// Check if there are sufficient rights at the moment. Nothing is changed from
+// the database.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::CheckRightsL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::CheckRightsL" ) );
+    TIntent intent;
+    TInt length = 0;
+    CDRMPermission* child = NULL;
+    HBufC8* cid = NULL;
+    HBufC8* buffer = NULL;
+    TPtr8 tmp( NULL, 0, 0 );
+    TInt r = KErrNone;
+    TInt size = 0;
+    TPckg<TInt> package( size );
+    TTime currentTime;
+    TTimeIntervalMicroSeconds change;
+    TUint32 reason = 0;
+    TPckg<TUint32> package2( reason );
+    TInt error = KErrNone;
+    HBufC8* uri = NULL;
+
+    delete iPreparedData;
+    iPreparedData = NULL;
+    intent = static_cast<TIntent>( aMessage.Int0() );
+    DRMLOG2(_L("Intent: %d"), intent);
+
+    if ( intent == EPlay || intent == EView ||
+         intent == EExecute || intent == EPrint || intent == EUnknown )
+        {
+        length = User::LeaveIfError( aMessage.GetDesLength( 1 ) );
+        cid = HBufC8::NewLC( length );
+        tmp.Set( cid->Des() );
+        aMessage.ReadL( 1, tmp );
+        DRMLOG(_L("CID:"));
+        DRMLOGHEX(tmp);
+        error = FindRightsObject( intent, *cid, child, uri, reason );
+        delete uri;
+        uri = NULL; // URI not used anywhere
+
+        // if an error occurs we still need to write the information to the client,
+        // but then we can leave
+        if( error )
+            {
+            aMessage.WriteL( 3, package2 );
+            User::Leave( error );
+            }
+
+        CleanupStack::PopAndDestroy( cid );
+        CleanupStack::PushL( child );
+        }
+    else if ( intent == EInstall || intent == EPeek )
+        {
+        length = User::LeaveIfError( aMessage.GetDesLength( 1 ) );
+        cid = HBufC8::NewLC( length );
+        tmp.Set( cid->Des() );
+        aMessage.ReadL( 1, tmp );
+        DRMLOG(_L("CID:"));
+        DRMLOGHEX(tmp);
+
+        // If we have the key, install and peek always have full rights
+        buffer = DRMDB.GetDecryptionKeyL( *cid );
+        CleanupStack::PopAndDestroy( cid );
+
+        if ( buffer )
+            {
+            delete buffer;
+            child = CDRMPermission::NewL();
+            CleanupStack::PushL( child );
+            child->iAvailableRights = ERightsAll;
+            }
+        else
+            {
+            r = KErrCANoRights;
+            }
+        }
+    else if ( ( intent == EPause || intent == EContinue || intent == EStop ) &&
+        iConsume )
+        {
+        // These intents only make sense if we have an ongoing session
+        child = CDRMPermission::NewL();
+        CleanupStack::PushL( child );
+        child->DuplicateL( iConsume->GetChild() );
+        }
+    else
+        {
+        r = KErrArgument;
+        }
+
+    if ( child )
+        {
+        UpdateSecureTime();
+        currentTime.HomeTime();
+        change = currentTime.Int64() - iTrustedTime.Int64();
+        ModifyRightsObjectByTimeL( child, change, ETrue );
+        iPreparedData = child->ExportL();
+        size = iPreparedData->Length();
+        aMessage.WriteL( 2, package );
+        CleanupStack::PopAndDestroy( child );
+        }
+
+    aMessage.Complete( r );
+
+    DRMLOG2( _L( "CDRMDbSession::CheckRightsL: ok (%d)" ), r );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::CountL
+// Tell the client how many ROs there are.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::CountL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::CountL" ) );
+    __UHEAP_MARK;
+    TInt count = DRMDB.GetAmountOfRightsObjectsL();
+
+    TPtr8 data( reinterpret_cast< TUint8* >( &count ),
+                sizeof( TInt ),
+                sizeof( TInt ) );
+
+    IPCWRITE0L( data );
+
+    aMessage.Complete( KErrNone );
+    __UHEAP_MARKEND;
+    DRMLOG( _L( "CDRMDbSession::CountL: ok" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::DeleteAll
+// Delete all ROs.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::DeleteAllL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::DeleteAllL" ) );
+
+    User::LeaveIfError( VerifyCredentials(NULL, NULL, EUnknown) );
+    if( iCredentialsChecked == ECheckedAndDenied )
+        {
+        User::Leave( KErrPermissionDenied );
+        }
+
+    //__UHEAP_MARK;
+
+    DRMDB.DeleteDBL();
+
+    REPLAYCACHE.Close();
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    #ifdef RD_DRM_METERING
+    METERINGDB.Close();
+    RFSSESSION.Delete( KMeteringDataBaseFile );
+    METERINGDB.InitL( KMeteringDataBaseFile );
+    #endif
+
+    RFSSESSION.Delete( KTimedReplayCacheFile );
+    RFSSESSION.Delete( KPlainReplayCacheFile );
+
+    REPLAYCACHE.InitL( KTimedReplayCacheFile, KPlainReplayCacheFile );
+
+#else //RD_MULTIPLE_DRIVE
+
+    TFileName tempPath;
+    TFileName tempPath2;
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+
+    RFSSESSION.DriveToChar( driveNumber, driveLetter );
+
+    #ifdef RD_DRM_METERING
+    tempPath.Format( KMeteringDataBaseFile, (TUint)driveLetter );
+
+    METERINGDB.Close();
+    RFSSESSION.Delete( tempPath );
+    METERINGDB.InitL( tempPath );
+    #endif
+
+    tempPath.Format( KTimedReplayCacheFile, (TUint)driveLetter );
+    tempPath2.Format( KPlainReplayCacheFile, (TUint)driveLetter );
+
+    RFSSESSION.Delete( tempPath );
+    RFSSESSION.Delete( tempPath2 );
+
+    REPLAYCACHE.InitL( tempPath, tempPath2 );
+
+#endif
+
+    if ( !iRoapClientConnected )
+        {
+        User::LeaveIfError( iRoapClient.Connect() );
+        iRoapClientConnected = ETrue;
+        }
+
+    iRoapClient.DeleteAllL();
+
+    aMessage.Complete( KErrNone );
+    //__UHEAP_MARKEND;
+    DRMLOG( _L( "CDRMDbSession::DeleteAllL ok" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::ListToFileL
+// Convert the list to a file representation.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::ListToFileL( RPointerArray< CDRMPermission >& aList,
+                                 TFileName& aFile )
+    {
+    __UHEAP_MARK;
+    DRMLOG( _L( "CDRMDbSession::ListToFileL" ) );
+
+    TInt count( 0 );
+
+
+    RFileWriteStream fileStream;
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    User::LeaveIfError(
+        fileStream.Temp( RFSSESSION,
+                         KDRMDbTempPath,
+                         aFile,
+                         EFileWrite | EFileStream ) );
+
+#else //RD_MULTIPLE_DRIVE
+
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+
+    RFSSESSION.DriveToChar( driveNumber, driveLetter );
+
+    TFileName dbTempPath;
+    dbTempPath.Format( KDbTempPath, (TUint)driveLetter );
+
+    User::LeaveIfError(
+      fileStream.Temp( RFSSESSION,
+                       dbTempPath,
+                       aFile,
+                       EFileWrite | EFileStream ) );
+
+#endif
+
+    CleanupClosePushL( fileStream );
+
+    TInt size( sizeof( TUint32 ) ); // streams store also other info there.
+
+    for( count = 0; count < aList.Count(); count++ )
+        {
+        size += aList[ count ]->Size();
+        }
+
+    // Reset count variable:
+    count = 0;
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    if ( SysUtil::DiskSpaceBelowCriticalLevelL( &RFSSESSION,
+                                                size,
+                                                EDriveC ) )
+
+#else //RD_MULTIPLE_DRIVE
+
+    if ( SysUtil::DiskSpaceBelowCriticalLevelL( &RFSSESSION,
+                                                size,
+                                                driveNumber ) )
+
+#endif
+        {
+        DRMLOG( _L( "CDRMDbSession::ListToFileL: KErrDiskFull" ) );
+        User::Leave( KErrDiskFull );
+        }
+
+    fileStream.WriteInt32L( aList.Count() );
+
+    // Write the whole stuff into the file.
+    // URIs are ignored. No use to put them to file (always the same
+    // and the client knows it already).
+    while( count < aList.Count() )
+        {
+        aList[ count ]->ExternalizeL( fileStream );
+        ++count;
+        }
+
+    fileStream.CommitL();
+
+    CleanupStack::PopAndDestroy( &fileStream );
+
+    DRMLOG( _L( "CDRMDbSession::ListToFileL: ok" ) );
+    __UHEAP_MARKEND;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::FindRightsObjectL
+// Try to locate the best RO from the given list which allows consuming of
+// content.
+// If end time is defined or an interval activated, the smallest endtime
+// is always chosen first.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::FindRightsObjectL( TIntent aIntent,
+                                       const TDesC8& aURI,
+                                       CDRMPermission*& aChild,
+                                       HBufC8*& aUsedURI,
+                                       TUint32& aReason )
+    {
+    DRMLOG( _L( "CDRMDbSession::FindRightsObjectL" ) );
+    TInt res = KErrNotFound;
+
+    if ( aUsedURI || aChild )
+        {
+        // Check that return parameters are null initially.
+        User::Leave( KErrArgument );
+        }
+
+    CDRMPermissionList *perms = CDRMPermissionList::NewLC();
+    TTime time;
+
+    perms->SetAutoCleanup( ETrue );
+    DRMDB.GetDBEntryByContentIDL( aURI , *perms );
+
+    UpdateSecureTime();
+
+    if ( iSecureTime )
+        {
+        time = iTrustedTime;
+        }
+    else
+        {
+        time = Time::NullTTime();
+        }
+
+    if ( aIntent == EPeek || aIntent == EInstall )
+        {
+        // There is at least one RO available.
+        // Use any RO, whether they are valid or not.
+        // Pick the first RO in the list.
+
+        aChild = (*perms)[0];
+        (*perms).Remove( 0 );
+
+        CleanupStack::PopAndDestroy( perms );
+        return;
+        }
+    else if ( aIntent == EUnknown )
+        {
+        // Pick one that works, no matter what the intent is
+        for ( TInt i = 0; res == KErrNotFound && i < perms->Count(); i++ )
+            {
+            if ( (*perms)[i]->Valid( time, IMSI, aReason ) )
+                {
+                res = i;
+                }
+            }
+        if ( res != KErrNotFound )
+            {
+            aChild = (*perms)[res];
+            perms->Remove( res );
+            }
+        else
+            {
+            User::Leave( KErrCANoPermission );
+            }
+        }
+    else
+        {
+        res = FindBestROsL( *perms, aURI, aIntent, aUsedURI, aReason );
+        if ( res >= 0 )
+            {
+            aChild = (*perms)[res];
+            perms->Remove( res );
+            }
+        else
+            {
+            User::Leave( KErrCANoPermission );
+            }
+        }
+    CleanupStack::PopAndDestroy( perms );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::FindRightsObject
+// Try to locate the best RO from the given list which allows consuming of
+// content.
+// If end time is defined or an interval activated, the smallest endtime
+// is always chosen first.
+// -----------------------------------------------------------------------------
+//
+TInt CDRMDbSession::FindRightsObject( TIntent aIntent,
+                                      const TDesC8& aURI,
+                                      CDRMPermission*& aChild,
+                                      HBufC8*& aUsedURI,
+                                      TUint32& aReason )
+    {
+    DRMLOG( _L( "CDRMDbSession::FindRightsObject" ) );
+    TInt error = KErrNone;
+
+    TRAP( error, FindRightsObjectL( aIntent, aURI, aChild, aUsedURI, aReason ) );
+    if ( ( error == KErrCANoRights || error == KErrCANoPermission ) &&
+        PendingRights(aURI) )
+        {
+        error = KErrCAPendingRights;
+        }
+    return error;
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::CheckConsumeL
+// Check if Consume is possible
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::CheckConsumeL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::CheckConsumeL" ) );
+
+    __UHEAP_MARK;
+
+    HBufC8* CID = NULL;
+    TPtr8 cid( NULL, 0, 0 );
+    TInt length = 0;
+    TIntent intent;
+    TUint32 reason = 0;
+
+    length = User::LeaveIfError( IPCGETDESLEN1 );
+    CID = HBufC8::NewLC( length );
+    cid.Set( CID->Des() );
+    IPCREAD1L( cid );
+    intent = static_cast<TIntent>(aMessage.Int0());
+
+    // Check only intents which are actually consuming something. All others
+    // always succeed, because CheckConsume is called by default when a file
+    // is opened.
+    if ( intent == EPlay || intent == EView ||
+         intent == EExecute || intent == EPrint || intent == EUnknown )
+        {
+        // Count constraints are valid for the duration of the
+        // session after they have been consumed earlier
+        if ( !( iConsume && iConsume->CountConstraintActive() ||
+                SERVER->HasActiveCountConstraint( *CID ) ) )
+            {
+            CDRMPermission* child( NULL );
+            HBufC8* uri( NULL );
+            TInt error( FindRightsObject( intent, *CID, child, uri, reason ) );
+            delete child;
+            delete uri;
+            User::LeaveIfError( error );
+            }
+        }
+/* Enable this code as soon as clients use EUnknown, and it is safe to fail
+   when no key is available
+    else if ( intent == EPeek || EInstall )
+        {
+        // We need at least the key for peek and install. This will leave if no
+        // key is there.
+        HBufC8* key = DRMDB.GetDecryptionKeyL( *CID );
+        delete key;
+        }
+*/
+
+    CleanupStack::PopAndDestroy( CID );
+    aMessage.Complete( KErrNone );
+    __UHEAP_MARKEND;
+    DRMLOG( _L( "CDRMDbSession::CheckConsumeL: ok" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::ConsumeL
+// Consume the right and register the consumption.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::ConsumeL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::ConsumeL" ) );
+
+    const TIntent intent = static_cast<TIntent>(aMessage.Int0());
+    HBufC8* CID = NULL;
+    TInt length = 0;
+    TPtr8 cid( NULL, 0, 0 );
+
+    length = User::LeaveIfError( IPCGETDESLEN1 );
+
+    CID = HBufC8::NewLC( length );
+
+    cid.Set( CID->Des() );
+    IPCREAD1L( cid );
+
+    if ( intent != EUnknown )
+        {
+        if ( intent == EPeek || intent == EInstall )
+            {
+            User::LeaveIfError( VerifyCredentials( CID, NULL, intent ) );
+            }
+        else
+            {
+            if ( intent == EPlay ||
+                 intent == EView ||
+                 intent == EExecute ||
+                 intent == EPrint ||
+                 intent == EStop )
+                {
+
+                if ( iConsume )
+                    {
+                    delete iConsume;
+                    iConsume = NULL;
+                    }
+                if ( intent != EStop )
+                    {
+                    CDRMConsume* consume( NULL );
+                    consume = CDRMConsume::NewLC( *this, *CID, NULL );
+                    consume->HandleL( intent );
+                    CleanupStack::Pop( consume );
+                    iConsume = consume;
+                    }
+                }
+            else
+                {
+                if ( !iConsume )
+                    {
+                    User::Leave( KErrNotReady );
+                    }
+
+                if ( intent == EPause )
+                    {
+                    iConsume->Pause();
+                    }
+                else if ( intent == EContinue )
+                    {
+                    iConsume->ContinueL();
+                    }
+                else
+                    {
+                    iConsume->Stop();
+                    }
+                }
+            }
+        }
+    else
+        {
+        // None of the other intents are allowed here, fail
+        User::Leave( KErrArgument );
+        }
+
+
+    CleanupStack::PopAndDestroy( CID );
+    aMessage.Complete( KErrNone );
+    DRMLOG( _L( "CDRMDbSession::ConsumeL: ok" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::CalculatePaddingL
+//
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::CalculatePaddingL( const RMessage2& aMessage )
+    {
+    __UHEAP_MARK;
+    DRMLOG( _L( "CDRMDbSession::CalculatePaddingL" ) );
+
+    CAESDecryptor* decryptor( NULL );
+    TInt i( 0 );
+
+    TBuf8<KDCFKeySize * 2> data;
+    TBuf8<KDCFKeySize> iv;
+    TBuf8<KDCFKeySize> block;
+    TPtr8 tmp( NULL, 0, 0 );
+
+    aMessage.ReadL( 0, data );
+
+    // Check that the data we read is actually of the proper length
+    if( data.Length() != KDCFKeySize*2 )
+        {
+        User::Leave(KErrArgument);
+        }
+
+    iv.Copy(data.Left(KDCFKeySize));
+    block.Copy(data.Right(KDCFKeySize));
+
+    if( iCek.Length() != KDRMKeyLength )
+        {
+        User::Leave(KErrNotReady);
+        }
+
+    decryptor = CAESDecryptor::NewLC(iCek);
+    decryptor->Transform(block);
+    CleanupStack::PopAndDestroy( decryptor );
+
+    for (i = 0; i < KDCFKeySize; i++)
+        {
+        block[i] ^= iv[i];
+        }
+
+    if ( block[ KDCFKeySize - 1 ] > 0 && block[ KDCFKeySize - 1 ] <= 16 )
+        {
+        for ( i = KDCFKeySize - block[ KDCFKeySize - 1 ];
+              i < KDCFKeySize - 1;
+              ++i )
+            {
+            if ( block[ i ] != block[ KDCFKeySize - 1 ] )
+                {
+                User::Leave( KErrCorrupt );
+                }
+            }
+
+        aMessage.Complete( block[ KDCFKeySize - 1 ] );
+        DRMLOG2( _L( "CDRMDbSession::CalculatePaddingL: Padding = %d" ),
+                 block[ KDCFKeySize - 1 ] );
+
+        return;
+        }
+
+    User::Leave( KErrCorrupt );
+
+__UHEAP_MARKEND;
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::SecureTimeL
+// returns the secure time
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::SecureTimeL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::SecureTimeL" ) );
+    __UHEAP_MARK;
+    TPckgBuf< TInt64 > time;
+    TPckg< TBool > levelPckg( iSecureTime );
+
+    UpdateSecureTime();
+
+    time() = iTrustedTime.Int64();
+
+    IPCWRITE0L( time );
+    IPCWRITE1L( levelPckg );
+
+    aMessage.Complete( KErrNone );
+    __UHEAP_MARKEND;
+    DRMLOG( _L( "CDRMDbSession::SecureTime: ok" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::EncryptL
+//
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::EncryptL(const RMessage2& aMessage)
+    {
+    TBuf8<KDCFKeySize> iv;
+    HBufC8* data = NULL;
+    TPtr8 ptr(NULL, 0, 0);
+    TBool addPadding;
+    __UHEAP_MARK;
+
+    DRMLOG(_L("CDRMDbSession::EncryptL"));
+
+    if( iCek.Length() != KDRMKeyLength )
+        {
+        User::Leave( KErrNotReady );
+        }
+
+    SanitizeL( aMessage.GetDesLength(0) );
+
+    addPadding = aMessage.Int2() != 0 ? ETrue : EFalse;
+    aMessage.Read(0, iv);
+    data = HBufC8::NewLC(aMessage.GetDesMaxLength(1));
+    ptr.Set(data->Des());
+    aMessage.Read(1, ptr);
+
+    AesEncryptL( iCek, iv, addPadding, ptr );
+
+    aMessage.Write(1, ptr);
+    aMessage.Complete(KErrNone);
+    CleanupStack::PopAndDestroy( data );
+    __UHEAP_MARKEND;
+    DRMLOG(_L("CDRMDbSession::EncryptL: Ok"));
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::DecryptL
+// Decrypt data and return it to the caller, using the CEK for this session
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::DecryptL(const RMessage2& aMessage)
+    {
+    DRMLOG(_L("CDRMDbSession::DecryptL"));
+
+    // If credentials haven't been checked, do it now, check for expired rights
+    if (iCredentialsChecked == ECheckedAndDenied ||
+        iCredentialsChecked == ENotChecked &&
+        VerifyCredentials(iContentId, NULL, EUnknown) != KErrNone)
+        {
+        DRMLOG(_L("Decrypt failed: untrusted client"));
+        aMessage.Complete(KErrAccessDenied);
+        }
+    else if ( iConsume && iConsume->IsExpired() )
+        {
+        DRMLOG(_L("Decrypt failed: rights expired"));
+        aMessage.Complete(KErrCANoPermission);
+        }
+    else
+        {
+        if (iCek.Length() > 0)
+            {
+            TBuf8<KDCFKeySize> iv;
+            HBufC8* data = NULL;
+            TPtr8 ptr(NULL, 0, 0);
+            TBool removePadding;
+
+            removePadding = aMessage.Int2() != 0 ? ETrue : EFalse;
+            aMessage.Read(0, iv);
+
+            data = HBufC8::NewMaxLC(aMessage.GetDesMaxLength(1));
+
+            ptr.Set(data->Des());
+            aMessage.Read(1, ptr);
+
+            AesDecryptL( iCek,
+                         iv,
+                         removePadding,
+                         ptr );
+
+            aMessage.Write(1, ptr);
+            aMessage.Complete(KErrNone);
+            CleanupStack::PopAndDestroy( data );
+            }
+        else
+            {
+            aMessage.Complete(KErrCANoRights);
+            }
+        }
+    DRMLOG(_L("CDRMDbSession::DecryptL: Ok"));
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::InitializeKeyL
+// Initialize the CEK for this session based on the content ID. Also sets the
+// content ID for later usage.
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::InitializeKeyL( const RMessage2& aMessage )
+    {
+    TPtr8 tmp(NULL, 0, 0);
+    HBufC8* key = NULL;
+    TInt error = KErrNone;
+
+    DRMLOG( _L( "CDRMDbSession::InitializeKeyL"));
+    if ( iContentId )
+        {
+        delete iContentId;
+        iContentId = NULL;
+        }
+    iContentId  = HBufC8::NewL( User::LeaveIfError( IPCGETDESLEN0 ) );
+    tmp.Set( iContentId->Des() );
+    IPCREAD0L( tmp );
+
+    __UHEAP_MARK;
+    TRAP( error, key = DRMDB.GetDecryptionKeyL( *iContentId  ) );
+    if ( ( error == KErrCANoRights || error == KErrCANoPermission ) &&
+        PendingRights( *iContentId , EFalse ) )
+        {
+        error = KErrCAPendingRights;
+        }
+
+    if ( error == KErrNone )
+        {
+        iCek.Copy( *key );
+        delete key;
+        aMessage.Complete( KErrNone );
+        }
+    else
+        {
+        aMessage.Complete( error );
+        }
+    __UHEAP_MARKEND;
+    DRMLOG2( _L( "CDRMDbSession::InitializeKeyL: %d" ), error );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::InitializeGroupKeyL
+// Initialize the CEK for this session from a given group key
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::InitializeGroupKeyL(const RMessage2& aMessage )
+    {
+    HBufC8* groupId = NULL;
+    HBufC8* groupKey = NULL;
+    TPtr8 tmp(NULL, 0, 0 );
+    HBufC8* key = NULL;
+    TRequestStatus status;
+    CAESDecryptor* aes = NULL;
+    CModeCBCDecryptor* cbc = NULL;
+
+    __UHEAP_MARK;
+
+    SanitizeL( aMessage.GetDesLength(0) );
+    SanitizeL( aMessage.GetDesLength(1) );
+
+    DRMLOG(_L("CDRMDbSession::InitializeGroupKeyL"));
+    if (aMessage.Int2() == EMethodAES_128_CBC)
+        {
+        groupId = HBufC8::NewLC(aMessage.GetDesLength(0));
+        tmp.Set(groupId->Des());
+        aMessage.Read(0, tmp);
+
+        groupKey = HBufC8::NewLC(aMessage.GetDesLength(1));
+        tmp.Set(groupKey->Des());
+        aMessage.Read(1, tmp);
+
+        key = DRMDB.GetDecryptionKeyL(*groupId);
+        CleanupStack::PushL(key);
+
+        if ( key )
+            {
+            aes = CAESDecryptor::NewLC(*key);
+            cbc = CModeCBCDecryptor::NewL(aes, groupKey->Left(KDCFKeySize));
+            CleanupStack::Pop( aes );
+            iCek.Copy(groupKey->Mid(KDCFKeySize, KDCFKeySize));
+            cbc->Transform(iCek);
+            delete cbc;
+            aMessage.Complete(KErrNone);
+            }
+        else
+            {
+            aMessage.Complete(KErrCANoRights);
+            }
+        CleanupStack::PopAndDestroy(3); // key, groupKey, groupId
+        }
+    else
+        {
+        aMessage.Complete(KErrNotSupported);
+        }
+
+    __UHEAP_MARKEND;
+    DRMLOG(_L("CDRMDbSession::InitializeGroupKeyL: Ok"));
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::GetPreparedDataL
+// Returns data which has been allocated before
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetPreparedDataL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::GetPreparedDataL" ) );
+
+    if( !iPreparedData )
+        {
+        User::Leave( KErrNotReady );
+        }
+
+    if( iPreparedData->Length() > aMessage.GetDesMaxLength(0) )
+        {
+        User::Leave(KErrArgument);
+        }
+
+    IPCWRITE0L( iPreparedData->Des() );
+
+    aMessage.Complete( KErrNone );
+    DRMLOG( _L( "CDRMDbSession::GetPreparedDataL: ok" ) );
+
+    // Delete the data
+    delete iPreparedData;
+    iPreparedData = NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::IsInCacheL
+// Checks whether the given entry is in replay cache or not.
+// -----------------------------------------------------------------------------
+void CDRMDbSession::IsInCacheL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::IsInCacheL" ) );
+
+    HBufC8* buf = HBufC8::NewLC(
+        User::LeaveIfError( IPCGETDESLEN0 ) );
+
+    TPckgBuf< TBool > res;
+    TPtr8 data( buf->Des() );
+
+    IPCREAD0L( data );
+
+    if ( aMessage.Ptr1() )
+        {
+        TPckgBuf< TTime > time;
+
+        IPCREAD1L( time );
+
+        res = REPLAYCACHE.InCacheL( *buf, time() );
+        }
+    else
+        {
+        res = REPLAYCACHE.InCacheL( *buf );
+        }
+
+    CleanupStack::PopAndDestroy( buf );
+
+    IPCWRITE2L( res );
+
+    aMessage.Complete( KErrNone );
+
+    DRMLOG( _L( "CDRMDbSession::IsInCache ok" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::AddToCacheL
+// Adds an entry to replay cache.
+// -----------------------------------------------------------------------------
+void CDRMDbSession::AddToCacheL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::AddToCacheL" ) );
+
+    HBufC8* buf = NULL;
+
+    UpdateSecureTime();
+
+    if ( !iSecureTime )
+        {
+        // DoSomething!
+        }
+
+    buf = HBufC8::NewLC(
+        User::LeaveIfError( IPCGETDESLEN0 ) );
+
+    TPtr8 data( buf->Des() );
+
+    IPCREAD0L( data );
+
+    if ( aMessage.Ptr1() )
+        {
+        TPckgBuf< TTime > time;
+
+        IPCREAD1L( time );
+
+        REPLAYCACHE.AddL( *buf, time(), iTrustedTime );
+        }
+
+    else
+        {
+        REPLAYCACHE.AddL( *buf, iTrustedTime );
+        }
+
+    CleanupStack::PopAndDestroy( buf );
+
+    aMessage.Complete( KErrNone );
+
+    DRMLOG( _L( "CDRMDbSession::AddToCacheL ok" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::AddDomainROL
+// Add domain ro xml data
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::AddDomainROL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::AddDomainROL" ) );
+    __UHEAP_MARK;
+    HBufC8* RoId = NULL;
+    HBufC8* XMLData = NULL;
+    TInt size = 0;
+    TPtr8 data( NULL, 0 );
+
+    size = User::LeaveIfError( IPCGETDESLEN0 );
+    RoId = HBufC8::NewLC( size );
+
+    size = User::LeaveIfError( IPCGETDESLEN1 );
+    XMLData = HBufC8::NewLC( size );
+
+    data.Set( RoId->Des() );
+    IPCREAD0L( data );
+
+    data.Set( XMLData->Des() );
+    IPCREAD1L( data );
+
+    DRMDB.AddDomainROL( *RoId, *XMLData );
+
+    CleanupStack::PopAndDestroy( 2 ); // RoId, XMLData
+
+    aMessage.Complete( KErrNone );
+    __UHEAP_MARKEND;
+    DRMLOG( _L( "CDRMDbSession::AddDomainROL done" ) );
+    };
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::GetDomainROL
+// Get domain ro xml data
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetDomainROL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::GetDomainROL" ) );
+
+    TInt size = 0;
+    TPckg< TInt > package( size );
+    HBufC8* RoId = NULL;
+    TPtr8 data(NULL, 0);
+
+    // Cleanup.
+    if ( iPreparedData )
+        {
+        delete iPreparedData;
+        iPreparedData = NULL;
+        }
+
+    size = User::LeaveIfError( IPCGETDESLEN1 );
+
+    RoId = HBufC8::NewLC( size );
+
+    data.Set( RoId->Des() );
+    IPCREAD1L( data );
+
+    iPreparedData = DRMDB.GetDomainROL( *RoId );
+
+    size = iPreparedData->Length();
+
+    IPCWRITE0L( package );
+
+    CleanupStack::PopAndDestroy( RoId );
+
+    aMessage.Complete( KErrNone );
+
+    DRMLOG( _L( "CDRMDbSession::GetDomainROL ok" ) );
+    };
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::DeleteDomainROL
+// Delete domain ro xml data
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::DeleteDomainROL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::DeleteDomainROL" ) );
+    __UHEAP_MARK;
+    TPtr8 data( NULL, 0 );
+    TInt size = 0;
+
+    size = User::LeaveIfError( IPCGETDESLEN0 );
+
+
+    HBufC8* RoId = HBufC8::NewLC( size );
+
+    data.Set( RoId->Des() );
+
+    IPCREAD0L( data );
+
+    DRMDB.DeleteDomainROL( *RoId );
+
+    CleanupStack::PopAndDestroy( RoId );
+
+    aMessage.Complete( KErrNone );
+    __UHEAP_MARKEND;
+    DRMLOG( _L( "CDRMDbSession::DeleteDomainROL ok" ) );
+    };
+
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::GetDomainRosForCidL
+// Return the domain ROs for a content ID in a buffer. Each RO is preceded
+// by a length field
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetDomainRosForCidL(
+    const RMessage2& aMessage)
+    {
+    DRMLOG(_L("CDRMDbSession::GetDomainRosForCidL"));
+    TInt size(0);
+    TInt roSize(0);
+    TInt pos = 0;
+    TInt indexLatest = -1;
+    TTime timeStamp = 0;
+    TTime timeLatest = 0;
+    TPckg<TInt> pkg(size);
+    TPtr8 ptr(NULL, 0);
+    TPtrC8 elementPtr(KNullDesC8);
+    TPckg<TInt> roSizePkg(roSize);
+    HBufC8* element = NULL;
+    HBufC8* id(NULL);
+    HBufC8* ro(NULL);
+    CDRMPointerArray<CDRMPermission>*
+        rights( CDRMPointerArray<CDRMPermission>::NewLC() );
+    rights->SetAutoCleanup(ETrue);
+
+    delete iPreparedData;
+    iPreparedData = NULL;
+
+    SanitizeL( aMessage.GetDesLength(0) );
+
+    id = HBufC8::NewLC(aMessage.GetDesLength(0));
+    ptr.Set(id->Des());
+    aMessage.Read(0, ptr);
+
+    TRAPD(r, DRMDB.GetDBEntryByContentIDL(*id, *rights));
+
+    if (r == KErrCANoRights || r == KErrCANoPermission )
+        {
+        r = KErrNone;
+        }
+    User::LeaveIfError(r);
+
+    for (TInt i(0); i < rights->Count(); i++)
+        {
+        if ( (*rights)[i]->iDomainID )
+            {
+            ro = DRMDB.GetDomainROL(*(*rights)[i]->iRoID);
+            CleanupStack::PushL(ro);
+
+            elementPtr.Set(ExtractElement(*ro, KTimeStamp, pos));
+
+            /* Check whether the timestamp was found or not and whether it is
+               the newest one so far or not */
+            if (pos >= 0)
+                {
+                element = elementPtr.AllocLC();
+                timeStamp = Iso8601ToTime(*element);
+                CleanupStack::PopAndDestroy(element);
+
+                if (timeStamp > timeLatest)
+                    {
+                    indexLatest = i;
+                    }
+                }
+            CleanupStack::PopAndDestroy(ro);
+            ro = NULL;
+            }
+        pos = 0;
+        }
+
+    /* At least one timestamp was found */
+    if (indexLatest >= 0 && indexLatest < rights->Count())
+        {
+        ro = DRMDB.GetDomainROL(*(*rights)[indexLatest]->iRoID);
+        CleanupStack::PushL(ro);
+
+        roSize = ro->Size();
+        if ( !iPreparedData )
+            {
+            iPreparedData = HBufC8::NewL(sizeof (TInt) + roSize);
+            }
+        else
+            {
+            iPreparedData = iPreparedData->ReAllocL(
+                size + sizeof (TInt) + roSize );
+            }
+        ptr.Set(iPreparedData->Des());
+        ptr.Append(roSizePkg);
+        ptr.Append(*ro);
+        size += sizeof (TInt) + roSize;
+        CleanupStack::PopAndDestroy(ro);
+        }
+
+    aMessage.Write(1, pkg);
+    CleanupStack::PopAndDestroy( id );
+    CleanupStack::PopAndDestroy( rights );
+
+    aMessage.Complete(KErrNone);
+    DRMLOG(_L("CDRMDbSession::GetDomainRosForCidL ok"));
+    }
+
+
+//------------------------------------------------------------------------------
+// CDRMDbSession::DeleteExpiredPermissionsL
+// Delete expired permissions if we have secure time.
+//------------------------------------------------------------------------------
+void CDRMDbSession::DeleteExpiredPermissionsL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::DeleteExpiredPermissionsL" ) );
+    CDRMActiveOperation* active( NULL );
+    TTime time;
+
+    User::LeaveIfError( VerifyCredentials(NULL, NULL, EUnknown) );
+    if( iCredentialsChecked == ECheckedAndDenied )
+        {
+        User::Leave( KErrPermissionDenied );
+        }
+
+    UpdateSecureTime();
+
+    if ( iSecureTime )
+        {
+        time = iTrustedTime;
+        }
+    else
+        {
+        time = Time::NullTTime();
+        }
+
+    if ( iPendingRequest )
+        {
+        User::Leave( KErrAlreadyExists );
+        }
+
+    active = CDRMActiveOperation::NewLC( aMessage, *this,
+                                         CDRMActiveOperation::EOperationDeleteExpired );
+    active->ActivateL( DRMDB, iTrustedTime );
+
+    iPendingRequest = active;
+
+    CleanupStack::Pop( active );
+
+    DRMLOG( _L( "CDRMDbSession::DeleteExpiredPermissionsL ok" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::SetEstimatedArrivalL
+// set the estimated arrival time for the content uri
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::SetEstimatedArrivalL( const RMessage2& aMessage )
+    {
+    HBufC8* CID = NULL;
+    TFileName fileName;
+    TInt length = 0;
+    TPtr8 inRead( NULL, 0 );
+    TTimeIntervalSeconds interval = 0;
+    TPckg<TTimeIntervalSeconds> package( interval );
+    RPointerArray<CDRMXOma>& array = XOMAHEADER;
+    CDRMXOma* omaData = NULL;
+
+    // Read the content id
+    length = User::LeaveIfError( IPCGETDESLEN0 );
+    CID = HBufC8::NewLC( length );
+    inRead.Set( CID->Des() );
+    IPCREAD0L( inRead );
+
+    // Read the interval
+    IPCREAD1L( package );
+
+
+    for( TInt i = 0; i < array.Count(); i++ )
+        {
+        if( !CID->Compare( (array)[i]->ContentID() ) )
+            {
+            omaData = (array)[i];
+            break;
+            }
+        }
+
+    // Update the secure time
+    UpdateSecureTime();
+
+    if( omaData ) // Exists, update
+        {
+        omaData->SetWaitTimeL( interval );
+        omaData->SetTimeStampL( iTrustedTime );
+        }
+    else // Doesn't exist, create a new one
+        {
+        omaData = CDRMXOma::NewLC( *CID, iTrustedTime, interval );
+        array.AppendL( omaData );
+        CleanupStack::Pop( omaData );
+        }
+
+    CleanupStack::PopAndDestroy( CID );
+
+    // Complete the command
+    aMessage.Complete( KErrNone );
+    };
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::GetEstimatedArrivalL
+// get the estimated arrival time for the content uri
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetEstimatedArrivalL( const RMessage2& aMessage )
+    {
+    HBufC8* CID = NULL;
+    TInt length = 0;
+    TPtr8 inRead( NULL, 0 );
+    RPointerArray<CDRMXOma>& array = XOMAHEADER;
+    CDRMXOma* omaData = NULL;
+    TInt64 interval = 0;
+    TInt i = 0;
+    TTimeIntervalSeconds result = 0;
+
+    // Read the content id
+    length = User::LeaveIfError( IPCGETDESLEN0 );
+    CID = HBufC8::NewLC( length );
+    inRead.Set( CID->Des() );
+    IPCREAD0L( inRead );
+
+    for( ; i < array.Count(); i++ )
+        {
+        if( !CID->Compare( (array)[i]->ContentID() ) )
+            {
+            omaData = (array)[i];
+            break;
+            }
+        }
+
+    // Update the secure time
+    UpdateSecureTime();
+
+    if( omaData ) // Exists, update
+        {
+
+        // Special case, the rights have expired before, but have not been removed
+        // so that we do not lose the notification
+        if( omaData->WaitTime().Int() == KErrCAPendingRights )
+            {
+            interval = -1; // Fixed value for this case:
+                           // -1 means the rights should have arrived already
+
+            delete omaData;
+            omaData = 0;
+
+            array.Remove( i );
+            }
+        else
+            {
+            // Update the secure time
+            UpdateSecureTime();
+
+            interval = omaData->WaitTime().Int();
+            interval -= ( iTrustedTime.Int64() - omaData->TimeStamp().Int64() ) /
+                KMicrosecondsToSecond;
+
+            if( interval <= 0 )
+                {
+                interval = -1; // Fixed value for this case:
+                               // -1 means the rights should have arrived already
+
+                // Clean up the data: if the function fails before this
+                // the instance remains like it should
+                delete omaData;
+                omaData = 0;
+
+                array.Remove( i ); // Remove from the array
+                }
+            }
+        result = I64INT(interval);
+        TPckg<TTimeIntervalSeconds> package( result );
+        IPCWRITE1L( package );
+        }
+    else // Doesn't exist, create a new one
+        {
+        User::Leave( KErrNotFound );
+        }
+
+    CleanupStack::PopAndDestroy( CID );
+
+    // Complete the command
+    aMessage.Complete( KErrNone );
+    };
+
+
+
+//------------------------------------------------------------------------------
+// CDRMDbSession::PendingRights
+// Check if rights are pending
+//------------------------------------------------------------------------------
+TBool CDRMDbSession::PendingRights(const TDesC8& aCid, TBool aRemoval)
+    {
+    TBool f = EFalse;
+    RPointerArray<CDRMXOma>& array = XOMAHEADER;
+    CDRMXOma* omaData = NULL;
+    TInt64 interval = 0;
+    TInt i = 0;
+    TTimeIntervalSeconds result = 0;
+
+    for( ; i < array.Count() && !f; i++ )
+        {
+        if( !aCid.Compare( (array)[i]->ContentID() ) )
+            {
+            omaData = (array)[i];
+            // Exists and is different from KErrCAPendingRights -> update
+            if( omaData && omaData->WaitTime().Int() != KErrCAPendingRights )
+                {
+                // Update the secure time
+                UpdateSecureTime();
+                interval = omaData->WaitTime().Int();
+                interval -= ( iTrustedTime.Int64() - omaData->TimeStamp().Int64() ) /
+                    KMicrosecondsToSecond;
+
+                // check if removal from the list is needed
+                if( aRemoval && interval <= 0 )
+                    {
+                    TRAPD( error, omaData->SetWaitTimeL( KErrCAPendingRights ) );
+                    error = error; // remove error
+                    }
+                f = ETrue;
+                }
+            }
+        }
+    return f;
+    }
+
+
+
+//------------------------------------------------------------------------------
+// CDRMDbSession::GetUdtDataL
+// Gets the user data transfer header data
+//------------------------------------------------------------------------------
+void CDRMDbSession::GetUdtDataL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::GetUdtDataL" ) );
+    __UHEAP_MARK;
+    // Usage intent.
+    HBufC8* udtData = NULL;
+
+    // Get the key
+    udtData = DRMDB.GetUdtDataLC();
+
+    // Write the udt data to the client.
+    // This shouldn't fail anyway.
+    IPCWRITE0L( *udtData );
+
+    CleanupStack::PopAndDestroy( udtData );
+
+    aMessage.Complete( KErrNone );
+    __UHEAP_MARKEND;
+    DRMLOG( _L( "CDRMDbSession::GetUdtDataL: Ok" ) );
+    };
+
+//------------------------------------------------------------------------------
+// CDRMDbSession::InitiateUdtL
+// Initiate user data transfer
+//------------------------------------------------------------------------------
+void CDRMDbSession::InitiateUdtL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::InitiateUdtL" ) );
+    __UHEAP_MARK;
+
+    HBufC8* encryptionKey = NULL;
+    TInt size = 0;
+    TPtr8 data( NULL, 0 );
+
+    SanitizeL( aMessage.GetDesLength(0));
+
+    size = User::LeaveIfError( IPCGETDESLEN0 );
+    encryptionKey = HBufC8::NewLC( size );
+
+    data.Set( encryptionKey->Des() );
+    IPCREAD0L( data );
+
+    // The encrypted data is encrypted with 2048 byte key, it always needs to be atleast this long
+    if( encryptionKey->Length() < 254)
+        {
+        User::Leave(KErrArgument);
+        }
+
+    DRMDB.InitiateUdtL( *encryptionKey );
+
+    CleanupStack::PopAndDestroy( encryptionKey );
+
+    aMessage.Complete( KErrNone );
+    __UHEAP_MARKEND;
+
+    DRMLOG( _L( "CDRMDbSession::InitiateUdtL done" ) );
+    };
+
+//------------------------------------------------------------------------------
+// CDRMDbSession::InitExportOrhanedCIDsL
+// Create and export the list of orphaned content id's
+//------------------------------------------------------------------------------
+void CDRMDbSession::InitExportOrphanedCIDsL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::InitExportOrphanedCIDsL" ) );
+    CDRMActiveOperation* active( NULL );
+    TBool performScan = EFalse;
+
+    User::LeaveIfError( VerifyCredentials(NULL,NULL,ContentAccess::EUnknown) );
+
+    if ( iPendingRequest )
+        {
+        User::Leave( KErrAlreadyExists );
+        }
+
+    // if the old filename exists, delete it, a new operation starts
+    if( iFileName )
+        {
+        delete iFileName;
+        iFileName = NULL;
+        }
+
+    // Read the scan data:
+    performScan = aMessage.Int0() != 0 ? ETrue : EFalse;
+
+
+    active = CDRMActiveOperation::NewLC( aMessage, *this,
+                                         CDRMActiveOperation::EOperationExportObsolete );
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    active->ActivateL( DRMDB, RFSSESSION, KDRMDbTempPath, performScan );
+
+#else //RD_MULTIPLE_DRIVE
+
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+
+    RFSSESSION.DriveToChar( driveNumber, driveLetter );
+
+    TFileName dbTempPath;
+    dbTempPath.Format( KDbTempPath, (TUint)driveLetter );
+
+    active->ActivateL( DRMDB, RFSSESSION, dbTempPath, performScan );
+
+#endif
+
+    iPendingRequest = active;
+
+    CleanupStack::Pop( active );
+
+    DRMLOG( _L( "CDRMDbSession::InitExportOrphanedCIDsL: ok" ) );
+    };
+
+
+//------------------------------------------------------------------------------
+// CDRMDbSession::ExportOrhanedCIDsL
+// Create and export the list of orphaned content id's
+//------------------------------------------------------------------------------
+void CDRMDbSession::ExportOrphanedCIDsL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::ExportOrphanedCIDsL" ) );
+    if( !iFileName )
+        {
+        aMessage.Complete( KErrNotReady );
+        return;
+        }
+
+    if( iFileName->Length() > aMessage.GetDesMaxLength(0) )
+        {
+        User::Leave(KErrArgument);
+        }
+
+    // It is virtually impossible to make WriteL to leave in this case,
+    // but anything is still possible...
+    IPCWRITE0L( *iFileName );
+
+    // if everything went well, delete the filename if not leave it
+    delete iFileName;
+    iFileName = NULL;
+
+    // All done
+    aMessage.Complete( KErrNone );
+
+    DRMLOG( _L( "CDRMDbSession::ExportOrphanedCIDsL: ok" ) );
+    };
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::UnwrapMacAndRekL
+// Unwraps public key encrypted MAC and REK keys
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::UnwrapMacAndRekL( const RMessage2& aMessage, TBool aDomainRo )
+    {
+    DRMLOG( _L( "CDRMDbSession::UnwrapMacAndRekL" ) );
+
+    __UHEAP_MARK;
+
+    MDrmKeyStorage* storage;
+    TBuf8<OmaCrypto::KMacSize> mac;
+    TBuf8<OmaCrypto::KKeySize> rek;
+    HBufC8* data = NULL;
+    TPtr8 dataPtr(0, 0);
+    TPtrC8 macAndRekPtr(0, 0);
+    HBufC8* riId = NULL;
+    TPtr8 riIdPtr(0, 0);
+    HBufC8* domainId = NULL;
+    TPtr8 domainIdPtr(0, 0);
+    CDRMRIContext* riContext = NULL;
+    TInt size = 0;
+    TKeyTransportScheme transport;
+    HBufC8* unwrappedMacAndRek = NULL;
+    CDRMDomainContext* domainContext;
+    HBufC8* domainKey = NULL;
+
+    DRMLOG(_L("CDRMDbSession::UnwrapMacAndRekL"));
+
+
+
+    SanitizeL( aMessage.GetDesLength(0) );
+    SanitizeL( aMessage.GetDesLength(1) );
+
+    size = User::LeaveIfError( IPCGETDESLEN0 );
+    data = HBufC8::NewLC( size );
+
+    size = User::LeaveIfError( IPCGETDESLEN1 );
+    riId = HBufC8::NewLC( size );
+
+    if(aDomainRo)
+        {
+        SanitizeL( aMessage.GetDesLength(2) );
+        size = User::LeaveIfError( IPCGETDESLEN2 );
+        domainId = HBufC8::NewLC( size );
+        }
+
+    dataPtr.Set( data->Des() );
+    IPCREAD0L( dataPtr );
+
+    riIdPtr.Set( riId->Des() );
+    IPCREAD1L( riIdPtr );
+
+    if(aDomainRo)
+        {
+        domainIdPtr.Set( domainId->Des() );
+        IPCREAD2L( domainIdPtr );
+        }
+
+    // The first byte defines the transport scheme
+    transport = static_cast<TKeyTransportScheme>(dataPtr[0]);
+    macAndRekPtr.Set(dataPtr.Mid(1));
+
+    DRMLOG2(_L("Transport scheme: %d"), transport);
+    DRMLOG(_L("MAC + REK:"));
+    DRMLOGHEX(macAndRekPtr);
+
+    if ( !iRoapClientConnected )
+        {
+        User::LeaveIfError( iRoapClient.Connect() );
+        iRoapClientConnected = ETrue;
+        }
+
+    if (!aDomainRo)
+        {
+        // get the trusted root from the rights issuer context
+        riContext = iRoapClient.GetRIContextL(riIdPtr);
+        if ( !riContext )
+            {
+            DRMLOG(_L("RI not registered"));
+            User::Leave(KErrRightsServerRiNotRegistered);
+            }
+        CleanupStack::PushL(riContext);
+        // connect to the storage of our PKI keys
+        storage = DrmKeyStorageNewL();
+        TCleanupItem storageCleanup( DeleteObject, storage );
+        CleanupStack::PushL(storageCleanup);
+        storage->SelectTrustedRootL(riContext->SelectedDeviceRoot());
+
+        if (transport == EOma)
+            {
+            OmaCrypto::RsaKemKwsDecryptL(storage, macAndRekPtr, rek, mac);
+            }
+        else
+            {
+            CmlaCrypto::CmlaIpDecryptL(transport, storage, macAndRekPtr, rek, mac);
+            }
+        CleanupStack::PopAndDestroy(4, data);
+        }
+    else
+        {
+        domainContext = iRoapClient.GetDomainContextL(domainIdPtr);
+        if ( !domainContext )
+            {
+            DRMLOG(_L("Domain not registered"));
+            User::Leave(KErrRightsServerDomainNotRegistered);
+            }
+        CleanupStack::PushL(domainContext);
+
+        // last three digits presents the domain generation
+        TInt generation = 0;
+        TLex8 lex( domainIdPtr.Right(3));
+        lex.Val(generation);
+
+        domainKey = domainContext->DomainKeyL(generation);
+        CleanupStack::PushL( domainKey );
+
+        // unwrap MAC and REK first with the domain key, the CEK with REK
+        unwrappedMacAndRek = OmaCrypto::AesUnwrapL(*domainKey, macAndRekPtr);
+        CleanupStack::PushL(unwrappedMacAndRek);
+
+        mac.Copy( unwrappedMacAndRek->Left( OmaCrypto::KKeySize) );
+        rek.Copy( unwrappedMacAndRek->Right( OmaCrypto::KKeySize) );
+        CleanupStack::PopAndDestroy(6, data);
+        }
+
+    DRMLOG(_L("REK:"));
+    DRMLOGHEX(rek);
+    DRMLOG(_L("MAC:"));
+    DRMLOGHEX(mac);
+
+    iMac.Copy(mac);
+    iRek.Copy(rek);
+
+    aMessage.Complete( KErrNone );
+
+    __UHEAP_MARKEND;
+
+    DRMLOG( _L( "CDRMDbSession::UnwrapMacAndRekL: ok" ) );
+    }
+
+//------------------------------------------------------------------------------
+// CDRMDbSession::FindParentsAndRemoveUnusableL()
+// Find the best ROs from aList and store references to aBest.
+//------------------------------------------------------------------------------
+void CDRMDbSession::FindParentsAndRemoveUnusableL( RDRMPermissionList& aList,
+                                                   const TDesC8& aURI,
+                                                   CDRMPointerArray<HBufC8>& aCids,
+                                                   const TIntent aIntent,
+                                                   const TTime& aDrmTime,
+                                                   TUint32& aReason )
+    {
+
+    CDRMPermissionList *permList = NULL;
+    TInt error = KErrNone;
+    HBufC8* uri = NULL;
+
+    aCids.ResetAndDestroy();
+
+
+    // to separate parents and children we store the content id, since the content id is needed
+    // by drm consume:
+    for( TInt count = 0; count < aList.Count(); count++ )
+        {
+        uri = aURI.AllocLC();
+        aCids.AppendL( uri );
+        CleanupStack::Pop( uri ); // uri
+        }
+
+
+    // Go though the list and remove the unusable RO's
+    for( TInt i = aList.Count() - 1 ; i >= 0; i-- )
+        {
+        // If the RO has valid parent rights add them to the list
+        if( aList[i]->iParentUID )
+            {
+            permList = CDRMPermissionList::NewLC();
+            permList->SetAutoCleanup( ETrue );
+
+            TRAP( error, DRMDB.GetDBEntryByContentIDL( *aList[i]->iParentUID, *permList ));
+            if( !error )
+                {
+                for( TInt j = 0; j < permList->Count(); j++ )
+                    {
+                    // check if the permission is valid and if the RI ID for child and parent
+                    // match
+                    if ( aList[i]->iRiId.Compare( (*permList)[j]->iRiId ) == 0 &&
+                        IsValidPermissionL( *(*permList)[j], aIntent, aDrmTime, aReason ) )
+                        {
+                        aList.AppendL( (*permList)[j] );
+                        (*permList)[j] = 0;
+                        uri = aList[i]->iParentUID->AllocLC();
+                        aCids.AppendL( uri );
+                        CleanupStack::Pop( uri );
+                        }
+                    }
+                }
+            CleanupStack::PopAndDestroy( permList );
+            }
+
+        // If the child is not valid remove it from the list
+        if ( !IsValidPermissionL( *aList[i], aIntent, aDrmTime, aReason ) )
+            {
+            CDRMPermission* perm = aList[i];
+            delete perm;
+            aList.Remove( i );
+
+            uri = aCids[i];
+            delete uri;
+            aCids.Remove( i );
+            perm = NULL;
+            uri = NULL;
+            }
+        }
+    // Now the list should contain only valid RO's or parents of the RO's
+    // which are valid
+    }
+
+
+//------------------------------------------------------------------------------
+// CDRMDbSession::FindBestROsL
+// Find the best ROs from aList and store references to aBest.
+//------------------------------------------------------------------------------
+TInt CDRMDbSession::FindBestROsL(
+    RDRMPermissionList& aList,
+    const TDesC8& aURI,
+    const TIntent aIntent,
+    HBufC8*& aUsedURI,
+    TUint32& aReason )
+    {
+    TTime time = Time::NullTTime();
+    CDRMPointerArray<HBufC8>* uriList = CDRMPointerArray<HBufC8>::NewLC();
+    uriList->SetAutoCleanup(ETrue);
+
+    TInt bestRo = -1;
+
+    if ( iSecureTime )
+        {
+        time = iTrustedTime;
+        }
+    else
+        {
+        time = Time::NullTTime();
+        }
+
+    FindParentsAndRemoveUnusableL( aList, aURI, *uriList, aIntent, time, aReason );
+
+    if( aList.Count() == 0 )
+        {
+        User::Leave(KErrCANoPermission);
+        }
+
+    bestRo = GetBestROL( aList, aIntent, aReason );
+
+    // Delete if it already exists
+    if( aUsedURI )
+        {
+        delete aUsedURI;
+        }
+    aUsedURI = NULL;
+
+    // if it's not the same as the normal URI return a value otherwise NULL
+    if( (*uriList)[ bestRo ]->Compare( aURI ) )
+        {
+        aUsedURI = (*uriList)[ bestRo ]->AllocL();
+        }
+
+    CleanupStack::PopAndDestroy( uriList );
+    return bestRo;
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::IsValidPermissionL
+// ETrue if not expired. If the candidate has expired permission (intent,
+// not top level), ETrue is returned if the child knows it is a child.
+// -----------------------------------------------------------------------------
+TBool CDRMDbSession::IsValidPermissionL(
+    CDRMPermission& aPermission,
+    const ContentAccess::TIntent aIntent,
+    const TTime& aTime,
+    TUint32& aReason )
+    {
+    CDRMConstraint* toplevel = NULL;
+    CDRMConstraint* constraint = NULL;
+    CDRMDomainContext* domainContext = NULL;
+    TBool r = ETrue;
+    #ifdef RD_DRM_METERING
+    CDRMRIContext* riContext = NULL;
+    #endif
+
+    toplevel = aPermission.TopLevelConstraint();
+    if ( toplevel && ( !( toplevel->Valid( aTime, IMSI, aReason ) ) ) )
+        {
+        r = EFalse;
+        }
+    else
+        {
+        constraint = aPermission.ConstraintForIntent( aIntent );
+        if ( !constraint || constraint &&
+            ( !( constraint->Valid( aTime, IMSI, aReason ) ) ) )
+            {
+            r = EFalse;
+            }
+        else if ( aPermission.iDomainID )
+            {
+            if ( !iRoapClientConnected )
+                {
+                User::LeaveIfError( iRoapClient.Connect() );
+                iRoapClientConnected = ETrue;
+                }
+            domainContext = iRoapClient.GetDomainContextL( *aPermission.iDomainID );
+            if ( domainContext )
+                {
+                delete domainContext;
+                }
+            else
+                {
+                r = EFalse;
+                }
+
+            }
+
+        // If the constraint is software constrained and the sw secureid does not match
+        // remove it from the list handling
+        if( r && aPermission.SoftwareConstrained() )
+            {
+            _LIT_SECURITY_POLICY_S0(swSidCheck, constraint->iSecureId.iUid);
+            if (constraint->iActiveConstraints & EConstraintSoftware)
+                {
+                if (!swSidCheck().CheckPolicy(iClient))
+                    {
+                    r = EFalse;
+                    }
+                }
+            }
+        }
+
+    #ifdef RD_DRM_METERING
+
+    // Check if metering restricts the content usage
+    if ( r != EFalse && constraint->iDrmMeteringInfo &&
+        !constraint->iDrmMeteringInfo->iAllowUseWithoutMetering )
+        {
+        if ( !iRoapClientConnected )
+            {
+            User::LeaveIfError( iRoapClient.Connect() );
+            iRoapClientConnected = ETrue;
+            }
+        riContext = iRoapClient.GetRIContextL( aPermission.iRiId );
+        if ( !riContext || !riContext->IsMeteringAllowed() )
+            {
+            aReason |= EConstraintMetering;
+            return EFalse;
+            }
+        }
+
+    delete riContext;
+
+    #endif
+
+    return r;
+    }
+
+//------------------------------------------------------------------------------
+// CDRMDbSession::GetBestROL
+// Find the best ROs from aList and store references to aBest.
+//------------------------------------------------------------------------------
+TInt CDRMDbSession::GetBestROL(
+    RDRMPermissionList& aList,
+    const TIntent aIntent,
+    TUint32& aReason )
+    {
+    TInt count( 0 );
+    TTime time;
+
+    CDRMConstraint* normalized = CDRMConstraint::NewLC();
+    CDRMConstraint* bestOne = CDRMConstraint::NewLC();
+
+    TInt bestRo( -1 );
+
+    if ( iSecureTime )
+        {
+        time = iTrustedTime;
+        }
+    else
+        {
+        time = Time::NullTTime();
+        }
+
+    // 'count' is updated if something useful is found, and aList is
+    // updated if the permission cannot be used.
+    while  ( count < aList.Count() )
+        {
+        CDRMPermission* perm = aList[ count ];
+        TBool found( EFalse );
+
+        // If there is no constraint for the intent, there is no need to normalize
+        // There can be no rights to use in that permission
+        if( perm->ConstraintForIntent( aIntent ) )
+            {
+            Normalize( *perm, *normalized, aIntent );
+            if ( normalized->Valid( time, IMSI, aReason ) )
+                {
+                found = ETrue;
+                }
+            }
+
+        if ( found )
+            {
+            // Compare whether "normalized" is more suitable than "bestOne".
+            // If this is the first usable child & parent combination,
+            // take it.
+            if ( ( bestRo < 0 ) || BetterPermission( *normalized, *bestOne ) )
+                {
+                // "normalized" is the new "bestOne"
+                CDRMConstraint* temp = bestOne;
+                bestOne = normalized;
+                normalized = temp;
+
+                bestRo = count;
+
+                ++count;
+                }
+            else
+                {
+                // This isn't any better than the previous ones. Throw it away.
+                found = EFalse;
+                }
+            }
+
+        if ( !found )
+            {
+            // Unusable child.
+            delete perm; perm = NULL;
+            aList.Remove( count );
+            }
+        }
+
+    CleanupStack::PopAndDestroy( 2 ); // bestOne, normalized
+
+    return bestRo;
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::Normalize
+// Normalizes a permission.
+// -----------------------------------------------------------------------------
+void CDRMDbSession::Normalize( CDRMPermission& aPermission,
+                               CDRMConstraint& aNormalized,
+                               const ContentAccess::TIntent aIntent )
+    {
+    __ASSERT_DEBUG( aPermission.ConstraintForIntent( aIntent ), User::Invariant() );
+
+    TRAPD( error, aNormalized.DuplicateL( *( aPermission.ConstraintForIntent( aIntent ) ) ) );
+    if( !error )
+        {
+        if ( aPermission.TopLevelConstraint() )
+            {
+            aNormalized.Merge( *( aPermission.TopLevelConstraint() ) );
+            }
+        }
+    }
+// -----------------------------------------------------------------------------
+// CDRMDbSession::BetterPermission
+// Compares two permissions, and returns ETrue if aNewOne is more suitable
+// for the usage. Assumes both are valid, i.e. not expired.
+// -----------------------------------------------------------------------------
+TBool CDRMDbSession::BetterPermission( const CDRMConstraint& aNewOne,
+                                       const CDRMConstraint& aOldOne )
+    {
+    // Check Order:
+    // 1. Full
+    // 2. Start End, closest end time first
+    // 3. Interval, shortest first
+    // 4. Accumulated, shortest first
+    // 5. Timed Counter, least counters first, longest time first
+    // 6. Counter, least counters first or the first one found
+
+    const TTime nullTime = Time::NullTTime();
+    TTime oldTime = nullTime;
+    TTime newTime = nullTime;
+    TTime oldTimePos = nullTime;
+    TTime newTimePos = nullTime;
+
+    // 1. Full
+    // If the old or new one is the ultimate one, don't bother to
+    // check anything else.
+    if ( aOldOne.iActiveConstraints == EConstraintNone )
+        {
+        return EFalse;
+        }
+
+    if ( aNewOne.iActiveConstraints == EConstraintNone )
+        {
+        return ETrue;
+        }
+
+    // 2. Start & End Time
+    // Choose the one with the closest end time first
+    // All RO's to this check are already checked to be valid
+    // ActiveIntervals Also hit this spot
+
+    // First get the start and end times from the intervals if they are active or inactive:
+    if ( aOldOne.iActiveConstraints & EConstraintInterval )
+        {
+        if( aOldOne.iIntervalStart == nullTime )
+            {
+            oldTimePos = iTrustedTime;
+            oldTimePos += TTimeIntervalSeconds( aOldOne.iInterval );
+            }
+        else
+            {
+            oldTime = aOldOne.iIntervalStart;
+            oldTime += TTimeIntervalSeconds( aOldOne.iInterval );
+            }
+        }
+
+    if( aNewOne.iActiveConstraints & EConstraintInterval )
+        {
+        if( aNewOne.iIntervalStart == nullTime )
+            {
+            newTimePos = iTrustedTime;
+            newTimePos += TTimeIntervalSeconds( aNewOne.iInterval );
+            }
+        else
+            {
+            newTime = aNewOne.iIntervalStart;
+            newTime += TTimeIntervalSeconds( aNewOne.iInterval );
+            }
+        }
+
+    if ( aOldOne.iActiveConstraints & EConstraintEndTime || oldTime != nullTime )
+        {
+        oldTime = EndTime( oldTime, aOldOne.iEndTime );
+
+        if ( aNewOne.iActiveConstraints & EConstraintEndTime || newTime != nullTime )
+            {
+            newTime = EndTime( newTime, aNewOne.iEndTime );
+
+            if( newTime != oldTime )
+                {
+                return ( newTime < oldTime );
+                }
+            }
+        else
+            {
+            return EFalse;
+            }
+        }
+    else if ( aNewOne.iActiveConstraints & EConstraintEndTime || newTime != nullTime )
+        {
+        return ETrue;
+        }
+
+
+    // 3. Inactive Intervals:
+    // Choose the one with the interval ending first:
+    // Continue here if the no SE's exist or SE's are the same
+    if( aOldOne.iActiveConstraints & EConstraintInterval )
+        {
+        if( aNewOne.iActiveConstraints & EConstraintInterval )
+            {
+            oldTimePos = EndTime( oldTime, oldTimePos );
+            newTimePos = EndTime( newTime, newTimePos );
+
+            if( oldTimePos != newTimePos )
+                {
+                return ( newTimePos < oldTimePos );
+                }
+            }
+        else
+            {
+            if( aNewOne.iActiveConstraints & EConstraintAccumulated ||
+                aNewOne.iActiveConstraints & EConstraintTimedCounter ||
+                aNewOne.iActiveConstraints & EConstraintCounter )
+                {
+                return EFalse;
+                }
+            else
+                {
+                return ETrue;
+                }
+            }
+        }
+    else if( aNewOne.iActiveConstraints & EConstraintInterval )
+        {
+        if( aOldOne.iActiveConstraints & EConstraintAccumulated ||
+            aOldOne.iActiveConstraints & EConstraintTimedCounter ||
+            aOldOne.iActiveConstraints & EConstraintCounter )
+            {
+            return ETrue;
+            }
+        else
+            {
+            return EFalse;
+            }
+        }
+
+    // 4. Accumulated:
+    // Choose the shortest accumulated first
+    // Continue here if SE's or intervals do not exist or they are the same
+    if( aOldOne.iActiveConstraints & EConstraintAccumulated )
+        {
+        if( aNewOne.iActiveConstraints & EConstraintAccumulated )
+            {
+            if( aNewOne.iAccumulatedTime != aOldOne.iAccumulatedTime )
+                {
+                return ( aNewOne.iAccumulatedTime < aOldOne.iAccumulatedTime );
+                }
+            }
+        else
+            {
+            if( aNewOne.iActiveConstraints & EConstraintTimedCounter ||
+                aNewOne.iActiveConstraints & EConstraintCounter )
+                {
+                return EFalse;
+                }
+            else
+                {
+                return ETrue;
+                }
+            }
+        }
+    else if( aNewOne.iActiveConstraints & EConstraintAccumulated )
+        {
+        if( aOldOne.iActiveConstraints & EConstraintTimedCounter ||
+            aOldOne.iActiveConstraints & EConstraintCounter )
+            {
+            return ETrue;
+            }
+        else
+            {
+            return EFalse;
+            }
+        }
+
+
+    // 5. Timed Counter
+    // Choose the one with least counters first. If there is an equal number of counters
+    // left, use the one with the longest time
+    // Continue here if SE's or intervals or accumulateds do not exist or they are the same
+    if( aOldOne.iActiveConstraints & EConstraintTimedCounter )
+        {
+        if( aNewOne.iActiveConstraints & EConstraintTimedCounter )
+            {
+            if( aNewOne.iTimedCounter == aOldOne.iTimedCounter )
+                {
+                if( aNewOne.iTimedInterval != aOldOne.iTimedInterval )
+                    {
+                    return ( aNewOne.iTimedInterval < aOldOne.iTimedInterval );
+                    }
+                else
+                    {
+                    if( aNewOne.iActiveConstraints & EConstraintCounter )
+                        {
+
+                        }
+                    }
+                }
+            else
+                {
+                return ( aNewOne.iTimedCounter < aOldOne.iTimedCounter );
+                }
+
+            }
+        else
+            {
+            if( aNewOne.iActiveConstraints & EConstraintCounter )
+                {
+                return EFalse;
+                }
+            else
+                {
+                return ETrue;
+                }
+            }
+        }
+    else if( aNewOne.iActiveConstraints & EConstraintTimedCounter )
+        {
+        if( aOldOne.iActiveConstraints & EConstraintCounter )
+            {
+            return ETrue;
+            }
+        else
+            {
+            return EFalse;
+            }
+        }
+
+    // 6. Counter
+    // Choose the one with least counters:
+    // if they are the same choose the first one.
+    // Continue here if SE's or intervals or accumulateds or timed counters
+    // do not exist or they are the same
+    if( aOldOne.iActiveConstraints & EConstraintCounter )
+        {
+        if( aNewOne.iActiveConstraints & EConstraintCounter )
+            {
+            return ( aNewOne.iCounter < aOldOne.iCounter );
+            }
+        else
+            {
+            return ETrue;
+            }
+        }
+
+    // If all else fails use the old one:
+    return EFalse;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::BetterPermission
+// Compares two permissions, and returns ETrue if aNewOne is more suitable
+// for the usage. Assumes both are valid, i.e. not expired.
+// -----------------------------------------------------------------------------
+TBool BetterPermissionOld( const CDRMConstraint& aNewOne,
+    const CDRMConstraint& aOldOne ) //const
+    {
+
+    const TTime nullTime = Time::NullTTime();
+    TTime oldTime = nullTime;
+    TTime newTime = nullTime;
+    TBool inactiveIntervals = EFalse;
+
+    // If the old or new one is the ultimate one, don't bother to
+    // check anything else.
+    if ( aOldOne.iActiveConstraints == EConstraintNone )
+        {
+        return EFalse;
+        }
+
+    if ( aNewOne.iActiveConstraints == EConstraintNone )
+        {
+        return ETrue;
+        }
+
+    // If old one has count constraints but the new doesn't, the new
+    // is better. If the old one doesn't have counters but the
+    // new has, the old one is better.
+    if ( aOldOne.iActiveConstraints & EConstraintCounter )
+        {
+        if ( !( aNewOne.iActiveConstraints & EConstraintCounter ) ||
+             ( aNewOne.iCounter < aOldOne.iCounter ) )
+            {
+            return ETrue;
+            }
+        }
+    else
+        {
+        if ( aNewOne.iActiveConstraints & EConstraintCounter )
+            {
+            return EFalse;
+            }
+        }
+
+    if ( aOldOne.iActiveConstraints & EConstraintTimedCounter )
+        {
+        if ( !( aNewOne.iActiveConstraints & EConstraintTimedCounter ) ||
+             ( aNewOne.iTimedCounter < aOldOne.iTimedCounter ) )
+            {
+            return ETrue;
+            }
+        }
+    else
+        {
+        if ( aNewOne.iActiveConstraints & EConstraintTimedCounter )
+            {
+            return EFalse;
+            }
+        }
+
+    if ( aOldOne.iActiveConstraints & EConstraintAccumulated )
+        {
+        if ( !( aNewOne.iActiveConstraints & EConstraintAccumulated ) ||
+             ( aNewOne.iAccumulatedTime < aOldOne.iAccumulatedTime ) )
+            {
+            return ETrue;
+            }
+        }
+    else
+        {
+        if ( aNewOne.iActiveConstraints & EConstraintAccumulated )
+            {
+            return EFalse;
+            }
+        }
+
+    // - No intervals is better than inactive intervals.
+    // - No intervals compared to activated interval goes to
+    //   end time constraint comparison.
+    // - Activated interval is better than inactive interval.
+    // - Two inactive intervals go to end time constraint comparison.
+    if ( aOldOne.iActiveConstraints & EConstraintInterval )
+        {
+        if ( aNewOne.iActiveConstraints & EConstraintInterval )
+            {
+            if ( aOldOne.iIntervalStart == nullTime )
+                {
+                if ( aNewOne.iIntervalStart != nullTime )
+                    {
+                    return ETrue;
+                    }
+
+                // Both have inactive intervals.
+                inactiveIntervals = ETrue;
+
+//                oldTime = iTrustedTime;
+                oldTime += TTimeIntervalSeconds( aOldOne.iInterval );
+
+//                newTime = iTrustedTime;
+                newTime += TTimeIntervalSeconds( aNewOne.iInterval );
+                }
+            else
+                {
+                // Old one has activated interval.
+                if ( aNewOne.iIntervalStart == nullTime )
+                    {
+                    return EFalse;
+                    }
+
+                // Both have activated intervals.
+                oldTime = aOldOne.iIntervalStart;
+                oldTime += TTimeIntervalSeconds( aOldOne.iInterval );
+
+                newTime = aNewOne.iIntervalStart;
+                newTime += TTimeIntervalSeconds( aNewOne.iInterval );
+                }
+            }
+        else
+            {
+            // No intervals in the new one.
+            if ( aOldOne.iIntervalStart == nullTime )
+                {
+                return ETrue;
+                }
+
+            oldTime = aOldOne.iIntervalStart;
+            oldTime += TTimeIntervalSeconds( aOldOne.iInterval );
+            }
+        }
+    else
+        {
+        // The old one doesn't have intervals.
+        if ( aNewOne.iActiveConstraints & EConstraintInterval )
+            {
+            if ( aNewOne.iIntervalStart == nullTime )
+                {
+                return EFalse;
+                }
+
+            newTime = aNewOne.iIntervalStart + TTimeIntervalSeconds( aNewOne.iInterval );
+            }
+        }
+
+    if ( inactiveIntervals )
+        {
+        // The one with end time goes first.
+        if ( aOldOne.iActiveConstraints & EConstraintEndTime )
+            {
+            if ( aNewOne.iActiveConstraints & EConstraintEndTime )
+                {
+                oldTime = EndTime( oldTime, aOldOne.iEndTime );
+                newTime = EndTime( newTime, aNewOne.iEndTime );
+
+                return ( newTime < oldTime );
+                }
+
+            return EFalse;
+            }
+
+        if( aNewOne.iActiveConstraints & EConstraintEndTime )
+            {
+            return ETrue;
+            }
+
+        // Both have just inactive intervals.
+        return ( newTime < oldTime );
+        }
+
+    // Check end times and/or activated intervals.
+    if ( aOldOne.iActiveConstraints & EConstraintEndTime || oldTime != nullTime )
+        {
+        oldTime = EndTime( oldTime, aOldOne.iEndTime );
+
+        if ( aNewOne.iActiveConstraints & EConstraintEndTime || newTime != nullTime )
+            {
+            newTime = EndTime( newTime, aNewOne.iEndTime );
+
+            return ( newTime < oldTime );
+            }
+
+        // The new one doesn't have end time constraint and/or activated intervals.
+        return EFalse;
+        }
+
+    if ( aNewOne.iActiveConstraints & EConstraintEndTime || newTime != nullTime )
+        {
+        return ETrue;
+        }
+
+    // Start time does not expire, so let's keep the old one.
+
+    return EFalse;
+    }
+
+
+// ----------------------------------------------------------------------------
+// UnwrapProtectedCekL
+// Unwraps the protected CEK aProtectedCek. Caller owns the returned buffer.
+// ----------------------------------------------------------------------------
+//
+HBufC8* CDRMDbSession::UnwrapProtectedCekL(
+    const TDesC8& aProtectedCek )
+    {
+    MDrmKeyStorage* storage;
+    TBuf8<OmaCrypto::KMacSize> mac;
+    TBuf8<OmaCrypto::KKeySize> rek;
+    HBufC8* cek = NULL;
+    TPtrC8 macAndRek(0, 0);
+    TPtrC8 wrappedCek(0, 0);
+    TKeyTransportScheme transport;
+    TBuf8<KRiIdSize> rightsIssuer;
+    CDRMRIContext* riContext = NULL;
+    TInt i;
+    TInt len;
+
+    DRMLOG(_L("CDRMDbSession::UnwrapProtectedCekL"));
+
+    // first element: one byte for the transport scheme
+    i = 0;
+    transport = static_cast<TKeyTransportScheme>(aProtectedCek[i]);
+    i++;
+
+    DRMLOG2(_L("Transport scheme: %d"), transport);
+
+    // second element: the concatenated MAC and REK wrapped with the KEK
+    len = aProtectedCek[i];
+    macAndRek.Set(aProtectedCek.Mid(i + 1, len));
+    i = i + 1 + len;
+    DRMLOG(_L("MAC + REK:"));
+    DRMLOGHEX(macAndRek);
+
+    // third element: 20 bytes with the rights issuer ID
+    len = aProtectedCek[i];
+    rightsIssuer.Copy(aProtectedCek.Mid(i + 1, len));
+    i = i + 1 + len;
+    DRMLOG(_L("RI ID:"));
+    DRMLOGHEX(rightsIssuer);
+
+    // get the trusted root from the rights issuer context
+    if ( !iRoapClientConnected )
+        {
+        User::LeaveIfError( iRoapClient.Connect() );
+        iRoapClientConnected = ETrue;
+        }
+    riContext = iRoapClient.GetRIContextL(rightsIssuer);
+    if ( !riContext )
+        {
+        DRMLOG(_L("RI not registered"));
+        User::Leave(KErrRightsServerRiNotRegistered);
+        }
+    CleanupStack::PushL(riContext);
+
+    // connect to the storage of our PKI keys
+    storage = DrmKeyStorageNewL();
+    TCleanupItem storageCleanup( DeleteObject, storage );
+    CleanupStack::PushL(storageCleanup);
+    storage->SelectTrustedRootL(riContext->SelectedDeviceRoot());
+
+    if (transport == EOma)
+        {
+        OmaCrypto::RsaKemKwsDecryptL(storage, macAndRek, rek, mac);
+        }
+    else
+        {
+        CmlaCrypto::CmlaIpDecryptL(transport, storage, macAndRek, rek, mac);
+        }
+
+    DRMLOG(_L("REK:"));
+    DRMLOGHEX(rek);
+    DRMLOG(_L("MAC:"));
+    DRMLOGHEX(mac);
+
+    iMac.Copy(mac);
+    iRek.Copy(rek);
+
+    // fourth element: 24 bytes for the CEK (wrapped with the REK),
+    // this can be empty, e.g. for a parent RO (indicated by a zero length)
+    len = aProtectedCek[i];
+    if (len > 0)
+        {
+        wrappedCek.Set(aProtectedCek.Mid(i + 1, len));
+        DRMLOG(_L("Wrapped CEK:"));
+        DRMLOGHEX(wrappedCek);
+        cek = OmaCrypto::AesUnwrapL(rek, wrappedCek);
+        DRMLOG(_L("CEK:"));
+        DRMLOGHEX(( *cek ));
+        }
+    else
+        {
+        DRMLOG(_L("No CEK"));
+        cek = KNullDesC8().AllocL();
+        }
+
+    CleanupStack::PopAndDestroy(2); // riContext, storageCleanup
+    return cek;
+    }
+
+// ----------------------------------------------------------------------------
+// UnwrapDomainCekL
+// Unwraps CEK with is wrapped with a domain key. Caller owns the returned
+// buffer.
+// ----------------------------------------------------------------------------
+//
+HBufC8* CDRMDbSession::UnwrapDomainCekL(
+    const TDesC8& aProtectedCek,
+    const TDesC8& aDomainId )
+    {
+    HBufC8* unwrappedMacAndRek = NULL;
+    HBufC8* cek = NULL;
+    TPtrC8 macAndRek(0, 0);
+    TPtrC8 wrappedCek(0, 0);
+    CDRMDomainContext* domainContext;
+    HBufC8* domainKey = NULL;
+    TInt i;
+    TInt len;
+
+    DRMLOG(_L("CDRMDbSession::UnwrapDomainCekL"));
+
+    // first element (one byte for the transport scheme) is ignored
+    i = 1;
+
+    // second element: MAC and REK wrapped with the domain key (40 bytes)
+    len = aProtectedCek[i];
+    macAndRek.Set(aProtectedCek.Mid(i + 1, len));
+    i = i + 1 + len;
+    DRMLOG(_L("MAC + REK:"));
+    DRMLOGHEX(macAndRek);
+
+    // third element: 20 bytes with the rights issuer ID, is ignored
+    len = aProtectedCek[i];
+    i = i + 1 + len;
+
+    // fourth element: 24 bytes for the CEK (wrapped with the REK)
+    len = aProtectedCek[i];
+    wrappedCek.Set(aProtectedCek.Mid(i + 1, len));
+    DRMLOG(_L("Wrapped CEK:"));
+    DRMLOGHEX(wrappedCek);
+
+    // get the domain key from the domain context
+    if ( !iRoapClientConnected )
+        {
+        User::LeaveIfError( iRoapClient.Connect() );
+        iRoapClientConnected = ETrue;
+        }
+    domainContext = iRoapClient.GetDomainContextL(aDomainId);
+    if ( !domainContext )
+        {
+        DRMLOG(_L("Domain not registered"));
+        User::Leave(KErrRightsServerDomainNotRegistered);
+        }
+    CleanupStack::PushL(domainContext);
+
+    // last three digits presents the domain generation
+    TInt generation = 0;
+    TLex8 lex( aDomainId.Right(3));
+    lex.Val(generation);
+
+    domainKey = domainContext->DomainKeyL(generation);
+    CleanupStack::PushL( domainKey );
+
+    // unwrap MAC and REK first with the domain key, the CEK with REK
+    unwrappedMacAndRek = OmaCrypto::AesUnwrapL(*domainKey, macAndRek);
+    CleanupStack::PushL(unwrappedMacAndRek);
+    cek = OmaCrypto::AesUnwrapL(unwrappedMacAndRek->Right(
+            OmaCrypto::KKeySize), wrappedCek);
+    iMac.Copy( unwrappedMacAndRek->Left( OmaCrypto::KKeySize) );
+    CleanupStack::PopAndDestroy(3); // unwrappedMacAndRek, domainKey, domainContext
+
+    return cek;
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::VerifyCredentials
+// Check if the client has enough credentials to grant access to later
+// decryption.
+// ----------------------------------------------------------------------------
+//
+TInt CDRMDbSession::VerifyCredentials(
+    HBufC8* aContentId,
+    CDRMPermission* aPermission,
+    TIntent aIntent)
+    {
+    CDRMConstraint* constraint = NULL;
+    _LIT_SECURITY_POLICY_C1(drmCheck, ECapabilityDRM);
+    _LIT_SECURITY_POLICY_V0(vidCheck, VID_DEFAULT); // Check Default VID
+    RPointerArray<CDRMPermission> permissions;
+    TInt r = KErrAccessDenied;
+    TBool hasOma2Permissions = EFalse;
+    TBool hasSoftwareConstraints = EFalse;
+    TInt i;
+
+    __UHEAP_MARK;
+    // Get the applicable permission, and check if there are OMA 2 permissions or
+    // software constraints
+    if (aPermission)
+        {
+        constraint = aPermission->ConstraintForIntent(aIntent);
+        }
+    if ( aContentId )
+        {
+        TRAP_IGNORE( DRMDB.GetDBEntryByContentIDL(*aContentId, permissions) );
+        for (i = 0; i < permissions.Count(); i++)
+            {
+            if (permissions[i]->iRightsObjectVersion.iVersionMain == EOma2Rights ||
+                permissions[i]->iRightsObjectVersion.iVersionMain == ECmlaRights)
+                {
+                hasOma2Permissions = ETrue;
+                }
+            if (permissions[i]->SoftwareConstrained())
+                {
+                hasSoftwareConstraints = ETrue;
+                }
+            }
+        permissions.ResetAndDestroy();
+        permissions.Close();
+        }
+
+    // First, check for DRM capability, access granted only if there are no software
+    // constraints.
+    if (drmCheck().CheckPolicy(iClient) && !hasSoftwareConstraints)
+        {
+        r = KErrNone;
+        }
+
+    // If a permission is given, check for license manager cases as well as
+    // OMA DRM 1.0 case
+    if ( r != KErrNone && aPermission )
+        {
+        // Fallback: Check if the vendor ID is the default vendor ID,
+        // allow access for OMA DRM 1.0 rights
+        if ((aPermission->iRightsObjectVersion.iVersionMain == EOma1Rights &&
+             vidCheck().CheckPolicy(iClient)))
+            {
+            r = KErrNone;
+            }
+
+        // Check the software constraint, this can override the fallback above!
+        if ( constraint )
+            {
+            _LIT_SECURITY_POLICY_S0(swSidCheck, constraint->iSecureId.iUid);
+            _LIT_SECURITY_POLICY_V0(swVidCheck, constraint->iVendorId.iUid);
+            if (constraint->iActiveConstraints & EConstraintVendor)
+                {
+                if (swVidCheck().CheckPolicy(iClient))
+                    {
+                    r = KErrNone;
+                    }
+                else
+                    {
+                    r = KErrAccessDenied;
+                    }
+                }
+            if (constraint->iActiveConstraints & EConstraintSoftware)
+                {
+                if (swSidCheck().CheckPolicy(iClient))
+                    {
+                    r = KErrNone;
+                    }
+                else
+                    {
+                    r = KErrAccessDenied;
+                    }
+                }
+            }
+
+        }
+
+    // Application installer needs to be able to use the content even if it has SW constraints
+    _LIT_SECURITY_POLICY_S0(swSidCheck2, KAppInstSrv);
+
+    if( swSidCheck2().CheckPolicy(iClient) && hasSoftwareConstraints )
+        {
+        r = KErrNone;
+        }
+
+
+    // Check if access can be granted when only
+    // OMA DRM 1.0 permissions are currently available, and the client
+    // has the default vendor ID
+    if ( r != KErrNone && !hasOma2Permissions &&
+        !hasSoftwareConstraints && vidCheck().CheckPolicy( iClient ) )
+        {
+        r = KErrNone;
+        }
+    __UHEAP_MARKEND;
+
+    if ( r == KErrNone )
+        {
+        iCredentialsChecked = ECheckedAndAllowed;
+        }
+    else
+        {
+        iCredentialsChecked = ECheckedAndDenied;
+        }
+    return r;
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::RemoveInvalidPermissionsL
+// Remove all permissions where the domain context is not available
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::RemoveInvalidPermissionsL(
+    CDRMPermissionList* aList )
+    {
+    CDRMDomainContext* domainContext = NULL;
+    TInt i;
+    if ( !iRoapClientConnected )
+        {
+        User::LeaveIfError( iRoapClient.Connect() );
+        iRoapClientConnected = ETrue;
+        }
+    for ( i = aList->Count() - 1; i >= 0; i-- )
+        {
+        if ( (*aList)[i]->iDomainID )
+            {
+            domainContext = iRoapClient.GetDomainContextL(
+                *(*aList)[i]->iDomainID );
+            if ( domainContext )
+                {
+                delete domainContext;
+                }
+            else
+                {
+                aList->Remove( i );
+                }
+            }
+        }
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::SetNameL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::SetNameL" ) );
+    __UHEAP_MARK;
+
+    SanitizeL( aMessage.GetDesLength( 0 ) );
+    SanitizeL( aMessage.GetDesLength( 1 ) );
+
+    TInt namelength = User::LeaveIfError( IPCGETDESLEN1 );
+    HBufC8* cid = HBufC8::NewLC( IPCGETDESLEN0 );
+    HBufC* name = HBufC::NewLC( namelength > 0 ? namelength : 1 );
+    TPtr8 tmp( cid->Des() );
+
+    IPCREAD0L( tmp );
+    if ( namelength )
+        {
+        TPtr tmp2( name->Des() );
+        IPCREAD1L( tmp2 );
+        }
+
+    DRMDB.NameContentL( *cid, *name );
+
+    CleanupStack::PopAndDestroy( 2 );
+    __UHEAP_MARKEND;
+    aMessage.Complete( KErrNone );
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetNameL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::GetNameL" ) );
+    HBufC8* cid = NULL;
+    TPckgBuf< TInt > size( 0 );
+
+    // Cleanup.
+    if ( iWidePreparedData )
+        {
+        delete iWidePreparedData;
+        iWidePreparedData = NULL;
+        }
+
+    SanitizeL( aMessage.GetDesLength( 0 ) );
+    cid = HBufC8::NewLC( IPCGETDESLEN0 );
+    TPtr8 tmp( cid->Des() );
+    IPCREAD0L( tmp );
+
+    iWidePreparedData = DRMDB.ContentNameLC( *cid );
+
+    CleanupStack::Pop( iWidePreparedData );
+    CleanupStack::PopAndDestroy( cid );
+
+    size() = iWidePreparedData->Length();
+    if ( iWidePreparedData->Length() == 0 )
+        {
+        // Empty name --> not asked.
+        delete iWidePreparedData;
+        iWidePreparedData = NULL;
+        }
+
+    IPCWRITE1L( size );
+
+    aMessage.Complete( KErrNone );
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetWideDataL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSesion::GetWideDataL" ) );
+    if ( iWidePreparedData )
+        {
+        if( iWidePreparedData->Length() > aMessage.GetDesMaxLength(0) )
+            {
+            User::Leave(KErrArgument);
+            }
+
+        IPCWRITE0L( *iWidePreparedData );
+
+        delete iWidePreparedData;
+        iWidePreparedData = NULL;
+
+        aMessage.Complete( KErrNone );
+        return;
+        }
+
+    aMessage.Complete( KErrNotReady );
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::Cancel( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::Cancel" ) );
+    if ( iPendingRequest )
+        {
+        static_cast<CDRMActiveOperation*>(iPendingRequest)->Remove();
+        }
+
+    aMessage.Complete( KErrNone );
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetFLUriL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::GetFLUriL" ) );
+
+    TBuf8< KMaxOmaV1CIDLength > URI;
+
+    GetFlURI( URI );
+
+    if( URI.Length() > aMessage.GetDesMaxLength(0) )
+        {
+        User::Leave(KErrArgument);
+        }
+
+    IPCWRITE0L( URI );
+    aMessage.Complete( KErrNone );
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::EncodeRightsIssuerL( const RMessage2& aMessage )
+    {
+    __UHEAP_MARK;
+
+    DRMLOG( _L( "CRMDbSession::EncodeRightsIssuerL" ) );
+    TBuf8< KDCFKeySize > iv;
+    HBufC8* data( NULL );
+    HBufC8* tmp( NULL );
+    iv.SetLength( KDCFKeySize );
+
+    TInt size( User::LeaveIfError( IPCGETDESLEN0 ) );
+    TPtr8 des( NULL, 0, 0 );
+
+    if ( size < 1 )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    // Calculate the size. It could be retrieved also from GetDesMaxLength,
+    // but at least now we can be sure we won't panic in case of
+    // descriptor overflow.
+    size += KDCFKeySize - ( size % KDCFKeySize ); //padding
+    size += KDCFKeySize; //iv
+    size = ( size + 2 ) / 3 * 4; //base64
+    size += IMEI.Length();
+    size += KFLPrefixLength;
+
+    data = HBufC8::NewLC( size < KMaxOmaV1CIDLength ? KMaxOmaV1CIDLength : size );
+    des.Set( data->Des() );
+
+    GetFlURI( des );
+
+    tmp = DRMDB.GetDecryptionKeyL( *data );
+    CleanupStack::PushL( tmp );
+
+    // Get the data from client.
+    IPCREAD0L( des );
+    GenerateIVL( iv );
+
+    // Fits ok.
+    AesEncryptL( *tmp, iv, ETrue, des );
+
+    CleanupStack::PopAndDestroy( tmp );
+
+    // Fits ok.
+    des.Insert( 0, iv );
+
+    tmp = Base64EncodeL( *data );
+
+    __ASSERT_DEBUG( tmp->Length() + KFLPrefixLength + IMEI.Length() <= size,
+        User::Invariant() );
+
+    // Overwrite the original data.
+    des = KFLPrefix;
+    des.Append( IMEI );
+    des.Append( *tmp );
+
+    delete tmp;
+    tmp = NULL;
+
+    IPCWRITE0L( *data );
+
+    CleanupStack::PopAndDestroy( data );
+
+    aMessage.Complete( KErrNone );
+
+    __UHEAP_MARKEND;
+    }
+
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::DecodeRightsIssuerL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::DecodeRightsIssuerL" ) );
+    __UHEAP_MARK;
+
+    HBufC8* data( NULL );
+    TInt size( IPCGETDESLEN0 );
+    TPtr8 des( NULL, 0, 0 );
+
+    if ( !size )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    SanitizeL( size );
+
+    data = HBufC8::NewLC( size );
+    des.Set( data->Des() );
+
+    IPCREAD0L( des );
+
+    if ( des.Left( KFLPrefixLength ).Compare( KFLPrefix ) == 0 )
+        {
+        HBufC8* tmp( NULL );
+        HBufC8* tmp2( NULL );
+        TPtr8 des2( NULL, 0, 0 );
+
+        tmp = CnvUtfConverter::ConvertFromUnicodeToUtf8L( IMEI );
+        CleanupStack::PushL( tmp );
+
+        if ( des.Mid( KFLPrefixLength, IMEI.Length() ).Compare( *tmp ) )
+            {
+            User::Leave( KErrCANoPermission );
+            }
+
+        tmp2 = Base64DecodeL( des.Mid( KFLPrefixLength + tmp->Length() ) );
+
+        *data = *tmp2;
+
+        delete tmp2;
+        tmp2 = NULL;
+
+        CleanupStack::PopAndDestroy( tmp );
+
+        if ( ( data->Length() % KDCFKeySize ) ||
+             data->Length() < ( KDCFKeySize << 1 ) )
+            {
+            User::Leave( KErrArgument );
+            }
+
+        tmp = HBufC8::NewLC( KMaxOmaV1CIDLength );
+
+        des.Set( tmp->Des() );
+
+        GetFlURI( des );
+
+        tmp2 = DRMDB.GetDecryptionKeyL( *tmp );
+
+        CleanupStack::PopAndDestroy( tmp );
+        CleanupStack::PushL( tmp2 );
+
+        des2.Set( const_cast< TText8* >( data->Ptr() ),
+            KDCFKeySize,
+            KDCFKeySize );
+
+        // AesDecrypt overwrites the data.
+        des.Set( const_cast< TText8* >( data->Ptr() ) + KDCFKeySize,
+            data->Length() - KDCFKeySize,
+            data->Length() - KDCFKeySize );
+
+        AesDecryptL( *tmp2, des2, ETrue, des );
+
+        // Erase the key.
+        des2.Set( tmp2->Des() );
+        des2.FillZ();
+
+        CleanupStack::PopAndDestroy( tmp2 );
+
+        if( des.Length() > aMessage.GetDesMaxLength(1) )
+            {
+            User::Leave(KErrArgument);
+            }
+        IPCWRITE1L( des );
+        }
+
+    // Something else, can't handle it. Leave it as it is.
+    CleanupStack::PopAndDestroy( data );
+
+    aMessage.Complete( KErrNone );
+
+    __UHEAP_MARKEND;
+
+    DRMLOG( _L( "CDRMDbSession::DecodeRightsIssuerL ok" ) );
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetFlURI( TDes8& aURI )
+    {
+    aURI = KFLLongPrefix;
+    aURI.Append( IMEI );
+    aURI.Append( KFLSuffix );
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::AesEncryptL
+// Encrypt data using a given key
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::AesEncryptL( const TDesC8& aKey,
+                                 const TDesC8& aIV,
+                                 const TBool aAddPadding,
+                                 TDes8& aData )
+    {
+    DRMLOG( _L( "CDRMDbSession::AesEncryptL" ) );
+
+    __UHEAP_MARK;
+
+    CModeCBCEncryptor* cbc( NULL );
+    TInt lastBlockStart( 0 );
+    TPtr8 data( NULL, 0, 0 );
+
+    if( aIV.Length() % KDCFKeySize ||
+        aKey.Length() % KDCFKeySize )
+        {
+        User::Leave( KErrArgument );
+        }
+
+    cbc = CModeCBCEncryptor::NewL( CAESEncryptor::NewLC( aKey ), aIV );
+    CleanupStack::Pop(); // CAESEncryptor, owned by cbc.
+    CleanupStack::PushL( cbc );
+
+    lastBlockStart = aData.Length() - ( aData.Length() % KDCFKeySize );
+    for ( TInt i = 0; i  < lastBlockStart; i+= KDCFKeySize )
+        {
+        data.Set( aData.MidTPtr( i, KDCFKeySize ) );
+
+        cbc->Transform( data );
+        }
+
+    if ( aAddPadding )
+        {
+        TInt dataLength = aData.Length();
+        TUint8 padding( static_cast< TUint8 >
+            ( lastBlockStart + KDCFKeySize - dataLength ) );
+
+        __ASSERT_DEBUG( lastBlockStart + KDCFKeySize - dataLength <= KDCFKeySize,
+                        User::Invariant() );
+
+        aData.SetLength( lastBlockStart + KDCFKeySize );
+
+        for ( TInt i = dataLength; i < aData.Length(); ++i )
+            {
+            aData[ i ] = padding;
+            }
+
+        data.Set( aData.MidTPtr( lastBlockStart, KDCFKeySize ) );
+        cbc->Transform( data );
+        }
+
+    CleanupStack::PopAndDestroy( cbc );
+
+    __UHEAP_MARKEND;
+
+    DRMLOG( _L( "CDRMDbSession::AesEncryptL ok" ) );
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::AesDecryptL
+// Decrypt data using a given key
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::AesDecryptL( const TDesC8& aKey,
+                                 const TDesC8& aIV,
+                                 const TBool aRemovePadding,
+                                 TDes8& aData )
+    {
+    DRMLOG( _L( "CDRMDbSession::AesDecryptL" ) );
+
+    __UHEAP_MARK;
+
+    CModeCBCDecryptor* cbc( NULL );
+
+    cbc = CModeCBCDecryptor::NewL(
+        CAESDecryptor::NewLC( aKey ), aIV );
+
+    CleanupStack::Pop(); // CAESDecryptor
+
+    __ASSERT_DEBUG( ( aData.Length() >= 0 ) &&
+                    ( aData.Length() % KDCFKeySize == 0 ),
+                    User::Invariant() );
+
+    for ( TInt count = 0; count < aData.Length(); count += KDCFKeySize )
+        {
+        TPtr8 d( aData.MidTPtr( count, KDCFKeySize ) );
+
+        cbc->Transform( d );
+        }
+
+    delete cbc; cbc = NULL;
+
+    if ( aRemovePadding )
+        {
+        TInt count( aData.Length() );
+        TUint8 c( aData[ count - 1 ] );
+
+        if ( c > KDCFKeySize )
+            {
+            User::Leave( KErrCorrupt );
+            }
+
+        aData.SetLength( count - c );
+        }
+
+    __UHEAP_MARKEND;
+
+    DRMLOG( _L( "CDRMDbSession::AesDecryptL ok" ) );
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::GenerateIVL( TDes8& aIV )
+    {
+    DRMLOG( _L( "CDRMDbSession::GenerateIVL" ) );
+    __UHEAP_MARK;
+
+    __ASSERT_DEBUG( aIV.MaxSize() >= KDCFKeySize, User::Invariant() );
+    MDrmKeyStorage* storage = DrmKeyStorageNewL();
+    TCleanupItem storageCleanup( DeleteObject, storage );
+    CleanupStack::PushL(storageCleanup);
+
+    storage->RandomDataGetL(aIV,KDCFKeySize);
+    CleanupStack::PopAndDestroy( storage );
+
+    DRMLOG(_L("random aIV:"));
+    DRMLOGHEX(aIV);
+
+
+    __UHEAP_MARKEND;
+    DRMLOG( _L( "CDRMDbSession::GenerateIVL ok" ) );
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::AsyncOperationDone()
+    {
+    DRMLOG( _L( "CDRMDbSession::AsyncOperationDone" ) );
+    // All done.
+    delete iPendingRequest;
+    iPendingRequest = NULL;
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::
+//
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::AsyncOperationDone( TFileName* aFileName )
+    {
+    DRMLOG( _L( "CDRMDbSession::AsyncOperationDone" ) );
+    // All done.
+    delete iPendingRequest;
+    iPendingRequest = NULL;
+
+    iFileName = aFileName;
+    }
+
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::SetAuthenticationSeedL
+// Sets the authentication seed for a content ID. Requires that the REK and KEK
+// have been set during a previous AddRecord operation
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::SetAuthenticationSeedL( const RMessage2& aMessage )
+    {
+    DRMLOG(_L("CDRMDbSession::SetAuthenticationSeedL"));
+
+    __UHEAP_MARK;
+    SanitizeL( aMessage.GetDesLength(0));
+    SanitizeL( aMessage.GetDesLength(1));
+
+    HBufC8* cid = HBufC8::NewLC(IPCGETDESLEN0);
+    HBufC8* wrappedSeed = HBufC8::NewLC(IPCGETDESLEN1);
+    HBufC8* seed = NULL;
+
+    if (iRek.Length() == 0)
+        {
+        User::Leave(KErrNotReady);
+        }
+
+    TPtr8 tmp(cid->Des());
+    IPCREAD0L(tmp );
+    TPtr8 tmp2(wrappedSeed->Des());
+    IPCREAD1L(tmp2);
+
+    seed = OmaCrypto::AesUnwrapL(iRek, *wrappedSeed);
+    CleanupStack::PushL(seed);
+    DRMDB.SetAuthenticationSeedL(*cid, *seed);
+    CleanupStack::PopAndDestroy(3); // seed, wrappedSeed, cid
+    __UHEAP_MARKEND;
+    aMessage.Complete(KErrNone);
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::GetAuthenticationSeedL
+// Returns the authentication seed for a content ID
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetAuthenticationSeedL( const RMessage2& aMessage )
+    {
+    DRMLOG(_L("CDRMDbSession::GetAuthenticationSeedL"));
+
+    __UHEAP_MARK;
+    HBufC8* cid = NULL;
+    HBufC8* seed = NULL;
+
+    SanitizeL( aMessage.GetDesLength(0));
+    cid = HBufC8::NewLC(IPCGETDESLEN0);
+
+    TPtr8 tmp(cid->Des());
+    IPCREAD0L(tmp);
+    User::LeaveIfError(VerifyCredentials(cid, NULL, EUnknown));
+    seed = DRMDB.GetAuthenticationSeedL(*cid);
+    CleanupStack::PushL(seed);
+
+    if( seed->Length() > aMessage.GetDesMaxLength(1) )
+        {
+        User::Leave(KErrArgument);
+        }
+
+    IPCWRITE1L(*seed);
+    CleanupStack::PopAndDestroy(2); // seed, cid
+    __UHEAP_MARKEND;
+    aMessage.Complete(KErrNone);
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::VerifyMacL
+// Integrity protection for protecets ROs
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::VerifyMacL( const RMessage2& aMessage )
+    {
+    DRMLOG(_L("CDRMDbSession::VerifyMacL"));
+
+    if( !iMac.Length() )
+        {
+        User::Leave(KErrNotReady);
+        }
+
+    __UHEAP_MARK;
+
+    CHMAC* hMac = NULL;
+    CSHA1* sha = NULL;
+    TPtrC8 hmac_value( KNullDesC8 );
+    TPtrC8 sha1_value( KNullDesC8 );
+    HBufC8* signedInfo = NULL;
+    HBufC8* macValue = NULL;
+    TInt ret = KErrNone;
+
+    signedInfo = HBufC8::NewLC(IPCGETDESLEN0);
+    TPtr8 signedInfoPtr(signedInfo->Des());
+    macValue = HBufC8::NewLC(IPCGETDESLEN1);
+    TPtr8 macValuePtr(macValue->Des());
+
+    IPCREAD0L(signedInfoPtr);
+    IPCREAD1L(macValuePtr);
+
+    DRMLOG(_L("Signed info:"));
+    DRMLOGHEX(signedInfoPtr);
+    DRMLOG(_L("MAC value:"));
+    DRMLOGHEX(macValuePtr);
+
+    sha = CSHA1::NewL();
+    CleanupStack::PushL( sha );
+    hMac = CHMAC::NewL( iMac, sha );
+    CleanupStack::Pop( sha ); // sha is now owned by hMac
+    CleanupStack::PushL( hMac );
+    hMac->Update( signedInfoPtr );
+    hmac_value.Set( hMac->Final() );
+
+    DRMLOG(_L("Calculated MAC value:"));
+    DRMLOGHEX(hmac_value);
+    if ( hmac_value.Compare( macValuePtr ) != 0 )
+        {
+        // MAC validation failed
+        ret = KErrRightsServerMacFailed;
+        }
+
+    CleanupStack::PopAndDestroy(3, signedInfo); // hMac, macValue, signedInfo
+    __UHEAP_MARKEND;
+    aMessage.Complete(ret);
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::GetSupportedIndividualsL
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetSupportedIndividualsL( const RMessage2& aMessage )
+    {
+    DRMLOG( _L( "CDRMDbSession::GetSupportedIndividualsL" ) );
+    TPckgBuf< TInt > size( 0 );
+    TInt stringSize = 0;
+    TInt offset = 0;
+    TUint8* ptr = 0;
+
+    // Cleanup.
+    if ( iPreparedData )
+        {
+        delete iPreparedData;
+        iPreparedData = NULL;
+        }
+
+    for ( TInt i = 0; i < IMSI.Count(); i++ )
+        {
+        stringSize += sizeof(TInt);
+        stringSize += IMSI[i]->Size();
+        }
+
+
+    // If it's empty, just return right away
+    if( !stringSize )
+        {
+        IPCWRITE0L( size );
+        aMessage.Complete(KErrNone);
+        return;
+        }
+
+    // Otherwise create a buffer and fill it:
+    iPreparedData = HBufC8::NewMaxL( stringSize );
+    ptr = const_cast<TUint8*>( iPreparedData->Ptr() );
+
+    size() = stringSize;
+
+    for(  TInt i = 0; i < IMSI.Count(); i++ )
+        {
+        // Write the size:
+        stringSize = IMSI[i]->Size();
+        Mem::Copy(ptr+offset, &stringSize, sizeof(TInt));
+        offset += sizeof(TInt);
+
+        // Write the data:
+        Mem::Copy(ptr+offset, IMSI[i]->Ptr(), IMSI[i]->Size());
+        offset += IMSI[i]->Size();
+        }
+    IPCWRITE0L( size );
+
+    aMessage.Complete( KErrNone );
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::StopWatchingL
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::StopWatchingL( const RMessage2& aMessage )
+    {
+    _LIT_SECURITY_POLICY_S0( sidCheck, KTrustedShutdownClient );
+    if ( sidCheck.CheckPolicy( aMessage ) )
+        {
+        SERVER->StopWatchingL();
+        }
+    aMessage.Complete( KErrNone );
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::DeleteAllowedL
+// ----------------------------------------------------------------------------
+//
+TBool CDRMDbSession::DeleteAllowedL( const TDesC8& aContentId )
+    {
+    TBuf8< KMaxOmaV1CIDLength > URI;
+
+    // Get the FL uri
+    GetFlURI( URI );
+
+    if( aContentId.Compare( URI ) &&
+        aContentId.Compare( KDCMUri ) &&
+        aContentId.Compare( KLDFUri ) )
+        {
+        return ETrue;
+        }
+    return EFalse;
+    }
+
+// ----------------------------------------------------------------------------
+// CDRMDbSession::GetRandomDataL
+// ----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetRandomDataL( const RMessage2& aMessage )
+    {
+    DRMLOG(_L("CDRMDbSession::GetRandomDataL"));
+
+    HBufC8* data = NULL;
+    SanitizeL( aMessage.GetDesMaxLength(0) );
+    SanitizeL( aMessage.GetDesLength(0));
+
+    data = HBufC8::NewMaxLC(IPCGETDESLEN0);
+    TPtr8 ptr(data->Des());
+
+    MDrmKeyStorage* storage = DrmKeyStorageNewL();
+    TCleanupItem storageCleanup( DeleteObject, storage );
+    CleanupStack::PushL(storageCleanup);
+    storage->RandomDataGetL(ptr,ptr.Size());
+    IPCWRITE0L(*data);
+
+    CleanupStack::PopAndDestroy(2, data);
+    aMessage.Complete( KErrNone );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::GetMeteringDataL
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::GetMeteringDataL( const RMessage2& aMessage )
+    {
+#ifndef RD_DRM_METERING
+    aMessage.Complete ( KErrNotSupported );
+#else
+    HBufC8* riId = NULL;
+    HBufC8* meteringData = NULL;
+    CDRMPointerArray<CDrmMeteringDbData>* meteringArray =
+        CDRMPointerArray<CDrmMeteringDbData>::NewLC();
+    meteringArray->SetAutoCleanup( ETrue );
+
+    TInt size = 0;
+    TPtr8 data( NULL, 0 );
+    TPckg<TInt> package( size );
+
+    SanitizeL( aMessage.GetDesLength(0));
+    // Empty old data
+    delete iPreparedData;
+    iPreparedData = NULL;
+
+    riId = HBufC8::NewLC( User::LeaveIfError( IPCGETDESLEN1 ) );
+    data.Set( riId->Des() );
+    IPCREAD1L( data );
+
+    if ( METERINGDB.GetL( *riId, *meteringArray ) )
+        {
+        meteringData = CreateMeteringDataL( meteringArray );
+        CleanupStack::PushL( meteringData );
+        }
+    else
+        {
+        _LIT8( KEmptyMetering, "<rawMeteringReportData>\r\n</rawMeteringReportData>");
+        meteringData = KEmptyMetering().AllocLC();
+        }
+    DRMLOGHEX( *meteringData );
+    size = meteringData->Size();
+    iPreparedData = meteringData;
+    CleanupStack::Pop( meteringData );
+
+    IPCWRITE0L( package );
+    CleanupStack::PopAndDestroy( 2 ); // riId, meteringArray
+    if ( !iPreparedData )
+        {
+        aMessage.Complete( KErrNotFound );
+        return;
+        }
+    aMessage.Complete( KErrNone );
+#endif
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMDbSession::DeleteMeteringDataL
+// -----------------------------------------------------------------------------
+//
+void CDRMDbSession::DeleteMeteringDataL( const RMessage2& aMessage )
+    {
+#ifndef RD_DRM_METERING
+    aMessage.Complete ( KErrNotSupported );
+#else
+// Metering supported
+    HBufC8* riId = NULL;
+    TPtr8 data( NULL, 0 );
+    TBool meteringDataDeleted;
+
+    riId = HBufC8::NewLC( User::LeaveIfError( IPCGETDESLEN0 ) );
+    data.Set( riId->Des() );
+    IPCREAD0L( data );
+    meteringDataDeleted = METERINGDB.DeleteL( *riId );
+
+        if( meteringDataDeleted )
+            {
+            DRMLOG( _L("CDRMDbSession::DeleteMeteringDataL -> some records were destroyed") );
+            }
+    // Do we have to do something else?
+    CleanupStack::PopAndDestroy( riId );
+    aMessage.Complete( KErrNone );
+#endif
+    }
+// -----------------------------------------------------------------------------
+// CDRMDbSession::ConnectRoapClient()
+// -----------------------------------------------------------------------------
+//
+TInt CDRMDbSession::ConnectRoapClient()
+    {
+    if( iRoapClientConnected )
+        {
+        return KErrNone;
+        }
+    TInt err( iRoapClient.Connect() );
+    if ( !err )
+        {
+        iRoapClientConnected = ETrue;
+        }
+    return err;
+    }
+
+//  End of File