Adding parts of the DRM Engine to be rebuilt
authorTom Pritchard <tomp@symbian.org>
Wed, 27 Oct 2010 13:24:02 +0100
changeset 88 ca165d35976d
parent 87 e9fb2728ea8b
child 89 1650c5a7be8c
Adding parts of the DRM Engine to be rebuilt
breakdeps/DRMEngine/DRMClock.cpp
breakdeps/DRMEngine/DRMClock.h
breakdeps/DRMEngine/DRMRightsServer.cpp
breakdeps/DRMEngine/DrmStdKeyStorage.cpp
breakdeps/DRMEngine/DrmStdKeyStorage.mmp
breakdeps/DRMEngine/ROAPHandler.mmp
breakdeps/DRMEngine/RightsServer.mmp
breakdeps/DRMEngine/RoapEng.cpp
group/bld.inf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/breakdeps/DRMEngine/DRMClock.cpp	Wed Oct 27 13:24:02 2010 +0100
@@ -0,0 +1,402 @@
+/*
+* Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Implementation of the DRM Clock
+*
+*/
+
+
+// INCLUDE FILES
+
+#include <mmtsy_names.h>
+
+#include "DRMClock.h"
+#include "drmlog.h"
+#include "DRMEventTimeChange.h"
+#include "wmdrmfileserverclient.h"
+
+#include <DRMNotifier.h>
+#include <s32strm.h>
+#include <s32file.h>
+#include <e32property.h>
+#include <e32keys.h>
+
+#ifdef RD_MULTIPLE_DRIVE
+#include <driveinfo.h>
+#endif
+
+#include "DRMNitzObserver.h"
+#include "GPSWatcher.h"
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES  
+
+// CONSTANTS
+const TInt KMinuteInMicroseconds = 60000000;
+const TInt KTimeZoneIncrement = 15;
+ 
+// The time zones sanity check values, not sure if -13 hours exists
+// But atleast +13 does in: Nuku'Alofa
+const TInt KTimeZoneLow = -52; // -13 hours
+const TInt KTimeZoneHigh = 55; // +13 hours 45 minutes Some NZ owned island
+
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// FORWARD DECLARATIONS
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+
+// -----------------------------------------------------------------------------
+// CDRMRightsDB::CDRMRightsDB
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//    
+CDRMClock::CDRMClock()
+    {      
+    };
+
+// -----------------------------------------------------------------------------
+// CDRMRightsDB::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CDRMClock::ConstructL()
+    {
+    DRMLOG( _L( "DRM Clock Starting: " ) );
+    TInt error = KErrNone;
+
+    // Create a notifier instance
+    iNotifier = CDRMNotifier::NewL();
+        
+#ifndef __WINS__
+    ConnectToPhoneL();            
+            
+    iObserver = CDRMNitzObserver::NewL( iPhone, const_cast<CDRMClock*>(this));
+
+    iObserver->Start();
+    
+    TRAP( error, iGpsWatcher = CGPSWatcher::NewL( const_cast<CDRMClock*>(this) ));
+    DRMLOG2( _L("DRMClock: GPS watcher started: %d"), error );    
+#endif
+
+    DRMLOG( _L( "DRM Clock started" ) );		    
+    };
+
+// -----------------------------------------------------------------------------
+// CDRMClock::NewLC
+// Two-phased constructor
+// -----------------------------------------------------------------------------
+//
+CDRMClock* CDRMClock::NewLC()
+    {
+    DRMLOG( _L( "CDRMClock::NewLC" ) );
+    
+    CDRMClock* self = new(ELeave) CDRMClock;
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    
+    DRMLOG( _L( "CDRMClock::NewLC ok" ) );
+    
+    return self;
+    };
+
+// -----------------------------------------------------------------------------
+// CDRMClock::NewL
+// Two-phased constructor
+// -----------------------------------------------------------------------------
+//
+CDRMClock* CDRMClock::NewL()
+    {
+    DRMLOG( _L( "CDRMClock::NewL" ) );
+    
+    CDRMClock* self = NewLC();
+    CleanupStack::Pop();
+
+    DRMLOG( _L( "CDRMClock::NewL ok" ) );
+    
+    return self;
+    };
+  
+// ---------------------------------------------------------
+// CDRMClock::~CDRMClock
+// Destructor
+// ---------------------------------------------------------
+//
+CDRMClock::~CDRMClock()
+    { 
+    DRMLOG( _L( "CDRMClock::~CDRMClock" ) );
+       
+    if( iNotifier )
+        {
+        delete iNotifier;
+        iNotifier = 0;
+        }
+        
+#ifndef __WINS__
+    if(iObserver)            
+        {
+        iObserver->Cancel();
+        delete iObserver;
+        iObserver = 0;
+        }  
+        
+    if( iGpsWatcher )
+        {
+        iGpsWatcher->Cancel();
+        delete iGpsWatcher;
+        iGpsWatcher = 0;
+        }   
+#endif // __WINS__        
+    };
+
+// -----------------------------------------------------------------------------
+// CDRMClock::GetSecureTime
+// returns time and security level
+// -----------------------------------------------------------------------------
+//
+void CDRMClock::GetSecureTime(TTime& aTime, TInt& aTimeZone, 
+                              DRMClock::ESecurityLevel& aSecurityLevel)
+    {
+    DRMLOG( _L( "CDRMClock::GetSecureTime" ) );
+    
+    TTime currentUniversal;
+    TTime currentHome;
+    TInt error = KErrNone;
+    
+    // if there is an error it's not initialized
+    error = aTime.UniversalTimeSecure();
+    
+    if( error == KErrNoSecureTime )
+        {
+        currentHome.HomeTime();               
+        currentUniversal.UniversalTime();         
+        
+        aTimeZone = ( currentHome.Int64() - currentUniversal.Int64() ) / 
+                   ( KMinuteInMicroseconds* KTimeZoneIncrement );
+        
+        
+        aTime.UniversalTime();
+
+        aSecurityLevel = DRMClock::KInsecure; 
+       
+        DRMLOG( _L( "CDRMClock::GetSecureTime: DRMClock is Insecure" ) );        
+        }
+    else 
+        {
+        currentHome.HomeTimeSecure();        
+        currentUniversal.UniversalTimeSecure();
+        
+        aTimeZone = ( currentHome.Int64() - currentUniversal.Int64() ) / 
+                   ( KMinuteInMicroseconds* KTimeZoneIncrement );
+        
+        aSecurityLevel = DRMClock::KSecure;     
+        DRMLOG( _L( "CDRMClock::GetSecureTime: DRMClock is Secure" ) );  
+        }    
+
+    DRMLOG( _L( "CDRMClock::GetSecureTime ok" ) );
+    };
+
+
+// -----------------------------------------------------------------------------
+// CDRMClock::ResetSecureTimeL
+// resets the secure time and recalculates the offsets
+// should not reset to 0
+// -----------------------------------------------------------------------------
+//
+// Do not reset the timezone, use whatever has been set or retrieved from the UI time
+// However check that the timezone is a valid one just in case
+void CDRMClock::ResetSecureTimeL( const TTime& aTime, const TInt& aTimeZone )
+    {
+    DRMLOG( _L( "CDRMClock::ResetSecureTimeL" ) );
+   
+    TRequestStatus status;  
+    TInt error = KErrNone;  
+    CDRMEventTimeChange* change = CDRMEventTimeChange::NewLC();
+	TTime previousTime;
+	TTime previousTimeLocal;
+	TTime newTime;
+	TInt timezone = 0;
+	TDateTime temppi; // Only for logging
+
+    // check for param that the time is even reasonably valid:
+    if( aTime.Int64() == 0 )
+        {
+        DRMLOG( _L("Trying to reset to zero time") );             
+    	User::Leave( KErrArgument );
+        }
+    
+    // Sanity check: Time zone has to be +/- certail hours
+    // for this check -13h to +13.75h
+    if( aTimeZone < KTimeZoneLow || aTimeZone > KTimeZoneHigh )
+        {
+        DRMLOG2( _L("TimeZone invalid, time may be as well, aborting change: %d"), aTimeZone  );
+        User::Leave( KErrArgument );
+        }
+    
+    
+    // Get the current secure time with timezone
+    // Ask the hometime first so that rounding of any divider goes correctly
+    error = previousTimeLocal.HomeTimeSecure(); 
+    
+    // If there is an error, the secure hometime has not been set
+    // Which means that the UI clock has the valid data
+    if( error )
+        {
+        previousTimeLocal.HomeTime();
+        previousTime.UniversalTime();
+        timezone = ( previousTimeLocal.Int64() - previousTime.Int64() ) / 
+                   ( KMinuteInMicroseconds* KTimeZoneIncrement );
+		change->SetOldSecurityLevel( DRMClock::KInsecure );
+		}
+	else
+		{
+		previousTime.UniversalTimeSecure();		                   
+        
+        timezone = ( previousTimeLocal.Int64() - previousTime.Int64() ) / 
+                   ( KMinuteInMicroseconds* KTimeZoneIncrement );
+
+		change->SetOldSecurityLevel( DRMClock::KSecure );
+		change->SetNewSecurityLevel( DRMClock::KSecure );
+		}
+    
+    // Since it's not important to get the timezone we keep what is set or reset it:
+    previousTimeLocal = aTime.Int64() + ( timezone * ( KMinuteInMicroseconds* KTimeZoneIncrement ) );
+
+    // Do the actual updating:
+    // Update using the wmdrm fileserver since it has TCB capability
+    RWmDrmFileServerClient resetclient;
+    User::LeaveIfError( resetclient.Connect() );
+    CleanupClosePushL( resetclient );
+    
+    newTime = aTime;
+    User::LeaveIfError( resetclient.UpdateSecureTime( previousTimeLocal, newTime ) );
+       
+    CleanupStack::PopAndDestroy();
+
+
+    DRMLOG( _L( "CDRMClock::ResetSecureTimeL: AFTER RESET." ));	
+
+    // DRM Notifier data:
+    // send info about the change:
+
+    change->SetNewSecurityLevel( DRMClock::KSecure );
+    
+    change->SetOldTime( previousTime );
+    change->SetOldTimeZone( timezone );
+
+    change->SetNewTime( aTime );
+    change->SetNewTimeZone( timezone );
+    
+    // Notify clients
+
+    iNotifier->SendEventL(*change,status);
+    User::WaitForRequest(status);
+    CleanupStack::PopAndDestroy();    
+    
+    DRMLOG( _L( "CDRMClock::ResetSecureTimeL ok" ) );
+    };
+
+// ---------------------------------------------------------
+// CDRMClock::Notify
+// Notify DRM clock about an event
+// ---------------------------------------------------------
+//
+void CDRMClock::Notify( TInt aNotify )
+    {
+    switch( aNotify )
+        {
+        case ENotifyGPSTimeReceived:
+            // GPS time received, listen again after the next boot, destroy GPS watcher:
+            DRMLOG(_L("Notify: ENotifyGPSTimeReceived, Deleting GPS watcher"));
+            delete iGpsWatcher;
+            iGpsWatcher = NULL;
+            DRMLOG(_L("Notify: GPS Watcher deleted"));
+            break;    
+        case ENotifyNone:
+        default:
+            break;  // Do nothing    
+        }    
+    }
+
+
+
+
+
+// ---------------------------------------------------------
+// CDRMClock::ConnectToPhoneL(const TDateTime& aDateTime)
+// Gets the nitz time from iNitzInfo
+// ---------------------------------------------------------
+//
+void CDRMClock::ConnectToPhoneL()
+    {
+    DRMLOG( _L( "CDRMClock::ConnectToPhoneL" ) );
+    
+    const TInt KTriesToConnectServer(10);
+    const TInt KTimeBeforeRetryingServerConnection(100000);
+    TInt thisTry(0);
+    TInt err(KErrNone);
+    TInt numPhone;
+    TName tsyName;
+    RTelServer::TPhoneInfo phoneInfo;
+    RMobilePhone::TMobilePhoneSubscriberId imsi;
+    TRequestStatus status;
+    
+
+    while ((err = iEtelServer.Connect()) != KErrNone &&
+                            (thisTry++) <= KTriesToConnectServer)
+        {
+        User::After(KTimeBeforeRetryingServerConnection);
+        }
+    User::LeaveIfError(err);
+
+    User::LeaveIfError(iEtelServer.LoadPhoneModule(KMmTsyModuleName));
+    User::LeaveIfError(iEtelServer.EnumeratePhones(numPhone));
+
+    for (TInt i(0); i < numPhone; i++)
+        {
+        User::LeaveIfError(iEtelServer.GetPhoneInfo(i, phoneInfo));
+        User::LeaveIfError(iEtelServer.GetTsyName(i,tsyName));
+
+        if (tsyName.CompareF(KMmTsyModuleName) == 0)
+            {
+            break;
+            }
+        }
+
+    User::LeaveIfError(iPhone.Open(iEtelServer, phoneInfo.iName));   
+    
+    iPhone.GetSubscriberId( status, imsi );
+    User::WaitForRequest( status );
+    
+    DRMLOG( imsi );    
+    DRMLOG( _L( "CDRMClock::ConnectToPhoneL ok" ) );
+    };
+
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+
+
+//  End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/breakdeps/DRMEngine/DRMClock.h	Wed Oct 27 13:24:02 2010 +0100
@@ -0,0 +1,170 @@
+/*
+* Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Interface for the DRMClock
+*
+*/
+
+
+#ifndef DRMCLOCK_H
+#define DRMCLOCK_H
+
+// INCLUDES
+
+#include <e32base.h>	// CBase
+#include <e32std.h>
+#include <e32def.h>		// Type definitions
+#include <bacntf.h>
+#include <etelmm.h>
+#include <DRMTypes.h>
+#include <e32property.h>
+
+// CONSTANTS
+
+// MACROS
+
+// DATA TYPES
+
+// FUNCTION PROTOTYPES
+
+// FORWARD DECLARATIONS
+class CDRMNitzObserver;
+class CDRMNotifier;
+class CGPSWatcher;
+
+// CLASS DECLARATION
+
+/**
+*  CDRMClock implements the drm clock required by DRM Engine
+*
+*  @lib unipertar.exe
+*  @since 2.8
+*/
+NONSHARABLE_CLASS( CDRMClock )
+    {
+    public:
+        // Notifications:        
+        enum 
+            {
+            ENotifyNone = 0,    
+            ENotifyGPSTimeReceived = 1    
+            };    
+    
+    public:
+
+        /**
+        * NewLC
+        *
+        * Creates an instance of the CDRMClock class and returns a pointer to it
+        * The function leaves the object into the cleanup stack
+        *
+        * @since  2.8
+        * @return Functional CDRMClock object, Function leaves if an error occurs.
+        */
+        static CDRMClock* NewLC();
+
+        /**
+        * NewL
+        *
+        * Creates an instance of the CDRMClock class and returns a pointer to it
+        *
+        * @since  2.8
+        * @return Functional CDRMClock object, Function leaves if an error occurs.
+        */
+        static CDRMClock* NewL();
+  
+        /**
+        * Destructor
+        */
+        virtual ~CDRMClock();
+
+        /**
+        * GetSecureTime
+        * 
+        * Return the current time and the security of the current time
+        *
+        * @since 2.8
+        * @param aTime : return parameter for time in UTC
+        * @param aTimeZone : return parameter for the timezone in +/-15 minutes
+        * @param aSecurityLevel : return parameter for security level
+        * @return none
+        */
+        void GetSecureTime(TTime& aTime, TInt& aTimeZone, 
+                           DRMClock::ESecurityLevel& aSecurityLevel);
+
+        /**
+        * ResetSecureTimeL
+        *
+        * Resets the secure time source and recalculates the offsets
+        *
+        * @since 2.8 
+        * @param aSecureTime, the new secure time in UTC
+        * @param aTimeZone, the time zone of the new secure time in +/- 15 minutes 
+        * @return none, Function leaves with Symbian OS error code if an
+        *         error occurs
+        */
+        void ResetSecureTimeL( const TTime& aSecureTime, const TInt& aTimeZone );
+        
+        
+        /**
+        * Notify
+        *
+        * Notifies about an event to the DRM Clock
+        *
+        * @since 9.2
+        * @param Message The notification event   
+        *
+        */
+        void Notify( TInt aMessage );
+        
+    protected:    
+    private:
+        /**
+        * Default Constructor - First phase
+        */
+        CDRMClock();
+
+         /**
+        * ConstructL
+        *
+        * Second phase constructor
+        *
+        * @since  2.8
+        * @return Leaves if an error occurs
+        */	   
+        void ConstructL();
+ 
+        /**
+        * ConnectToPhoneL
+        *
+        * Connects to the phone services
+        *
+        * @since 2.8
+        * @return Leaves with symbian os error codes if an error occurs
+        */
+        void ConnectToPhoneL();
+        
+        // Variables
+        CDRMNotifier* iNotifier;   
+        
+        // Nitz information handles      
+        RTelServer iEtelServer;
+        RMobilePhone iPhone;
+        CDRMNitzObserver* iObserver;
+        
+        // GPS watcher component, updates DRM time from GPS if available
+        CGPSWatcher* iGpsWatcher;
+    };
+#endif      // DRMCLOCK_H   
+            
+// End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/breakdeps/DRMEngine/DRMRightsServer.cpp	Wed Oct 27 13:24:02 2010 +0100
@@ -0,0 +1,1543 @@
+/*
+* Copyright (c) 2003 - 2007 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:  DRM3 Engine manages all DRM related database operations.
+*
+*/
+
+
+// INCLUDE FILES
+#include <e32std.h>
+#include <e32test.h>
+#include <etelmm.h>
+#include <DRMTypes.h>
+#include <starterclient.h>
+#include <featmgr.h>
+
+#ifdef RD_MULTIPLE_DRIVE
+#include <driveinfo.h>
+#endif
+
+#include "DRMRightsServer.h"
+#include "drmrightsdb.h"
+#include "DRMDbSession.h"
+#include "DRMEngineClientServer.h"
+#include "drmlog.h"
+#include "DRMNotifier.h"
+#include "DrmKeyStorage.h"
+#include "DRMNotifierServer.h"
+#include "RoapStorageServer.h"
+#include "drmnotifierclientserver.h"
+#include "drmroapclientserver.h"
+#include "DRMXOma.h"
+#include "DRMBackupObserver.h"
+#include "DRMBackup.h"
+#include "flogger.h"
+#include "DrmRightsParser.h"
+#include "DRMRights.h"
+#include "DRMHelperCommon.h"
+
+#include  "wmdrmclientwrapper.h"
+
+
+
+#ifdef __DRM_CLOCK
+#include "DRMClockServer.h"
+#include "drmclockclientserver.h"
+#endif
+
+#include <utf.h>
+#include <DRMIndividualConstraintExtension.h>
+
+/*
+_LIT( KLogDir, "drm");
+_LIT( KLogName, "backup.log");
+*/
+
+// EXTERNAL DATA STRUCTURES
+// EXTERNAL FUNCTION PROTOTYPES
+// CONSTANTS
+LOCAL_C const TUint KMaxHeapsize = 0x7A120;
+
+_LIT8( KImsiId,"IMSI:");
+
+// MACROS
+#ifdef _DRM_TESTING
+_LIT( KDateTimeFormat, "%F%Y%M%D%H%T%S%C" );
+#endif
+
+// LOCAL CONSTANTS AND MACROS
+const TUint8 KMaxStartTries = 30;
+const TInt KWaitingTime = 2000000; // 2 sec
+_LIT( KRightsServerThread, "RightsServer" );
+
+#ifdef RD_MULTIPLE_DRIVE
+
+_LIT( KDbTempPath, "%c:\\system\\temp\\" );
+_LIT( KIndividualConstraintExtensionDll, "%c:\\sys\\bin\\DRMIndividualConstraintExtension.dll" );
+_LIT( KRightsDir, "%c:\\private\\101F51F2\\rdb\\" );
+_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
+
+#define USE_RO_IMPORT
+
+#ifdef USE_RO_IMPORT
+_LIT( KInternalImportDir, "%c:\\private\\101F51F2\\import\\" );
+_LIT( KUserDiskImportDir, "%c:\\import\\" ); // usually embedded MMC
+_LIT( KUserRemovableDiskImportDir, "%c:\\import\\" ); // usually external MMC
+_LIT( KDrSuffix, ".dr" );
+#endif
+
+#else
+
+_LIT( KRightsDir, "c:\\private\\101F51F2\\rdb\\" );
+_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
+
+#define USE_RO_IMPORT
+
+#ifdef USE_RO_IMPORT
+_LIT( KInternalImportDir, "c:\\private\\101F51F2\\import\\" );
+_LIT( KUserDiskImportDir, "e:\\import\\" );
+_LIT( KDrSuffix, ".dr" );
+#endif
+
+#endif
+
+_LIT(KWmDrmClientWrapperName, "wmdrmclientwrapper.dll");
+
+// MODULE DATA STRUCTURES
+
+NONSHARABLE_STRUCT( TUnloadModule )
+    {
+    RTelServer* iServer;
+    const TDesC* iName;
+    };
+
+// LOCAL FUNCTION PROTOTYPES
+
+LOCAL_C TInt Startup( void );
+LOCAL_C void SignalClient();
+LOCAL_C TInt StartDBServer( void );
+
+#if defined( __WINS__ )
+#else
+#define DRM_USE_SERIALNUMBER_URI
+#include <mmtsy_names.h>
+#endif
+
+
+#ifdef DRM_USE_SERIALNUMBER_URI
+LOCAL_C void DoUnloadPhoneModule( TAny* aAny );
+#endif
+
+// #define USE_RO_IMPORT
+
+// FORWARD DECLARATIONS
+
+// ============================= LOCAL FUNCTIONS ===============================
+// -----------------------------------------------------------------------------
+// Function Startup().
+// This function starts the actual DRM Rights server after initializing
+// the cleanup stack and active scheduler.
+// Returns: TInt: Symbian OS error code.
+// -----------------------------------------------------------------------------
+//
+LOCAL_C TInt Startup( void )
+    {
+    TInt error = KErrNone;
+    CTrapCleanup* trap = CTrapCleanup::New();
+    CActiveScheduler* scheduler = new CActiveScheduler();
+
+    if ( trap && scheduler )
+        {
+        CActiveScheduler::Install( scheduler );
+
+        error = StartDBServer();
+        }
+    else
+        {
+        error = KErrNoMemory;
+        }
+
+    delete scheduler;
+    scheduler = NULL;
+
+    delete trap;
+    trap = NULL;
+
+    if ( error )
+        {
+        // Something went wrong. Release the client (if any).
+        SignalClient();
+
+        if ( error == KErrAlreadyExists )
+            {
+            error = KErrNone;
+            }
+        }
+
+    return error;
+    }
+
+// -----------------------------------------------------------------------------
+// Function SignalClient().
+// Signal the waiting client (one of them if any exists).
+// -----------------------------------------------------------------------------
+//
+void SignalClient( void )
+    {
+    RSemaphore semaphore;
+    if ( !semaphore.OpenGlobal( DRMEngine::KDRMSemaphore ) )
+        {
+        semaphore.Signal();
+        semaphore.Close();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// Function StartDBServer().
+// This function starts the actual server under TRAP harness and starts
+// waiting for connections. This function returns only if there has been
+// errors during server startup or the server is stopped for some reason.
+//
+// Returns: TInt: Symbian OS error code.
+// -----------------------------------------------------------------------------
+TInt StartDBServer( void )
+    {
+    TInt error = KErrNone;
+    CDRMRightsServer* server = NULL;
+    TUint8 count = 0;
+
+    do
+        {
+        DRMLOG2( _L( "RightsServer.exe: StartDBServer: %d" ), error );
+
+        ++count;
+
+        TRAP( error, ( server = CDRMRightsServer::NewL() ) );
+
+        if ( error )
+            {
+            User::After( TTimeIntervalMicroSeconds32(KWaitingTime) );
+            }
+
+        } while( error && ( count <= KMaxStartTries ) );
+
+    if( error )
+        {
+        DRMLOG2( _L( "RightsServer.exe: CDRMRightsServer::NewL failed: %d " ), error );
+        // Failed
+        return error;
+        }
+
+    // Release the semaphore if necessary.
+    SignalClient();
+
+    // Start waiting for connections
+    CActiveScheduler::Start();
+
+    // Dying...
+    // Delete CDRMRigntsServer
+
+    DRMLOG( _L( "RightsServer.exe: DB server dying..." ) );
+
+    delete server;
+
+    return KErrNone;
+    }
+
+#ifdef DRM_USE_SERIALNUMBER_URI
+// -----------------------------------------------------------------------------
+// Function DoUnloadPhoneModule
+// Unload phone module
+// -----------------------------------------------------------------------------
+//
+void DoUnloadPhoneModule( TAny* aAny )
+    {
+    __ASSERT_DEBUG( aAny, User::Invariant() );
+    TUnloadModule* module = ( TUnloadModule* ) aAny;
+    module->iServer->UnloadPhoneModule( *( module->iName ) );
+    }
+#endif
+
+#ifdef USE_RO_IMPORT
+// -----------------------------------------------------------------------------
+// PointerArrayResetDestroyAndClose
+// Template method used to push RPointerArrays to the cleanup stack. Takes
+// care of deleting all pointers in the array.
+// -----------------------------------------------------------------------------
+//
+template<class S>
+void PointerArrayResetDestroyAndClose(TAny* aPtr)
+    {
+    (reinterpret_cast<RPointerArray<S>*>(aPtr))->ResetAndDestroy();
+    (reinterpret_cast<RPointerArray<S>*>(aPtr))->Close();
+    }
+#endif
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// CUsageUrl:
+
+//--------------------------------------------------------------------------
+// CUsageUrl::CUsageUrl
+// Storage class default constructor
+//--------------------------------------------------------------------------
+//
+CUsageUrl::CUsageUrl()
+    {
+    }
+
+//--------------------------------------------------------------------------
+// CUsageUrl::~CUsageUrl
+// Storage class destructor
+//--------------------------------------------------------------------------
+//
+CUsageUrl::~CUsageUrl()
+    {
+    delete iUrl;    
+    }
+
+// CDRMRightsServer:
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CDRMRightsServer* CDRMRightsServer::NewL()
+    {
+    CDRMRightsServer* self = new( ELeave ) CDRMRightsServer();
+
+    CleanupStack::PushL( self );
+
+    self->ConstructL();
+
+    CleanupStack::Pop( self );
+
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// Destructor
+// -----------------------------------------------------------------------------
+CDRMRightsServer::~CDRMRightsServer()
+    {
+    DRMLOG( _L( "CDRMRightsServer::~" ) );
+
+    delete iIMEI; iIMEI = NULL;
+
+    delete iIMSI; iIMSI = NULL;
+
+    delete iDb; iDb = NULL;
+
+    iClock.Close();
+    iCache.Close();
+
+    iMeteringDb.Close();
+
+    iFs.Close();
+    iActiveCountConstraints.ResetAndDestroy();
+    iActiveCountConstraints.Close();
+
+    delete iBackupObserver;
+    delete iBackupHandler;
+    delete iActiveBackupClient;
+    delete iDbWatcher;
+
+#if 0
+    // Close and delete the shared data client
+    if( iSharedDataClient )
+        {
+        iSharedDataClient->Close();
+        delete iSharedDataClient;
+        iSharedDataClient = NULL;
+        }
+#endif
+
+    if( iNotifier )
+        {
+        delete iNotifier; iNotifier = NULL;
+        }
+
+    iActiveUrls.ResetAndDestroy();
+
+    //An empty semaphore
+    RSemaphore semaphore;
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::GetSecureTime
+// Fetch the time from (secure) source.
+// -----------------------------------------------------------------------------
+//
+TBool CDRMRightsServer::GetSecureTime( TTime& aTime ) const
+    {
+    DRMClock::ESecurityLevel secLevel = DRMClock::KInsecure;
+
+    TInt timezone( 0 );
+
+    iClock.GetSecureTime( aTime, timezone, secLevel );
+
+    if( secLevel == DRMClock::KSecure )
+        {
+        DRMLOG( _L( "CDRMRightsServer::GetSecureTime: Time is secure\r\n" ) );
+        return ETrue;
+        }
+
+    DRMLOG( _L( "CDRMRightsServer::GetSecureTime: Time is not secure\r\n" ) );
+
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::Notifier
+// Return a handle to DRM Notifier.
+// -----------------------------------------------------------------------------
+//
+CDRMNotifier& CDRMRightsServer::Notifier()
+    {
+    return *iNotifier;
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::Notifier
+// Return a handle to DRM Notifier.
+// -----------------------------------------------------------------------------
+//
+CDRMRightsDB& CDRMRightsServer::Database()
+    {
+    return *iDb;
+    }
+
+RFs& CDRMRightsServer::FileServerSession()
+    {
+    return iFs;
+    }
+
+
+RDRMReplayCache& CDRMRightsServer::ReplayCache()
+    {
+    return iCache;
+    }
+
+
+RDrmMeteringDb& CDRMRightsServer::MeteringDatabase()
+    {
+    return iMeteringDb;
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::HandleNotifyL
+// Forward the event to the database.
+// -----------------------------------------------------------------------------
+//
+void CDRMRightsServer::HandleNotifyL(const TUid /*aUid*/,
+                                     const TDesC& /*aKey*/,
+                                     const TDesC& /*aValue*/)
+    {
+    /* XXX Backup via Publish/Subscribe
+    __ASSERT_DEBUG( iDb, User::Invariant() );
+    TInt value = -1;
+    TLex16 parser( aValue );
+
+    if ( aUid == KSDUidSystem )
+        {
+        // Check if it's a backup / restore status event
+        if( !aKey.Compare( KBackupRestoreStatus ) )
+            {
+            User::LeaveIfError( parser.Val( value ) );
+            if( value == 3 ) // Complete
+                {
+                iDb->MergeDBL();
+                }
+            }
+        // Check if it's a drm backup restore status event
+        else if ( aUid == KSDUidSystem )
+            {
+            if( !aKey.Compare( KDRMBackupRestoreStatus ) )
+                {
+                User::LeaveIfError( parser.Val( value ) );
+
+                if( value == 1 ) // PrepareForBackup
+                    {
+                    TRAPD( error, iDb->BackupDBL( KNullDesC,
+                                                  KNullDesC8 ) );
+                    // Notify that it's done
+                    User::LeaveIfError( iSharedDataClient->AssignToTemporaryFile(
+                                        KSDUidSystem ) );
+                    User::LeaveIfError( iSharedDataClient->SetInt(
+                                        KDRMBackupRestoreStatus, 0 ) );
+                    iSharedDataClient->Flush();
+                    }
+                }
+            }
+        }
+    */
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::RunErrorL
+// From CActive. Complete the request and restart the scheduler.
+// -----------------------------------------------------------------------------
+//
+TInt CDRMRightsServer::RunError( TInt aError )
+    {
+    DRMLOG2( _L( "CDRMRightsServer::RunError: %d" ), aError );
+
+    // Inform the client.
+    if ( !Message().IsNull() )
+        {
+        Message().Complete( aError );
+        }
+
+    // Restart the scheduler.
+    ReStart();
+
+    // Error handled.
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::NewSessionL
+// Called when a client requires a new instance.
+// -----------------------------------------------------------------------------
+CSession2* CDRMRightsServer::NewSessionL( const TVersion& aVersion,
+                                          const RMessage2& /*aMessage*/ ) const
+    {
+    DRMLOG( _L( "CDRMRightsServer::NewSessionL" ) );
+
+    if ( ! User::QueryVersionSupported( TVersion( DRMEngine::KServerMajorVersion,
+        DRMEngine::KServerMinorVersion,
+        DRMEngine::KServerBuildVersion ),
+        aVersion ) )
+        {
+        // Sorry, no can do.
+        User::Leave( KErrNotSupported );
+        }
+
+    DRMLOG( _L( "CDRMRightsServer::NewSessionL: Creating a new session" ) );
+
+    return CDRMDbSession::NewL();
+    }
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::CDRMRightsServer
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CDRMRightsServer::CDRMRightsServer() :
+    CServer2( EPriorityStandard ),
+    iIMEI( NULL ),
+    iArmed( EFalse ),
+    iIMSI( NULL ),
+    iGetImsi( ETrue )
+    {
+    // Nothing
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CDRMRightsServer::ConstructL()
+    {
+    DRMLOG( _L( "CDRMRightsServer::ConstructL" ) );
+
+    TDRMKey key;
+    RSemaphore semaphore;
+    RProcess currentprocess;
+
+    // Ignore errors
+    User::RenameThread( KRightsServerThread );
+    User::LeaveIfError( iFs.Connect() );
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    // Ignore errors
+    iFs.MkDirAll( KDRMDbTempPath );
+
+#else //RD_MULTIPLE_DRIVE
+
+    TFileName tempPath;
+    TFileName tempPath2;
+    TFileName tempRemovablePath;
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    TChar driveLetterRemovable;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+
+    tempPath.Format( KDbTempPath, (TUint)driveLetter );
+
+    // Ignore errors
+    iFs.MkDirAll( tempPath );
+
+#endif
+
+    DRMLOG( _L( "CDRMRightsServer::ConstructL: SharedDataClient" ) );
+
+    // Create and instance of the shared data client
+    // iSharedDataClient = new (ELeave) RSharedDataClient(this);
+
+    // Connecting to the shared data server
+    // User::LeaveIfError(iSharedDataClient->Connect());
+
+    /* XXX Backup via Publish/Subscribe
+    User::LeaveIfError(iSharedDataClient->NotifyChange(
+        KSDUidSystem, &KBackupRestoreStatus ) );
+    User::LeaveIfError(iSharedDataClient->NotifyChange(
+        KSDUidSystem, &KDRMBackupRestoreStatus) );
+    */
+
+
+    GetDbKeyL( key );
+
+
+    DRMLOG( _L( "CDRMRightsServer::ConstructL: database" ) );
+
+    GetIMEIL();
+
+    // Create the imsi pointer array:
+    iIMSI = CDRMPointerArray<HBufC8>::NewL();
+    iIMSI->SetAutoCleanup(ETrue);
+
+    GetIMSIL();
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    iDb = CDRMRightsDB::NewL( iFs, KRightsDir, key, *iIMEI, const_cast<CDRMRightsServer*>(this) );
+
+#else //RD_MULTIPLE_DRIVE
+
+    tempPath.Format( KRightsDir, (TUint)driveLetter );
+
+    iDb = CDRMRightsDB::NewL( iFs, tempPath, key, *iIMEI, const_cast<CDRMRightsServer*>(this) );
+
+#endif
+
+    key.FillZ();
+
+    DRMLOG( _L( "CDRMRightsServer::ConstructL: DB started." ) );
+
+    DRMLOG( _L( "CDRMRightsServer::ConstructL: Starting Notifier ." ) );
+
+    User::LeaveIfError( semaphore.CreateGlobal( KDRMEngCommonSemaphore, 0 ) );
+    CleanupClosePushL( semaphore );
+
+    StartThreadL( DRMNotifier::KServerName, StartupNotifier, semaphore );
+    DRMLOG( _L( "CDRMRightsServer::ConstructL: Notifier thread created." ) );
+
+    StartThreadL( Roap::KServerName, StartupRoapStorage, semaphore );
+    DRMLOG( _L( "CDRMRightsServer::ConstructL: ROAP thread created." ) );
+
+#ifdef __DRM_CLOCK
+    StartThreadL( DRMClock::KServerName, StartupClock, semaphore );
+    DRMLOG( _L( "CDRMRightsServer::ConstructL: clock thread created." ) );
+#endif
+
+    CleanupStack::PopAndDestroy(); // semaphore
+
+    iNotifier = CDRMNotifier::NewL();
+
+    iCache.Set( iFs );
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    iCache.InitL( KTimedReplayCacheFile, KPlainReplayCacheFile );
+
+#ifdef RD_DRM_METERING
+    iMeteringDb.Set( iFs );
+    iMeteringDb.InitL( KMeteringDataBaseFile );
+#endif
+
+#else //RD_MULTIPLE_DRIVE
+
+    tempPath.Format( KTimedReplayCacheFile, (TUint)driveLetter );
+    tempPath2.Format( KPlainReplayCacheFile, (TUint)driveLetter );
+
+    iCache.InitL( tempPath, tempPath2 );
+
+#ifdef RD_DRM_METERING
+
+    tempPath.Format( KMeteringDataBaseFile, (TUint)driveLetter );
+
+    iMeteringDb.Set( iFs );
+    iMeteringDb.InitL( tempPath );
+
+#endif
+
+#endif
+
+    User::LeaveIfError( iClock.Connect() );
+
+    // xoma header list creation
+    iXOmaHeaders = new (ELeave) RPointerArray< CDRMXOma >();
+
+    // p/s
+    iBackupObserver = CDRMBackupObserver::NewL( *(const_cast<CDRMRightsServer*>(this)));
+    iBackupObserver->Start();
+
+#ifdef USE_RO_IMPORT
+    // Import any OMA DRM 1.0 RO in the import directory, ignore all errors (except
+    // when checking the default removable mass storage)
+    TInt r = KErrNone;
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    TRAP( r, ImportRightsObjectsL( KInternalImportDir ) );
+    TRAP( r, ImportRightsObjectsL( KUserDiskImportDir ) );
+
+#else //RD_MULTIPLE_DRIVE
+
+    tempPath.Format( KInternalImportDir, (TUint)driveLetter );
+
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultMassStorage, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+
+    // Default mass storage is usually eMMC
+    tempPath2.Format( KUserDiskImportDir, (TUint)driveLetter );
+
+    // Find out if a removable mass storage also exists
+    r = DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRemovableMassStorage, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetterRemovable );
+
+    // Import is not needed from the default removable mass storage drive if the drive
+    // letter of the default mass storage and the default removable mass storage are
+    // the same or the removable mass storage is not supported
+    if ( ( driveLetter != driveLetterRemovable ) && ( r == KErrNone ) )
+        {
+        tempRemovablePath.Format( KUserRemovableDiskImportDir, (TUint)driveLetterRemovable );
+        TRAP( r, ImportRightsObjectsL( tempRemovablePath ) );
+        }
+
+    TRAP( r, ImportRightsObjectsL( tempPath ) );
+    TRAP( r, ImportRightsObjectsL( tempPath2 ) );
+
+#endif
+
+#endif
+
+    // Add the server to the scheduler.
+    StartL( DRMEngine::KServerName );
+
+    // Start watching our RDB
+    iDbWatcher = CDbWatcher::NewL( *this );
+    iDbWatcher->StartWatching();
+
+    // Start watching the helper server
+    iProcWatcher = CProcWatcher::NewL( *this, _L( "*DcfRepSrv*" ), _L( "DcfRepSrv" ) );
+    iProcWatcher->StartWatching();
+
+    // Ready to watch
+    iArmed = ETrue;
+
+    __UHEAP_MARK;
+    TRAP( r, FeatureManager::InitializeLibL() );
+    if( !r && FeatureManager::FeatureSupported( KFeatureIdWindowsMediaDrm ) )
+        {
+        static const TInt KGateOrdinal = 1;
+        RLibrary library;
+        r = library.Load( KWmDrmClientWrapperName );
+        if( !r )
+            {
+            CWmDrmClientWrapper* wrapper = NULL;
+            TLibraryFunction function = library.Lookup( KGateOrdinal );
+            if( function != NULL )
+                {
+                __UHEAP_MARK;
+                TRAP( r, wrapper = reinterpret_cast<CWmDrmClientWrapper*>( function() ) );
+                if( !r )
+                    {
+                    r = wrapper->Connect();
+                    }
+                delete wrapper;
+                __UHEAP_MARKEND;
+                }
+            }
+        library.Close();
+        }
+    FeatureManager::UnInitializeLib();
+    __UHEAP_MARKEND;
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::StartThreadL
+// Start a new thread.
+// -----------------------------------------------------------------------------
+void CDRMRightsServer::StartThreadL( const TDesC& aThreadName,
+                                     TThreadFunction aFunc,
+                                     RSemaphore& aSemaphore )
+    {
+    RThread thread;
+
+    User::LeaveIfError(
+          thread.Create( aThreadName,
+                         aFunc,
+                         KDefaultStackSize,
+                         KMinHeapSize,
+                         KMaxHeapsize,
+                         NULL ) );
+
+    thread.Resume();
+
+    aSemaphore.Wait();
+
+    thread.Close();
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::GetDbKeyL
+// Fetches the rights database key from Wallet or uses a constant
+// key if Wallet is not supported.
+// -----------------------------------------------------------------------------
+//
+void CDRMRightsServer::GetDbKeyL( TDRMKey& aKey  )
+    {
+    TInt r = KErrNone;
+
+    DRMLOG( _L( "CDRMRightsServer::GetDbKey" ) );
+    MDrmKeyStorage* storage = DrmKeyStorageNewL();
+    TRAP( r, storage->GetDeviceSpecificKeyL( aKey ) );
+    delete storage;
+    User::LeaveIfError( r );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::GenerateKeyL
+// Generates the actual key based on the given key seed.
+// -----------------------------------------------------------------------------
+//
+void CDRMRightsServer::GenerateKeyL( HBufC*& aKeySeed,
+                                    TDRMKey& aKey ) const
+    {
+    __ASSERT_ALWAYS( aKeySeed->Size() >= KDRMKeyLength,
+        User::Leave( KErrUnderflow ) );
+
+    TPtrC8 key( reinterpret_cast< TUint8* >( const_cast< TUint16* >( aKeySeed->Ptr() ) ),
+                KDRMKeyLength );
+
+    aKey = key;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::XOmaHeaders()
+// return the pointer of the X-Oma headers list
+// -----------------------------------------------------------------------------
+//
+RPointerArray< CDRMXOma >& CDRMRightsServer::XOmaHeaders( void )
+    {
+    return *iXOmaHeaders;
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::GetIMEIL
+// -----------------------------------------------------------------------------
+//
+const TDesC& CDRMRightsServer::GetIMEIL()
+    {
+    if ( iIMEI )
+        {
+        return *iIMEI;
+        }
+
+#ifdef DRM_USE_SERIALNUMBER_URI
+    TInt error( KErrNone );
+    TInt count( 0 );
+    TInt count2( 0 );
+    TUint32 caps( 0 );
+    TBool found (EFalse);
+
+    RTelServer etelServer;
+    RMobilePhone phone;
+
+    TUint KMaxImeiTries = 5;
+
+    for ( TUint8 i = 0; i < KMaxImeiTries; ++i )
+        {
+        error = etelServer.Connect();
+        if ( error )
+            {
+            User::After( TTimeIntervalMicroSeconds32( KWaitingTime ) );
+            }
+        else
+            {
+            break;
+            }
+        }
+
+    User::LeaveIfError( error );
+    CleanupClosePushL( etelServer );
+
+    User::LeaveIfError( etelServer.LoadPhoneModule( KMmTsyModuleName ) );
+
+    TUnloadModule unload;
+    unload.iServer = &etelServer;
+    unload.iName = &KMmTsyModuleName;
+
+    TCleanupItem item( DoUnloadPhoneModule, &unload );
+    CleanupStack::PushL( item );
+    User::LeaveIfError( etelServer.EnumeratePhones( count ) );
+
+    for ( count2 = 0; count2 < count && !found; ++count2 )
+        {
+        RTelServer::TPhoneInfo phoneInfo;
+        User::LeaveIfError( etelServer.GetTsyName( count2, phoneInfo.iName ) );
+
+        if ( phoneInfo.iName.CompareF(KMmTsyModuleName()) == 0 )
+           {
+            User::LeaveIfError( etelServer.GetPhoneInfo( count2, phoneInfo ) );
+            User::LeaveIfError( phone.Open( etelServer, phoneInfo.iName ) );
+            CleanupClosePushL( phone );
+            found = ETrue;
+            }
+        }
+
+    if ( !found )
+        {
+        // Not found.
+        User::Leave( KErrNotFound );
+        }
+
+    User::LeaveIfError( phone.GetIdentityCaps( caps ) );
+    if ( caps & RMobilePhone::KCapsGetSerialNumber )
+        {
+        RMobilePhone::TMobilePhoneIdentityV1 id;
+        TRequestStatus status;
+
+        phone.GetPhoneId( status, id );
+
+        User::WaitForRequest( status );
+
+        User::LeaveIfError( status.Int() );
+
+        iIMEI = id.iSerialNumber.AllocL();
+
+        CleanupStack::PopAndDestroy( 3 ); // phone, item, etelServer
+
+        HBufC8* buf = HBufC8::NewL( iIMEI->Size() );
+        TPtr8 ptr( buf->Des() );
+        ptr.Copy( *iIMEI );
+
+        DRMLOG(_L("IMEI:"));
+        DRMLOGHEX(ptr);
+        delete buf;
+
+        return *iIMEI;
+        }
+
+    User::Leave( KErrNotFound );
+
+    // Never happens...
+    return *iIMEI;
+
+#else
+    _LIT( KDefaultSerialNumber, "123456789123456789" );
+    iIMEI = KDefaultSerialNumber().AllocL();
+
+    return *iIMEI;
+#endif
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::GetIMSIL
+// -----------------------------------------------------------------------------
+//
+const CDRMPointerArray<HBufC8>& CDRMRightsServer::GetIMSIL()
+    {
+
+    if ( !iGetImsi )
+        {
+        return *iIMSI;
+        }
+
+#ifndef __WINS__
+    TInt error( KErrNone );
+    TInt count( 0 );
+    TInt count2( 0 );
+    TUint32 caps( 0 );
+    TBool found (EFalse);
+    HBufC8* imsi = NULL;
+    HBufC8* imsiNumber = NULL;
+
+    RTelServer etelServer;
+    RMobilePhone phone;
+
+    TUint KMaxImeiTries = 5;
+    for ( TUint8 i = 0; i < KMaxImeiTries; ++i )
+        {
+        error = etelServer.Connect();
+        if ( error )
+            {
+            User::After( TTimeIntervalMicroSeconds32( KWaitingTime ) );
+            }
+        else
+            {
+            break;
+            }
+        }
+
+    User::LeaveIfError( error );
+    CleanupClosePushL( etelServer );
+    User::LeaveIfError( etelServer.LoadPhoneModule( KMmTsyModuleName ) );
+
+    TUnloadModule unload;
+    unload.iServer = &etelServer;
+    unload.iName = &KMmTsyModuleName;
+
+    TCleanupItem item( DoUnloadPhoneModule, &unload );
+    CleanupStack::PushL( item );
+
+    User::LeaveIfError( etelServer.EnumeratePhones( count ) );
+
+    for ( count2 = 0; count2 < count && !found; ++count2 )
+        {
+        RTelServer::TPhoneInfo phoneInfo;
+        User::LeaveIfError( etelServer.GetTsyName( count2, phoneInfo.iName ) );
+
+        if ( phoneInfo.iName.CompareF(KMmTsyModuleName()) == 0 )
+           {
+            User::LeaveIfError( etelServer.GetPhoneInfo( count2, phoneInfo ) );
+            User::LeaveIfError( phone.Open( etelServer, phoneInfo.iName ) );
+            CleanupClosePushL( phone );
+            found = ETrue;
+            }
+        }
+
+    if ( !found )
+        {
+        // Not found.
+        User::Leave( KErrNotFound );
+        }
+
+
+    User::LeaveIfError( phone.GetIdentityCaps( caps ) );
+
+    if( caps & RMobilePhone::KCapsGetSubscriberId )
+        {
+        RMobilePhone::TMobilePhoneSubscriberId imsiId;
+        TRequestStatus status;
+
+        phone.GetSubscriberId( status, imsiId );
+
+        User::WaitForRequest( status );
+
+        if( ! status.Int() )
+            {
+            imsi = HBufC8::NewMaxLC( imsiId.Length() + KImsiId().Size() );
+            TPtr8 imsiPtr(const_cast<TUint8*>(imsi->Ptr()), 0, imsi->Size());
+
+            imsiNumber = CnvUtfConverter::ConvertFromUnicodeToUtf8L( imsiId );
+            CleanupStack::PushL( imsiNumber );
+
+            imsiPtr.Copy( KImsiId() );
+            imsiPtr.Append( *imsiNumber );
+            CleanupStack::PopAndDestroy(); // imsiNumber
+            }
+        else
+            {
+            imsi = NULL;
+            }
+        }
+    else
+        {
+        imsi = NULL;
+        }
+
+
+    // Clean up whatever is in there
+    iIMSI->ResetAndDestroy();
+
+    if( imsi )
+        {
+        // if we got it we wont try again
+        iIMSI->AppendL( imsi );
+        CleanupStack::Pop(); // imsi
+        iGetImsi = EFalse;
+        }
+
+    // Check for possible extra IMSI individual constraints
+    AppendExtendedIndividualConstraintsL(&phone);
+
+    CleanupStack::PopAndDestroy(); // phone
+    CleanupStack::PopAndDestroy(); // cleanup item
+    CleanupStack::PopAndDestroy(); // etel server
+
+    return *iIMSI;
+
+#else
+    HBufC8* imsi = NULL;
+
+    if( iGetImsi )
+        {
+        iGetImsi = EFalse;
+        _LIT8( KDefaultSerialNumber, "IMSI:123456789123456789" );
+        imsi = KDefaultSerialNumber().AllocLC();
+        iIMSI->AppendL( imsi );
+        CleanupStack::Pop();
+        AppendExtendedIndividualConstraintsL();
+        }
+
+
+    return *iIMSI;
+#endif // __WINS__
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::AppendExtendedIndividualConstraintsL
+// If the extension DLL exists it is loaded and used to obtain additional
+// valid individual constraints
+// -----------------------------------------------------------------------------
+void CDRMRightsServer::AppendExtendedIndividualConstraintsL(RMobilePhone* aMobilePhone)
+    {
+    // Load the externsion DLL
+    RLibrary lib;
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    if (lib.LoadRomLibrary(KDRMIndividualConstraintExtensionDll,KNullDesC)==KErrNone)
+
+#else //RD_MULTIPLE_DRIVE
+
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+
+    TFileName individualConstraindExtensionDll;
+    individualConstraindExtensionDll.Format(
+                        KIndividualConstraintExtensionDll, (TUint)driveLetter );
+
+    if ( lib.LoadRomLibrary( individualConstraindExtensionDll, KNullDesC ) == KErrNone )
+
+#endif
+
+        {
+        CleanupClosePushL(lib);
+
+        // Get first exported ordinal - factory method returning
+        // MDRMIndividualConstraintExtension*
+        TLibraryFunction factory = lib.Lookup(1);
+
+        if (factory)
+            {
+            // Instantiate object
+            MDRMIndividualConstraintExtension* extendedConstraints =
+                reinterpret_cast<MDRMIndividualConstraintExtension*>(factory());
+
+            if (extendedConstraints)
+                {
+                CleanupStack::PushL(TCleanupItem(Release,extendedConstraints));
+                extendedConstraints->AppendConstraintsL(*iIMSI,aMobilePhone);
+                CleanupStack::PopAndDestroy(extendedConstraints); //calls Release
+                }
+            }
+
+        // unload library
+        CleanupStack::PopAndDestroy(&lib); //close
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::Release
+// -----------------------------------------------------------------------------
+void CDRMRightsServer::Release(TAny* aIndividualConstraintExtension)
+    {
+    MDRMIndividualConstraintExtension* extendedConstraints =
+        reinterpret_cast<MDRMIndividualConstraintExtension*>(aIndividualConstraintExtension);
+    extendedConstraints->Release(); //free resources
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::HandleBackupEventL
+// Handle Backup Events
+// -----------------------------------------------------------------------------
+//
+
+void CDRMRightsServer::HandleBackupEventL( TInt aBackupEvent )
+    {
+    //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::BackupCalled\n\r"));
+
+    //conn::TBURPartType eventType;
+    //conn::TBackupIncType incType;
+    TDriveList aDriveList;
+
+    //RFileLogger::WriteFormat(KLogDir, KLogName, EFileLoggingModeAppend, _L8("backupevent: %d"), aBackupEvent);
+
+    // If there is no operation going or state is normal
+    // Delete the client and handler
+
+    if( aBackupEvent == conn::EBURUnset ||
+        aBackupEvent & conn::EBURNormal )
+        {
+        /*
+        if( aBackupEvent == conn::EBURUnset )
+            {
+                        RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Unset\n\r"));
+            }
+        else
+            {
+            RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Normal\n\r"));
+            }
+        */
+        if( iActiveBackupClient )
+            {
+            delete iActiveBackupClient;
+            iActiveBackupClient = NULL;
+            }
+
+        if( iBackupHandler )
+            {
+            delete iBackupHandler;
+            iBackupHandler = NULL;
+            }
+        }
+    else if( aBackupEvent & conn::EBURBackupFull ||
+             aBackupEvent & conn::EBURRestoreFull )
+        {
+        //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Full\n\r"));
+        // ab handler
+        iBackupHandler = CDRMBackup::NewL( iDb, iFs );
+
+        // ab client
+        iActiveBackupClient = conn::CActiveBackupClient::NewL( iBackupHandler );
+
+        // Confirm that we have done everything if there even was anything to do
+        //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Confirm F \n\r"));
+        iActiveBackupClient->ConfirmReadyForBURL( KErrNone );
+        }
+    else if( aBackupEvent & conn::EBURBackupPartial ||
+             aBackupEvent & conn::EBURRestorePartial )
+        {
+        //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Partial\n\r"));
+        // ab handler
+        iBackupHandler = CDRMBackup::NewL( iDb, iFs );
+
+        // ab client
+        iActiveBackupClient = conn::CActiveBackupClient::NewL( iBackupHandler );
+
+        if( !iActiveBackupClient->DoesPartialBURAffectMeL() )
+            {
+            //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::NotMe\n\r"));
+            delete iActiveBackupClient;
+            iActiveBackupClient = NULL;
+
+            delete iBackupHandler;
+            iBackupHandler = NULL;
+            }
+        else
+            {
+            //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Confirm P \n\r"));
+            // Confirm that we have done everything if there even was anything to do
+            iActiveBackupClient->ConfirmReadyForBURL( KErrNone );
+            //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Confirm P Done \n\r"));
+            }
+        }
+    else
+        {
+        //RFileLogger::Write(KLogDir, KLogName, EFileLoggingModeAppend, _L8("Handle::Argument\n\r"));
+        // Unknown operation
+        User::Leave(KErrArgument);
+        }
+    };
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::WatchedObjectChangedL
+// Handle Backup Events
+// -----------------------------------------------------------------------------
+//
+void CDRMRightsServer::WatchedObjectChangedL( const TDesC& aObject )
+    {
+    DRMLOG( _L( "CDRMRightsServer::WatchedObjectChangedL ->" ) );
+    DRMLOG( aObject );
+
+    if ( aObject.Left( KDirIdentifier().Length() ) == KDirIdentifier &&
+         !iDb->Updating() && iArmed )
+        {
+#ifdef _DEBUG
+        DRMLOG( _L( "RDB modified by outside party (DEBUG mode, not deleting the DB)" ) );
+#else
+        DRMLOG( _L( "RDB modified by outside party, deleting the DB" ) );
+        iDb->MarkAsCorrupted();
+        RStarterSession starter;
+        User::LeaveIfError( starter.Connect() );
+        starter.Reset( RStarterSession::EDRMReset );
+        starter.Close();
+#endif
+        }
+    else if ( aObject.Left( KProcIdentifier().Length() ) == KProcIdentifier && iArmed )
+        {
+#ifdef _DEBUG
+        DRMLOG( _L( "Peer process killed (DEBUG mode, not rebooting)" ) );
+#else
+        DRMLOG( _L( "Peer process killed, rebooting" ) );
+        RStarterSession starter;
+        User::LeaveIfError( starter.Connect() );
+        starter.Reset( RStarterSession::EDRMReset );
+        starter.Close();
+#endif
+        }
+
+    DRMLOG( _L( "CDRMRightsServer::WatchedObjectChangedL <-" ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::HasActiveCountConstraint
+// Check ID for active count constraint
+// -----------------------------------------------------------------------------
+//
+TBool CDRMRightsServer::HasActiveCountConstraint( const TDesC8& aContentId )
+    {
+    TInt i;
+    TBool r = EFalse;
+
+    for ( i = 0; r == EFalse && i < iActiveCountConstraints.Count(); i++ )
+        {
+        if ( iActiveCountConstraints[i]->CompareF( aContentId ) == 0 )
+            {
+            r = ETrue;
+            }
+        }
+    return r;
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::RemoveActiveCountConstraint
+// Remove ID from count constraint list
+// -----------------------------------------------------------------------------
+//
+void CDRMRightsServer::RemoveActiveCountConstraint( const TDesC8& aContentId )
+    {
+    TInt i;
+    TInt r = KErrNotFound;
+    HBufC8* id = NULL;
+
+    for ( i = 0; r == KErrNotFound && i < iActiveCountConstraints.Count(); i++ )
+        {
+        if ( iActiveCountConstraints[i]->CompareF( aContentId ) == 0 )
+            {
+            r = i;
+            }
+        }
+    if ( r != KErrNotFound )
+        {
+        id = iActiveCountConstraints[r];
+        iActiveCountConstraints.Remove( r );
+        delete id;
+        id = NULL;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::AddActiveCountConstraint
+// Add ID to count constraint list
+// -----------------------------------------------------------------------------
+//
+void CDRMRightsServer::AddActiveCountConstraintL( const TDesC8& aContentId )
+    {
+    if ( !HasActiveCountConstraint( aContentId ) )
+        {
+        iActiveCountConstraints.AppendL( aContentId.AllocL() );
+        }
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::IsAccessingUrl
+// Add ID to count constraint list
+// -----------------------------------------------------------------------------
+//
+TInt CDRMRightsServer::IsAccessingUrl( const TDesC8& aContentId )
+    {
+    for( TInt i = 0; i < iActiveUrls.Count(); i++ )
+        {
+        if( !iActiveUrls[i]->iUrl->Compare( aContentId ) ) 
+            {
+            return i;
+            }    
+        }
+    return KErrNotFound;        
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::RemoveAccessingUrl
+// Add ID to count constraint list
+// -----------------------------------------------------------------------------
+//
+void CDRMRightsServer::RemoveAccessingUrl( const TDesC8& aContentId )
+    {
+    CUsageUrl* usage = NULL;    
+    TInt index = KErrNotFound;
+    
+    index = IsAccessingUrl( aContentId );
+    
+    if( index != KErrNotFound )
+        {
+        // If there are negative or 0 values in the list for some reason
+        // remove them    
+        if( iActiveUrls[index]->iRefCounter <= 1 )
+            {
+            usage = iActiveUrls[index];    
+            iActiveUrls.Remove( index );    
+            delete usage;
+            }
+        else
+            {
+            iActiveUrls[index]->iRefCounter--;
+            }           
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::AddAccessingUrlL
+// Add ID to count constraint list
+// -----------------------------------------------------------------------------
+//
+void CDRMRightsServer::AddAccessingUrlL( const TDesC8& aContentId )
+    {
+    CUsageUrl* usage = NULL;
+    TInt index = KErrNotFound;
+    
+    index = IsAccessingUrl( aContentId );
+    
+    if( index == KErrNotFound )
+        {
+        usage = new ( ELeave ) CUsageUrl();
+        CleanupStack::PushL( usage );
+        usage->iUrl = aContentId.AllocL();
+        usage->iRefCounter = 1;
+        iActiveUrls.AppendL( usage );
+        CleanupStack::Pop( usage );
+        }
+    else
+        {
+        usage = iActiveUrls[index];
+        usage->iRefCounter++;    
+        }           
+    }
+
+
+
+
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::StopWatchingL
+// Delete the watchers
+// -----------------------------------------------------------------------------
+//
+void CDRMRightsServer::StopWatchingL()
+    {
+    iArmed = EFalse;
+    }
+
+#ifdef USE_RO_IMPORT
+// -----------------------------------------------------------------------------
+// CDRMRightsServer::ImportRightsObjectsL
+// Open the import directory and add all ROs that can be found there. ROs file
+// names must end with .dr. Only OMA DRM 1.0 ROs in XML format are supported for
+// security reasons
+// -----------------------------------------------------------------------------
+//
+void CDRMRightsServer::ImportRightsObjectsL( const TDesC& aImportDir )
+    {
+    CDrmRightsParser* p;
+    HBufC8* d = NULL;
+    HBufC8* k = NULL;
+    RFs fs;
+    RFile file;
+    TInt size;
+    RPointerArray<CDRMRights> rights;
+    CDir* dir;
+    TFileName name;
+    TPtr8 ptr( NULL, 0 );
+    TInt i;
+    TInt r = KErrNone;
+    TCleanupItem listCleanup(PointerArrayResetDestroyAndClose<CDRMRights>,
+        &rights);
+    TDRMUniqueID id;
+    TTime time;
+
+    DRMLOG( _L( "CDRMRightsServer::ImportRightsObjectsL" ) );
+    DRMLOG( aImportDir );
+    __UHEAP_MARK;
+    GetSecureTime( time );
+    p = CDrmRightsParser::NewL();
+    CleanupStack::PushL( p );
+    User::LeaveIfError( iFs.GetDir( aImportDir, KEntryAttNormal,
+        ESortNone, dir ) );
+    CleanupStack::PushL( dir );
+    for (i = 0; i < dir->Count(); i++)
+        {
+        name.Copy( aImportDir );
+        name.Append( (*dir)[i].iName );
+        if ( ( name.Length() > 3 && name.Right(3).CompareF( KDrSuffix ) == 0 ) )
+            {
+            User::LeaveIfError( file.Open( iFs, name, EFileRead ) );
+            CleanupClosePushL( file );
+            User::LeaveIfError( file.Size( size ) );
+            d = HBufC8::NewLC( size );
+            ptr.Set( d->Des() );
+            User::LeaveIfError( file.Read( ptr ) );
+            p->ParseL( ptr, rights );
+            if ( rights.Count() > 0 )
+                {
+                k = NULL;
+                CleanupStack::PushL( listCleanup );
+                CDRMPermission& permission = rights[0]->GetPermission();
+                CDRMAsset& asset = rights[0]->GetAsset();
+
+                // Add RO only if no rights are available at all for this content
+                TRAP( r, k = iDb->GetDecryptionKeyL( *asset.iUid ) );
+                if (k == NULL )
+                    {
+                    iDb->AddDBEntryL( *asset.iUid, permission, asset.iKey, id );
+                    }
+                else
+                    {
+                    delete k;
+                    }
+                CleanupStack::PopAndDestroy(); // listCleanup
+                }
+            CleanupStack::PopAndDestroy( 2 ); // d, file
+            iFs.Delete( name );
+            }
+        }
+    CleanupStack::PopAndDestroy( 2 ); // dir, p
+    __UHEAP_MARKEND;
+    DRMLOG( _L( "CDRMRightsServer::ImportRightsObjectsL done" ) );
+    }
+#endif
+
+
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+
+
+TInt E32Main()
+    {
+    return Startup();
+    }
+
+
+//  End of File
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/breakdeps/DRMEngine/DrmStdKeyStorage.cpp	Wed Oct 27 13:24:02 2010 +0100
@@ -0,0 +1,1186 @@
+/*
+* Copyright (c) 2002-2010 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:  OMA DRM 2.0 Key Storage
+*
+*/
+
+
+// INCLUDE FILES
+#include <e32std.h>
+#include <asymmetric.h>
+#include <symmetric.h>
+#include <hash.h>
+#include <asn1dec.h>
+#include <x509cert.h>
+#include <etelmm.h>
+#include <mmtsy_names.h>
+#include <featmgr.h>
+
+#ifdef RD_MULTIPLE_DRIVE
+#include <driveinfo.h>
+#endif
+
+#include "DrmKeyStorage.h"
+#include "DrmStdKeyStorage.h"
+
+#ifdef _DEBUG
+#define LOGGING
+#endif
+
+#ifdef LOGGING
+_LIT(KLogDir, "DRM");
+_LIT(KLogName, "KeyStorage.log");
+#include "flogger.h"
+#define LOG(string) \
+    RFileLogger::Write(KLogDir, KLogName, \
+        EFileLoggingModeAppend, string);
+#define LOGHEX(buffer) \
+    RFileLogger::HexDump(KLogDir, KLogName, \
+        EFileLoggingModeAppend, _S(""), _S(""), \
+        buffer.Ptr(), buffer.Length());
+#else
+#define LOG(string)
+#define LOGHEX(buffer)
+#endif
+
+#pragma message("Compiling DRM Std KeyStorage..")
+
+
+// LOCAL CONSTANTS AND MACROS
+
+const TInt KKeyLength = 128;
+const TInt KWaitingTime = 2000000; // 2 sec
+
+#ifdef RD_MULTIPLE_DRIVE
+_LIT(KKeyStoragePath, "%c:\\private\\101F51F2\\PKI\\");
+_LIT(KRomKeyStoragePath, "%c:\\private\\101F51F2\\PKI\\");
+
+#else
+_LIT(KKeyStoragePath, "c:\\private\\101F51F2\\PKI\\");
+_LIT(KRomKeyStoragePath, "z:\\private\\101F51F2\\PKI\\");
+#endif
+
+_LIT(KDeviceKeyFileName, "DevicePrivateKey.der");
+_LIT(KDeviceCertFileName, "DeviceCert.der");
+_LIT(KSingingCertFmt, "SigningCert%02d.der");
+_LIT(KSingingCertPattern, "SigningCert*");
+_LIT8(KDefaultKey, "0000000000000000");
+
+#ifdef RD_MULTIPLE_DRIVE
+_LIT(KSerialNumberFile, "%c:\\private\\101F51F2\\rdbserial.dat");
+_LIT(KUdtCertFileName, "%c:\\private\\101F51F2\\PKI\\UdtCertificate.der");
+#else
+_LIT(KSerialNumberFile, "c:\\private\\101F51F2\\rdbserial.dat");
+_LIT(KUdtCertFileName, "z:\\private\\101F51F2\\PKI\\UdtCertificate.der");
+#endif
+
+_LIT(KCmla, "CMLA");
+_LIT(KPadding, "\x0");
+
+NONSHARABLE_STRUCT( TUnloadModule )
+    {
+    RTelServer* iServer;
+    const TDesC* iName;
+    };
+
+
+// ============================ LOCAL FUNCTIONS ================================
+LOCAL_C void DoUnloadPhoneModule( TAny* aAny );
+
+LOCAL_C void WriteFileL(RFs& aFs, const TDesC& aName, const TDesC8& aData)
+    {
+    RFile file;
+
+    User::LeaveIfError(file.Replace(aFs, aName, EFileWrite));
+    User::LeaveIfError(file.Write(aData));
+    file.Close();
+    }
+
+LOCAL_C void ReadFileL(RFs& aFs, const TDesC& aName, HBufC8*& aContent)
+    {
+    RFile file;
+    TInt size = 0;
+
+    User::LeaveIfError(file.Open(aFs, aName, EFileRead));
+    CleanupClosePushL(file);
+    User::LeaveIfError(file.Size(size));
+    aContent = HBufC8::NewLC(size);
+    TPtr8 ptr(aContent->Des());
+    User::LeaveIfError(file.Read(ptr, size));
+    CleanupStack::Pop(); //aContent
+    CleanupStack::PopAndDestroy(); // file
+    }
+
+HBufC8* I2OSPL(
+    RInteger& aInt, TInt& aKeySize )
+    {
+    HBufC8* integer = aInt.BufferLC();
+    if (integer->Length() < aKeySize)
+        {
+        HBufC8* r = HBufC8::NewLC(aKeySize);
+        TPtr8 ptr(r->Des());
+        for(TInt i = integer->Length(); i < aKeySize; i++)
+            {
+            ptr.Append(KPadding());
+            }
+        ptr.Append(*integer);
+        CleanupStack::Pop(r);
+        CleanupStack::PopAndDestroy(integer);
+        return r;
+        }
+    else
+        {
+        CleanupStack::Pop(integer);
+        return integer;
+        }
+    }
+
+RInteger OS2IPL(
+    const TDesC8& aOctetStream)
+    {
+    RInteger r;
+    TInt i;
+
+    r = RInteger::NewL(0);
+    for (i = 0; i < aOctetStream.Length(); i++)
+        {
+        r *= 256;
+        r += aOctetStream[i];
+        }
+    return r;
+    }
+
+void DoUnloadPhoneModule( TAny* aAny )
+    {
+    __ASSERT_DEBUG( aAny, User::Invariant() );
+    TUnloadModule* module = ( TUnloadModule* ) aAny;
+    module->iServer->UnloadPhoneModule( *( module->iName ) );
+    }
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage* CDrmStdKeyStorage::NewL
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CDrmStdKeyStorage* CDrmStdKeyStorage::NewL(RLibrary aLibrary)
+    {
+    CDrmStdKeyStorage* self = new (ELeave) CDrmStdKeyStorage(aLibrary);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop();
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::CDrmStdKeyStorage
+//
+// -----------------------------------------------------------------------------
+//
+CDrmStdKeyStorage::CDrmStdKeyStorage(RLibrary aLibrary):
+    iFileMan(NULL),
+    iRootSelected(EFalse),
+    iKey(NULL),
+    iImei(NULL),
+    iLibrary(aLibrary)
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::ConstructL
+//
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::ConstructL()
+    {
+
+    LOG(_L("CDrmStdKeyStorage::ConstructL ->"));
+    User::LeaveIfError(iFs.Connect());
+    iFileMan = CFileMan::NewL(iFs);
+
+    FeatureManager::InitializeLibL();
+    
+#ifdef __DRM_OMA2 
+    if ( FeatureManager::FeatureSupported( KFeatureIdFfOmadrm2Support ) )
+        {
+        TRAP_IGNORE( SelectDefaultRootL() );
+        }
+#endif
+    
+    FeatureManager::UnInitializeLib();
+    
+    iDeviceSpecificKey.Copy(KDefaultKey);
+
+    LOG(_L("CDrmStdKeyStorage::ConstructL <-"));
+    }
+
+// -----------------------------------------------------------------------------
+// MDrmKeyStorage::~MDrmKeyStorage
+//
+// -----------------------------------------------------------------------------
+//
+
+MDrmKeyStorage::~MDrmKeyStorage()
+    {
+    }
+// -----------------------------------------------------------------------------
+// DrmStdKeyStorage::~CDrmStdKeyStorage
+//
+// -----------------------------------------------------------------------------
+//
+
+CDrmStdKeyStorage::~CDrmStdKeyStorage()
+    {
+    LOG(_L("CDrmStdKeyStorage::~CDrmStdKeyStorage ->"));
+    delete iFileMan;
+    delete iKey;
+    delete iImei; iImei = NULL;
+    iFs.Close();
+    //iLibrary.Close();
+    LOG(_L("CDrmStdKeyStorage::~CDrmStdKeyStorage <-"));
+    }
+
+// -----------------------------------------------------------------------------
+// DrmStdKeyStorage::ModulusSize
+//
+// -----------------------------------------------------------------------------
+//
+
+TInt CDrmStdKeyStorage::ModulusSize()
+    {
+    LOG(_L("CDrmStdKeyStorage::ModulusSize ->"));
+
+    if(iKey == NULL)
+        {
+        return KErrGeneral;
+        }
+    LOG(_L("CDrmStdKeyStorage::ModulusSize <-"));
+    return iKey->N().BitCount();
+    }
+
+// -----------------------------------------------------------------------------
+// DrmStdKeyStorage::SelectTrustedRootL
+//
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::SelectTrustedRootL(
+    const TDesC8& aRootKeyHash)
+    {
+    TFileName fileName;
+    TEntry entry;
+    TInt i;
+
+    LOG(_L("CDrmStdKeyStorage::SelectTrustedRootL ->"));
+    LOG(aRootKeyHash);
+    if (aRootKeyHash.Length() != 0)
+        {
+
+#ifndef RD_MULTIPLE_DRIVE
+
+        fileName.Copy(KKeyStoragePath);
+
+#else //RD_MULTIPLE_DRIVE
+
+        TFileName tempPath;
+        TInt driveNumber( -1 );
+        TChar driveLetter;
+        DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+        iFs.DriveToChar( driveNumber, driveLetter );
+
+        tempPath.Format( KKeyStoragePath, (TUint)driveLetter );
+
+        fileName.Copy(tempPath);
+
+#endif
+
+        for (i = 0; i < SHA1_HASH; i++)
+            {
+            fileName.AppendNumFixedWidth(aRootKeyHash[i], EHex, 2);
+            }
+        fileName.Append('\\');
+        if (iFs.Entry(fileName, entry) != KErrNone)
+            {
+
+#ifndef RD_MULTIPLE_DRIVE
+
+            fileName.Copy(KRomKeyStoragePath);
+
+#else //RD_MULTIPLE_DRIVE
+
+            DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber );
+            iFs.DriveToChar( driveNumber, driveLetter );
+
+            tempPath.Format( KRomKeyStoragePath, (TUint)driveLetter );
+
+            fileName.Copy(tempPath);
+
+#endif
+
+            for (i = 0; i < SHA1_HASH; i++)
+                {
+                fileName.AppendNumFixedWidth(aRootKeyHash[i], EHex, 2);
+                }
+            fileName.Append('\\');
+            // check that the path exists
+            User::LeaveIfError(iFs.Entry(fileName, entry));
+            }
+        User::LeaveIfError(iFs.SetSessionPath(fileName));
+        InitializeKeyL();
+        CheckRootForCmlaL();
+        iRootSelected = ETrue;
+        }
+    else
+        {
+        SelectDefaultRootL();
+        }
+    LOG(_L("CDrmStdKeyStorage::SelectTrustedRootL <-"));
+    }
+
+// -----------------------------------------------------------------------------
+// DrmStdKeyStorage::SelectDefaultRootL
+//
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::SelectDefaultRootL()
+    {
+    CDir* dir = NULL;
+    TFileName dirName;
+    TBool found = EFalse;
+
+    LOG(_L("CDrmStdKeyStorage::SelectDefaultRootL ->"));
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    if (iFs.GetDir(KKeyStoragePath, KEntryAttDir, ESortByName, dir) == KErrNone)
+
+#else //RD_MULTIPLE_DRIVE
+
+    TFileName tempPath;
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+
+    tempPath.Format( KKeyStoragePath, (TUint)driveLetter );
+
+    if (iFs.GetDir(tempPath, KEntryAttDir, ESortByName, dir) == KErrNone)
+
+#endif
+
+        {
+        __UHEAP_MARK;
+        LOG(_L("  Checking keys on C:"));
+        CleanupStack::PushL(dir);
+        if (dir->Count() >= 1)
+            {
+
+#ifndef RD_MULTIPLE_DRIVE
+
+            dirName.Copy(KKeyStoragePath);
+
+#else //RD_MULTIPLE_DRIVE
+
+            dirName.Copy(tempPath);
+
+#endif
+
+            dirName.Append((*dir)[0].iName);
+            dirName.Append('\\');
+            User::LeaveIfError(iFs.SetSessionPath(dirName));
+            found = ETrue;
+            }
+        CleanupStack::PopAndDestroy(dir);
+        __UHEAP_MARKEND;
+        }
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    if (!found && iFs.GetDir(KRomKeyStoragePath, KEntryAttDir, ESortByName, dir) == KErrNone)
+
+#else //RD_MULTIPLE_DRIVE
+
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+
+    tempPath.Format( KRomKeyStoragePath, (TUint)driveLetter );
+
+    if (!found && iFs.GetDir(tempPath, KEntryAttDir, ESortByName, dir) == KErrNone)
+
+#endif
+        {
+        LOG(_L("  Checking keys on Z:"));
+        CleanupStack::PushL(dir);
+        if (dir->Count() < 1)
+            {
+            User::Leave(KErrGeneral);
+            }
+
+#ifndef RD_MULTIPLE_DRIVE
+
+        dirName.Copy(KRomKeyStoragePath);
+
+#else //RD_MULTIPLE_DRIVE
+
+        dirName.Copy(tempPath);
+
+#endif
+
+        dirName.Append((*dir)[0].iName);
+        dirName.Append('\\');
+        User::LeaveIfError(iFs.SetSessionPath(dirName));
+        CleanupStack::PopAndDestroy(dir);
+        found = ETrue;
+        }
+    if (!found)
+        {
+        User::Leave(KErrGeneral);
+        }
+    InitializeKeyL();
+    CheckRootForCmlaL();
+    iRootSelected = ETrue;
+    LOG(_L("CDrmStdKeyStorage::SelectDefaultRootL <-"));
+    }
+
+TBool CDrmStdKeyStorage::SelectedRootIsCmla()
+    {
+    return iRootIsCmla;
+    }
+
+// -----------------------------------------------------------------------------
+// DrmStdKeyStorage::GetTrustedRootsL
+//
+// -----------------------------------------------------------------------------
+//
+
+void CDrmStdKeyStorage::GetTrustedRootsL(
+    RPointerArray<HBufC8>& aRootList)
+    {
+    CDir* dir = NULL;
+    TInt i;
+    TInt j;
+    TBuf8<SHA1_HASH> hash;
+    TEntry entry;
+    TUint8 c;
+    TInt r = KErrNone;
+
+    LOG(_L("CDrmStdKeyStorage::GetTrustedRootsL ->"));
+    aRootList.ResetAndDestroy();
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    if (iFs.GetDir(KKeyStoragePath, KEntryAttDir, ESortByName, dir) == KErrNone)
+
+#else //RD_MULTIPLE_DRIVE
+
+    TFileName tempPath;
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+
+    tempPath.Format( KKeyStoragePath, (TUint)driveLetter );
+
+    if (iFs.GetDir(tempPath, KEntryAttDir, ESortByName, dir) == KErrNone)
+
+#endif
+        {
+        LOG(_L("  Getting roots on C:"));
+        CleanupStack::PushL(dir);
+        for (i = 0; i < dir->Count(); i++)
+            {
+            entry = (*dir)[i];
+            hash.SetLength(0);
+            LOG(entry.iName);
+            r = KErrNone;
+            for (j = 0; r == KErrNone && j < SHA1_HASH; j++)
+                {
+                TLex lex(entry.iName.Mid(j * 2, 2));
+                r = lex.Val(c, EHex);
+                hash.Append(c);
+                }
+            if (r == KErrNone)
+                {
+                aRootList.Append(hash.AllocL());
+                }
+            }
+        CleanupStack::PopAndDestroy(dir);
+        }
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    if (iFs.GetDir(KRomKeyStoragePath, KEntryAttDir, ESortByName, dir) == KErrNone)
+
+#else //RD_MULTIPLE_DRIVE
+
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+
+    tempPath.Format( KRomKeyStoragePath, (TUint)driveLetter );
+
+    if (iFs.GetDir(tempPath, KEntryAttDir, ESortByName, dir) == KErrNone)
+
+#endif
+        {
+        LOG(_L("  Getting roots on Z:"));
+        CleanupStack::PushL(dir);
+        for (i = 0; i < dir->Count(); i++)
+            {
+            LOG(entry.iName);
+            entry = (*dir)[i];
+            hash.SetLength(0);
+            r = KErrNone;
+            for (j = 0; r == KErrNone && j < SHA1_HASH; j++)
+                {
+                TLex lex(entry.iName.Mid(j * 2, 2));
+                r = lex.Val(c, EHex);
+                hash.Append(c);
+                }
+            if (r == KErrNone)
+                {
+                aRootList.Append(hash.AllocL());
+                }
+            }
+        CleanupStack::PopAndDestroy(dir);
+        }
+    LOG(_L("CDrmStdKeyStorage::GetTrustedRootsL <-"));
+    }
+
+// -----------------------------------------------------------------------------
+// DrmStdKeyStorage::GetCertificateChainL
+//
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::GetCertificateChainL(
+    RPointerArray<HBufC8>& aCertChain)
+    {
+    TFileName fileName;
+    TInt i;
+    CDir* dir = NULL;
+    HBufC8* cert = NULL;
+
+    LOG(_L("CDrmStdKeyStorage::GetCertificateChainL ->"));
+    if (!iRootSelected)
+        {
+        User::Leave(KErrGeneral);
+        }
+    aCertChain.ResetAndDestroy();
+    ReadFileL(iFs, KDeviceCertFileName, cert);
+    aCertChain.Append(cert);
+    iFs.GetDir(KSingingCertPattern, KEntryAttNormal, ESortByName, dir);
+    CleanupStack::PushL(dir);
+    for (i = 0; i < dir->Count(); i++)
+        {
+        ReadFileL(iFs, (*dir)[i].iName, cert);
+        aCertChain.AppendL(cert);
+        }
+    CleanupStack::PopAndDestroy(); // dir
+    LOG(_L("CDrmStdKeyStorage::GetCertificateChainL <-"));
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::RsaSignL
+// -----------------------------------------------------------------------------
+//
+HBufC8* CDrmStdKeyStorage::RsaSignL(
+    const TDesC8& aInput)
+    {
+    return ModularExponentiateWithKeyL(aInput);
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::RsaDecryptL
+// -----------------------------------------------------------------------------
+//
+HBufC8* CDrmStdKeyStorage::RsaDecryptL(
+    const TDesC8& aInput)
+    {
+    return ModularExponentiateWithKeyL(aInput);
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::ImportDataL
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::ImportDataL(
+    const TDesC8& aPrivateKey,
+    const RArray<TPtrC8>& aCertificateChain)
+    {
+    TInt i;
+    TInt n;
+    HBufC8* publicKey = NULL;
+    CX509Certificate* cert = NULL;
+    CSHA1* hasher = NULL;
+    TBuf8<SHA1_HASH> publicKeyHash;
+    TFileName fileName;
+
+    LOG(_L("CDrmStdKeyStorage::ImportDataL ->"));
+    n = aCertificateChain.Count();
+    cert = CX509Certificate::NewLC(aCertificateChain[n - 1]);
+    publicKey = cert->DataElementEncoding(
+        CX509Certificate::ESubjectPublicKeyInfo)->AllocL();
+    CleanupStack::PushL(publicKey);
+    hasher = CSHA1::NewL();
+    CleanupStack::PushL(hasher);
+    hasher->Update(*publicKey);
+    publicKeyHash.Copy(hasher->Final());
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    fileName.Copy(KKeyStoragePath);
+
+#else //RD_MULTIPLE_DRIVE
+
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+
+    TFileName keyStorageDir;
+    keyStorageDir.Format( KKeyStoragePath, (TUint)driveLetter );
+
+    fileName.Copy(keyStorageDir);
+
+#endif
+
+    for (i = 0; i < SHA1_HASH; i++)
+        {
+        fileName.AppendNumFixedWidth(publicKeyHash[i], EHex, 2);
+        }
+    fileName.Append('\\');
+    iFileMan->Delete(fileName, CFileMan::ERecurse);
+    iFs.MkDirAll(fileName);
+    iFs.SetSessionPath(fileName);
+    WriteFileL(iFs, KDeviceKeyFileName, aPrivateKey);
+    fileName.Copy(fileName);
+    WriteFileL(iFs, KDeviceCertFileName, aCertificateChain[0]);
+    for (i = 1; i < n; i++)
+        {
+        fileName.SetLength(0);
+        fileName.AppendFormat(KSingingCertFmt, i - 1);
+        WriteFileL(iFs, fileName, aCertificateChain[i]);
+        }
+    CleanupStack::PopAndDestroy(3); // hasher, publicKey, cert
+    LOG(_L("CDrmStdKeyStorage::ImportDataL <-"));
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::GetDeviceSpecificKeyL
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::GetDeviceSpecificKeyL(
+    TBuf8<KDeviceSpecificKeyLength>& aKey)
+    {
+
+    HBufC8* key = NULL;
+    TInt n;
+    CSHA1* hasher = NULL;
+    TBuf8<SHA1_HASH> hash;
+
+    if (iDeviceSpecificKey.Compare(KDefaultKey) == 0)
+        {
+
+        GetImeiL();
+
+        HBufC8* buf = HBufC8::NewLC( iImei->Size() + sizeof(VID_DEFAULT) );
+        TPtr8 ptr( buf->Des() );
+        ptr.Copy( *iImei );
+        ptr.Append(VID_DEFAULT);
+
+        hasher = CSHA1::NewL();
+        CleanupStack::PushL(hasher);
+        hasher->Update(ptr);
+        hash.Copy(hasher->Final());
+        key=hash.AllocL();
+        CleanupStack::PopAndDestroy(2,buf); // hasher,buf;
+
+        n = Min(key->Length(), KDeviceSpecificKeyLength);
+        iDeviceSpecificKey.Copy(key->Right(n));
+        delete key;
+        n = KDeviceSpecificKeyLength - n;
+        while (n > 0)
+            {
+            iDeviceSpecificKey.Append(0);
+            n--;
+            }
+        }
+
+    aKey.Copy(iDeviceSpecificKey);
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::InitializeKeyL
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::InitializeKeyL()
+    {
+    HBufC8* key = NULL;
+    TASN1DecInteger encInt;
+    TInt pos = 0;
+
+    LOG(_L("CDrmStdKeyStorage::InitializeKeyL ->"));
+    delete iKey;
+    iKey = NULL;
+    ReadFileL(iFs, KDeviceKeyFileName, key);
+    CleanupStack::PushL(key);
+    TASN1DecGeneric gen(*key);
+    gen.InitL();
+    pos += gen.LengthDERHeader();
+    if (gen.Tag() != EASN1Sequence)
+        {
+        User::Leave(KErrArgument);
+        }
+    encInt.DecodeDERShortL(*key, pos); // version
+    RInteger modulus = encInt.DecodeDERLongL(*key, pos);
+    CleanupStack::PushL(modulus);
+    RInteger publicExponent = encInt.DecodeDERLongL(*key, pos);
+    CleanupStack::PushL(publicExponent);
+    RInteger privateExponent = encInt.DecodeDERLongL(*key, pos);
+    CleanupStack::PushL(privateExponent);
+    iKey = CRSAPrivateKeyStandard::NewL(modulus, privateExponent);
+    CleanupStack::Pop(); // privateExponent
+    CleanupStack::PopAndDestroy();// publicExponent
+    CleanupStack::Pop(); // modulus
+    CleanupStack::PopAndDestroy(); // key
+    LOG(_L("CDrmStdKeyStorage::InitializeKeyL <-"));
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::ModularExponentiateWithKeyL
+// -----------------------------------------------------------------------------
+//
+HBufC8* CDrmStdKeyStorage::ModularExponentiateWithKeyL(
+    const TDesC8& aInput)
+    {
+    RInteger result;
+    RInteger input;
+    HBufC8* output;
+    TInt keyLength = KKeyLength;
+
+    LOG(_L("CDrmStdKeyStorage::ModularExponentiateWithKeyL ->"));
+    input = OS2IPL(aInput);
+    CleanupClosePushL(input);
+    result = TInteger::ModularExponentiateL(input,iKey->D(), iKey->N());
+    CleanupClosePushL(result);
+    output = I2OSPL(result,  keyLength);
+    CleanupStack::PopAndDestroy(2); // result, input
+    LOG(_L("CDrmStdKeyStorage::ModularExponentiateWithKeyL <-"));
+    return output;
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::CheckRootForCmlaL
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::CheckRootForCmlaL()
+    {
+    CDir* dir = NULL;
+    HBufC8* buffer = NULL;
+    HBufC* name = NULL;
+    CX509Certificate* cert = NULL;
+
+    LOG(_L("CDrmStdKeyStorage::CheckRootForCmlaL ->"));
+    __UHEAP_MARK;
+    iFs.GetDir(KSingingCertPattern, KEntryAttNormal, ESortByName, dir);
+    CleanupStack::PushL(dir);
+    ReadFileL(iFs, (*dir)[dir->Count() - 1].iName, buffer);
+    CleanupStack::PushL(buffer);
+    cert = CX509Certificate::NewL(*buffer);
+    CleanupStack::PushL(cert);
+    name = cert->SubjectName().DisplayNameL();
+    CleanupStack::PushL(name);
+    if (name->Find(KCmla) != KErrNotFound)
+        {
+        iRootIsCmla = ETrue;
+        }
+    else
+        {
+        iRootIsCmla = EFalse;
+        }
+    CleanupStack::PopAndDestroy(4); // name, cert, buffer, dir
+    LOG(_L("CDrmStdKeyStorage::CheckRootForCmlaL <-"));
+    __UHEAP_MARKEND;
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::GetRdbSerialNumberL
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::GetRdbSerialNumberL(
+    TBuf8<KRdbSerialNumberLength>& aSerialNumber)
+    {
+    HBufC8* buffer = NULL;
+    TUint att;
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    if (iFs.Att(KSerialNumberFile, att) != KErrNone)
+
+#else //RD_MULTIPLE_DRIVE
+
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+
+    TFileName serialNoFile;
+    serialNoFile.Format( KSerialNumberFile, (TUint)driveLetter );
+
+    if (iFs.Att(serialNoFile, att) != KErrNone)
+
+#endif
+        {
+        GenerateNewRdbSerialNumberL();
+        }
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    ReadFileL(iFs, KSerialNumberFile, buffer);
+
+#else //RD_MULTIPLE_DRIVE
+
+    ReadFileL(iFs, serialNoFile, buffer);
+
+#endif
+
+    aSerialNumber.Copy(*buffer);
+    delete buffer;
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::GenerateNewRdbSerialNumberL
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::GenerateNewRdbSerialNumberL()
+    {
+    TBuf8<KRdbSerialNumberLength> serialNumber;
+    TPtr8 random( const_cast<TUint8*>(serialNumber.Ptr()),
+                  KRdbSerialNumberLength,
+                  KRdbSerialNumberLength );
+
+    RandomDataGetL(random,KRdbSerialNumberLength);
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    WriteFileL(iFs, KSerialNumberFile, random);
+
+#else //RD_MULTIPLE_DRIVE
+
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+
+    TFileName serialNoFile;
+    serialNoFile.Format( KSerialNumberFile, (TUint)driveLetter );
+
+    WriteFileL(iFs, serialNoFile, random);
+
+#endif
+
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::UdtEncryptL
+// -----------------------------------------------------------------------------
+//
+HBufC8* CDrmStdKeyStorage::UdtEncryptL(
+    const TDesC8& aInput)
+    {
+    HBufC8* buffer = NULL;
+    HBufC8* output = HBufC8::NewMaxLC( 256 );
+    CX509Certificate* cert = NULL;
+    CRSAPublicKey* key = NULL;
+    TX509KeyFactory factory;
+    CRSAPKCS1v15Encryptor* encryptor = NULL;
+    TPtr8 result(const_cast<TUint8*>(output->Ptr()), 0, 256);
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    ReadFileL(iFs, KUdtCertFileName, buffer);
+
+#else //RD_MULTIPLE_DRIVE
+
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+
+    TFileName udtCertFile;
+    udtCertFile.Format( KUdtCertFileName, (TUint)driveLetter );
+
+    ReadFileL(iFs, udtCertFile, buffer);
+
+#endif
+
+    CleanupStack::PushL(buffer);
+    cert = CX509Certificate::NewL(*buffer);
+    CleanupStack::PushL(cert);
+    key = factory.RSAPublicKeyL(cert->PublicKey().KeyData());
+    CleanupStack::PushL(key);
+
+    encryptor = CRSAPKCS1v15Encryptor::NewLC(*key);
+    encryptor->EncryptL(aInput, result);
+
+    CleanupStack::PopAndDestroy(4); // encryptor, key, cert, buffer
+    CleanupStack::Pop();// output
+    return output;
+    };
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::GetRootCertificatesL
+// -----------------------------------------------------------------------------
+//
+void CDrmStdKeyStorage::GetRootCertificatesL(
+          RPointerArray<HBufC8>& aRootCerts)
+    {
+    CDir* dir = NULL;
+    CDir* rootCerts = NULL;
+    TFileName dirName;
+    HBufC8* cert = NULL;
+    TInt i = 0;
+    TBuf<256> path;
+
+    iFs.SessionPath( path );
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    if (iFs.GetDir(KKeyStoragePath, KEntryAttDir, ESortByName, dir) == KErrNone)
+
+#else //RD_MULTIPLE_DRIVE
+
+    TFileName tempPath;
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+
+    tempPath.Format( KKeyStoragePath, (TUint)driveLetter );
+
+    if (iFs.GetDir(tempPath, KEntryAttDir, ESortByName, dir) == KErrNone)
+
+#endif
+        {
+        CleanupStack::PushL(dir);
+        for(i = 0; i < dir->Count(); i++)
+            {
+            if ((*dir)[i].IsDir())
+                {
+
+#ifndef RD_MULTIPLE_DRIVE
+
+                dirName.Copy(KKeyStoragePath);
+
+#else //RD_MULTIPLE_DRIVE
+
+                dirName.Copy(tempPath);
+
+#endif
+
+                dirName.Append((*dir)[i].iName);
+                dirName.Append('\\');
+                User::LeaveIfError(iFs.SetSessionPath(dirName));
+                User::LeaveIfError(iFs.GetDir(KSingingCertPattern, KEntryAttNormal, ESortByName, rootCerts));
+                CleanupStack::PushL(rootCerts);
+                ReadFileL(iFs, (*rootCerts)[rootCerts->Count() - 1].iName, cert);
+                CleanupStack::PushL(cert);
+                aRootCerts.AppendL(cert);
+                CleanupStack::Pop(cert);
+                CleanupStack::PopAndDestroy(); // rootCerts
+                }
+            }
+        CleanupStack::PopAndDestroy(dir);
+        }
+
+#ifndef RD_MULTIPLE_DRIVE
+
+    if (iFs.GetDir(KRomKeyStoragePath, KEntryAttDir, ESortByName, dir) == KErrNone)
+
+#else //RD_MULTIPLE_DRIVE
+
+    DriveInfo::GetDefaultDrive( DriveInfo::EDefaultRom, driveNumber );
+    iFs.DriveToChar( driveNumber, driveLetter );
+
+    tempPath.Format( KRomKeyStoragePath, (TUint)driveLetter );
+
+    if (iFs.GetDir(tempPath, KEntryAttDir, ESortByName, dir) == KErrNone)
+
+#endif
+        {
+        CleanupStack::PushL(dir);
+        for(i = 0; i < dir->Count(); i++)
+            {
+            if ((*dir)[i].IsDir())
+                {
+
+#ifndef RD_MULTIPLE_DRIVE
+
+                dirName.Copy(KRomKeyStoragePath);
+
+#else //RD_MULTIPLE_DRIVE
+
+                dirName.Copy(tempPath);
+
+#endif
+
+                dirName.Append((*dir)[i].iName);
+                dirName.Append('\\');
+                User::LeaveIfError(iFs.SetSessionPath(dirName));
+                User::LeaveIfError(iFs.GetDir(KSingingCertPattern, KEntryAttNormal, ESortByName, rootCerts));
+                CleanupStack::PushL(rootCerts);
+                ReadFileL(iFs, (*rootCerts)[rootCerts->Count() - 1].iName, cert);
+                CleanupStack::PushL(cert);
+                aRootCerts.AppendL(cert);
+                CleanupStack::Pop(cert);
+                CleanupStack::PopAndDestroy(); // rootCerts
+                }
+            }
+        CleanupStack::PopAndDestroy(dir);
+        }
+    iFs.SetSessionPath( path );
+    }
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::GetIMEIL
+// -----------------------------------------------------------------------------
+//
+const TDesC& CDrmStdKeyStorage::GetImeiL()
+    {
+    if ( iImei )
+        {
+        return *iImei;
+        }
+
+#if (defined __WINS__ || defined WINSCW)
+    // Default IMEI used for emulator
+    _LIT( KDefaultSerialNumber, "123456789123456789" );
+    iImei = KDefaultSerialNumber().AllocL();
+
+    return *iImei;
+#else
+
+    TInt error( KErrNone );
+    TInt count( 0 );
+    TInt count2( 0 );
+    TUint32 caps( 0 );
+    TBool found (EFalse);
+
+    RTelServer etelServer;
+    RMobilePhone phone;
+
+    TUint KMaxImeiTries = 5;
+
+    for ( TUint8 i = 0; i < KMaxImeiTries; ++i )
+        {
+        error = etelServer.Connect();
+        if ( error )
+            {
+            User::After( TTimeIntervalMicroSeconds32( KWaitingTime ) );
+            }
+        else
+            {
+            break;
+            }
+        }
+
+    User::LeaveIfError( error );
+    CleanupClosePushL( etelServer );
+
+    User::LeaveIfError( etelServer.LoadPhoneModule( KMmTsyModuleName ) );
+
+    TUnloadModule unload;
+    unload.iServer = &etelServer;
+    unload.iName = &KMmTsyModuleName;
+
+    TCleanupItem item( DoUnloadPhoneModule, &unload );
+    CleanupStack::PushL( item );
+    User::LeaveIfError( etelServer.EnumeratePhones( count ) );
+
+    for ( count2 = 0; count2 < count && !found; ++count2 )
+        {
+        RTelServer::TPhoneInfo phoneInfo;
+        User::LeaveIfError( etelServer.GetTsyName( count2, phoneInfo.iName ) );
+
+        if ( phoneInfo.iName.CompareF(KMmTsyModuleName()) == 0 )
+           {
+            User::LeaveIfError( etelServer.GetPhoneInfo( count2, phoneInfo ) );
+            User::LeaveIfError( phone.Open( etelServer, phoneInfo.iName ) );
+            CleanupClosePushL( phone );
+            found = ETrue;
+            }
+        }
+
+    if ( !found )
+        {
+        // Not found.
+        User::Leave( KErrNotFound );
+        }
+
+    User::LeaveIfError( phone.GetIdentityCaps( caps ) );
+    if (!( caps & RMobilePhone::KCapsGetSerialNumber ))
+        {
+         User::Leave( KErrNotFound );
+        }
+
+    RMobilePhone::TMobilePhoneIdentityV1 id;
+    TRequestStatus status;
+
+    phone.GetPhoneId( status, id );
+
+    User::WaitForRequest( status );
+
+    User::LeaveIfError( status.Int() );
+
+    iImei = id.iSerialNumber.AllocL();
+
+    CleanupStack::PopAndDestroy( 3 ); // phone, item, etelServer
+
+    HBufC8* buf = HBufC8::NewL( iImei->Size() );
+    TPtr8 ptr( buf->Des() );
+    ptr.Copy( *iImei );
+
+    LOG(_L("IMEI:"));
+    LOGHEX(ptr);
+    delete buf;
+
+    return *iImei;
+#endif /* __WINS__ , WINSCW */
+
+    }
+
+
+// -----------------------------------------------------------------------------
+// CDrmStdKeyStorage::RandomDataGetL
+// -----------------------------------------------------------------------------
+//
+
+void CDrmStdKeyStorage::RandomDataGetL( TDes8& aData, const TInt aLength )
+    {
+    if ( aLength <= 0 )
+        {
+         User::Leave(KErrArgument);
+        }
+
+    TInt size = aData.MaxSize();
+
+    if( size < aLength )
+        {
+        User::Leave(KErrOverflow);
+        }
+
+    TRandom::Random( aData );
+    }
+
+// end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/breakdeps/DRMEngine/DrmStdKeyStorage.mmp	Wed Oct 27 13:24:02 2010 +0100
@@ -0,0 +1,68 @@
+/*
+* Copyright (c) 2004-2006 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:  DRM Std Key Storage Module
+*
+*/
+
+
+#include <platform_paths.hrh>
+
+TARGET          DrmStdKeyStorage.dll
+TARGETTYPE      DLL
+UID             0x1000008D 0x10205CAF
+CAPABILITY      CAP_GENERAL_DLL DRM CommDD
+VENDORID        VID_DEFAULT
+
+USERINCLUDE     ../keystorage/inc
+USERINCLUDE     ../utils/inc
+USERINCLUDE	    ../../../inc   // ADo level inc dir
+
+// Default system include paths for middleware layer modules.
+MW_LAYER_SYSTEMINCLUDE
+SYSTEMINCLUDE   /epoc32/include/libc
+SYSTEMINCLUDE   /epoc32/include/ecom
+
+SOURCEPATH      ../keystorage/src
+SOURCE          DrmStdKeyStorage.cpp
+
+LIBRARY         euser.lib
+LIBRARY         efsrv.lib    
+LIBRARY         asn1.lib
+LIBRARY         cryptography.lib 
+LIBRARY         crypto.lib 
+LIBRARY         x500.lib
+LIBRARY         x509.lib
+LIBRARY         pkixcert.lib
+LIBRARY         random.lib
+LIBRARY         hash.lib
+LIBRARY         etel.lib
+LIBRARY	        etelmm.lib
+LIBRARY         flogger.lib
+LIBRARY		featmgr.lib
+
+#ifdef RD_MULTIPLE_DRIVE
+LIBRARY       platformenv.lib
+#endif
+
+#if defined(ARMCC)
+deffile ../eabi/ 
+#elif defined( WINSCW )
+deffile ../bwinscw/ 
+#elif defined( WINS )
+deffile ../bwins/ 
+#else
+deffile ../bmarm/ 
+#endif
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/breakdeps/DRMEngine/ROAPHandler.mmp	Wed Oct 27 13:24:02 2010 +0100
@@ -0,0 +1,141 @@
+/*
+* Copyright (c) 2004-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:  ROAP Handler build configuration
+*
+*/
+
+
+#include <platform_paths.hrh>
+#include <data_caging_paths.hrh>
+
+TARGET          ROAPHandler.dll
+TARGETTYPE      DLL
+UID             0x1000008D 0x101F6DB5
+CAPABILITY      CAP_GENERAL_DLL DRM
+VENDORID        VID_DEFAULT
+
+USERINCLUDE     ../dcf/inc
+USERINCLUDE     ../dm/inc
+USERINCLUDE     ../agentv2/inc
+USERINCLUDE     ../ro/inc
+USERINCLUDE     ../roap/inc
+USERINCLUDE     ../utils/inc
+USERINCLUDE     ../server/inc
+USERINCLUDE     ../roapstorage/inc
+USERINCLUDE     ../drmclock/Inc
+USERINCLUDE     ../dcfrepository/client/inc
+USERINCLUDE     ../../../inc   // ADo level inc dir
+
+// Default system include paths for middleware layer modules.
+APP_LAYER_SYSTEMINCLUDE
+SYSTEMINCLUDE   /epoc32/include/libc
+SYSTEMINCLUDE   /epoc32/include/ecom
+
+SOURCEPATH  ../roap/src
+
+SOURCE      RoapEngBase.cpp
+SOURCE      RoapEng.cpp
+SOURCE      RoapTrigger.cpp
+SOURCE      RoapHttpHandler.cpp
+SOURCE      RoapConnection.cpp
+SOURCE      RoapResponse.cpp
+SOURCE      RoapSyncWrapper.cpp
+
+SOURCE      RoapSigner.cpp
+
+SOURCE      RoapParser.cpp
+SOURCE      JoinDomainRespParser.cpp
+SOURCE      LeaveDomainRespParser.cpp
+SOURCE      RegistrationRespParser.cpp
+SOURCE      RightsRespParser.cpp
+SOURCE      RIHelloParser.cpp
+SOURCE      RoapTriggerParser.cpp
+
+SOURCE      RoapMessage.cpp
+SOURCE      DeviceHello.cpp
+SOURCE      RIHello.cpp
+SOURCE      RegistrationReq.cpp
+SOURCE      RegistrationResp.cpp
+SOURCE      RightsReq.cpp
+SOURCE      RightsResp.cpp
+SOURCE      JoinDomainReq.cpp
+SOURCE      JoinDomainResp.cpp
+SOURCE      LeaveDomainReq.cpp
+SOURCE      LeaveDomainResp.cpp
+
+#ifdef RD_DRM_METERING
+SOURCE      MeteringReportReq.cpp
+SOURCE      MeteringReportResp.cpp
+SOURCE      MeteringReportRespParser.cpp
+#endif
+
+SOURCEPATH  ../utils/src
+SOURCE      MultipartHandler.cpp
+
+LIBRARY     euser.lib
+LIBRARY     estor.lib
+LIBRARY     efsrv.lib
+LIBRARY     commdb.lib
+LIBRARY     bafl.lib
+LIBRARY     esock.lib
+LIBRARY     http.lib
+LIBRARY     inetprotutil.lib
+LIBRARY     XmlFramework.lib
+LIBRARY     apmime.lib
+LIBRARY     asn1.lib
+LIBRARY     cryptography.lib
+LIBRARY     crypto.lib
+LIBRARY     ecom.lib
+LIBRARY     x509.lib
+LIBRARY     x500.lib
+LIBRARY     pkixcert.lib
+LIBRARY     random.lib
+LIBRARY     hash.lib
+LIBRARY     etel.lib
+LIBRARY     etelmm.lib
+LIBRARY     CharConv.lib
+LIBRARY     drmcrypto.lib
+LIBRARY     DrmParsers.lib
+LIBRARY     DrmDcf.lib
+LIBRARY     DrmRights.lib
+LIBRARY     DrmServerInterfaces.lib
+LIBRARY     DcfRep.lib
+LIBRARY     caf.lib                     // Embedding domain ROs
+LIBRARY     cafutils.lib                // Embedding domain ROs
+LIBRARY     centralrepository.lib       // Browser default AP
+LIBRARY     cmmanager.lib
+LIBRARY	    featmgr.lib
+
+LIBRARY     SysUtil.lib
+LIBRARY     HttpFilterCommon.lib
+LIBRARY     CommonUI.lib
+LIBRARY     PlatformEnv.lib
+LIBRARY     drmroapwbxmlparser.lib
+
+
+// Uncomment the following lines to enable internal logging.
+macro      _ROAP_TESTING
+LIBRARY    flogger.lib
+
+#if defined(ARMCC)
+deffile ../eabi/
+#elif defined( WINSCW )
+deffile ../bwinscw/
+#elif defined( WINS )
+deffile ../bwins/
+#else
+deffile ../bmarm/
+#endif
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/breakdeps/DRMEngine/RightsServer.mmp	Wed Oct 27 13:24:02 2010 +0100
@@ -0,0 +1,187 @@
+/*
+* 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:  Makefile of DRM Engine & DRM Rights Database
+*
+*/
+
+
+#include <platform_paths.hrh>
+
+TARGET          RightsServer.exe
+TARGETTYPE      EXE
+
+UID             0x1000008d 0x101F51F2
+CAPABILITY      CAP_SERVER DRM CommDD ProtServ PowerMgmt Location
+VENDORID        VID_DEFAULT
+
+// Default system include paths for middleware layer modules.
+MW_LAYER_SYSTEMINCLUDE
+SYSTEMINCLUDE   /epoc32/include/libc
+SYSTEMINCLUDE   /epoc32/include/connect
+
+USERINCLUDE     ../server/inc
+USERINCLUDE     ../agentv2/inc
+USERINCLUDE     ../ro/inc
+USERINCLUDE     ../dcf/inc
+USERINCLUDE     ../notifier/inc
+USERINCLUDE     ../utils/inc
+USERINCLUDE     ../roap/inc
+USERINCLUDE     ../roapstorage/inc
+USERINCLUDE     ../drmclock/Inc
+USERINCLUDE     ../keystorage/inc
+USERINCLUDE     ../drmbackup/inc
+USERINCLUDE     ../../../inc   // ADo level inc dir
+
+SOURCEPATH      ../server/src
+
+// DRM Engine (server side)
+SOURCE          DRMRightsServer.cpp
+SOURCE          DRMDbSession.cpp
+// SOURCE       drmpermissionlist.cpp
+SOURCE          drmparentstorage.cpp
+// SOURCE       drmpermissionitem.cpp
+SOURCE          DRMReplayCache.cpp
+SOURCE          DRMXOma.cpp
+SOURCE          DRMActiveOperation.cpp
+SOURCE          DRMObsoleteFinder.cpp
+SOURCE          drmconsume.cpp
+
+// DRM Rights Database
+SOURCE          drmrightsdb.cpp
+SOURCE          DRMRightsData.cpp
+SOURCE          DRMCommonData.cpp
+SOURCE          DRMRightsCleaner.cpp
+
+// DRM Metering
+#ifdef RD_DRM_METERING
+SOURCE          drmmeteringdbdata.cpp
+#endif
+SOURCE          drmmeteringdb.cpp
+
+// DRM Backup implementation
+SOURCEPATH      ../drmbackup/src
+SOURCE          DRMBackup.cpp
+SOURCE          DRMBackupObserver.cpp
+
+// DRM Notifier
+SOURCEPATH      ../notifier/src
+
+SOURCE          DRMMessageStorage.cpp
+SOURCE          DRMNotifierServer.cpp
+SOURCE          DRMNotifierSession.cpp
+
+// RoapStorage
+SOURCEPATH      ../roapstorage/src
+
+SOURCE          RoapStorageClient.cpp
+SOURCE          RoapStorageServer.cpp
+SOURCE          RoapStorageSession.cpp
+SOURCE          DRMContextDB.cpp
+// OCSP cert classes
+SOURCE          responsedecoder.cpp
+SOURCE          response.cpp
+SOURCE          responsecertinfo.cpp
+SOURCE          certid.cpp
+
+
+// DRM Clock
+#ifdef __DRM_CLOCK
+SOURCEPATH      ../drmclock/Src
+SOURCE          DRMClock.cpp
+SOURCE          DRMClockServer.cpp
+SOURCE          DRMClockSession.cpp
+
+SOURCE          DRMNitzObserver.cpp
+SOURCE          GPSWatcher.cpp
+SOURCE          GPSTimeUpdater.cpp
+
+#else
+#ifdef __DRM_OMA2
+SOURCEPATH      ../DRMClock/src
+SOURCE          OMA2NotSupportedWithoutDRMClock:define__DRM_CLOCKvariation.cpp
+#endif // __DRM_OMA2
+#endif // __DRM_CLOCK
+
+// RDB and Process Watcher
+SOURCEPATH      ../utils/src
+SOURCE          dbwatcher.cpp
+SOURCE          dirwatcher.cpp
+SOURCE          procwatcher.cpp
+
+LIBRARY         drmdcf.lib
+LIBRARY         drmrights.lib
+LIBRARY         drmserverinterfaces.lib
+LIBRARY         euser.lib
+LIBRARY         estor.lib
+LIBRARY         efsrv.lib
+LIBRARY         hash.lib
+LIBRARY         cryptography.lib
+LIBRARY         crypto.lib
+LIBRARY         asn1.lib
+LIBRARY         x509.lib
+LIBRARY         x500.lib
+LIBRARY         pkixcert.lib
+LIBRARY         drmcrypto.lib
+LIBRARY         drmkeystorage.lib
+LIBRARY         edbms.lib
+LIBRARY         bafl.lib
+LIBRARY         etel.lib
+LIBRARY         etelmm.lib
+LIBRARY         abclient.lib
+LIBRARY         charconv.lib
+LIBRARY         dcfrep.lib
+LIBRARY         drmparsers.lib              // DRM message parser for RO import
+LIBRARY         centralrepository.lib       // Browser default AP
+LIBRARY         InetProtUtil.lib            // URI parser
+LIBRARY         flogger.lib
+LIBRARY         featmgr.lib                 // Feature Manager
+LIBRARY         wmdrmfileserverclient.lib
+LIBRARY         lbs.lib                     // GPS libraries
+LIBRARY         eposindicator.lib           // GPS positioner indicator lib
+#ifdef RD_DRM_METERING
+LIBRARY         random.lib
+#endif
+
+LIBRARY StarterClient.lib // reset
+
+#ifdef RD_MULTIPLE_DRIVE
+LIBRARY         platformenv.lib
+#endif
+
+LIBRARY         SysUtil.lib
+// LIBRARY      commonengine.lib // Backup
+
+/*
+#if !defined(WINS)
+MACRO           DRM_USE_SERIALNUMBER
+LIBRARY         etel.lib
+#endif
+*/
+// Uncomment the following lines to enable internal logging.
+/*
+macro _DRM_TESTING
+USERINCLUDE     ../internal/tsrc_internal
+SOURCEPATH      ../internal/tsrc_internal
+LIBRARY         drmdebugtools.lib
+LIBRARY         HAL.lib
+LIBRARY         charconv.lib
+*/
+
+#if defined( WINSCW )
+deffile ../bwinscw/
+#elif defined( WINS )
+deffile ../bwins/
+#endif
+
+//SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/breakdeps/DRMEngine/RoapEng.cpp	Wed Oct 27 13:24:02 2010 +0100
@@ -0,0 +1,2695 @@
+/*
+* Copyright (c) 2002-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:  Roap engine
+ *
+*/
+
+
+// INCLUDE FILES
+
+#include <random.h>
+
+#include <DocumentHandler.h>
+
+#ifdef RD_MULTIPLE_DRIVE
+#include  <pathinfo.h>
+#include  <driveinfo.h>
+#else
+#include  <pathinfo.h>
+#endif
+
+#ifndef __WINS__
+#include <etelmm.h>
+#include <mmtsy_names.h>
+#include <SysUtil.h>
+#endif
+
+#include <flogger.h>
+#include <x509cert.h>
+#include <x509certext.h>
+#include <hash.h>
+#include <utf.h>
+#include <asn1dec.h>
+#include <centralrepository.h>
+#include <e32base.h>  // CleanupResetAndDestroyPushL dependencies
+
+#include "cleanupresetanddestroy.h" // CleanupResetAndDestroyPushL
+#include "DRMRights.h"
+#include "RoapEng.h"
+#include "RoapTrigger.h"
+#include "wbxmlroaptriggerparser.h"
+#include "RoapResponse.h"
+#include "RoapMessage.h"
+#include "RoapParser.h"
+#include "RoapSigner.h"
+#include "DeviceHello.h"
+#include "RIHello.h"
+#include "RegistrationReq.h"
+#include "RegistrationResp.h"
+#include "RightsReq.h"
+#include "RightsResp.h"
+#include "JoinDomainReq.h"
+#include "JoinDomainResp.h"
+#include "LeaveDomainReq.h"
+#include "LeaveDomainResp.h"
+#ifdef RD_DRM_METERING
+#include "MeteringReportReq.h"
+#include "MeteringReportResp.h"
+#endif
+#include "RoapStorageClient.h"
+#include "RoapDef.h"
+#include "RoapLog.h"
+#include "RoapObserver.h"
+#include "CmlaCrypto.h"
+#include "DRMRIContext.h"
+#include "DRMDomainContext.h"
+#include "DRMProtectedRoParser.h"
+#include "DRMClockClient.h"
+#include "DcfRep.h"
+#include "DcfEntry.h"
+#include "Base64.h"
+#include "drmsettingsplugininternalcrkeys.h"
+
+
+#define STUB_C_CLASS_IN_NAMESPACE( n, c ) namespace n { class c: public CBase { private: c(); public: virtual ~c(); }; } n::c::c() {} n::c::~c() {}
+#define STUB_C_CLASS( c ) class c : public CBase { private: c(); public: virtual ~c(); }; c::c() {} c::~c() {}
+// This class does not do anything.
+// It is defined here only to keep binary compatibility,
+// because of unintentional class name leak in
+// armv5 export history.
+// Don't ever use this class for anything.
+STUB_C_CLASS_IN_NAMESPACE( Roap , CWbxmlRoapTriggerToXmlParser )
+
+// Yet another stub classes because of moved classes
+// which have leaked virtual table entries
+STUB_C_CLASS( COCSPResponse )
+STUB_C_CLASS( COCSPResponseCertInfo )
+
+
+using namespace Roap;
+// ================= CONSTANTS =======================
+// For parsing multipart content
+_LIT8(KCmlaIp1, "http://www.cm-la.com/tech/cmlaip/cmlaip#cmlaip-1");
+_LIT8(KLeaveDomainElement, "leaveDomain");
+_LIT8(KSignedInfoElement, "SignedInfo");
+_LIT(KBOM1, "\xFFFE");
+_LIT(KBOM2, "\xFEFF");
+#ifdef RD_DRM_METERING
+_LIT8( KRoapVersion11, "1.1" );
+#endif
+
+static const TInt KDomainGenerationLength( 3 );
+static const TInt KMinCertChainLength( 3 );
+// ================= LOCAL FUNCTIONS =======================
+
+LOCAL_C TBool SortArrays(
+    RPointerArray<HBufC8>& aKeys,
+    RPointerArray<HBufC8>& aMacs,
+    RPointerArray<HBufC8>& aElements,
+    RArray<TInt>& aOrder )
+    {
+    TInt i;
+    TInt j;
+    TInt index;
+    HBufC8* temp1 = NULL;
+    HBufC8* temp2 = NULL;
+    HBufC8* temp3 = NULL;
+    TBool isInOrder = ETrue;
+
+    if ( aOrder.Count() != aKeys.Count() || aKeys.Count() != aMacs.Count()
+        || aMacs.Count() != aElements.Count() )
+        {
+        return EFalse;
+        }
+
+    for ( i = 0; i < aKeys.Count(); i++ )
+        {
+        index = aOrder[i];
+        temp1 = aKeys[i];
+        temp2 = aMacs[i];
+        temp3 = aElements[i];
+        j = i;
+        while ( ( j > 0 ) && ( aOrder[j - 1] > index ) )
+            {
+            isInOrder = EFalse;
+            aOrder[j] = aOrder[j - 1];
+            aKeys[j] = aKeys[j - 1];
+            aMacs[j] = aMacs[j - 1];
+            aElements[j] = aElements[j - 1];
+            j = j - 1;
+            }
+        aOrder[j] = index;
+        aKeys[j] = temp1;
+        aMacs[j] = temp2;
+        aElements[j] = temp3;
+        }
+    return isInOrder;
+    }
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CRoapEng::NewL()
+// ---------------------------------------------------------
+//
+EXPORT_C CRoapEng* CRoapEng::NewL()
+    {
+    CRoapEng* engine = new ( ELeave ) CRoapEng();
+    CleanupStack::PushL( engine );
+    engine->ConstructL();
+    CleanupStack::Pop( engine );
+    return engine;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::~CRoapEng()
+// ---------------------------------------------------------
+//
+EXPORT_C CRoapEng::~CRoapEng()
+    {
+    if ( iStorageClient )
+        {
+        iStorageClient->Close();
+        }
+    delete iStorageClient;
+    if ( iClockClient )
+        {
+        iClockClient->Close();
+        }
+    delete iClockClient;
+    delete iParser;
+    delete iSigner;
+    delete iDeviceId;
+    delete iRoParser;
+    delete iDcfRep;
+    iRiAlgorithms.ResetAndDestroy();
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::~CRoapEng()
+// ---------------------------------------------------------
+//
+void CRoapEng::ConstructL()
+    {
+    LOGLIT( "CRoapEng::ConstructL" )
+
+    CRoapEngBase::ConstructL();
+    iParser = CRoapParser::NewL();
+    iStorageClient = new ( ELeave ) RRoapStorageClient;
+    User::LeaveIfError( iStorageClient->Connect() );
+    iClockClient = new ( ELeave ) RDRMClockClient;
+    User::LeaveIfError( iClockClient->Connect() );
+    TBuf8<SHA1_HASH> deviceId;
+    iStorageClient->GetDevicePublicKeyHashL( deviceId );
+    iDeviceId = deviceId.AllocL();
+    iSigner = CRoapSigner::NewL( *iStorageClient );
+    iRoParser = CDrmProtectedRoParser::NewL();
+    iDcfRep = CDcfRep::NewL();
+    iCertNeeded = ETrue;
+    iRiSupportsCertCaching = EFalse;
+    iTransStatus = ENotAsked;
+    iSelectedAlgorithms = EOma;
+    iSelectedRoot = KNullDesC8;
+    iStorageClient->SelectTrustedRootL( KNullDesC8 );
+    iDeviceTimeError = EFalse;
+    iDomainId.SetLength( 0 );
+    iSecureTime = ETrue;
+    iZone = 0;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::CRoapEng()
+// ---------------------------------------------------------
+//
+CRoapEng::CRoapEng() :
+    CRoapEngBase()
+    {
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::ParseTriggerL()
+// ---------------------------------------------------------
+//
+CRoapTrigger* CRoapEng::ParseTriggerL( const TDesC8& aTrigger )
+    {
+    LOGLIT( "CRoapEng::ParseTriggerL" )
+
+    CRoapTrigger* trigger( NULL );
+    RBuf8 xmlTrigger;
+    CleanupClosePushL( xmlTrigger );
+    _LIT8( KRoap, "<roap:roapTrigger" );
+    if ( aTrigger.FindF( KRoap ) == KErrNotFound )
+        {
+        DRM::CWbxmlRoapTriggerParser* wbParser(
+            DRM::CWbxmlRoapTriggerParser::NewLC() );
+        HBufC8* b( NULL );
+        TRAPD( parseError, b = wbParser->ParseL( aTrigger ) );
+        if ( parseError == KErrNone )
+            {
+            xmlTrigger.Assign( b );
+            b = NULL;
+            LOGLIT( "  We have a WBXML trigger" )
+            }
+        else
+            { // OMA BCAST: Check if this is an XML trigger after all..
+            LOGLIT( "  We have an XML trigger after all" )
+            xmlTrigger.CreateL( aTrigger );
+            }
+        CleanupStack::PopAndDestroy( wbParser );
+        }
+    else
+        {
+        xmlTrigger.CreateL( aTrigger );
+        }
+    trigger = iParser->ParseRoapTriggerL( xmlTrigger );
+
+    CleanupStack::PushL( trigger );
+    if ( !trigger || !trigger->ValidTrigger() )
+        {
+        User::Leave( KErrRoapGeneral );
+        }
+
+    // check that SilentRightsUrl is on the white list
+    // URL is searched from pre-configured white list
+    TBool fromPreConfiguredWhiteList( ETrue );
+    if ( iStorageClient->WhiteListURLExistsL( *trigger->iRoapUrl, fromPreConfiguredWhiteList ) )
+        {
+        iAllowedToContactRi = ETrue;
+        }
+
+    if ( trigger->iTriggerType == ELeaveDomainTrigger && trigger->iSignature )
+        {
+        if ( !VerifyTriggerSignatureL( xmlTrigger, *trigger ) )
+            {
+            User::Leave( KErrRoapServerFatal );
+            }
+        }
+
+    CleanupStack::Pop( trigger );
+    CleanupStack::PopAndDestroy( &xmlTrigger );
+
+    return trigger;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::GetRIContextL()
+// ---------------------------------------------------------
+//
+void CRoapEng::GetRIContextL( TBool& aRegistered, const TDesC8& aRiId )
+    {
+    LOGLIT( "CRoapEng::GetRIContextL" )
+
+    CDRMRIContext* context = NULL;
+
+    aRegistered = EFalse;
+
+    // delete old RI context and obtain a new one
+    delete iStoredRiContext;
+    iStoredRiContext = NULL;
+    context = iStorageClient->GetRIContextL( aRiId );
+    if ( !context )
+        {
+        return;
+        }
+
+    iStoredRiContext = context;
+    iRiSupportsCertCaching = iStoredRiContext->DeviceCertCached();
+    iSelectedRoot = iStoredRiContext->SelectedDeviceRoot();
+    iStorageClient->SelectTrustedRootL( iSelectedRoot );
+
+    if ( context->CertificateChain().Count() && context->ExpiryTime()
+        > GetDrmTimeL() )
+        {
+        aRegistered = ETrue;
+        iUseRiContextUrl = EFalse;
+        }
+    else
+        {
+        // Received Context was invalid or expired
+        iUseRiContextUrl = EFalse;
+        delete iStoredRiContext;
+        iStoredRiContext = NULL;
+        }
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::GetDomainContextL()
+// ---------------------------------------------------------
+//
+void CRoapEng::GetDomainContextL(
+    TBool& aIsJoined,
+    TBool& aIsValidGeneration,
+    const TDesC8& aDomainId )
+    {
+    LOGLIT( "CRoapEng::GetDomainContextL" )
+
+    TInt generation = 0;
+    CDRMDomainContext* context = NULL;
+
+    aIsJoined = EFalse;
+    aIsValidGeneration = EFalse;
+
+    // last 3 digits are for Domain generation
+    context = iStorageClient->GetDomainContextL( aDomainId );
+
+    if ( !context )
+        {
+        return;
+        }
+
+    if ( context->ExpiryTime() > GetDrmTimeL() || context->ExpiryTime()
+        == Time::NullTTime() )
+        {
+        aIsJoined = ETrue;
+        }
+
+    TLex8 lex( aDomainId.Right( KDomainGenerationLength ) );
+    lex.Val( generation );
+
+    if ( context->DomainGeneration() >= generation )
+        {
+        aIsValidGeneration = ETrue;
+        }
+
+    delete context;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::CreateReqMessageL()
+// ---------------------------------------------------------
+//
+void CRoapEng::CreateReqMessageL()
+    {
+    LOGLIT( "CRoapEng::CreateReqMessageL" )
+
+    __ASSERT_ALWAYS( iTrigger, User::Invariant() );
+    __ASSERT_ALWAYS( !iRequest, User::Invariant() );
+
+    switch ( iReqMessage )
+        {
+        case EDeviceHello:
+            {
+            iRequest = CreateDeviceHelloL();
+            break;
+            }
+        case ERegistration:
+            {
+            iRequest = CreateRegistrationRequestL();
+            break;
+            }
+        case EROAcquisition:
+            {
+            iRequest = CreateRightsRequestL();
+            break;
+            }
+        case EJoinDomain:
+            {
+            iRequest = CreateJoinDomainRequestL();
+            break;
+            }
+        case ELeaveDomain:
+            {
+            iRequest = CreateLeaveDomainRequestL();
+            break;
+            }
+#ifdef RD_DRM_METERING
+        case EMeteringRequest:
+            {
+            iRequest = CreateMeteringReportRequestL();
+            break;
+            }
+#endif
+        default:
+            {
+            User::Leave( KErrArgument );
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::CreateDeviceHelloL()
+// ---------------------------------------------------------
+//
+CRoapMessage* CRoapEng::CreateDeviceHelloL()
+    {
+    LOGLIT( "CRoapEng::CreateDeviceHelloL" )
+    PERFORMANCE_LOGLIT( "Registration protocol started" )
+
+    RPointerArray<TDesC8> idArray;
+    CDeviceHello* req = CDeviceHello::NewL();
+    CleanupStack::PushL( req );
+
+    // Multi-PKI addition
+    CleanupResetAndDestroyPushL( idArray );
+    CreateDeviceIdHashArrayL( idArray );
+    for ( TInt i = 0; i < idArray.Count(); i++ )
+        {
+        req->iDeviceIdArray.AppendL( *idArray[i] );
+        }
+    CleanupStack::PopAndDestroy( &idArray );
+    // Multi-PKI
+
+#ifndef RD_DRM_METERING
+    req->iVersion.Copy( KRoapVersion ); // Version 1.0
+#else
+    req->iVersion.Copy( KRoapVersion11 );
+#endif
+    if ( iTrigger->iNonce )
+        {
+        req->iTriggerNonce = iTrigger->iNonce->AllocL();
+        }
+    CmlaCrypto::SupportedAlgorithmsL( req->iAlgorithms );
+    iSelectedAlgorithms = EOma;
+
+    CleanupStack::Pop( req );
+    return req;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::CreateRegistrationRequestL()
+// ---------------------------------------------------------
+//
+CRoapMessage* CRoapEng::CreateRegistrationRequestL()
+    {
+    LOGLIT( "CRoapEng::CreateRegistrationRequestL ->" )
+
+    __ASSERT_ALWAYS( iResponse, User::Invariant() );
+
+    CRegistrationReq* req = NULL;
+    CRIHello* resp = NULL;
+    RPointerArray<HBufC8> trustedRootArray;
+    HBufC8* temp = NULL;
+
+    resp = STATIC_CAST( CRIHello*, iResponse );
+    req = CRegistrationReq::NewL();
+    CleanupStack::PushL( req );
+    if ( resp->iSession )
+        {
+        req->iSession = resp->iSession->AllocL();
+        }
+    else
+        {
+        User::Leave( KErrRoapServerFatal );
+        }
+
+    req->iNonce.SetLength( KDeviceNonceLength );
+    TRandom::Random( req->iNonce );
+
+    req->iTime = GetDrmTimeL();
+
+    // store the nonce for DRM Time sync
+    iRegReqNonce = req->iNonce;
+
+    if ( iCertNeeded )
+        {
+        req->iCertificateChain = GetCertificateChainL();
+        if ( resp->iCertificateCaching )
+            {
+            iCertNeeded = EFalse;
+            }
+        }
+
+    // Send all our trusted roots to the RI
+    CleanupResetAndDestroyPushL( trustedRootArray );
+
+    LOGLIT( "  Getting trusted roots" )
+
+    iStorageClient->GetTrustedRootsL( trustedRootArray );
+
+    if ( !trustedRootArray.Count() )
+        {
+        // No trusted roots found!
+        LOGLIT( "  No trusted roots found!" )
+        User::Leave( KErrRoapDevice );
+        }
+    for ( TInt i = 0; i < trustedRootArray.Count(); i++ )
+        {
+        temp = trustedRootArray[i]->AllocLC();
+        req->iTrustedAuthorities.AppendL( temp );
+        CleanupStack::Pop( temp );
+        }
+
+    LOGLIT( "  Setting server info" )
+    if ( resp->iServerInfo && resp->iServerInfo->Size() )
+        {
+        req->iServerInfo = resp->iServerInfo->AllocL();
+        }
+
+    if ( iStoredRiContext )
+        {
+        LOGLIT( "  RI context available" )
+        req->iPeerKeyIdentifier = iStoredRiContext->RIID();
+
+        if ( iStoredRiContext->OCSPResponse().Count() && !iDeviceTimeError )
+            {
+            req->iOcspInfoStored = ETrue;
+            req->iOcspResponderKeyId = GetOCSPResponderKeyHashL();
+            }
+        }
+    if ( resp->iNeedDeviceDetails )
+        {
+        LOGLIT( "  Getting device details" )
+        GetDeviceDetailsL( req->iDeviceDetailsManufacturer,
+            req->iDeviceDetailsModel, req->iDeviceDetailsVersion );
+        }
+
+    if ( iTrigger->iNonce )
+        {
+        req->iTriggerNonce = iTrigger->iNonce->AllocL();
+        }
+
+    CleanupStack::PopAndDestroy( &trustedRootArray );
+    CleanupStack::Pop( req );
+
+    LOGLIT( "CRoapEng::CreateRegistrationRequestL <-" )
+
+    return req;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::CreateRightsRequestL()
+// ---------------------------------------------------------
+//
+CRoapMessage* CRoapEng::CreateRightsRequestL()
+    {
+    LOGLIT( "CRoapEng::CreateRightsRequestL" )
+    PERFORMANCE_LOGLIT( "RO acquisition protocol started" )
+
+    __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() );
+
+    CRightsReq* req = NULL;
+    RPointerArray<HBufC8> ttIDs;
+    RPointerArray<HBufC8> cids;
+    HBufC8* temp = NULL;
+    TBuf8<SHA1_HASH> deviceId;
+
+    req = CRightsReq::NewL();
+    CleanupStack::PushL( req );
+
+    req->iNonce.SetLength( KDeviceNonceLength );
+    TRandom::Random( req->iNonce );
+
+    req->iTime = GetDrmTimeL();
+
+    iStorageClient->GetDevicePublicKeyHashL( deviceId );
+    delete iDeviceId;
+    iDeviceId = NULL;
+    iDeviceId = deviceId.AllocL();
+    req->iDeviceId = *iDeviceId;
+
+    req->iRiId.Copy( iTrigger->iRiId );
+
+    if ( !iRiSupportsCertCaching )
+        {
+        req->iCertificateChain = GetCertificateChainL();
+        }
+    if ( iTrigger->iDomainId )
+        {
+        req->iDomainId = iTrigger->iDomainId->AllocL();
+        }
+
+    for ( TInt i = 0; i < iTrigger->iRoIdList.Count(); i++ )
+        {
+        temp = iTrigger->iRoIdList[i]->AllocLC();
+        req->iRoIdList.AppendL( temp );
+        CleanupStack::Pop( temp );
+        }
+
+    if ( iStoredRiContext )
+        {
+        req->iPeerKeyIdentifier = iStoredRiContext->RIID();
+
+        if ( iStoredRiContext->OCSPResponse().Count() )
+            {
+            req->iOcspInfoStored = ETrue;
+            req->iOcspResponderKeyId = GetOCSPResponderKeyHashL();
+            }
+        }
+
+    CleanupResetAndDestroyPushL( cids );
+
+    CleanupResetAndDestroyPushL( ttIDs );
+
+    FetchTransactionIDL( ttIDs, cids );
+
+    for ( TInt i = 0; i < ttIDs.Count() && i < cids.Count(); i++ )
+        {
+        temp = ttIDs[i]->AllocLC();
+        req->iTransTrackIDs.AppendL( temp );
+        CleanupStack::Pop( temp );
+        temp = cids[i]->AllocLC();
+        req->iContentIDs.AppendL( temp );
+        CleanupStack::Pop( temp );
+        }
+
+    CleanupStack::PopAndDestroy( &ttIDs );
+    CleanupStack::PopAndDestroy( &cids );
+
+    if ( iTrigger->iNonce )
+        {
+        req->iTriggerNonce = iTrigger->iNonce->AllocL();
+        }
+
+    CleanupStack::Pop( req );
+    return req;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::CreateJoinDomainRequestL()
+// ---------------------------------------------------------
+//
+CRoapMessage* CRoapEng::CreateJoinDomainRequestL()
+    {
+    LOGLIT( "CRoapEng::CreateJoinDomainRequestL" )
+    PERFORMANCE_LOGLIT( "Join domain protocol started" )
+
+    __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() );
+
+    CJoinDomainReq* req = NULL;
+    TBuf8<SHA1_HASH> deviceId;
+
+    req = CJoinDomainReq::NewL();
+    CleanupStack::PushL( req );
+
+    req->iNonce.SetLength( KDeviceNonceLength );
+    TRandom::Random( req->iNonce );
+
+    req->iTime = GetDrmTimeL();
+
+    iStorageClient->GetDevicePublicKeyHashL( deviceId );
+    delete iDeviceId;
+    iDeviceId = NULL;
+    iDeviceId = deviceId.AllocL();
+    req->iDeviceId = *iDeviceId;
+
+    req->iRiId.Copy( iTrigger->iRiId );
+
+    if ( !iRiSupportsCertCaching )
+        {
+        req->iCertificateChain = GetCertificateChainL();
+        }
+    if ( iTrigger->iDomainId )
+        {
+        req->iDomainId = iTrigger->iDomainId->AllocL();
+        iDomainId.Copy( *req->iDomainId );
+        }
+    else if ( iDomainId.Length() && iTrigger->iTriggerType
+        == ERoAcquisitionTrigger )
+        {
+        req->iDomainId = iDomainId.AllocL();
+        }
+    else
+        {
+        User::Leave( KErrRoapServerFatal );
+        }
+
+    if ( iStoredRiContext )
+        {
+        req->iPeerKeyIdentifier = iStoredRiContext->RIID();
+
+        if ( iStoredRiContext->OCSPResponse().Count() )
+            {
+            req->iOcspInfoStored = ETrue;
+            req->iOcspResponderKeyId = GetOCSPResponderKeyHashL();
+            }
+        }
+
+#ifdef _DISABLE_HASH_CHAIN_GENERATION
+    req->iHashChainSupport = EFalse;
+#endif
+
+    if ( iTrigger->iNonce )
+        {
+        req->iTriggerNonce = iTrigger->iNonce->AllocL();
+        }
+
+    CleanupStack::Pop( req );
+    return req;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::CreateLeaveDomainRequestL()
+// ---------------------------------------------------------
+//
+CRoapMessage* CRoapEng::CreateLeaveDomainRequestL()
+    {
+    LOGLIT( "CRoapEng::CreateLeaveDomainRequestL" )
+    PERFORMANCE_LOGLIT( "Leave domain protocol started" )
+
+    __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() );
+
+    if ( !iTrigger->iDomainId )
+        {
+        User::Leave( KErrRoapServerFatal );
+        }
+    // delete Domain context before sending LeaveDomain req
+    TRAPD( ret, iStorageClient->DeleteDomainContextL( *iTrigger->iDomainId ));
+
+    CLeaveDomainReq* req = NULL;
+    TBuf8<SHA1_HASH> deviceId;
+
+    req = CLeaveDomainReq::NewL();
+    CleanupStack::PushL( req );
+
+    if ( ret == KErrNotFound )
+        {
+        req->iNotMember = ETrue;
+        }
+    else
+        {
+        req->iNotMember = EFalse;
+        User::LeaveIfError( ret );
+        }
+
+    req->iNonce.SetLength( KDeviceNonceLength );
+    TRandom::Random( req->iNonce );
+
+    req->iTime = GetDrmTimeL();
+
+    iStorageClient->GetDevicePublicKeyHashL( deviceId );
+    delete iDeviceId;
+    iDeviceId = NULL;
+    iDeviceId = deviceId.AllocL();
+    req->iDeviceId = *iDeviceId;
+
+    req->iRiId.Copy( iTrigger->iRiId );
+
+    if ( !iRiSupportsCertCaching )
+        {
+        req->iCertificateChain = GetCertificateChainL();
+        }
+    if ( iTrigger->iDomainId )
+        {
+        req->iDomainId = iTrigger->iDomainId->AllocL();
+        }
+
+    if ( iTrigger->iNonce )
+        {
+        req->iTriggerNonce = iTrigger->iNonce->AllocL();
+        }
+
+    CleanupStack::Pop( req );
+    return req;
+    }
+// ---------------------------------------------------------
+// CRoapEng::CreateMeteringReportRequestL()
+// ---------------------------------------------------------
+//
+CRoapMessage* CRoapEng::CreateMeteringReportRequestL()
+    {
+#ifndef RD_DRM_METERING
+    return NULL;
+#else
+
+    LOGLIT( "CRoapEng::CreateMeteringReportRequestL" )
+    PERFORMANCE_LOGLIT( "Metering report creation started" )
+
+    CMeteringReportReq* req = NULL;
+    TBuf8<SHA1_HASH> deviceId;
+    TBuf8<OmaCrypto::KMacSize> macKey;
+    TBool registered( EFalse );
+
+    req = CMeteringReportReq::NewL();
+    CleanupStack::PushL( req );
+    req->iAlgorithmInUse = iSelectedAlgorithms;
+    // check if we are not using OMA algorithms
+    // and update selected algorithm accordingly
+    GetRIContextL( registered, iTrigger->iRiId );
+    if ( registered && iStoredRiContext )
+        {
+        for ( TInt i = 0; i < iStoredRiContext->Algorithms().Count(); i++ )
+            {
+            if ( iStoredRiContext->Algorithms()[i]->CompareF( KCmlaIp1() )
+                == KErrNone )
+                {
+                // note currently assumed that only
+                // 1 of 7 ppossible algorithms used
+                req->iAlgorithmInUse = ECmlaIp1;
+                break;
+                }
+            }
+        }
+
+    // generate DeviceNonce
+    req->iNonce.SetLength( KDeviceNonceLength );
+    TRandom::Random( req->iNonce );
+
+    // generate MeteringNonce
+    req->iReportNonce.SetLength( KDeviceNonceLength );
+    TRandom::Random( req->iReportNonce );
+
+    // fetch secure time for request
+    req->iTime = GetDrmTimeL();
+
+    // insert DeviceId
+    iStorageClient->GetDevicePublicKeyHashL( deviceId );
+    delete iDeviceId;
+    iDeviceId = NULL;
+    iDeviceId = deviceId.AllocL();
+    req->iDeviceId = *iDeviceId;
+
+    // insert RiId
+    req->iRiId.Copy( iTrigger->iRiId );
+
+    // insert Certificate chain if needed
+    if ( !iRiSupportsCertCaching )
+        {
+        req->iCertificateChain = GetCertificateChainL();
+        }
+
+    // add trigger Nonce
+    if ( iTrigger->iNonce )
+        {
+        req->iTriggerNonce = iTrigger->iNonce->AllocL();
+        }
+
+    // Get from server encrypted metering report mac key as plain,
+    // MEK and MAC key as encypted, and hash of
+    // PKI public key used in encryition
+    req->iCipherValue = iStorageClient->GetMeteringDataL( req->iRiId, macKey,
+        req->iEncKeyHash, req->iEncryptedMekAndMak );
+
+    // calculate mac over <encryptedMeteringReport>
+    req->InsertMacL( macKey );
+
+    CleanupStack::Pop( req );
+    return req;
+
+#endif //RD_DRM_METERING
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::HandleRoapResponseL()
+// ---------------------------------------------------------
+//
+void CRoapEng::HandleRoapResponseL( const TDesC8& aXmlResponse )
+    {
+    LOGLIT( "CRoapEng::HandleRoapMessageL" )
+
+    delete iResponse;
+    iResponse = NULL;
+
+    switch ( iReqMessage )
+        {
+        case EDeviceHello:
+            {
+            HandleRIHelloPduL( aXmlResponse );
+            break;
+            }
+        case ERegistration:
+            {
+            HandleReqResponsePduL( aXmlResponse );
+            break;
+            }
+        case EROAcquisition:
+            {
+            HandleRightsResponsePduL( aXmlResponse, EFalse );
+            break;
+            }
+        case EJoinDomain:
+            {
+            HandleJoinDomainResponsePduL( aXmlResponse );
+            break;
+            }
+        case ELeaveDomain:
+            {
+            HandleLeaveDomainResponsePduL( aXmlResponse );
+            break;
+            }
+#ifdef RD_DRM_METERING
+        case EMeteringRequest:
+            {
+            HandleMeteringReportResponsePduL( aXmlResponse );
+            break;
+            }
+#endif
+        default:
+            {
+            User::Leave( KErrArgument );
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::HandleRIHelloPduL()
+// ---------------------------------------------------------
+//
+void CRoapEng::HandleRIHelloPduL( const TDesC8& aRiHello )
+    {
+    LOGLIT( "CRoapEng::HandleRIHelloPduL" )
+
+    CRIHello* resp = NULL;
+    HBufC8* temp = NULL;
+
+    resp = iParser->ParseRIHelloL( aRiHello );
+    iRoapStatus = resp->iStatus;
+    iResponse = resp;
+    if ( iRoapStatus == ESuccess )
+        {
+        iCertNeeded = ETrue;
+        iRiSupportsCertCaching = EFalse;
+
+        if ( resp->iPeerKeyIdentifier )
+            {
+            iRiSupportsCertCaching = ETrue;
+            if ( resp->iPeerKeyId.Length() )
+                {
+                if ( resp->iPeerKeyId.CompareF( *iDeviceId ) == KErrNone )
+                    {
+                    iCertNeeded = EFalse;
+                    }
+                }
+            else
+                {
+                iCertNeeded = EFalse;
+                }
+            }
+        else if ( resp->iCertificateCaching )
+            {
+            iRiSupportsCertCaching = ETrue;
+            }
+
+        if ( resp->iAlgorithms.Count() )
+            {
+            iRiAlgorithms.ResetAndDestroy();
+            for ( TInt i = 0; i < resp->iAlgorithms.Count(); i++ )
+                {
+                if ( resp->iAlgorithms[i]->CompareF( KCmlaIp1() ) == KErrNone )
+                    {
+                    iSelectedAlgorithms = ECmlaIp1;
+                    }
+                temp = resp->iAlgorithms[i]->AllocLC();
+                iRiAlgorithms.AppendL( temp );
+                CleanupStack::Pop( temp );
+                }
+            }
+        iRiId.Copy( resp->iRiId );
+        iRiVersion.Copy( resp->iSelectedVersion );
+
+        /***
+         This is needed when the multiple PKIs are supported.
+         ***/
+        if ( resp->iTrustedAuthorities.Count() )
+            {
+            // select the first matching root from the list
+            LOGLIT( "Choose the first matching trust anchor" )
+            iStorageClient->SelectTrustedRootL( resp->iTrustedAuthorities,
+                iSelectedRoot );
+            LOGLIT( "The trust anchor selected" )
+            DETAILLOGHEX( iSelectedRoot.Ptr(), iSelectedRoot.Length() )
+            }
+        else
+            {
+            if ( iStoredRiContext && iStoredRiContext->RIID() == iRiId )
+                {
+                if ( iSelectedRoot != iStoredRiContext->SelectedDeviceRoot() )
+                    {
+                    DETAILLOGLIT( "Changing trusted root to that of saved RI context" )
+                    DETAILLOGLIT( "old root" )
+                    DETAILLOGHEX( iSelectedRoot.Ptr(), iSelectedRoot.Length() )
+
+                    iSelectedRoot = iStoredRiContext->SelectedDeviceRoot();
+                    iStorageClient->SelectTrustedRootL( iSelectedRoot );
+                    }
+                DETAILLOGLIT( "Using trusted root of saved RI context" )
+                DETAILLOGHEX( iSelectedRoot.Ptr(), iSelectedRoot.Length() )
+                }
+            else
+                {
+                DETAILLOGLIT( "Using default trusted root" )
+                iSelectedRoot = KNullDesC8;
+                iStorageClient->SelectTrustedRootL( iSelectedRoot );
+                }
+            }
+
+        iSigner->AddRequestL( aRiHello );
+        }
+    else if ( resp->iErrorUrl )
+        {
+        if ( iObserver )
+            {
+            iObserver->ErrorUrlL( *resp->iErrorUrl );
+            }
+        }
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::HandleReqResponsePduL()
+// ---------------------------------------------------------
+//
+void CRoapEng::HandleReqResponsePduL( const TDesC8& aRegResp )
+    {
+    LOGLIT( "CRoapEng::HandleReqResponsePduL" )
+
+    CRegistrationResp* resp = NULL;
+    CDRMRIContext* context = NULL;
+    CX509Certificate* cert = NULL;
+    TTime riExpiry;
+    TBool status = EFalse;
+    TUint8 riCertCaching = EFalse;
+
+    resp = iParser->ParseRegistrationRespL( aRegResp );
+    iRoapStatus = resp->iStatus;
+    iResponse = resp;
+    if ( iRoapStatus == ESuccess )
+        {
+        if ( resp->iOcspResponse.Count() > 0 )
+            {
+            // adjust DRM Time according to OCSP response
+            // All needed verifications done in server side
+            TBool deviceTimeUpdated( EFalse );
+            if ( resp->iCertificateChain.Count() > 0 )
+                {
+                deviceTimeUpdated = iStorageClient->UpdateDrmTimeL(
+                    resp->iCertificateChain, resp->iOcspResponse,
+                    iRegReqNonce );
+                }
+            else if ( iStoredRiContext )
+                {
+                deviceTimeUpdated = iStorageClient->UpdateDrmTimeL(
+                    iStoredRiContext->CertificateChain(),
+                    resp->iOcspResponse, iRegReqNonce );
+                }
+            if ( deviceTimeUpdated )
+                {
+                LOGLIT( "drm time updated" )
+                iDeviceTimeError = EFalse;
+                }
+            }
+
+        if ( !iStoredRiContext || ( resp->iCertificateChain.Count()
+            && resp->iOcspResponse.Count() ) )
+            {
+            status = VerifyCertificateChainL( resp->iCertificateChain,
+                resp->iOcspResponse );
+            if ( !status )
+                {
+                LOGLIT( "Certificate chain validation failed" )
+                User::Leave( KErrRoapServerFatal );
+                }
+            status = ValidateRiIdL( iRiId, *resp->iCertificateChain[0] );
+            if ( !status )
+                {
+                LOGLIT( "RI ID validation failed" )
+                User::Leave( KErrRoapServerFatal );
+                }
+            }
+
+        if ( iStoredRiContext )
+            {
+            // if we have already stored certificates -> use those.
+            status = VerifySignatureL( aRegResp, *resp->iSignature,
+                iStoredRiContext->CertificateChain() );
+            }
+        else
+            {
+            // otherwise use the received certificates
+            status = VerifySignatureL( aRegResp, *resp->iSignature,
+                resp->iCertificateChain );
+            }
+
+        if ( !status )
+            {
+            LOGLIT( "Signature verification failed" )
+            User::Leave( KErrRoapServerFatal );
+            }
+
+        if ( resp->iCertificateChain.Count() )
+            {
+            // Validate RI certificate
+            cert = CX509Certificate::NewLC( *resp->iCertificateChain[0] );
+
+            status = ValidateRiCertificateL( cert );
+            if ( !status )
+                {
+                User::LeaveIfError( KErrRoapServerFatal );
+                }
+
+            riExpiry = cert->ValidityPeriod().Finish();
+
+            iRiSupportsCertCaching ? riCertCaching = ETrue : riCertCaching
+                = EFalse;
+
+            context = CDRMRIContext::NewLC( iRiId, *iRiAlias, iRiVersion,
+                iRiAlgorithms, resp->iWhiteList, *resp->iRiUrl, riExpiry,
+                resp->iCertificateChain, resp->iOcspResponse, riCertCaching,
+                iSelectedRoot, ETrue );
+
+            iStorageClient->AddRIContextL( *context );
+            delete iStoredRiContext;
+            iStoredRiContext = context;
+            CleanupStack::Pop( context );
+            CleanupStack::PopAndDestroy( cert );
+            }
+        }
+    else
+        {
+        if ( resp->iErrorUrl )
+            {
+            if ( iObserver )
+                {
+                iObserver->ErrorUrlL( *resp->iErrorUrl );
+                }
+            }
+        iSigner->ResetResponses();
+        }
+
+    PERFORMANCE_LOGLIT( "Registration protocol completed" )
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::HandleRightsResponseL()
+// ---------------------------------------------------------
+//
+void CRoapEng::HandleRightsResponsePduL(
+    const TDesC8& aRightsResp,
+    TBool aOnePass )
+    {
+    LOGLIT( "CRoapEng::HandleRightsResponsePduL" )
+
+    CRightsResp* resp = NULL;
+    TBool status = EFalse;
+
+    resp = iParser->ParseRightsRespL( aRightsResp );
+
+    CleanupStack::PushL( resp );
+
+    if ( resp->iStatus == ESuccess )
+        {
+        if ( !aOnePass )
+            {
+            // 2-pass protocol
+            __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() );
+
+            CRightsReq* request = NULL;
+            request = STATIC_CAST( CRightsReq*, iRequest );
+            if ( resp->iDeviceId.CompareF( request->iDeviceId ) != KErrNone
+                || resp->iRiId.CompareF( request->iRiId ) != KErrNone
+                || resp->iNonce->CompareF( request->iNonce ) != KErrNone )
+                {
+                User::Leave( KErrRoapServerFatal );
+                }
+            }
+        else
+            {
+            LOGLIT( "1-pass ROAP" )
+            // 1-pass protocol
+            TBool registered = EFalse;
+            GetRIContextL( registered, resp->iRiId );
+            if ( !registered )
+                {
+                // Recoverable error by re-registering the device
+                // (after receiving user consent or iv device belongs to whiteliust)
+                LOGLIT( "Device not registered to RI" )
+                User::Leave( KErrRoapNotRegistered );
+                }
+            if ( resp->iDeviceId.CompareF( *iDeviceId ) != KErrNone )
+                {
+                // Unrecoverable error
+                LOGLIT( "Device ID mismatch!" )
+                User::Leave( KErrRoapServerFatal );
+                }
+            }
+
+        if ( !iStoredRiContext || ( resp->iCertificateChain.Count()
+            && resp->iOcspResponse.Count() ) )
+            {
+            status = VerifyCertificateChainL( resp->iCertificateChain,
+                resp->iOcspResponse );
+            if ( !status )
+                {
+                LOGLIT( "Certificate chain validation failed" )
+                User::Leave( KErrRoapServerFatal );
+                }
+            status = ValidateRiIdL( resp->iRiId, *resp->iCertificateChain[0] );
+            if ( !status )
+                {
+                LOGLIT( "RI ID validation failed" )
+                User::Leave( KErrRoapServerFatal );
+                }
+            }
+
+        status = VerifySignatureL( aRightsResp, *resp->iSignature,
+            iStoredRiContext->CertificateChain() );
+        if ( !status )
+            {
+            LOGLIT( "Signature verification failed" )
+            User::Leave( KErrRoapServerFatal );
+            }
+
+        iReturnedROs.ResetAndDestroy();
+        TRAPD( r, iRoParser->ParseAndStoreL( aRightsResp, iReturnedROs ));
+
+        if ( r == KErrRightsServerDomainNotRegistered )
+            {
+            // perform implicit Join Domain
+            LOGLIT( "Domain RO received - Not joined" )
+            LOGLIT( "Perform impicit Join Domain before storing the RO" )
+
+            HBufC8* domainID = NULL;
+
+            domainID = iRoParser->GetDomainIdL( aRightsResp );
+
+            if ( domainID && domainID->Length() <= KDomainIdLength )
+                {
+                iDomainId.Copy( *domainID );
+                delete domainID;
+                domainID = NULL;
+                }
+            else
+                {
+                LOGLIT( "No Domain ID available!" )
+                User::Leave( KErrRoapServerFatal );
+                }
+
+            delete iDomainRightsResp;
+            iDomainRightsResp = NULL;
+            iDomainRightsResp = aRightsResp.AllocL();
+            iImplicitJoinDomain = ETrue;
+            }
+        else
+            {
+            User::LeaveIfError( r );
+
+            if ( !aOnePass )
+                {
+                if ( iObserver )
+                    {
+                    iObserver->RightsObjectDetailsL( iReturnedROs ); // pass RO details to UI
+                    }
+                }
+            }
+
+            TRAP( r, InsertTransactionIDL( resp->iTransTrackIDs, resp->iContentIDs ) );
+            TRAP( r, InsertDomainRosL() );
+
+        // Device DRM Time is insecure, but server thinks that the time is correct
+        // -> Set DRM Time as secure
+        if ( !iSecureTime )
+            {
+            SetDrmTimeSecureL();
+            }
+        }
+    else
+        {
+        if ( resp->iErrorUrl )
+            {
+            if ( iObserver )
+                {
+                iObserver->ErrorUrlL( *resp->iErrorUrl );
+                }
+            }
+        iSigner->ResetResponses();
+        }
+
+    CleanupStack::Pop( resp );
+
+    if ( !aOnePass )
+        {
+        iRoapStatus = resp->iStatus;
+        iResponse = resp;
+        }
+
+    PERFORMANCE_LOGLIT( "RO acquisition protocol completed" )
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::HandleJoinDomainResponseL()
+// ---------------------------------------------------------
+//
+void CRoapEng::HandleJoinDomainResponsePduL( const TDesC8& aJoinResp )
+    {
+    LOGLIT( "CRoapEng::HandleJoinDomainResponsePduL" )
+
+    __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() );
+
+    CJoinDomainResp* resp = NULL;
+    CDRMDomainContext* context = NULL;
+    RPointerArray<HBufC8> domainKeyElements;
+    TBool status = EFalse;
+
+    CleanupResetAndDestroyPushL( domainKeyElements );
+
+    resp = iParser->ParseJoinDomainRespL( aJoinResp, domainKeyElements );
+
+    iResponse = resp;
+    iRoapStatus = resp->iStatus;
+
+    if ( iRoapStatus == ESuccess )
+        {
+        if ( resp->iDomainKeyRiId != resp->iRiId )
+            {
+            LOGLIT( "resp->iDomainKeyRiId != resp->iRiId" )
+            User::Leave( KErrRoapServerFatal );
+            }
+
+        if ( !iStoredRiContext || ( resp->iCertificateChain.Count()
+            && resp->iOcspResponse.Count() ) )
+            {
+            status = VerifyCertificateChainL( resp->iCertificateChain,
+                resp->iOcspResponse );
+            if ( !status )
+                {
+                LOGLIT( "Certificate chain validation failed" )
+                User::Leave( KErrRoapServerFatal );
+                }
+            status = ValidateRiIdL( resp->iRiId, *resp->iCertificateChain[0] );
+            if ( !status )
+                {
+                LOGLIT( "RI ID validation failed" )
+                User::Leave( KErrRoapServerFatal );
+                }
+            }
+
+        status = VerifySignatureL( aJoinResp, *resp->iSignature,
+            iStoredRiContext->CertificateChain() );
+        if ( !status )
+            {
+            LOGLIT( "Signature verification failed" )
+            User::Leave( KErrRoapServerFatal );
+            }
+
+        if ( resp->iDomainKeys.Count() > 1 && resp->iDomainKeyIDs.Count() > 1
+            && resp->iDomainKeys.Count() == resp->iDomainKeyIDs.Count() )
+            {
+            // Sort domain keys by generation (000 generation is first)
+            TLex8 lex;
+            TInt generation = 0;
+            RArray<TInt> generations;
+            CleanupClosePushL( generations );
+
+            for ( TInt i = 0; i < resp->iDomainKeyIDs.Count(); i++ )
+                {
+                lex = resp->iDomainKeyIDs[i]->Right( KDomainGenerationLength );
+                lex.Val( generation );
+                generations.AppendL( generation );
+                }
+
+            SortArrays( resp->iDomainKeys, resp->iMacs, domainKeyElements,
+                generations );
+
+            CleanupStack::PopAndDestroy( &generations );
+            }
+
+        if ( !resp->iDomainKeys.Count() )
+            {
+            LOGLIT( "No valid domain keys present!" )
+            User::Leave( KErrRoapServerFatal );
+            }
+
+#ifdef _DISABLE_HASH_CHAIN_GENERATION
+        resp->iHashChainSupport = EFalse;
+#endif
+
+        if ( resp->iHashChainSupport )
+            {
+            if ( resp->iDomainKeys.Count() > 1 )
+                {
+                LOGLIT( "More than one Domain key present, hash chain key generation is supported!" )
+                // Might be KErrRoapServerFatal server error
+                }
+            }
+
+        context = CDRMDomainContext::NewLC( iDomainId,
+            resp->iDomainExpiration, resp->iHashChainSupport,
+            resp->iDomainKeys, resp->iRiId,
+            iStoredRiContext->RightsIssuerURL() );
+        iStorageClient->AddDomainContextL( *context, resp->iMacs,
+            domainKeyElements, resp->iTransportScheme );
+        iDomainId.SetLength( 0 );
+        CleanupStack::PopAndDestroy( context );
+
+        if ( iDomainRightsResp )
+            {
+            // It's a implicit Join Domain case
+            // We still need to store the domain RO
+            StoreDomainRightsL();
+            }
+
+        // Device DRM Time is insecure, but server thinks that the time is correct
+        // -> Set DRM Time as secure
+        if ( !iSecureTime )
+            {
+            SetDrmTimeSecureL();
+            }
+        }
+    else
+        {
+        if ( resp->iErrorUrl )
+            {
+            if ( iObserver )
+                {
+                iObserver->ErrorUrlL( *resp->iErrorUrl );
+                }
+            }
+        iSigner->ResetResponses();
+        }
+    CleanupStack::PopAndDestroy( &domainKeyElements );
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::HandleLeaveDomainResponseL()
+// ---------------------------------------------------------
+//
+void CRoapEng::HandleLeaveDomainResponsePduL( const TDesC8& aLeaveResp )
+    {
+    LOGLIT( "CRoapEng::HandleLeaveDomainResponsePduL" )
+
+    __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() );
+
+    CLeaveDomainResp* resp = NULL;
+    resp = iParser->ParseLeaveDomainRespL( aLeaveResp );
+    iRoapStatus = resp->iStatus;
+    iResponse = resp;
+    if ( iRoapStatus == ESuccess )
+        {
+
+        }
+    else if ( resp->iErrorUrl )
+        {
+        if ( iObserver )
+            {
+            iObserver->ErrorUrlL( *resp->iErrorUrl );
+            }
+        }
+
+    PERFORMANCE_LOGLIT( "Leave domain protocol completed" )
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::HandleMeteringReportResponsePduL()
+// ---------------------------------------------------------
+//
+#ifndef RD_DRM_METERING
+void CRoapEng::HandleMeteringReportResponsePduL( const TDesC8& /*aMeteringResp*/)
+    {
+    }
+#else
+void CRoapEng::HandleMeteringReportResponsePduL( const TDesC8& aMeteringResp )
+    {
+    LOGLIT( "CRoapEng::HandleMeteringReportResponsePduL" )
+    __ASSERT_ALWAYS( iStoredRiContext, User::Invariant() );
+
+    CMeteringResp* resp = NULL;
+    CMeteringReportReq* request = NULL;
+
+    resp = iParser->ParseMeteringRespL( aMeteringResp );
+
+    request = static_cast<CMeteringReportReq*> ( iRequest );
+
+    iRoapStatus = resp->iStatus;
+    iResponse = resp;
+    if ( iRoapStatus == ESuccess )
+        {
+        if ( resp->iDeviceId.CompareF( *iDeviceId ) != KErrNone
+            || resp->iDeviceNonce->CompareF( request->iNonce ) != KErrNone )
+            {
+            LOGLIT( "Mismatch in deviceId or in nonce" )
+            LOGLIT( "Observed DeviceId" )
+            LOGHEX( resp->iDeviceId.Ptr(), resp->iDeviceId.Length() )
+            LOGLIT( "Expected DeviceId" )
+            LOGHEX( request->iDeviceId.Ptr(), request->iDeviceId.Length() )
+            LOGLIT( "Observed nonce" )
+            LOGHEX( resp->iDeviceNonce->Ptr(), resp->iDeviceNonce->Length() )
+            LOGLIT( "Expected nonce" )
+            User::Leave( KErrRoapServerFatal );
+            }
+
+        if ( !iStoredRiContext || ( resp->iCertificateChain.Count()
+            && resp->iOcspResponse.Count() ) )
+            {
+            if ( !VerifyCertificateChainL( resp->iCertificateChain,
+                resp->iOcspResponse ) )
+                {
+                LOGLIT( "Certificate chain validation failed" )
+                User::Leave( KErrRoapServerFatal );
+                }
+            if ( !ValidateRiIdL( resp->iRiId, *resp->iCertificateChain[0] ) )
+                {
+                LOGLIT( "RI ID validation failed" )
+                User::Leave( KErrRoapServerFatal );
+                }
+            }
+
+        if ( !VerifySignatureL( aMeteringResp, *resp->iSignature,
+            iStoredRiContext->CertificateChain() ) )
+            {
+            LOGLIT( "Signature verification failed" )
+            User::Leave( KErrRoapServerFatal );
+            }
+
+        // Everything is fine, we can delete metering data
+        iStorageClient->DeleteMeteringDataL( resp->iRiId );
+
+        // notify PostResponseUrl for iObserver
+        if ( resp->iPrUrl )
+            {
+            HBufC8* prUrl( resp->iPrUrl );
+            LOGLIT( "PrUrl" )
+            LOGHEX( prUrl->Ptr(), prUrl->Length() )
+            if ( iObserver )
+                {
+                iObserver->PostResponseUrlL( *prUrl );
+                LOGLIT( "Notified observer with PostResponseUrl" )
+                }
+            else
+                {
+                LOGLIT( "Warning no observer for PostResponseUrl" )
+                }
+            }
+        }
+    return;
+    }
+#endif //RD_DRM_METERING
+// ---------------------------------------------------------
+// CRoapEng::HandleMultipartL()
+// ---------------------------------------------------------
+//
+void CRoapEng::HandleMultipartL()
+    {
+    LOGLIT( "CRoapEng::HandleMultipartL" )
+
+    TInt rightsErr( KErrNone );
+    TInt err( KErrNone );
+    TInt docErr( KErrNone );
+    TDataType type = TDataType();
+    TBool mmcAllowed( EFalse );
+    HBufC* contentName( NULL );
+    RBuf newPath;
+    TUid app_uid;
+    RBuf rootPath;
+
+    TRAP( rightsErr, HandleRoapResponseL( iRoapResp->ProtocolUnit() ) );
+
+    newPath.CreateL( KMaxFileName );
+    CleanupClosePushL( newPath  );
+
+    CDocumentHandler* docHandler( CDocumentHandler::NewLC() );
+
+    if ( iRoapResp->DcfFileName().Left( 1 ).CompareF( _L ("e") ) == 0 )
+        {
+        mmcAllowed = ETrue;
+        }
+
+    RFs fs;
+    User::LeaveIfError( fs.Connect() );
+    CleanupClosePushL( fs );
+
+#ifndef RD_MULTIPLE_DRIVE
+    rootPath.CreateL( mmcAllowed ?
+        PathInfo::MemoryCardRootPath() :
+        PathInfo::PhoneMemoryRootPath() );
+
+#else //RD_MULTIPLE_DRIVE
+    _LIT( KSysDriveRoot, "_:\\Data\\");
+    _LIT( KMassDriveRoot, "_:\\" );
+    TInt driveNumber( -1 );
+    TChar driveLetter;
+
+    if ( mmcAllowed )
+        {
+        // Set root path to memory card root
+        rootPath.CreateL( KMassDriveRoot() );
+        DriveInfo::GetDefaultDrive( DriveInfo::EDefaultMassStorage, driveNumber );
+        }
+    else
+        {
+        // Set root path to system root
+        rootPath.CreateL( KSysDriveRoot() );
+        DriveInfo::GetDefaultDrive( DriveInfo::EDefaultSystem, driveNumber );
+        }
+    fs.DriveToChar( driveNumber, driveLetter );
+    __ASSERT_ALWAYS( rootPath.Length()>0, User::Invariant() );
+    rootPath[0] = (TUint)driveLetter;
+
+
+#endif
+    CleanupClosePushL( rootPath );
+
+    iRoapResp->GetContentNameLC( contentName );
+
+    if ( contentName && contentName->Length()
+        && fs.IsValidName( *contentName ) )
+        {
+        if ( !rightsErr )
+            {
+            TRAP( err, docErr = docHandler->SilentMoveL( iRoapResp->DcfFileName(),
+                    *contentName, rootPath, type, KEntryAttNormal ) );
+            }
+        else
+            {
+            // when an error occured during RO storing -> show "saved to" note
+            TRAP( err, docErr = docHandler->MoveL( iRoapResp->DcfFileName(),
+                    *contentName, type, KEntryAttNormal ) );
+            }
+
+        }
+    else
+        {
+        if ( !rightsErr )
+            {
+            // use the default name
+            User::LeaveIfError( docHandler->SilentMoveL(
+                iRoapResp->DcfFileName(), KNullDesC(), rootPath, type,
+                KEntryAttNormal ) );
+            }
+        else
+            {
+            // when an error occured during RO storing -> show "saved to" note
+            docHandler->MoveL( iRoapResp->DcfFileName(), KNullDesC(), type,
+                KEntryAttNormal );
+            }
+        }
+
+    if ( err || docErr )
+        {
+        if ( !rightsErr )
+            {
+            // use the default name
+            User::LeaveIfError( docHandler->SilentMoveL(
+                iRoapResp->DcfFileName(), KNullDesC(), rootPath, type,
+                KEntryAttNormal ) );
+            }
+        else
+            {
+            // when an error occured during RO storing -> show "saved to" note
+            docHandler->MoveL( iRoapResp->DcfFileName(), KNullDesC(), type,
+                KEntryAttNormal );
+            }
+        }
+    User::LeaveIfError( rightsErr );
+
+    User::LeaveIfError( docHandler->GetPath( newPath ) );
+    User::LeaveIfError( docHandler->HandlerAppUid( app_uid ) );
+
+    if ( iObserver )
+        {
+        iObserver->ContentDetailsL( newPath, type.Des8(), app_uid );
+        }
+
+    CleanupStack::PopAndDestroy( contentName );
+    CleanupStack::PopAndDestroy( &rootPath );
+
+    CleanupStack::PopAndDestroy( &fs );
+    CleanupStack::PopAndDestroy( docHandler );
+    CleanupStack::PopAndDestroy( &newPath );
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::SignMessageL()
+// ---------------------------------------------------------
+//
+HBufC8* CRoapEng::SignMessageL( const TDesC8& aMessage ) const
+    {
+    LOGLIT( "CRoapEng::SignMessageL" )
+    HBufC8* r = NULL;
+
+    if ( iReqMessage == EDeviceHello )
+        {
+        // Device Hello always resets signing chain!!
+        iSigner->ResetRequests();
+        iSigner->ResetResponses();
+        // Device Hello or RI Hello is not signed
+        iSigner->AddRequestL( aMessage );
+        r = aMessage.AllocL();
+        }
+    else
+        {
+        r = iSigner->SignAndAddRequestL( aMessage );
+        iSigner->ResetRequests();
+
+        if ( iReqMessage == ERegistration )
+            {
+            // Add signed request to the signer for verifying signature on
+            // response (for Registration protocol only).
+            iSigner->AddResponseL( *r );
+            }
+        }
+    return r;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::VerifySignatureL()
+// ---------------------------------------------------------
+//
+TBool CRoapEng::VerifySignatureL(
+    const TDesC8& aMessage,
+    const TDesC8& aSignature,
+    const RPointerArray<HBufC8>& aCertificateChain ) const
+    {
+    LOGLIT( "CRoapEng::VerifySignatureL" )
+
+    TBool isValid = ETrue;
+
+    if ( iReqMessage != EDeviceHello && iReqMessage != ELeaveDomain )
+        {
+        // RI Hello and Leave Domain resp are not signed
+        isValid = iSigner->VerifyAndAddResponseL( aMessage, aSignature,
+            aCertificateChain );
+        iSigner->ResetResponses();
+        }
+
+#ifdef _DISABLE_SIGNATURE_CHECK
+    isValid = ETrue;
+#endif
+    return isValid;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::VerifyTriggerSignatureL()
+// ---------------------------------------------------------
+//
+TBool CRoapEng::VerifyTriggerSignatureL(
+    const TDesC8& aXmlTrigger,
+    const CRoapTrigger& aTrigger ) const
+    {
+    LOGLIT( "CRoapEng::ValidateTriggerSignatureL" )
+
+    TPtrC8 element( KNullDesC8 );
+    TPtrC8 signedInfo( KNullDesC8 );
+    CDRMDomainContext* context( NULL );
+    HBufC8* domainKey( NULL );
+    HBufC8* unwrappedMacKey( NULL );
+    CSHA1* digest( NULL );
+    CMessageDigest* hMac( NULL );
+    TBool result( ETrue );
+    TInt pos( 0 );
+    TInt generation( 0 );
+
+    element.Set( iParser->ExtractElement( aXmlTrigger, KLeaveDomainElement(),
+        pos ) );
+    pos = 0;
+    signedInfo.Set( iParser->ExtractElement( aXmlTrigger,
+        KSignedInfoElement(), pos ) );
+
+    if ( !element.Length() || !signedInfo.Length() || !aTrigger.iEncKey
+        || !aTrigger.iSignature )
+        {
+        User::Leave( KErrRoapServerFatal );
+        }
+
+    context = iStorageClient->GetDomainContextL( *aTrigger.iDomainId );
+
+    if ( !context )
+        {
+        // we are not member of the domain
+        LOGLIT( "No DomainContext for the domain -> Cannot verify Trigger signature" )
+        return ETrue;
+        }
+    CleanupStack::PushL( context );
+
+    TLex8 lex( aTrigger.iDomainId->Right( KDomainGenerationLength ) );
+    lex.Val( generation );
+    domainKey = context->DomainKeyL( generation );
+    User::LeaveIfNull( domainKey );
+    CleanupStack::PushL( domainKey );
+
+    unwrappedMacKey = OmaCrypto::AesUnwrapL( *domainKey, *aTrigger.iEncKey );
+    CleanupStack::PopAndDestroy( domainKey );
+    CleanupStack::PushL( unwrappedMacKey );
+
+    // hash the leaveDomain element
+    digest = CSHA1::NewL();
+    CleanupStack::PushL( digest );
+    digest->Update( element );
+
+    if ( digest->Final().CompareF( *aTrigger.iDigestValue ) )
+        {
+        LOGLIT( "Reference Validation failed!" )
+        result = EFalse;
+        }
+
+    if ( result )
+        {
+        // calculate HMAC signature
+        hMac = CMessageDigestFactory::NewHMACLC( CMessageDigest::ESHA1,
+            *unwrappedMacKey );
+        hMac->Update( signedInfo );
+
+        if ( hMac->Final().CompareF( *aTrigger.iSignature ) != 0 )
+            {
+            LOGLIT( "Signature Validation failed!" )
+            result = EFalse;
+            }
+        CleanupStack::PopAndDestroy( hMac );
+        }
+
+    CleanupStack::PopAndDestroy( digest );
+    CleanupStack::PopAndDestroy( unwrappedMacKey );
+    CleanupStack::PopAndDestroy( context );
+
+    if ( !result )
+        {
+        LOGLIT( "Trigger signature check failed!" )
+        }
+
+#ifdef _DISABLE_SIGNATURE_CHECK
+    result = ETrue;
+#endif
+    return result;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::VerifyCertificateChainL()
+// ---------------------------------------------------------
+//
+TBool CRoapEng::VerifyCertificateChainL(
+    const RPointerArray<HBufC8>& aCertificateChain,
+    const RPointerArray<HBufC8>& aOcspResponses ) const
+    {
+    LOGLIT( "CRoapEng::VerifyCertificateChainL" )
+
+    CX509Certificate* cert = NULL;
+    CX509Certificate* signingCert = NULL;
+    CX509Certificate* riCA = NULL;
+    TBool result = EFalse;
+    RPointerArray<HBufC8> serialNums;
+    CX500DistinguishedName* rootDistName = NULL;
+    HBufC* rootName = NULL;
+    HBufC8* rootCert = NULL;
+    HBufC8* temp = NULL;
+
+    if ( !aCertificateChain.Count() || !aOcspResponses.Count() )
+        {
+        User::Leave( KErrRoapServerFatal );
+        }
+
+    // Get the last cert from the chain. It is signed by some of our trusted anchor
+    riCA = CX509Certificate::NewLC(
+        *( aCertificateChain[aCertificateChain.Count() - 1] ) );
+    rootDistName = CX500DistinguishedName::NewLC( riCA->IssuerName() );
+    rootName = rootDistName->DisplayNameL();
+    CleanupStack::PushL( rootName );
+    // Get the correct root cert for validating the whole chain
+    rootCert = iStorageClient->GetRootCertificateL( *rootName );
+    CleanupStack::PopAndDestroy( rootName );
+    CleanupStack::PopAndDestroy( rootDistName );
+    CleanupStack::PopAndDestroy( riCA );
+
+    if ( !rootCert )
+        {
+        LOGLIT( "No root certificate present!" )
+        LOGLIT( "Certificate chain verification failed." )
+        return EFalse;
+        }
+    CleanupStack::PushL( rootCert );
+
+    CleanupResetAndDestroyPushL( serialNums );
+
+    for ( TInt i = 0; i < aCertificateChain.Count(); i++ )
+        {
+        cert = CX509Certificate::NewLC( *aCertificateChain[i] );
+        temp = cert->SerialNumber().AllocLC();
+        serialNums.AppendL( temp );
+        CleanupStack::Pop( temp );
+        if ( aCertificateChain.Count() - 1 == i )
+            {
+            // signingCert = Trusted root cert
+            signingCert = CX509Certificate::NewLC( *rootCert );
+            }
+        else
+            {
+            signingCert = CX509Certificate::NewLC( *aCertificateChain[i + 1] );
+            }
+        result = cert->VerifySignatureL( signingCert->PublicKey().KeyData() );
+
+#ifdef _DISABLE_CERT_CHECK
+        result = ETrue;
+#endif
+        CleanupStack::PopAndDestroy( signingCert );
+        CleanupStack::PopAndDestroy( cert );
+        if ( !result )
+            {
+            LOGLIT( "Certificate chain verification failed." )
+            CleanupStack::PopAndDestroy( 2, rootCert );
+            return result;
+            }
+        }
+
+    if ( aCertificateChain.Count() >= 2 )
+        {
+        result = VerifyOcspResponsesL( aOcspResponses, *aCertificateChain[1],
+            serialNums );
+
+        if ( !result )
+            {
+            // CoreMedia's OCSP responder cert is signed by the root -> against CMLA spec
+            LOGLIT( "Try to verify OCSP response cert using root cert" )
+            result = VerifyOcspResponsesL( aOcspResponses, *rootCert,
+                serialNums );
+            }
+        }
+    else if ( aCertificateChain.Count() == 1 )
+        {
+        // There is only one cert in the cert chain -> the OCSP response cert is verified with root cert
+        result = VerifyOcspResponsesL( aOcspResponses, *rootCert, serialNums );
+        }
+    else
+        {
+        result = EFalse;
+        }
+
+    if ( iStoredRiContext && aCertificateChain.Count() && result )
+        {
+        cert = CX509Certificate::NewLC( *aCertificateChain[0] );
+        if ( iStoredRiContext->ExpiryTime() < cert->ValidityPeriod().Finish() )
+            {
+            iStoredRiContext->SetCertificateChainL( aCertificateChain );
+            iStoredRiContext->SetOCSPResponseL( aOcspResponses );
+
+            // update RI Context
+            iStorageClient->AddRIContextL( *iStoredRiContext );
+            }
+        CleanupStack::PopAndDestroy( cert );
+        }
+
+    CleanupStack::PopAndDestroy( 2, rootCert ); // serialNums, rootCert
+
+#ifdef _ROAP_TESTING
+    if ( result )
+        {
+        LOGLIT( "Certificate chain verification ok." )
+        }
+    else
+        {
+        LOGLIT( "Certificate chain verification failed." )
+        }
+#endif
+#ifdef _DISABLE_CERT_CHECK
+    result = ETrue;
+#endif
+
+    return result;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::VerifyOcspResponsesL()
+// ---------------------------------------------------------
+//
+TBool CRoapEng::VerifyOcspResponsesL(
+    const RPointerArray<HBufC8>& aOcspResponses,
+    const TDesC8& aRiCaCert,
+    const RPointerArray<HBufC8>& aCertSerialNums ) const
+    {
+    LOGLIT( "CRoapEng::VerifyOcspResponsesL" )
+
+#ifdef _DISABLE_OCSP_CHECK
+    TBool result( ETrue );
+#else
+    // Get verification result from the server
+    TBool result( iStorageClient->VerifyOcspResponsesL( aOcspResponses,
+        aRiCaCert, aCertSerialNums ) );
+#endif
+
+#ifdef _ROAP_TESTING
+    if ( result )
+        {
+        LOGLIT( "OCSP response verification ok." )
+        }
+    else
+        {
+        LOGLIT( "OCSP response verification failed." )
+        }
+#endif
+
+    return result;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::ValidateRiCertificateL()
+// ---------------------------------------------------------
+//
+TBool CRoapEng::ValidateRiCertificateL( const CX509Certificate* aCert )
+    {
+    LOGLIT( "CRoapEng::ValidateRiCertificateL" )
+
+    TBool ret = ETrue;
+    const CX509CertExtension* ext = NULL;
+    CX509KeyUsageExt* keyUsageExt = NULL;
+    CX509ExtendedKeyUsageExt* extendedKeyUsage = NULL;
+    TTime riExpiry;
+    TInt count = 0;
+
+    if ( iSelectedAlgorithms == ECmlaIp1 )
+        {
+        // Check RI certificate extensions only in CMLA case
+        ext = aCert->Extension( KKeyUsage() );
+        if ( !ext || !( ext->Critical() ) )
+            {
+            LOGLIT( "RI cert KeyUsage extension missing or not critical!" )
+            ret = EFalse;
+            }
+
+        if ( ext && ret )
+            {
+            keyUsageExt = CX509KeyUsageExt::NewLC( ext->Data() );
+            if ( !keyUsageExt->IsSet( EX509DigitalSignature ) )
+                {
+                LOGLIT( "DigitalSignature bit is not set in KeyUsageExt of RI cert!" )
+                ret = EFalse;
+                }
+            CleanupStack::PopAndDestroy( keyUsageExt );
+            }
+
+        ext = aCert->Extension( KExtendedKeyUsage() );
+        if ( !ext || !( ext->Critical() ) )
+            {
+            LOGLIT( "RI cert ExtendedKeyUsage extension missing or not critical!" )
+            ret = EFalse;
+            }
+
+        if ( ext && ret )
+            {
+            ret = EFalse;
+            extendedKeyUsage = CX509ExtendedKeyUsageExt::NewLC( ext->Data() );
+            count = extendedKeyUsage->KeyUsages().Count();
+            for ( TInt i = 0; i < count && !ret; i++ )
+                {
+                if ( extendedKeyUsage->KeyUsages().At( i )->CompareF(
+                    KOmaKpRightsIssuerOid() ) == 0 )
+                    {
+                    ret = ETrue;
+                    }
+                }
+            if ( !ret )
+                {
+                LOGLIT( "OmaKpRightsIssuer OID is not set in ExtendedKeyUsageExt of RI cert!" )
+                }
+            CleanupStack::PopAndDestroy( extendedKeyUsage );
+            }
+        }
+
+    riExpiry = aCert->ValidityPeriod().Finish();
+
+    if ( riExpiry < GetDrmTimeL() )
+        {
+        LOGLIT( "RI Context certificate is expired!" )
+        ret = EFalse;
+        }
+#ifdef _DISABLE_CERT_CHECK
+    ret = ETrue;
+#endif
+    return ret;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::GetCertificateChainL()
+// ---------------------------------------------------------
+//
+RPointerArray<HBufC8> CRoapEng::GetCertificateChainL() const
+    {
+    LOGLIT( "CRoapEng::GetCertificateChainL ->" )
+
+    TInt err = KErrNone;
+    RPointerArray<HBufC8> certificateChain;
+    HBufC8* root = NULL;
+
+    CleanupResetAndDestroyPushL( certificateChain );
+
+    err = iStorageClient->GetDeviceCertificateChainL( certificateChain );
+
+    if ( err )
+        {
+        User::Leave( err );
+        }
+
+    if ( certificateChain.Count() < KMinCertChainLength )
+        {
+        // the CMLA chain must always contain:
+        // the device certificate,
+        // at lest one signing certificate (device CA),
+        // and the root certificate
+        DETAILLOGLIT( "Got improper certificate chain!!" )
+        // Leaving in production devices.
+        User::Leave( KErrRoapDevice );
+        __ASSERT_DEBUG( ETrue, User::Invariant() );
+        }
+
+    // delete and remove the root certificate (it's always the last one in the list)
+    root = certificateChain[certificateChain.Count() - 1];
+    delete root;
+    certificateChain.Remove( certificateChain.Count() - 1 );
+
+    CleanupStack::Pop( &certificateChain );
+
+    LOGLIT( "CRoapEng::GetCertificateChainL <-" )
+
+    return certificateChain;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::GetDeviceDetailsL()
+// ---------------------------------------------------------
+//
+void CRoapEng::GetDeviceDetailsL(
+    HBufC8*& aManufacturer,
+    HBufC8*& aModel,
+    HBufC8*& aVersion )
+    {
+    LOGLIT( "-> CRoapEng::GetDeviceDetailsL" )
+
+#ifndef __WINS__
+    TInt numPhone = 0;
+    TUint32 caps = 0;
+    TName tsyName;
+    RMobilePhone phone;
+    RTelServer etelServer;
+    RTelServer::TPhoneInfo phoneInfo;
+    HBufC* version = NULL;
+
+    User::LeaveIfError( etelServer.Connect() );
+
+    CleanupClosePushL( etelServer );
+
+    User::LeaveIfError( etelServer.LoadPhoneModule( KMmTsyModuleName ) );
+    User::LeaveIfError( etelServer.EnumeratePhones( numPhone) );
+
+    for (TInt i(0); i < numPhone; i++)
+        {
+        User::LeaveIfError( etelServer.GetPhoneInfo( i, phoneInfo ) );
+        User::LeaveIfError( etelServer.GetTsyName( i,tsyName ) );
+
+        if ( tsyName.CompareF( KMmTsyModuleName ) == 0)
+            {
+            break;
+            }
+        }
+
+    User::LeaveIfError( phone.Open( etelServer, phoneInfo.iName ) );
+    CleanupClosePushL( phone );
+
+    phone.GetIdentityCaps( caps );
+    if ( !( caps & RMobilePhone::KCapsGetManufacturer ) &&
+        !( caps & RMobilePhone::KCapsGetModel ) )
+        {
+        User::Leave( KErrRoapGeneral );
+        }
+
+    RMobilePhone::TMobilePhoneIdentityV1 details;
+    TRequestStatus status;
+
+    phone.GetPhoneId( status, details );
+    User::WaitForRequest( status );
+
+    User::LeaveIfError( status.Int() );
+
+    HBufC8* manufacturer( HBufC8::NewLC( details.iManufacturer.Length() ) );
+    manufacturer->Des().Copy( details.iManufacturer );
+    HBufC8* model( HBufC8::NewLC( details.iModel.Length() ) );
+    model->Des().Copy( details.iModel );
+
+    version = HBufC::NewLC( KSysUtilVersionTextLength );
+    TPtr ptr( version->Des() );
+    User::LeaveIfError( SysUtil::GetSWVersion( ptr ) );
+
+    // remove possible BOM from the end
+    if ( ptr.Right( KBOM1().Length() ).CompareF( KBOM1 ) == KErrNone )
+        {
+        ptr.Delete( ptr.Length() - KBOM1().Length(), KBOM1().Length() );
+        }
+    if ( ptr.Right( KBOM2().Length() ).CompareF( KBOM2 ) == KErrNone )
+        {
+        ptr.Delete( ptr.Length() - KBOM2().Length(), KBOM2().Length() );
+        }
+
+    aVersion = CnvUtfConverter::ConvertFromUnicodeToUtf8L( ptr );
+
+    CleanupStack::PopAndDestroy( version );
+    CleanupStack::Pop( model );
+    CleanupStack::Pop( manufacturer );
+    aManufacturer = manufacturer;
+    aModel = model;
+    CleanupStack::PopAndDestroy( &phone );
+    CleanupStack::PopAndDestroy( &etelServer );
+#else
+    aManufacturer = _L8("Nokia").AllocL();
+    aModel = _L8("Emulator").AllocL();
+    aVersion = _L8("9.0").AllocL();
+#endif
+
+    LOGLIT( "Device details:" )
+    LOGLIT( "   Manufacturer: " )
+    LOG( aManufacturer->Des() )
+    LOGLIT( "   Model: " )
+    LOG( aModel->Des() )
+    LOGLIT( "   Revision: " )
+    LOG( aVersion->Des() )
+
+    LOGLIT( "<- CRoapEng::GetDeviceDetailsL" )
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::FetchTransactionIDL()
+// ---------------------------------------------------------
+//
+void CRoapEng::FetchTransactionIDL(
+    RPointerArray<HBufC8>& aTransIDs,
+    RPointerArray<HBufC8>& aContentIDs )
+    {
+    LOGLIT( "CRoapEng::FetchTransactionIDL" )
+
+    __ASSERT_ALWAYS( iTrigger, User::Invariant() );
+
+    RArray<TPair> array;
+    TInt err = KErrNone;
+
+    CleanupClosePushL( array );
+
+    if ( !iTrigger->iContentIdList.Count() )
+        {
+        CleanupStack::PopAndDestroy( &array );
+        return;
+        }
+
+    if ( iTransStatus == ENotAsked && iObserver )
+        {
+        UpdateTransactionTrackingStatusL();
+        }
+    if ( iTransStatus == EAllowed )
+        {
+        for ( TInt i = 0; i < iTrigger->iContentIdList.Count(); i++ )
+            {
+            TPair pair;
+            pair.iCid = iTrigger->iContentIdList[i]->Alloc(); // duplicate contentID,
+            pair.iTtid = NULL; // pair.iCid is deleted by iRequest
+            err = array.Append( pair );
+            if ( err )
+                {
+                delete pair.iCid;
+                pair.iCid = NULL;
+                }
+            }
+
+            TRAP_IGNORE(iDcfRep->GetTtidL( array ) );
+
+        for ( TInt i = 0; i < array.Count(); i++ )
+            {
+            if ( array[i].iTtid && array[i].iCid && array[i].iTtid->Length()
+                && array[i].iCid->Length() )
+                {
+                err = aContentIDs.Append( array[i].iCid );
+                if ( !err )
+                    {
+                    aTransIDs.Append( array[i].iTtid );
+                    }
+                else
+                    {
+                    delete array[i].iCid;
+                    array[i].iCid = NULL;
+                    delete array[i].iTtid;
+                    array[i].iTtid = NULL;
+                    }
+                }
+            else if ( array[i].iTtid || array[i].iCid )
+                {
+                delete array[i].iTtid;
+                array[i].iTtid = NULL;
+                delete array[i].iCid;
+                array[i].iCid = NULL;
+                }
+            }
+        }
+    CleanupStack::PopAndDestroy( &array );
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::InsertTransactionIDL()
+// ---------------------------------------------------------
+//
+void CRoapEng::InsertTransactionIDL(
+    RPointerArray<HBufC8>& aTransIDs,
+    RPointerArray<HBufC8>& aContentIDs )
+    {
+    LOGLIT( "CRoapEng::InsertTransactionIDL" )
+
+    RArray<TPair> array;
+    TRequestStatus status;
+
+    CleanupClosePushL( array );
+
+    if ( !aTransIDs.Count() || !aContentIDs.Count() )
+        {
+        LOGLIT( "Insert ttID: Wrong input data" )
+        CleanupStack::PopAndDestroy( &array );
+        return;
+        }
+
+    if ( aTransIDs.Count() != aContentIDs.Count() )
+        {
+        LOGLIT( "Insert ttID: ttID.Count != cid.Count" )
+        CleanupStack::PopAndDestroy( &array );
+        return;
+        }
+
+    if ( iTransStatus == ENotAsked && iObserver )
+        {
+        UpdateTransactionTrackingStatusL();
+        }
+    if ( iTransStatus == EAllowed )
+        {
+        for ( TInt i = 0; i < aContentIDs.Count() && i < aTransIDs.Count(); i++ )
+            {
+            TPair pair;
+            pair.iCid = aContentIDs[i];
+            pair.iTtid = aTransIDs[i];
+            array.Append( pair );
+            }
+
+        iDcfRep->SetTtid( array, status );
+        User::WaitForRequest( status );
+        }
+
+    CleanupStack::PopAndDestroy( &array );
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::GetOCSPResponderKeyHashL()
+// ---------------------------------------------------------
+//
+HBufC8* CRoapEng::GetOCSPResponderKeyHashL() const
+    {
+    LOGLIT( "CRoapEng::GetOCSPResponderKeyHashL" )
+
+    if ( !iStoredRiContext )
+        {
+        User::Leave( KErrRoapNotRegistered );
+        }
+    return iStorageClient->GetOcspResponderIdL( iStoredRiContext->RIID() );
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::GetDrmTimeL()
+// ---------------------------------------------------------
+//
+TTime CRoapEng::GetDrmTimeL()
+    {
+    LOGLIT( "CRoapEng::GetDrmTimeL" )
+
+    TTime drmTime;
+    DRMClock::ESecurityLevel secureTime;
+    TInt zone( 0 );
+
+    User::LeaveIfError( iClockClient->GetSecureTime( drmTime, zone,
+        secureTime ) );
+
+    if ( secureTime == DRMClock::KInsecure )
+        {
+        iSecureTime = EFalse;
+        }
+    else
+        {
+        iSecureTime = ETrue;
+        }
+
+    return drmTime;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::SetDrmTimeSecureL()
+// ---------------------------------------------------------
+//
+void CRoapEng::SetDrmTimeSecureL()
+    {
+    LOGLIT( "CRoapEng::SetDrmTimeSecureL" )
+
+    TTime drmTime;
+    DRMClock::ESecurityLevel secureTime;
+    TInt zone( 0 );
+
+    User::LeaveIfError( iClockClient->GetSecureTime( drmTime, zone,
+        secureTime ) );
+    User::LeaveIfError( iClockClient->UpdateSecureTime( drmTime, zone ) );
+
+    iSecureTime = ETrue;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::AdjustDrmTime()
+// ---------------------------------------------------------
+//
+void CRoapEng::AdjustDrmTimeL(
+    const RPointerArray<HBufC8>& aOcspResponses,
+    TDesC8& aRegReqNonce ) const
+    {
+    // To be removed on next API change.
+    // Replace calls with direct call to RRoapStorageClient.
+    LOGLIT( "CRoapEng::AdjustDrmTime calling server" )
+    if ( aOcspResponses.Count() > 0 )
+        {
+        iStorageClient->UpdateDrmTimeL( iStoredRiContext->CertificateChain(),
+            aOcspResponses, aRegReqNonce );
+        }
+    else
+        {
+        LOGLIT( "No OCSP responses present." )
+        }
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::StoreDomainRightsL()
+// ---------------------------------------------------------
+//
+void CRoapEng::StoreDomainRightsL()
+    {
+    LOGLIT( "CRoapEng::StoreDomainRightsL" )
+
+    RPointerArray<CDRMRights> returnedROs;
+
+    CleanupResetAndDestroyPushL( returnedROs );
+
+    iRoParser->ParseAndStoreL( *iDomainRightsResp, returnedROs );
+
+    if ( iObserver )
+        {
+        iObserver->RightsObjectDetailsL( returnedROs ); // pass RO details to UI
+        }
+
+    delete iDomainRightsResp;
+    iDomainRightsResp = NULL;
+
+    iImplicitJoinDomain = EFalse;
+
+    CleanupStack::PopAndDestroy( &returnedROs );
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::InsertDomainRosL()
+// ---------------------------------------------------------
+//
+void CRoapEng::InsertDomainRosL()
+    {
+    CDcfRep* rep = NULL;
+    CDcfEntry* entry = NULL;
+    CContent* content = NULL;
+    TPtr8 ptr( NULL, 0 );
+    TInt i;
+    RFile file;
+    RFs fs;
+    TInt error( 0 );
+
+    User::LeaveIfError( fs.Connect() );
+    CleanupClosePushL( fs );
+    rep = CDcfRep::NewL();
+    CleanupStack::PushL( rep );
+    for ( i = 0; i < iReturnedROs.Count(); i++ )
+        {
+        if ( iReturnedROs[i]->GetPermission().iDomainID )
+            {
+            rep->OrderListL( *iReturnedROs[i]->GetAsset().iUid );
+            entry = rep->NextL();
+            while ( entry )
+                {
+                CleanupStack::PushL( entry );
+                error = file.Open( fs, entry->FileName(), EFileWrite
+                    | EFileShareReadersOrWriters );
+                if ( !error )
+                    {
+                    CleanupClosePushL( file );
+                    content = CContent::NewLC( file );
+                    content->AgentSpecificCommand( EEmbedDomainRo,
+                        KNullDesC8, ptr );
+                    CleanupStack::PopAndDestroy( 2, &file ); // content, file
+                    }
+                CleanupStack::PopAndDestroy( entry );
+                entry = rep->NextL();
+                }
+            }
+        }
+    CleanupStack::PopAndDestroy( 2, &fs ); // rep, fs
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::MapStatusL()
+// ---------------------------------------------------------
+//
+TInt CRoapEng::MapStatusL()
+    {
+    LOGLIT( "CRoapEng::MapStatusL" )
+
+    if ( iRoapStatus == ESuccess )
+        {
+        LOGLIT( "ROAP Status: success " )
+        return KErrNone;
+        }
+
+    if ( iRoapStatus == ENotRegistered || iRoapStatus == EDeviceTimeError )
+        {
+        // Initiate registration protocol
+        LOG2( _L ( "Not Registered! Status: %d" ), iRoapStatus )
+
+        if ( iRoapStatus == EDeviceTimeError )
+            {
+            iDeviceTimeError = ETrue;
+            }
+
+        return KErrRoapNotRegistered;
+        }
+
+    LOG2( _L ( "ROAP Error! Status: %d" ), iRoapStatus )
+
+    switch ( iRoapStatus )
+        {
+        case EUnknownError:
+        case EAbort:
+            {
+            User::Leave( KErrRoapServer );
+            }
+        case ENotSupported:
+        case EAccessDenied:
+        case ENotFound:
+        case EMalformedRequest:
+        case EUnknownRequest:
+        case EUnknownCriticalExtension:
+        case EUnsupportedVersion:
+        case EUnsupportedAlgorithm:
+        case ESignatureError:
+        case EInvalidDCFHash:
+            {
+            User::Leave( KErrRoapServerFatal );
+            }
+        case ENoCertificateChain:
+        case EInvalidCertificateChain:
+        case ETrustedRootCertificateNotPresent:
+            {
+            User::Leave( KErrRoapDevice );
+            }
+        case EInvalidDomain:
+            {
+            User::Leave( KErrRoapInvalidDomain );
+            }
+        case EDomainFull:
+            {
+            User::Leave( KErrRoapDomainFull );
+            }
+        default:
+            {
+            User::Leave( KErrRoapUnsupported );
+            }
+        }
+    return KErrNone;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::ValidateRiIdL()
+//
+// Validates that RI ID equals to public key hash of RI certificate
+// ---------------------------------------------------------
+//
+TBool CRoapEng::ValidateRiIdL( TDesC8& aRiId, TDesC8& aCertBuf )
+    {
+    TBool valid = EFalse;
+    CX509Certificate* riCert = NULL;
+    CSHA1* hash = NULL;
+    HBufC8* publicKeyHash = NULL;
+
+    riCert = CX509Certificate::NewLC( aCertBuf );
+
+    // hash the SubjectPublicKeyInfo element
+    hash = CSHA1::NewL();
+    CleanupStack::PushL( hash );
+    hash->Hash( *riCert->DataElementEncoding(
+        CX509Certificate::ESubjectPublicKeyInfo ) );
+    publicKeyHash = hash->Final().AllocLC();
+
+    if ( aRiId.Compare( *publicKeyHash ) == KErrNone )
+        {
+        valid = ETrue;
+        }
+
+    CleanupStack::PopAndDestroy( publicKeyHash );
+    CleanupStack::PopAndDestroy( hash );
+    CleanupStack::PopAndDestroy( riCert );
+
+    return valid;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::UpdateTransactionTrackingStatusL()
+//
+// Update the status of transaction tracking variable
+// ---------------------------------------------------------
+//
+void CRoapEng::UpdateTransactionTrackingStatusL()
+    {
+    TInt value = KErrNone;
+    CRepository* repository = CRepository::NewL( KCRUidDRMSettings );
+    repository->Get( KDRMSettingsTransactionTracking, value );
+    delete repository;
+    iTransStatus = value ? EAllowed : EForbidden;
+    }
+
+// ---------------------------------------------------------
+// CRoapEng::CreateDeviceIdHashArrayL()
+// ---------------------------------------------------------
+//
+TInt CRoapEng::CreateDeviceIdHashArrayL( RPointerArray<TDesC8>& aIdArray )
+    {
+    TInt err( KErrNone );
+    RPointerArray<HBufC8> certChain;
+    CSHA1* hasher = NULL;
+    HBufC8* publicKey = NULL;
+    CX509Certificate* cert = NULL;
+
+    err = iStorageClient->GetDeviceCertificateChainL( certChain );
+
+    CleanupResetAndDestroyPushL( certChain );
+
+    hasher = CSHA1::NewL();
+    CleanupStack::PushL( hasher );
+    // take the hash of device certificate
+    if (certChain.Count()<=0)
+        {
+        LOGLIT( "Could get Device id Hash!!!" )
+        User::Leave( KErrGeneral );
+        }
+    cert = CX509Certificate::NewL( *certChain[0] );
+    CleanupStack::PushL( cert );
+    publicKey = cert->DataElementEncoding(
+        CX509Certificate::ESubjectPublicKeyInfo )->AllocLC();
+
+    hasher->Hash( *publicKey );
+
+    HBufC8 *elem( hasher->Final().AllocLC() );
+    aIdArray.AppendL( elem );
+    CleanupStack::Pop( elem );
+
+    CleanupStack::PopAndDestroy( publicKey );
+    CleanupStack::PopAndDestroy( cert );
+
+    CleanupStack::PopAndDestroy( hasher );
+    CleanupStack::PopAndDestroy( &certChain );
+    return err;
+    }
+
+// End of file
--- a/group/bld.inf	Tue Oct 19 14:23:00 2010 +0100
+++ b/group/bld.inf	Wed Oct 27 13:24:02 2010 +0100
@@ -40,3 +40,8 @@
 // Rebuild the "original" TimeZone localisation resources as they're eclipsed by something else in the PDK
 /sf/mw/appsupport/tzservices/tzlocrscfactory/group/TzLocalizationRscFactory.mmp
 
+// based on /sf/mw/drm
+../breakdeps/DRMEngine/ROAPHandler.mmp
+../breakdeps/DRMEngine/RightsServer.mmp
+../breakdeps/DRMEngine/DrmStdKeyStorage.mmp
+