bearermanagement/mpm/src/mpmcommsdataccess.cpp
changeset 0 5a93021fdf25
child 3 f7816ffc66ed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bearermanagement/mpm/src/mpmcommsdataccess.cpp	Thu Dec 17 08:55:21 2009 +0200
@@ -0,0 +1,3109 @@
+/*
+* Copyright (c) 2007-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: MPM CommsDat access functions
+*
+*/
+
+/**
+@file mpmcommsdataccess.cpp
+Mobility Policy Manager CommsDat access functions.
+*/
+
+// INCLUDE FILES
+#include <e32base.h>
+#include <commdb.h>
+#include <metadatabase.h>
+#include <commsdattypeinfov1_1.h>
+#include <commsdattypesv1_1.h>
+#include <datamobilitycommsdattypes.h>
+#include <cmpluginbaseeng.h>
+#include <WlanCdbCols.h>
+#include <cmmanagerdef.h>
+#include <cmconnectionmethoddef.h>
+#include <wlancontainer.h>
+#include <utf.h>
+#include <cmpluginwlandef.h>
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <commsdattypeinfov1_1_internal.h>
+#include <commsdattypesv1_1_partner.h>
+#endif
+
+#include <in_sock.h>
+#include <cmgenconnsettings.h>
+#include <cmdestination.h>
+
+#include "mpmcommsdataccess.h"
+#include "mpmserversession.h"
+#include "mpmconnmonevents.h"
+#include "mpmiapselection.h"
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::NewL
+// -----------------------------------------------------------------------------
+//
+CMPMCommsDatAccess* CMPMCommsDatAccess::NewL()
+    {
+    CMPMCommsDatAccess* self = new ( ELeave ) CMPMCommsDatAccess();
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::CMPMCommsDatAccess
+// -----------------------------------------------------------------------------
+//
+CMPMCommsDatAccess::CMPMCommsDatAccess()
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::ConstructL()
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::~CMPMCommsDatAccess
+// -----------------------------------------------------------------------------
+//
+CMPMCommsDatAccess::~CMPMCommsDatAccess()
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::FindAllSnapsL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::FindAllSnapsL( RArray<TUint>& aSnapIds )
+    {
+    MPMLOGSTRING( "CMPMCommsDatAccess::FindAllSnapsL " )
+
+    CMDBSession* db = CMDBSession::NewLC( KCDVersion1_1 );
+    
+    // Get the table id from generic
+    // 
+    CMDBGenericRecord* generic = static_cast<CMDBGenericRecord*>
+        ( CCDRecordBase::RecordFactoryL( 0 ) );
+    CleanupStack::PushL( generic );
+    generic->InitializeL( TPtrC( KCDTypeNameDataMobilitySelectionPolicy ), 
+                          NULL );
+    generic->LoadL( *db );
+
+    // Create the DN-IAP record set
+    // 
+    CMDBRecordSet<CCDDataMobilitySelectionPolicyRecord>* dnIAPRecordSet = 
+        new ( ELeave ) CMDBRecordSet<CCDDataMobilitySelectionPolicyRecord>( 
+        generic->TableId() );
+    CleanupStack::PushL( dnIAPRecordSet );
+
+    dnIAPRecordSet->LoadL( *db );
+    for ( TInt i = 0; i < dnIAPRecordSet->iRecords.Count(); i++ )
+        {
+        CCDDataMobilitySelectionPolicyRecord* dnRecord = new ( ELeave ) 
+        CCDDataMobilitySelectionPolicyRecord( generic->TableId() );
+                
+        dnRecord->SetElementId( GetRealElementId( dnIAPRecordSet->iRecords[i] ) );
+        dnRecord->LoadL( *db );
+
+        TUint snapId = dnRecord->iSNAP;
+        MPMLOGSTRING2( "CMPMCommsDatAccess::FindAllSnapsL snap %d", snapId )
+
+        // Insert unique ids to array
+        //
+        aSnapIds.InsertInOrder( snapId );
+        delete dnRecord;
+        }
+
+    CleanupStack::PopAndDestroy( dnIAPRecordSet );
+    CleanupStack::PopAndDestroy( generic );
+    CleanupStack::PopAndDestroy( db );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::ValidateIapL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::ValidateIapL( 
+    const TConnectionId         aConnId,
+    TUint32&                    aIapId, 
+    TUint32&                    aNetId, 
+    TBool&                      aLanOrWlan,
+    CMPMServerSession&          aSession )
+    {
+    MPMLOGSTRING2(
+        "CMPMCommsDatAccess::ValidateIapL: Validating chosen IAP Id = %i", 
+        aIapId )
+
+    aLanOrWlan = EFalse;
+
+    SearchAccessNetIdL( aIapId, aNetId );
+
+    CCommsDatabase* commsDatabase = CCommsDatabase::NewL();
+    CleanupStack::PushL( commsDatabase );
+
+    // Make hidden records visible
+    // 
+    commsDatabase->ShowHiddenRecords();
+
+    CCommsDbTableView* commsDbIapTableView = 
+        commsDatabase->OpenViewMatchingUintLC( TPtrC( IAP ),
+                                               TPtrC( COMMDB_ID ),
+                                               aIapId );
+
+    User::LeaveIfError( commsDbIapTableView->GotoFirstRecord() );
+
+    TInt length1( 0 );
+
+    commsDbIapTableView->ReadColumnLengthL( TPtrC( IAP_SERVICE_TYPE ), 
+                                            length1 );
+    HBufC* buf1 = HBufC::NewLC( length1 );
+    TPtr ptr1( buf1->Des() );
+
+    // Read IAP's service type
+    //
+    commsDbIapTableView->ReadTextL(TPtrC( IAP_SERVICE_TYPE ), ptr1 );
+    MPMLOGSTRING2(
+        "CMPMCommsDatAccess::ValidateIapL: IAP service type = %S",
+        &ptr1)
+
+    // In case offline mode is enabled, we need to find out what type 
+    // of bearer is used. Only LAN or WLAN is allowed in offline mode.
+    // 
+    if ( ptr1.Compare( TPtrC( LAN_SERVICE ) ) == KErrNone )
+        {
+        aLanOrWlan = ETrue;
+
+        TUint32 service( 0 );
+        commsDbIapTableView->ReadUintL( TPtrC( IAP_SERVICE ), service );
+
+        // Now open a view to LAN_SERVICE table
+        //
+        CCommsDbTableView* commsDbLanTableView = 
+            commsDatabase->OpenViewMatchingUintLC( TPtrC( LAN_SERVICE ),
+                                                   TPtrC( COMMDB_ID ),
+                                                   service );
+
+        User::LeaveIfError( commsDbLanTableView->GotoFirstRecord() );
+
+        TUint32 commDbId( 0 );
+
+        commsDbLanTableView->ReadUintL( TPtrC( COMMDB_ID ), commDbId );
+
+        // Now open a view to WLAN_SERVICE table
+        //
+        // If non wlan product, wlan tables won't exist and this will 
+        // leave. In that case do not check WLAN related issues 
+        //
+        CCommsDbTableView* commsDbWlanTableView( NULL );
+        TRAPD( err2, commsDbWlanTableView = 
+                    commsDatabase->OpenViewMatchingUintLC( TPtrC( WLAN_SERVICE ),
+                                                   TPtrC( WLAN_SERVICE_ID ),
+                                                   commDbId );
+                    CleanupStack::Pop( commsDbWlanTableView ) );
+        if( err2 == KErrNone )
+            {
+            // Push back to cleanup stack. Object must be popped within 
+            // TRAP, to avoid unbalance in cleanup stack and panic 71
+            CleanupStack::PushL( commsDbWlanTableView );
+            
+            TInt err = commsDbWlanTableView->GotoFirstRecord();
+
+            if ( err == KErrNone )
+                {
+                TWlanSsid ssid;
+                commsDbWlanTableView->ReadTextL( TPtrC( NU_WLAN_SSID ), ssid );
+
+                MPMLOGSSID( "CMPMCommsDatAccess<0x%x>::ValidateIapL: SSID = %S", 
+                    aSession.ConnectionId(), &ssid )
+
+                TUint32 presumedIapId = aIapId; 
+
+                // Find and change Iap and Net Id if SSID exist
+                //
+                if ( !CheckEasyWLanL( aIapId ) )
+                    {
+                    aSession.MyServer().Events()->FindSSID( ssid, aIapId, aNetId );
+                    }
+
+                // Store Iap Id, Net Id and empty APN to TConnInfo, 
+                // so that FindAPN can utilise the information 
+                // during the validation of next IAP to support 
+                // using existing WLAN connection SSID.
+                //
+                aSession.MyServer().Events()->AppendConnInfo( aConnId );
+                aSession.MyServer().Events()->SetConnInfo( aConnId, 
+                                                           aIapId, 
+                                                           presumedIapId, 
+                                                           aNetId, 
+                                                           ssid );
+                }
+            else
+                {
+                MPMLOGSTRING2( "CMPMCommsDatAccess::ValidateIapL\
+ GotoFirstRecord returned %d", err )
+                }
+            CleanupStack::PopAndDestroy( commsDbWlanTableView );
+            }
+        else
+            {
+            MPMLOGSTRING2(
+                        "CMPMCommsDatAccess::ValidateIapL: WLAN table view failed, err %d", err2 )
+            }                
+        CleanupStack::PopAndDestroy( commsDbLanTableView );
+        }
+
+    // If this IAP needs PDP Context management, we'll do it here
+    // 
+    else if ( ptr1.Compare(TPtrC(OUTGOING_WCDMA)) == KErrNone )
+        {
+        TUint32 service;
+        commsDbIapTableView->ReadUintL( TPtrC( IAP_SERVICE ), service );
+
+        // Now open a view to OUTGOING_WCDMA table
+        //
+        CCommsDbTableView* commsDbPsdTableView = 
+            commsDatabase->OpenViewMatchingUintLC( TPtrC( OUTGOING_WCDMA ),
+                                                   TPtrC( COMMDB_ID ),
+                                                   service );
+
+        User::LeaveIfError( commsDbPsdTableView->GotoFirstRecord() );
+
+        TInt length2( 0 );
+
+        commsDbPsdTableView->ReadColumnLengthL( TPtrC( GPRS_APN ), length2 );
+
+        HBufC* buf2 = HBufC::NewLC( length2 );
+        TPtr ptr2( buf2->Des() );
+
+        // Read APN
+        //
+        commsDbPsdTableView->ReadTextL( TPtrC( GPRS_APN ), ptr2 );
+        MPMLOGSTRING2(
+            "CMPMCommsDatAccess::ValidateIapL: APN = %S", &ptr2)
+
+        TUint32 presumedIapId = aIapId; 
+
+        // Find and change Iap and Net Id if APN exist
+        //
+        aSession.MyServer().Events()->FindAPN( ptr2, aIapId, aNetId ); 
+
+        // Store Iap Id, Net Id and APN to TConnInfo, 
+        // so that FindAPN can utilise the information 
+        // during the validation of next IAP to support 
+        // using existing PDP context per APN.
+        //
+        aSession.MyServer().Events()->AppendConnInfo( aConnId );
+        aSession.MyServer().Events()->SetConnInfo( aConnId, 
+                                                   aIapId, 
+                                                   presumedIapId, 
+                                                   aNetId, 
+                                                   ptr2 );
+        CleanupStack::PopAndDestroy( buf2 );
+        CleanupStack::PopAndDestroy( commsDbPsdTableView );
+        }
+    else if ( ptr1.Compare(TPtrC( VPN_SERVICE )) == KErrNone )
+        {
+        MPMLOGSTRING(
+            "CMPMCommsDatAccess::ValidateIapL: Enable VPN in offline mode" )
+        aLanOrWlan = ETrue;
+        }
+    else
+        {
+        MPMLOGSTRING(
+            "CMPMCommsDatAccess::ValidateIapL: Service Type out of range" )
+        }
+
+    CleanupStack::PopAndDestroy( buf1 );
+    CleanupStack::PopAndDestroy( commsDbIapTableView );
+    CleanupStack::PopAndDestroy( commsDatabase );
+
+    MPMLOGSTRING2(
+        "CMPMCommsDatAccess::ValidateIapL: Validated IAP Id = %i", aIapId )
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::CheckBearerL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::CheckBearerL( 
+    TUint32&                    aIapId, 
+    TBool&                      aLanOrWlan, 
+    const RAvailableIAPList&    aAvailableIAPList,
+    CMPMServerSession&          aSession )
+    {
+    MPMLOGSTRING2( "CMPMCommsDatAccess::CheckBearerL: IAP Id = %i", aIapId )
+
+    aLanOrWlan = EFalse;
+
+    // Use FindRealIapL to find the real IAP behind the virtual IAP.
+    // 
+    TUint32 realIapId( 0 );
+    FindRealIapL( aIapId, 
+                  realIapId, 
+                  aAvailableIAPList,
+                  aSession );
+
+    if ( ( realIapId != 0 ) && ( aIapId != realIapId ) )
+        {
+        aIapId = realIapId;
+        MPMLOGSTRING2(
+            "CMPMCommsDatAccess::CheckBearerL: Found real IAP Id = %i", 
+            aIapId )
+        }
+
+    CCommsDatabase* commsDatabase = CCommsDatabase::NewL();
+    CleanupStack::PushL(commsDatabase);
+
+    // Make hidden records visible
+    // 
+    commsDatabase->ShowHiddenRecords();
+
+    CCommsDbTableView* commsDbIapTableView = 
+        commsDatabase->OpenViewMatchingUintLC( TPtrC(IAP),
+                                               TPtrC(COMMDB_ID),
+                                               aIapId);
+
+    User::LeaveIfError( commsDbIapTableView->GotoFirstRecord() );
+
+    TInt length1( 0 );
+
+    commsDbIapTableView->ReadColumnLengthL(TPtrC(IAP_SERVICE_TYPE), length1);
+    HBufC* buf1 = HBufC::NewLC(length1);
+    TPtr ptr1( buf1->Des() );
+
+    // Read IAP's service type
+    //
+    commsDbIapTableView->ReadTextL(TPtrC(IAP_SERVICE_TYPE), ptr1);
+    MPMLOGSTRING2(
+        "CMPMCommsDatAccess::CheckBearerL: IAP_SERVICE_TYPE from CommsDat = %S",
+        &ptr1 )
+
+    // In case offline mode is enabled, we need to find out what type 
+    // of bearer is used. Only LAN or WLAN is allowed in offline mode.
+    // 
+    if ( ptr1.Compare(TPtrC(LAN_SERVICE)) == KErrNone )
+        {
+        aLanOrWlan = ETrue;
+        MPMLOGSTRING( "CMPMCommsDatAccess::CheckBearerL: Bearer type LAN/WLAN" )
+        }
+    else
+        {
+        aLanOrWlan = EFalse;
+        MPMLOGSTRING( "CMPMCommsDatAccess::CheckBearerL: Bearer type GSM/UMTS" )
+        }
+
+    CleanupStack::PopAndDestroy(buf1);
+    CleanupStack::PopAndDestroy(commsDbIapTableView);    
+    CleanupStack::PopAndDestroy(commsDatabase);
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::CheckEasyWLanL
+// -----------------------------------------------------------------------------
+//
+TBool CMPMCommsDatAccess::CheckEasyWLanL( TUint32 aIapId ) const
+    {
+    MPMLOGSTRING2( "CMPMCommsDatAccess::CheckEasyWLanL: IAP Id = %i", aIapId)
+
+    TBool easyWlan = EFalse;
+    CCommsDatabase* commsDatabase = CCommsDatabase::NewL();
+    CleanupStack::PushL( commsDatabase );
+
+    // Make hidden records visible
+    // 
+    commsDatabase->ShowHiddenRecords();
+
+    CCommsDbTableView* commsDbIapTableView = 
+        commsDatabase->OpenViewMatchingUintLC( TPtrC( IAP ),
+                                               TPtrC( COMMDB_ID ),
+                                               aIapId );
+
+    User::LeaveIfError( commsDbIapTableView->GotoFirstRecord() );
+
+    TInt length1( 0 );
+
+    commsDbIapTableView->ReadColumnLengthL( TPtrC( IAP_SERVICE_TYPE ), 
+                                            length1 );
+
+    HBufC* buf1 = HBufC::NewLC( length1 );
+    TPtr ptr1( buf1->Des() );
+
+    // Read IAP's service type
+    //
+    commsDbIapTableView->ReadTextL(TPtrC( IAP_SERVICE_TYPE ), ptr1 );
+    MPMLOGSTRING2(
+        "CMPMCommsDatAccess::CheckEasyWLanL: IAP service type = %S", &ptr1 )
+
+    if ( ptr1.Compare( TPtrC( LAN_SERVICE ) ) == KErrNone )
+        {
+        TUint32 service( 0 );
+        commsDbIapTableView->ReadUintL( TPtrC( IAP_SERVICE ), service );
+
+        // Now open a view to LAN_SERVICE table
+        //
+        CCommsDbTableView* commsDbLanTableView = 
+            commsDatabase->OpenViewMatchingUintLC( TPtrC( LAN_SERVICE ),
+                                                   TPtrC( COMMDB_ID ),
+                                                   service );
+
+        User::LeaveIfError( commsDbLanTableView->GotoFirstRecord() );
+
+        TUint32 commDbId( 0 );
+
+        commsDbLanTableView->ReadUintL( TPtrC( COMMDB_ID ), commDbId );
+
+        // Now open a view to WLAN_SERVICE table
+        //
+        // If non wlan product, wlan tables won't exist and this will 
+        // leave. In that case do not check WLAN related issues 
+        //
+        CCommsDbTableView* commsDbWlanTableView( NULL );
+        TRAPD( err2, commsDbWlanTableView =
+                     commsDatabase->OpenViewMatchingUintLC( TPtrC( WLAN_SERVICE ),
+                                                            TPtrC( WLAN_SERVICE_ID ),
+                                                            commDbId );
+                     CleanupStack::Pop( commsDbWlanTableView ) );
+        if ( err2 == KErrNone )
+            {
+            // Push back to cleanup stack. Object must be popped within 
+            // TRAP, to avoid unbalance in cleanup stack and panic 71
+            CleanupStack::PushL( commsDbWlanTableView );
+
+            TInt err = commsDbWlanTableView->GotoFirstRecord();
+
+            if ( err == KErrNone )
+                {
+                TInt ssidLength( 0 );
+                commsDbWlanTableView->ReadColumnLengthL( TPtrC( NU_WLAN_SSID ), 
+                                                                ssidLength );
+                if ( ssidLength == 0 )
+                    {
+                    MPMLOGSTRING(
+                        "CMPMCommsDatAccess::CheckEasyWLanL: IAP is Easy WLAN" )
+                    easyWlan = ETrue;
+                    }
+                else
+                    {
+                    MPMLOGSTRING(
+                        "CMPMCommsDatAccess::CheckEasyWLanL: IAP isn't Easy WLAN" )
+                    easyWlan = EFalse;
+                    }
+                }
+            else
+                {
+                MPMLOGSTRING2( "CMPMCommsDatAccess::CheckEasyWLanL\
+ GotoFirstRecord returned %d", err )
+                }
+
+            // Release memory
+            //
+            CleanupStack::PopAndDestroy( commsDbWlanTableView );
+            }
+        else
+            {
+            MPMLOGSTRING2(
+                        "CMPMCommsDatAccess::CheckEasyWLanL: WLAN table view failed, err %d", err2 )
+            }    
+        CleanupStack::PopAndDestroy( commsDbLanTableView );
+        }
+
+    // Release memory
+    //
+    CleanupStack::PopAndDestroy( buf1 );
+    CleanupStack::PopAndDestroy( commsDbIapTableView );
+    CleanupStack::PopAndDestroy( commsDatabase );
+
+    return easyWlan;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::DumpIAPsL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::DumpIAPsL() const
+    {
+#ifdef _DEBUG
+
+    // Dump CommsDat IAPs to log in order to support testing
+    // 
+    TInt err( KErrNone );
+
+    MPMLOGSTRING( "Display CommsDat IAPs - Start" )
+    MPMLOGSTRING( "" )
+
+    CCommsDatabase* commsDatabase = CCommsDatabase::NewL();
+    CleanupStack::PushL(commsDatabase);
+
+    // Make hidden records visible
+    // 
+    commsDatabase->ShowHiddenRecords();
+
+    // Iterate the IAP table from CommsDat
+    CCommsDbTableView* table = NULL;
+    table = commsDatabase->OpenTableLC( TPtrC( IAP ) );
+
+    err = table->GotoFirstRecord();
+
+    while ( !err )
+        {
+        TUint32 iapId( 0 );
+        TInt    length1( 0 );
+        TInt    length2( 0 );
+
+        // Read IAP's ID
+        //
+        table->ReadUintL( TPtrC( COMMDB_ID ), iapId );
+
+        // Read IAP's connection name
+        //
+        table->ReadColumnLengthL( TPtrC( COMMDB_NAME ), length1 );
+        HBufC* buf1 = HBufC::NewLC( length1 );
+        TPtr ptr1( buf1->Des() );
+        table->ReadTextL( TPtrC( COMMDB_NAME ), ptr1 );
+
+        // Read IAP's service type
+        //
+        table->ReadColumnLengthL(TPtrC( IAP_SERVICE_TYPE ), length2 );
+        HBufC* buf2 = HBufC::NewLC( length2 );
+        TPtr ptr2( buf2->Des() );
+        table->ReadTextL(TPtrC( IAP_SERVICE_TYPE ), ptr2 );
+
+        // Dump information to log
+        // 
+        MPMLOGSTRING3( "IAP %i: Name = %S", iapId, &ptr1 )
+        MPMLOGSTRING2( "Service type = %S", &ptr2 )
+
+        MPMLOGSTRING( "" )
+        
+        err = table->GotoNextRecord();
+
+        CleanupStack::PopAndDestroy( buf2 );
+        CleanupStack::PopAndDestroy( buf1 );
+        }
+
+    MPMLOGSTRING( "Display CommsDat IAPs - End" )
+
+    CleanupStack::PopAndDestroy( table );
+    CleanupStack::PopAndDestroy( commsDatabase );
+#endif // _DEBUG
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::DumpSnapsL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::DumpSnapsL()
+    {
+#ifdef _DEBUG
+
+    // Dump CommsDat Snaps to log in order to support testing
+    // 
+    MPMLOGSTRING( "Display CommsDat Snaps - Start" )
+    MPMLOGSTRING( "" )
+
+    // Creating a session with the latest version
+    // 
+    CMDBSession* db = CMDBSession::NewLC( KCDVersion1_1 );
+
+    db->SetAttributeMask( ECDHidden | ECDProtectedWrite );
+
+    // Create the generic record set
+    // 
+    CMDBGenericRecord* generic = static_cast<CMDBGenericRecord*>
+        ( CCDRecordBase::RecordFactoryL( 0 ) ); 
+    CleanupStack::PushL( generic );  
+    generic->InitializeL( TPtrC( KCDTypeNameDataMobilitySelectionPolicy ), 
+                          NULL );
+    generic->LoadL( *db );
+
+    // Create the DN-IAP record set
+    // 
+    CMDBRecordSet<CCDDataMobilitySelectionPolicyRecord>* dnIAPRecordSet = 
+        new ( ELeave ) CMDBRecordSet<CCDDataMobilitySelectionPolicyRecord>( 
+        generic->TableId() );
+    CleanupStack::PushL( dnIAPRecordSet ); 
+
+    CCDDataMobilitySelectionPolicyRecord* dnIAPRecord = new ( ELeave ) 
+        CCDDataMobilitySelectionPolicyRecord( generic->TableId() );
+    CleanupStack::PushL( dnIAPRecord );
+
+    // Find all the DN-IAP records
+    // 
+    dnIAPRecordSet->LoadL( *db );
+
+    CCDIAPRecord*       linkedIAP;
+    //CCDNetworkRecord*   linkedDN;
+    //CCDNetworkRecord*   linkedDN2;
+    CCDAccessPointRecord*   linkedAP;
+    CCDAccessPointRecord*   linkedAP2;
+    RArray<TInt>        prevRecordIds;
+    CleanupClosePushL( prevRecordIds );
+
+    for ( TInt i = 0; i < dnIAPRecordSet->iRecords.Count(); i++ )
+        {
+        // Load each DN-IAP entry based on the elementId in the record set
+        // 
+        dnIAPRecord->SetElementId( GetRealElementId( dnIAPRecordSet->iRecords[i] ) );
+        dnIAPRecord->LoadL( *db );
+
+
+        linkedAP =  static_cast<CCDAccessPointRecord*>( CCDAccessPointRecord::RecordFactoryL( KCDTIdAccessPointRecord ) );
+        CleanupStack::PushL( linkedAP );
+
+        // Find the SNAP AP pointed by DN-IAP entry
+        //
+        linkedAP->iRecordTag = (TInt)dnIAPRecord->iSNAP;
+        TBool found = linkedAP->FindL( *db );
+
+        // Don't print duplicates
+        // 
+        if ( found && KErrNotFound == prevRecordIds.Find( linkedAP->RecordId() ) )
+            {
+            prevRecordIds.Append( linkedAP->RecordId() );
+            
+            // Print the DN and host name pointed by DN-IAP entry.
+            // HostName is EText field.
+            // 
+            TBuf<KCommsDatTextBufferLength> dn = linkedAP->iRecordName.GetL();
+            MPMLOGSTRING3( "Snap: %d Snap Name = %s", (TInt)linkedAP->iRecordTag, dn.PtrZ() )
+            
+            // Related DN-IAP records 
+            // Get the table id from generic record
+            // 
+            CMDBGenericRecord* generic2 = static_cast<CMDBGenericRecord*>
+                ( CCDRecordBase::RecordFactoryL( 0 ) ); 
+            CleanupStack::PushL( generic2 );  
+            generic2->InitializeL( TPtrC( 
+                KCDTypeNameDataMobilitySelectionPolicy ), NULL );
+            generic2->LoadL( *db );
+            
+            // Doesn't quite work with generic records
+            // 
+            CMDBRecordSet<CCDDataMobilitySelectionPolicyRecord>* 
+                dnIAPRecordSet2 = new ( ELeave ) 
+                CMDBRecordSet<CCDDataMobilitySelectionPolicyRecord>( 
+                generic2->TableId() );
+            CleanupStack::PushL( dnIAPRecordSet2 ); 
+            
+            // Prime one record with DN 
+            // 
+            CCDDataMobilitySelectionPolicyRecord* dnIAPRecord2 = 
+                new ( ELeave ) CCDDataMobilitySelectionPolicyRecord( 
+                generic2->TableId() );
+            CleanupStack::PushL( dnIAPRecord2 );
+            dnIAPRecord2->iSNAP = (TInt)linkedAP->iRecordTag;
+            dnIAPRecordSet2->iRecords.Append( dnIAPRecord2 );
+            CleanupStack::Pop( dnIAPRecord2 );
+
+            if ( dnIAPRecordSet2->FindL( *db ) )
+                {
+                for (TInt j = 0; j < dnIAPRecordSet2->iRecords.Count(); j++)
+                    {
+                    dnIAPRecord2->SetElementId( GetRealElementId( dnIAPRecordSet2->iRecords[j] ) );
+                    dnIAPRecord2->LoadL( *db );
+
+                    if ( dnIAPRecord2->iIAP != 0 )
+                        {
+                        linkedIAP = static_cast<CCDIAPRecord*>
+                            ( LoadLinkedRecordL( *db, dnIAPRecord2->iIAP ) );
+                        MPMLOGSTRING3( "IAP = %d Priority = %d", 
+                            linkedIAP->RecordId(), 
+                            static_cast<TUint32>( dnIAPRecord2->iPriority ) )
+                        delete linkedIAP;
+                        dnIAPRecord2->iIAP = 0;
+                        }
+                    else if( dnIAPRecord2->iEmbeddedSNAP != 0 )
+                        {
+                        linkedAP2 =  static_cast<CCDAccessPointRecord*>( 
+                                CCDAccessPointRecord::RecordFactoryL( KCDTIdAccessPointRecord ) );
+                        CleanupStack::PushL( linkedAP2 );
+                        TInt esnap = dnIAPRecord2->iEmbeddedSNAP;
+                        linkedAP2->iRecordTag = esnap;
+                        if ( !linkedAP->FindL( *db ))
+                            {
+                            User::Leave( KErrNotFound );
+                            }
+                        
+                        MPMLOGSTRING3( "Embedded Snap = %d Priority = %d", 
+                            (TInt)linkedAP2->iRecordTag, 
+                            static_cast<TUint32>( dnIAPRecord2->iPriority ) )
+                        CleanupStack::PopAndDestroy( linkedAP2 );
+                        dnIAPRecord2->iEmbeddedSNAP = 0;
+                        }
+                    else
+                        {
+                        // Each Snap has an initial entry in this table,
+                        // where both the IAP and EmbeddedSNAP links 
+                        // have null value. 
+                        }
+                    }
+                }
+            CleanupStack::PopAndDestroy( dnIAPRecordSet2 );
+            CleanupStack::PopAndDestroy( generic2 );
+            MPMLOGSTRING( "" )
+            }
+        CleanupStack::PopAndDestroy( linkedAP );
+        }
+
+    MPMLOGSTRING( "Display CommsDat Snaps - End" )
+
+    CleanupStack::PopAndDestroy( &prevRecordIds );
+    CleanupStack::PopAndDestroy( dnIAPRecord );
+    CleanupStack::PopAndDestroy( dnIAPRecordSet );
+    CleanupStack::PopAndDestroy( generic );
+    CleanupStack::PopAndDestroy( db );
+#endif // _DEBUG
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::DeterminePrioritiesL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::DeterminePrioritiesL( 
+    RArray<TNetIap>&          aDNIaps, 
+    const RAvailableIAPList&  aAvailableIAPList,
+    CMPMServerSession&        aSession )
+    {
+    MPMLOGSTRING( "CMPMCommsDatAccess::DeterminePrioritiesL" )
+
+    TBool useGlobalPriorities( EFalse );
+
+    for( TInt i( 0 ); ( i < aDNIaps.Count() ) && !useGlobalPriorities; i++ )
+        {
+        if( aDNIaps[i].iRanking == 
+            CMManager::KDataMobilitySelectionPolicyPriorityWildCard )
+            {
+            // If any of the IAPs in the array has wildcard priority, 
+            // then global bearer priorities should be used. 
+            //
+            useGlobalPriorities = ETrue;
+            }
+        }
+
+    if( !useGlobalPriorities )
+        {
+        // If not a single IAP in the array had wildcard priority, 
+        // then local priorities defined by user should be used. 
+        //
+        return;
+        }
+
+    for( TInt i( 0 ); i < aDNIaps.Count() ; i++ )
+        {
+        MPMLOGSTRING2(
+            "CMPMCommsDatAccess::DeterminePrioritiesL: IapId = %i \
+has wildcard priority", aDNIaps[i].iIapId )
+
+        // Find out the real IAP Id and check 
+        // the global bearer priority for that.
+        // 
+        TUint32 priority( KLowestPriority );
+        TUint32 iapId;
+        FindRealIapL( aDNIaps[i].iIapId, 
+                      iapId, 
+                      aAvailableIAPList,
+                      aSession );
+
+        GlobalBearerPriorityL( iapId, 
+                               priority );
+
+        aDNIaps[i].iGlobalPriority = priority;
+
+        MPMLOGSTRING3(
+            "CMPMCommsDatAccess::DeterminePrioritiesL: IapId = %i \
+has global priority: %i", aDNIaps[i].iIapId, priority )
+        }
+
+    // Finally, sort the array according to global bearer priorities. 
+    // 
+    aDNIaps.Sort( TNetIap::CompareGlobalAndLocalPriority );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::GlobalBearerPriorityL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::GlobalBearerPriorityL( const TUint32   aIapId,
+                                               TUint32&        aPriority )
+    {
+    MPMLOGSTRING2( "CMPMCommsDatAccess::GlobalBearerPriorityL: IapId: %i", 
+        aIapId )
+
+    CMDBSession* db = CMDBSession::NewLC( KCDVersion1_1 );
+
+    db->SetAttributeMask( ECDHidden | ECDProtectedWrite );
+
+    // Get the IAP record
+    // 
+    CCDIAPRecord* iap = LoadIapRecordLC( aIapId, db );
+
+    // Get the service type of aIapId
+    // 
+    TBuf<KMaxTextLength + 1> service;
+    service = iap->iServiceType.GetL();
+    MPMLOGSTRING2(
+        "CMPMCommsDatAccess::GlobalBearerPriorityL: Service type = %s",
+        service.PtrZ() )
+
+    // Get the table id from generic
+    // 
+    CMDBGenericRecord* record = static_cast<CMDBGenericRecord*>
+        ( CCDRecordBase::RecordFactoryL( 0 ) );
+    CleanupStack::PushL( record );
+    record->InitializeL( TPtrC( KCDTypeNameGlobalService ), NULL );
+    record->SetRecordId( KCDInitialRecordId );
+    record->LoadL( *db );
+
+    // Create Global Bearer Type Priorization Record
+    // 
+    CCDGlobalBearerTypePriorizationRecord* globalBearer = new ( ELeave ) 
+        CCDGlobalBearerTypePriorizationRecord( record->TableId() );
+    CleanupStack::PushL( globalBearer );
+
+    // Set the service type of aIapId to Global 
+    // Bearer Type Priorization Record
+    // 
+    globalBearer->iServiceType.SetL( service );
+
+    if( globalBearer->FindL( *db ) )
+        {
+        // Get the priority of specified service type
+        // 
+        aPriority = ( TUint32 )globalBearer->iPriority;
+        MPMLOGSTRING2(
+            "CMPMCommsDatAccess::GlobalBearerPriorityL: Priority = %i", 
+            aPriority )
+        }
+
+    // Release memory
+    //
+    CleanupStack::PopAndDestroy( globalBearer );
+    CleanupStack::PopAndDestroy( record );
+    CleanupStack::PopAndDestroy( iap );
+    CleanupStack::PopAndDestroy( db );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::CheckWLANIapL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::CheckWLANIapL(CMPMServerSession& aSession)
+    {
+    MPMLOGSTRING( "CMPMCommsDatAccess::CheckWLANIapL" )
+
+    TInt err( KErrNone );
+    TBool found( EFalse );
+
+    CCommsDatabase* commsDatabase = CCommsDatabase::NewL();
+    CleanupStack::PushL( commsDatabase );
+
+    // Make hidden records visible
+    // 
+    commsDatabase->ShowHiddenRecords();
+
+    // Iterate the IAP table from CommsDat
+    CCommsDbTableView* table = NULL;
+    table = commsDatabase->OpenTableLC( TPtrC( IAP ) );
+
+    err = table->GotoFirstRecord();
+
+    while ( !err && !found )
+        {
+        TUint32 iapId( 0 );
+        TInt    length( 0 );
+
+        // Read IAP's ID
+        //
+        table->ReadUintL( TPtrC( COMMDB_ID ), iapId );
+
+        // Read IAP's service type
+        //
+        table->ReadColumnLengthL(TPtrC( IAP_SERVICE_TYPE ), length );
+        HBufC* buf = HBufC::NewLC( length );
+        TPtr ptr( buf->Des() );
+        table->ReadTextL(TPtrC( IAP_SERVICE_TYPE ), ptr );
+
+        if ( ptr.Compare( TPtrC( LAN_SERVICE ) ) == KErrNone )
+            {
+            TUint32 service( 0 );
+            table->ReadUintL( TPtrC( IAP_SERVICE ), service );
+
+            // Now open a view to LAN_SERVICE table
+            //
+            CCommsDbTableView* commsDbLanTableView = 
+                commsDatabase->OpenViewMatchingUintLC( TPtrC( LAN_SERVICE ),
+                                                       TPtrC( COMMDB_ID ),
+                                                       service );
+
+            User::LeaveIfError( commsDbLanTableView->GotoFirstRecord() );
+
+            TUint32 commDbId( 0 );
+
+            commsDbLanTableView->ReadUintL( TPtrC( COMMDB_ID ), commDbId );
+
+            // Now open a view to WLAN_SERVICE table
+            //
+            // If non wlan product, wlan tables won't exist and this will 
+            // leave. In that case do not check WLAN related issues 
+            //
+
+            CCommsDbTableView* commsDbWlanTableView( NULL );
+            TRAP( err, commsDbWlanTableView = 
+                         commsDatabase->OpenViewMatchingUintLC( 
+                                                TPtrC( WLAN_SERVICE ),
+                                                TPtrC( WLAN_SERVICE_ID ),
+                                                commDbId ); 
+                         CleanupStack::Pop( commsDbWlanTableView ); );
+            if ( err == KErrNone )
+                {
+                // Push back to cleanup stack. Object must be popped within 
+                // TRAP, to avoid unbalance in cleanup stack and panic 71
+                CleanupStack::PushL( commsDbWlanTableView );
+                
+                TInt error = commsDbWlanTableView->GotoFirstRecord();
+
+                if ( error == KErrNone )
+                    {
+                    // Easy WLAN is not considered to be "real" WLAN IAP
+                    // 
+                    TInt ssidLength( 0 );
+                    commsDbWlanTableView->ReadColumnLengthL( 
+                                                    TPtrC( NU_WLAN_SSID ), 
+                                                    ssidLength );
+                    if ( ssidLength != 0 )
+                        {
+                        found = ETrue;
+
+                        MPMLOGSTRING( "CMPMCommsDatAccess::CheckWLANIapL:\
+ Found WLAN IAP" )
+
+                        // If a single WLAN IAP was found in CommsDat, 
+                        // then set the need to scan WLAN networks as true.
+                        // 
+                        aSession.MyServer().SetWLANScanRequired( ETrue );
+                        }
+                    }
+
+                
+
+                // Release memory
+                //
+                CleanupStack::PopAndDestroy( commsDbWlanTableView );
+                }
+            else
+                {
+                MPMLOGSTRING2(
+                            "CMPMCommsDatAccess::CheckWLANIapL: WLAN table view failed, err %d", err )
+                }
+            CleanupStack::PopAndDestroy( commsDbLanTableView );
+            }
+        err = table->GotoNextRecord();
+
+        CleanupStack::PopAndDestroy( buf );
+        }
+
+    // If not a single WLAN IAP was found in CommsDat, 
+    // then set the need to scan WLAN networks as false.
+    // 
+    if ( !found )
+        {
+        MPMLOGSTRING( "CMPMCommsDatAccess::CheckWLANIapL: Not found WLAN IAP" )
+        aSession.MyServer().SetWLANScanRequired( EFalse );
+        }
+
+    CleanupStack::PopAndDestroy( table );
+    CleanupStack::PopAndDestroy( commsDatabase );
+    }
+        
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::CheckWLANIapWithSsidL
+// -----------------------------------------------------------------------------
+//
+
+TUint32 CMPMCommsDatAccess::CheckWLANIapWithSsidL( TWlanSsid& aSsid, 
+                                                   TUint32 aSecMode,
+                                                   TWlanNetMode aConnMode )
+    {
+    MPMLOGSTRING( "CMPMCommsDatAccess::CheckWLANIapWithSsidL" )
+    TUint iapId( 0 );
+
+    // Creating a session with the latest version
+    //     
+    CMDBSession* db = CMDBSession::NewLC( KCDVersion1_1 );
+
+    db->SetAttributeMask( ECDHidden | ECDProtectedWrite );
+
+    // Find Wlan service record
+    //
+    TBuf<KWlanMaxSsidLength> ssid16;
+    CnvUtfConverter::ConvertToUnicodeFromUtf8( ssid16, aSsid );
+    MPMLOGSTRING4( "CMPMCommsDatAccess::CheckWLANIapWithSsidL sec:%d, conn:%d ssid %S", 
+                   aSecMode, 
+                   aConnMode, 
+                   &ssid16 )
+    CMDBRecordSet<CCDWlanServiceRecord>* wlanSet = 
+        new ( ELeave ) CMDBRecordSet<CCDWlanServiceRecord>( 
+         CCDWlanServiceRecord::TableIdL( *db ) );
+    CleanupStack::PushL( wlanSet ); 
+
+    CCDWlanServiceRecord* wlanRecord = new ( ELeave ) 
+        CCDWlanServiceRecord( CCDWlanServiceRecord::TableIdL( *db ) );
+
+    CleanupStack::PushL( wlanRecord ); 
+    wlanSet->LoadL( *db );
+    
+    MPMLOGSTRING2( "CMPMCommsDatAccess::CheckWLANIapWithSsidL, record count:%d", 
+                   wlanSet->iRecords.Count() )
+    TBool matchFound( EFalse );
+    for (TInt i = 0; ( i < wlanSet->iRecords.Count() ) && !matchFound; i++ )
+        {
+        wlanRecord->SetElementId( GetRealElementId( wlanSet->iRecords[i] ) );
+        wlanRecord->LoadL( *db );
+        TBuf<KWlanMaxSsidLength> ssid;
+        ssid = wlanRecord->iWLanSSID;
+        //if not easywlan, continue
+        //
+        if( ssid.Compare( KNullDesC() ) )
+            {
+            ssid = wlanRecord->iWLanSSID.GetL();
+            TUint32 secMode = wlanRecord->iWlanSecMode;
+            TUint32 connMode = wlanRecord->iWlanConnMode;
+        
+            if ( connMode )
+                {
+                connMode = 1;    
+                }
+            MPMLOGSTRING3( "CMPMCommsDatAccess::CheckWLANIapWithSsidL CommsDat secmode:%d, connmode:%d ", 
+        				   secMode, 
+        				   connMode )
+
+            if ( !ssid.Compare( ssid16 ) && ( aConnMode == connMode ) )
+        	    {
+        	    //compare sec mode
+        	    if ( aSecMode == EWlanSecModeOpen || aSecMode == EWlanSecModeWep )
+        		    {
+        		    if ( aSecMode == secMode )
+        		        {
+        		        MPMLOGSTRING( "CMPMCommsDatAccess::CheckWLANIapWithSsidL match found, open/wep " )
+        		        matchFound = ETrue;
+        		        }
+        			    
+        		    }
+            	//WPA PSK case
+            	else if ( aSecMode == EWlanSecModeWpa2 )
+            		{
+        	    	if ( ( secMode > EWlanSecModeWep ) && (wlanRecord->iWlanEnableWpaPsk) )
+        	    	    {
+        	    	    MPMLOGSTRING( "CMPMCommsDatAccess::CheckWLANIapWithSsidL match found, wpa psk " )
+        	    	    matchFound = ETrue;
+        	    	    }
+            		}
+            	//aSecMode = EWlanSecModeWpa
+            	else
+            		{
+        	    	if ( secMode > EWlanSecModeWep )
+        	    	    {
+        	    	    MPMLOGSTRING( "CMPMCommsDatAccess::CheckWLANIapWithSsidL match found, wpa " )
+        	    	    matchFound = ETrue;
+        	    	    }
+            		}
+        			
+        		}
+        	}
+        }
+    
+    if ( matchFound )
+        {
+        // load Iap record
+        //
+        CCDIAPRecord* iapRecord = static_cast<CCDIAPRecord*> ( 
+            CCDRecordBase::RecordFactoryL( KCDTIdIAPRecord ) );
+        CleanupStack::PushL( iapRecord );
+
+        CCDLANServiceRecord* lanRecord = static_cast<CCDLANServiceRecord*> (
+            CCDRecordBase::RecordFactoryL( KCDTIdLANServiceRecord ));
+        CleanupStack::PushL( lanRecord );
+        
+        iapRecord->iServiceType.SetL( TPtrC( KCDTypeNameLANService ) );
+        
+        lanRecord->SetRecordId( wlanRecord->iWlanServiceId );
+        lanRecord->LoadL( *db );
+
+        iapRecord->iService = lanRecord->ElementId();
+
+/*        iapRecord->iServiceType.SetL( TPtrC( KCDTypeNameLANService ) );
+        iapRecord->iService = wlanRecord->iWlanServiceId;
+*/
+        if( iapRecord->FindL( *db ) )
+            {
+            MPMLOGSTRING( "CMPMCommsDatAccess::CheckWLANIapWithSsidL iap found" )
+            // Iap record found
+            //
+            iapId = iapRecord->RecordId();
+            }
+        CleanupStack::PopAndDestroy( lanRecord );
+        CleanupStack::PopAndDestroy( iapRecord );
+        }
+    CleanupStack::PopAndDestroy( wlanRecord );
+    CleanupStack::PopAndDestroy( wlanSet );
+    CleanupStack::PopAndDestroy( db );
+    
+    return iapId;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::SetEasyWlanDataL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::SetEasyWlanDataL( const TWlanSsid& aSsid,
+                                           TUint            aSecMode,
+                                           TWlanNetMode     aConnMode,
+                                           TWepKeyData      aWepData,
+                                           TUint            aEnableWpaPsk,
+                                           const TDesC8&    aWpaPsk,
+                                           TUint            aWpaKeyLen )
+    {
+    MPMLOGSTRING( "CMPMCommsDatAccess::SetEasyWlanDataL" )
+    CMDBSession* dbSession = CMDBSession::NewL( KCDVersion1_1 );
+    CleanupStack::PushL(dbSession);
+
+    // Try to open a transaction to obtain write lock
+    dbSession->OpenTransactionL();
+
+    TUint32 wlanId = FindEasyWlanServiceIdL( dbSession );
+    if( !wlanId )
+        {
+        MPMLOGSTRING( "CMPMCommsDatAccess::SetEasyWlanDataL unable to store \
+ easy wlan settings" )
+        dbSession->Close();		
+		CleanupStack::PopAndDestroy( dbSession );
+        return;
+        }
+    
+    CMDBGenericRecord* record = static_cast<CMDBGenericRecord*> 
+				    ( CCDRecordBase::RecordFactoryL( 0));
+    CleanupStack::PushL( record );
+    record->InitializeL( TPtrC( WLAN_SERVICE ),NULL );
+    record->SetRecordId( wlanId );
+    record->LoadL( *dbSession );
+
+        TBuf<KWlanMaxSsidLength> ssid16;
+        CnvUtfConverter::ConvertToUnicodeFromUtf8( ssid16, aSsid );
+        CMDBField<TDesC>* textField = (CMDBField<TDesC>*)record->GetFieldByIdL(KCDTIdWlanUsedSSID);
+        textField->SetMaxLengthL( ssid16.Length());
+        textField->SetL( ssid16 );
+    
+        *((CMDBField<TUint32>*)record->GetFieldByIdL(KCDTIdWlanSecMode)) = aSecMode;
+        *((CMDBField<TUint32>*)record->GetFieldByIdL(KCDTIdWlanConnMode)) = aConnMode;
+    
+        if (aEnableWpaPsk)
+    	    {
+    	    MPMLOGSTRING( "CMPMCommsDatAccess::SetEasyWlanDataL wpa psk" )
+    	    CMDBField<TDesC8>* binField = (CMDBField<TDesC8>*)
+		   									record->GetFieldByIdL(KCDTIdWlanWpaPreSharedKey);
+		    binField->SetMaxLengthL( aWpaKeyLen );
+		    binField->SetL( aWpaPsk );
+
+		    *((CMDBField<TUint32>*)record->GetFieldByIdL(KCDTIdWlanWpaKeyLength)) = aWpaKeyLen;
+		    *((CMDBField<TUint32>*)record->GetFieldByIdL(KCDTIdWlanEnableWpaPsk)) = aEnableWpaPsk;
+    	    }
+        else if (aSecMode == EWlanSecModeWep)
+    	    {
+    	    MPMLOGSTRING( "CMPMCommsDatAccess::SetEasyWlanDataL wep psk" )
+     	    *((CMDBField<TUint32>*)record->GetFieldByIdL( KCDTIdWlanWepIndex )) = 
+     	        aWepData.iDefaultWep;
+ 
+    	    SetWepKeyL( KCDTIdWlanFormatKey1, KCDTIdWlanWepKey1, 
+    	                aWepData.iWep1, aWepData.iWepFormat1, record );
+            SetWepKeyL( KCDTIdWlanFormatKey2, KCDTIdWlanWepKey2, 
+                        aWepData.iWep2, aWepData.iWepFormat2, record );
+            SetWepKeyL( KCDTIdWlanFormatKey3, KCDTIdWlanWepKey3, 
+                        aWepData.iWep3, aWepData.iWepFormat3, record );
+            SetWepKeyL( KCDTIdWlanFormatKey4, KCDTIdWlanWepKey4, 
+                        aWepData.iWep4, aWepData.iWepFormat4, record );
+    	    }
+    	else
+    	    {
+    	    MPMLOGSTRING2( "CMPMCommsDatAccess::SetEasyWlanDataL sec mode %d, no key data written",
+    	         aSecMode )
+    	    }
+    
+        //Finally save all to commsdat.
+        record->ModifyL( *dbSession );
+        dbSession->CommitTransactionL();
+        dbSession->Close();
+        CleanupStack::PopAndDestroy( record );
+        CleanupStack::PopAndDestroy( dbSession );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::SetWepKeyL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::SetWepKeyL( TMDBElementId       aFormatId,
+                                     TMDBElementId       aKeyId, 
+                                     TWlanWepKey         aWepKey,
+                                     TUint               aWepFormat,
+                                     CMDBGenericRecord*  aRecord )
+    {
+    CMDBField<TUint32>* formatField = static_cast<CMDBField<TUint32>*>
+            ( aRecord->GetFieldByIdL( aFormatId ) );
+    formatField->SetL( aWepFormat );
+    CMDBField<TDesC8>* wepKey = static_cast<CMDBField<TDesC8>*>
+            ( aRecord->GetFieldByIdL( aKeyId ) );
+    if ( aWepFormat )
+        {
+        wepKey->SetL( aWepKey );
+        }
+    else
+        {
+        //Convert Ascii to Hex format, as only Hex value to be stored in CommsDat
+        HBufC8* buf8Conv = HBufC8::NewLC( aWepKey.Length() * KMpmDoubleLength );
+        ConvertAsciiToHex( aWepKey, buf8Conv );
+        wepKey->SetL( buf8Conv->Des() );
+        CleanupStack::PopAndDestroy( buf8Conv );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::ConvertAsciiToHex
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::ConvertAsciiToHex( const TDesC8& aSource, 
+        							        HBufC8* aDest )
+    {
+    MPMLOGSTRING( "CMPMCommsDatAccess::ConvertAsciiToHex" )
+    _LIT( hex, "0123456789ABCDEF" );
+    TInt size = aSource.Size();
+    TPtr8 ptr = aDest->Des();
+    for ( TInt ii = 0; ii < size; ii++ )
+    	{
+    	TText8 ch = aSource[ii];
+    	ptr.Append( hex()[(ch/16)&0x0f] );
+    	ptr.Append( hex()[ch&0x0f] );
+    	}
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::FindEasyWlanServiceIdL
+// -----------------------------------------------------------------------------
+//
+TUint32 CMPMCommsDatAccess::FindEasyWlanServiceIdL( CMDBSession* aDb )
+    {
+    // if the method returns the record container there is for 
+    // some reason garbage data in the key values
+    //
+    TUint32 wlanId( 0 );
+    MPMLOGSTRING( "CMPMCommsDatAccess::FindEasyWlanServiceIdL" )    
+
+    CMDBRecordSet<CCDWlanServiceRecord>* wlanSet = 
+        new ( ELeave ) CMDBRecordSet<CCDWlanServiceRecord>( 
+         CCDWlanServiceRecord::TableIdL( *aDb ) );
+    CleanupStack::PushL( wlanSet ); 
+    wlanSet->LoadL( *aDb );
+    
+    TBool found( EFalse );
+    for ( TInt i = 0; i < wlanSet->iRecords.Count() && !found; i++ )
+        {
+        CCDWlanServiceRecord* wlanRecord = new ( ELeave ) 
+            CCDWlanServiceRecord( CCDWlanServiceRecord::TableIdL( *aDb ) );
+        CleanupStack::PushL( wlanRecord );
+
+        wlanRecord->SetElementId( GetRealElementId( wlanSet->iRecords[i] ) );
+        wlanRecord->LoadL( *aDb );
+        
+        TDesC ssid = wlanRecord->iWLanSSID;
+        if( !ssid.Compare( KNullDesC() ) )
+            {
+            MPMLOGSTRING2( "CMPMCommsDatAccess::FindEasyWlanServiceIdL: \
+found service entry %i", wlanRecord->RecordId() )
+            wlanId = wlanRecord->RecordId();
+            found = ETrue;
+            }
+        CleanupStack::PopAndDestroy( wlanRecord );
+        }
+    CleanupStack::PopAndDestroy( wlanSet );
+    return wlanId;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::CheckHiddenAgentL
+// -----------------------------------------------------------------------------
+//
+TBool CMPMCommsDatAccess::CheckHiddenAgentL( const TUint32 aIapId ) const
+    {
+    MPMLOGSTRING2( "CMPMCommsDatAccess::CheckHiddenAgentL: IapId: %i", aIapId )
+
+    TBool retValue( EFalse );
+
+    CMDBSession* db = CMDBSession::NewLC( KCDVersion1_1 );
+
+    db->SetAttributeMask( ECDHidden | ECDProtectedWrite );
+
+    // First check that IAP exists
+    // 
+    CCDIAPRecord* iap = LoadIapRecordLC( aIapId, db );
+
+    // Initialize generic record
+    // 
+    CMDBGenericRecord* generic = static_cast<CMDBGenericRecord*> ( 
+        CCDRecordBase::RecordFactoryL( 0 ) );
+    CleanupStack::PushL( generic );
+    generic->InitializeL( TPtrC( KCDTypeNameIAPMetadata ), NULL );
+    generic->LoadL( *db );
+
+    CCDIAPMetadataRecord* record = new( ELeave ) CCDIAPMetadataRecord( 
+        generic->TableId() );
+    CleanupStack::PushL( record );
+
+    // Check if the metadata entry exists
+    // 
+    record->iIAP.SetL( GetRealElementId( iap ) );
+    if ( record->FindL( *db ) )
+        {
+        // Metadata is specified, check is it true or false.
+        // 
+        if ( record->iMetadata & EMetaHiddenAgent )
+            {
+            MPMLOGSTRING( "CMPMCommsDatAccess::CheckHiddenAgentL: True" )
+            retValue = ETrue;
+            }
+        else
+            {
+            MPMLOGSTRING( "CMPMCommsDatAccess::CheckHiddenAgentL: False" )
+            retValue = EFalse;
+            }
+        }
+    else
+        {
+        // Metadata unspecified, use default value.
+        // 
+        MPMLOGSTRING( "CMPMCommsDatAccess::CheckHiddenAgentL: False" )
+        retValue = EFalse;
+        }
+
+    // Release memory
+    //
+    CleanupStack::PopAndDestroy( record );
+    CleanupStack::PopAndDestroy( generic );
+    CleanupStack::PopAndDestroy( iap );
+    CleanupStack::PopAndDestroy( db );
+
+    return retValue;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::MatchSSIDL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::MatchSSIDL( const TWlanSsid&   aSSID,
+                                     TUint32            aIapId, 
+                                     TBool&             aMatchFound,
+                                     CMPMServerSession& aSession )
+    {
+#ifdef __WINS__    	
+    // To suppress compilation warning in WINSCW UREL build. aSession is used only for logging. 
+    aSession;
+#endif
+    
+    MPMLOGSSID( "CMPMCommsDatAccess<0x%x>::MatchSSIDL: aSSID = %S", 
+        aSession.ConnectionId(), &aSSID )
+
+    MPMLOGSTRING3( "CMPMCommsDatAccess<0x%x>::MatchSSIDL: aIapId = %d", 
+        aSession.ConnectionId(), aIapId )
+
+    aMatchFound = EFalse;
+
+    CCommsDatabase* commsDatabase = CCommsDatabase::NewL();
+    CleanupStack::PushL( commsDatabase );
+
+    // Make hidden records visible
+    // 
+    commsDatabase->ShowHiddenRecords();
+
+    CCommsDbTableView* commsDbIapTableView = 
+        commsDatabase->OpenViewMatchingUintLC( TPtrC( IAP ),
+                                               TPtrC( COMMDB_ID ),
+                                               aIapId );
+
+    User::LeaveIfError( commsDbIapTableView->GotoFirstRecord() );
+
+    TInt length1( 0 );
+
+    commsDbIapTableView->ReadColumnLengthL( TPtrC( IAP_SERVICE_TYPE ), 
+                                            length1 );
+    HBufC* buf1 = HBufC::NewLC( length1 );
+    TPtr ptr1( buf1->Des() );
+
+    // Read IAP's service type
+    //
+    commsDbIapTableView->ReadTextL(TPtrC( IAP_SERVICE_TYPE ), ptr1 );
+
+    MPMLOGSTRING3(
+        "CMPMCommsDatAccess<0x%x>::MatchSSIDL: IAP service type = %S",
+        aSession.ConnectionId(), &ptr1 )
+
+    // In case offline mode is enabled, we need to find out what type 
+    // of bearer is used. Only LAN or WLAN is allowed in offline mode.
+    // 
+    if ( ptr1.Compare( TPtrC( LAN_SERVICE ) ) == KErrNone )
+        {
+        TUint32 service( 0 );
+        commsDbIapTableView->ReadUintL( TPtrC( IAP_SERVICE ), service );
+
+        // Now open a view to LAN_SERVICE table
+        //
+        CCommsDbTableView* commsDbLanTableView = 
+            commsDatabase->OpenViewMatchingUintLC( TPtrC( LAN_SERVICE ),
+                                                   TPtrC( COMMDB_ID ),
+                                                   service );
+
+        User::LeaveIfError( commsDbLanTableView->GotoFirstRecord() );
+
+        TUint32 commDbId( 0 );
+
+        commsDbLanTableView->ReadUintL( TPtrC( COMMDB_ID ), commDbId );
+
+        // Now open a view to WLAN_SERVICE table
+        //
+        CCommsDbTableView* commsDbWlanTableView = 
+            commsDatabase->OpenViewMatchingUintLC( TPtrC( WLAN_SERVICE ),
+                                                   TPtrC( WLAN_SERVICE_ID ),
+                                                   commDbId );
+
+        TInt err = commsDbWlanTableView->GotoFirstRecord();
+
+        if ( err == KErrNone )
+            {
+            TWlanSsid ssid;
+            commsDbWlanTableView->ReadTextL( TPtrC( NU_WLAN_SSID ), ssid );
+
+            if ( aSSID.Compare( ssid ) == KErrNone )
+                {
+                aMatchFound = ETrue;
+                MPMLOGSTRING2(
+                    "CMPMCommsDatAccess<0x%x>::MatchSSIDL Found matching SSID",
+                    aSession.ConnectionId() )
+                }
+            }
+        else
+            {
+            MPMLOGSTRING3( "CMPMCommsDatAccess<0x%x>::MatchSSID\
+ GotoFirstRecord returned %d", aSession.ConnectionId(), err )
+            }
+
+        // Release memory
+        //
+        CleanupStack::PopAndDestroy( commsDbWlanTableView );
+        CleanupStack::PopAndDestroy( commsDbLanTableView );
+        }
+
+    // Release memory
+    //
+    CleanupStack::PopAndDestroy( buf1 );
+    CleanupStack::PopAndDestroy( commsDbIapTableView );
+    CleanupStack::PopAndDestroy( commsDatabase );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::IsVirtualIapL
+// -----------------------------------------------------------------------------
+//
+TBool CMPMCommsDatAccess::IsVirtualIapL( const TUint32 aVirtualIapId ) const
+    {
+    MPMLOGSTRING2( "CMPMCommsDatAccess::IsVirtualIapL: VirtualIapId: %i", 
+        aVirtualIapId )
+    TBool isVirtual( EFalse );
+
+    // Open transaction
+    // 
+    CMDBSession* db = CMDBSession::NewLC( KCDVersion1_1 );
+
+    db->SetAttributeMask( ECDHidden | ECDProtectedWrite );
+
+    // Get IAP
+    // 
+    CCDIAPRecord* iap = LoadIapRecordLC( aVirtualIapId, db );
+
+    TDesC& type = iap->iBearerType.GetL();
+
+    if( type.Compare( TPtrC ( KCDTypeNameVirtualBearer ) ) == 0 )
+        {
+        isVirtual = ETrue;
+        MPMLOGSTRING( "CMPMCommsDatAccess::IsVirtualIapL: \
+is virtual" )
+        }
+    CleanupStack::PopAndDestroy( iap );
+    CleanupStack::PopAndDestroy( db );
+    return isVirtual;
+    }
+    
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::SnapContainsWlanL
+// -----------------------------------------------------------------------------
+//
+TBool CMPMCommsDatAccess::SnapContainsWlanL( TUint32			aSnapRecord, 
+                                             RArray<TUint>& 	aIapPath, 
+                                             TInt 		    	aMinNrWlan )
+    {
+    MPMLOGSTRING3( "CMPMCommsDatAccess::SnapContainsWlanL: snap %d, nr Wlans %d", 
+        aSnapRecord, aMinNrWlan )
+    TInt wlanFound(0);
+    RArray<TNetIap> destNetIaps;
+    CleanupClosePushL( destNetIaps );
+
+    // Find the valid IAPs belonging to the Snap 
+    // and possible embedded SNAP. Store both in same array.
+    //
+    SearchDNEntriesWithEmbeddedL( aSnapRecord, destNetIaps, destNetIaps );
+
+    // Check type of each IAP 
+    // Stop when specified number of WLAN IAPs has been found
+    // 
+    for( TInt j( 0 ); ( j < destNetIaps.Count() ) && 
+                      ( wlanFound < aMinNrWlan ); j++ )
+        {
+        // If entry is for embedded SNAP there are more than two chained 
+        // embedded snaps. This is illegal configuration. Skip this entry.
+        // 
+        if ( destNetIaps[j].iEmbeddedSnap != 0 )
+            {
+            MPMLOGSTRING( "CMPMCommsDatAccess::SnapContainsWlanL: \
+Illegal configuration, more than one chained SNAP" )
+            }
+        else
+            {
+            if( CheckWlanL( destNetIaps[j].iIapId ) != ENotWlanIap )
+                {
+                MPMLOGSTRING(
+                    "CMPMCommsDatAccess::SnapContainsWlanL: WLAN IAP found" )
+                wlanFound++;
+                }
+            // If virtual IAP, check whether it may be using WLAN
+            // 
+            if( wlanFound < aMinNrWlan && IsVirtualIapL( destNetIaps[j].iIapId ) )
+                {
+                if ( WlanUnderVirtualL( destNetIaps[j].iIapId,
+                                        aIapPath ) )
+                    {
+                    MPMLOGSTRING( "CMPMCommsDatAccess::SnapContainsWlanL: \
+WLAN IAP under virtual IAP found" )
+                    wlanFound++;
+                    }
+            
+                }
+            }
+        }
+    CleanupStack::PopAndDestroy( &destNetIaps );
+    if( wlanFound < aMinNrWlan ) 
+        {
+        MPMLOGSTRING( "CMPMCommsDatAccess::SnapContainsWlanL: result false" )
+        return EFalse;
+        }
+    else
+        {
+        MPMLOGSTRING( "CMPMCommsDatAccess::SnapContainsWlanL: result true" )
+        return ETrue;
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::SearchDNEntriesWithEmbeddedL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::SearchDNEntriesWithEmbeddedL( TUint32 aSnap, 
+                                                      RArray<TNetIap>& aDestNetIaps,
+                                                      RArray<TNetIap>& aEmbeddedIaps )
+    {
+    // Find the valid IAPs belonging to the Snap.
+    //
+    SearchDNEntriesL( aSnap, aDestNetIaps );
+
+    TBool embeddedFound( EFalse );
+
+    // Find the valid IAPs belonging to the embedded Snaps.
+    // 
+    for( TInt j = 0;( ( j < aDestNetIaps.Count() ) && !embeddedFound ); j++ )
+        {
+        // Go through the destNetIaps-array looking for EmbeddedId.
+        // 
+        if( aDestNetIaps[j].iEmbeddedSnap != 0 )
+            {
+            MPMLOGSTRING2( "CMPMCommsDatAccess::SearchDNEntriesWithEmbeddedL: \
+Search Embedded SNAP: %i", aDestNetIaps[j].iEmbeddedSnap )
+
+            TUint32 embedded = aDestNetIaps[j].iEmbeddedSnap;
+            // Exclude embedded Snap from destNetIaps, since 
+            // the IAPs it contains are listed in embeddedIaps. 
+            // 
+            aDestNetIaps.Remove( j );
+
+            // If found, then search the IAPs belonging 
+            // to that embedded Snap.
+            // 
+            SearchDNEntriesL( embedded, aEmbeddedIaps );
+            embeddedFound = ETrue;
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::CheckWLanL
+// -----------------------------------------------------------------------------
+//
+TWlanIapType CMPMCommsDatAccess::CheckWlanL( TUint32 aIapId ) const
+    {
+    MPMLOGSTRING2( "CMPMCommsDatAccess::CheckWlanL: IAP Id = %i", aIapId)
+
+    TWlanIapType wlan( ENotWlanIap );
+    CCommsDatabase* commsDatabase = CCommsDatabase::NewL();
+    CleanupStack::PushL( commsDatabase );
+
+    // Make hidden records visible
+    // 
+    commsDatabase->ShowHiddenRecords();
+
+    CCommsDbTableView* commsDbIapTableView = 
+        commsDatabase->OpenViewMatchingUintLC( TPtrC( IAP ),
+                                               TPtrC( COMMDB_ID ),
+                                               aIapId );
+
+    User::LeaveIfError( commsDbIapTableView->GotoFirstRecord() );
+
+    TInt length1( 0 );
+
+    commsDbIapTableView->ReadColumnLengthL( TPtrC( IAP_SERVICE_TYPE ), 
+                                            length1 );
+
+    HBufC* buf1 = HBufC::NewLC( length1 );
+    TPtr ptr1( buf1->Des() );
+
+    // Read IAP's service type
+    //
+    commsDbIapTableView->ReadTextL(TPtrC( IAP_SERVICE_TYPE ), ptr1 );
+    MPMLOGSTRING2(
+        "CMPMCommsDatAccess::CheckWlanL: IAP service type = %S", &ptr1 )
+
+    if ( ptr1.Compare( TPtrC( LAN_SERVICE ) ) == KErrNone )
+        {
+        TUint32 service( 0 );
+        commsDbIapTableView->ReadUintL( TPtrC( IAP_SERVICE ), service );
+
+        // Now open a view to LAN_SERVICE table
+        //
+        CCommsDbTableView* commsDbLanTableView = 
+            commsDatabase->OpenViewMatchingUintLC( TPtrC( LAN_SERVICE ),
+                                                   TPtrC( COMMDB_ID ),
+                                                   service );
+
+        User::LeaveIfError( commsDbLanTableView->GotoFirstRecord() );
+
+        TUint32 commDbId( 0 );
+
+        commsDbLanTableView->ReadUintL( TPtrC( COMMDB_ID ), commDbId );
+
+        // Now open a view to WLAN_SERVICE table
+        //
+        // If non wlan product, wlan tables won't exist and this will 
+        // leave. In that case do not check WLAN related issues 
+        //
+
+        CCommsDbTableView* commsDbWlanTableView( NULL );
+        TRAPD( err2, commsDbWlanTableView = 
+                     commsDatabase->OpenViewMatchingUintLC( TPtrC( WLAN_SERVICE ),
+                                                            TPtrC( WLAN_SERVICE_ID ),
+                                                            commDbId );
+                     CleanupStack::Pop( commsDbWlanTableView ) );
+        if ( err2 == KErrNone )
+            {
+            // Push back to cleanup stack. Object must be popped within 
+            // TRAP, to avoid unbalance in cleanup stack and panic 71
+            CleanupStack::PushL( commsDbWlanTableView );
+
+            TInt err = commsDbWlanTableView->GotoFirstRecord();
+
+            if ( err == KErrNone )
+                {
+                MPMLOGSTRING( "CMPMCommsDatAccess::CheckWlanL: IAP is WLAN" )
+                wlan = EWlanIap;
+                TInt ssidLength( 0 );
+                commsDbWlanTableView->ReadColumnLengthL( TPtrC( NU_WLAN_SSID ), 
+                                                     ssidLength );
+                if ( ssidLength == 0 )
+                    {
+                    MPMLOGSTRING(
+                        "CMPMCommsDatAccess::CheckWlanL: IAP is Easy WLAN" )
+                    wlan = EEasyWlanIap;
+                    }
+                }
+            else
+                {
+                MPMLOGSTRING2( "CMPMCommsDatAccess::CheckWlanL\
+ GotoFirstRecord returned %d", err )
+               }
+            // Release memory
+            //
+            CleanupStack::PopAndDestroy( commsDbWlanTableView );            
+            }
+        else
+            {
+            MPMLOGSTRING2(
+                        "CMPMCommsDatAccess::CheckWlanL: WLAN table view failed, err %d", err2 )
+            }                
+        CleanupStack::PopAndDestroy( commsDbLanTableView );
+        }
+
+    // Release memory
+    //
+    CleanupStack::PopAndDestroy( buf1 );
+    CleanupStack::PopAndDestroy( commsDbIapTableView );
+    CleanupStack::PopAndDestroy( commsDatabase );
+
+    return wlan;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::RemoveCategorisedIapsL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::RemoveCategorisedIapsL( RAvailableIAPList& aIAPList )
+    {
+    MPMLOGSTRING( "CMPMCommsDatAccess::RemoveCategorisedIapsL" )
+
+    // Creating a session with the latest version
+    // 
+    CMDBSession* db = CMDBSession::NewLC( KCDVersion1_1 );
+
+    db->SetAttributeMask( ECDHidden | ECDProtectedWrite );
+
+    // Create the generic record set
+    // 
+    CMDBGenericRecord* generic = static_cast<CMDBGenericRecord*>
+        ( CCDRecordBase::RecordFactoryL( 0 ) ); 
+    CleanupStack::PushL( generic );  
+    generic->InitializeL( TPtrC( KCDTypeNameDataMobilitySelectionPolicy ), 
+                          NULL );
+    generic->LoadL( *db );
+
+    // Create the DN-IAP record set
+    // 
+    CMDBRecordSet<CCDDataMobilitySelectionPolicyRecord>* dnIAPRecordSet = 
+        new ( ELeave ) CMDBRecordSet<CCDDataMobilitySelectionPolicyRecord>( 
+        generic->TableId() );
+    CleanupStack::PushL( dnIAPRecordSet ); 
+
+    CCDDataMobilitySelectionPolicyRecord* dnIAPRecord = new ( ELeave ) 
+        CCDDataMobilitySelectionPolicyRecord( generic->TableId() );
+    CleanupStack::PushL( dnIAPRecord );
+
+    // Find all the DN-IAP records
+    // Trap leave in case no records exist
+    // 
+    TRAPD( err, dnIAPRecordSet->LoadL( *db ) )
+    if( err != KErrNone )
+        {
+        // print error code to log
+        //
+        MPMLOGSTRING2( "CMPMCommsDatAccess::RemoveCategorisedIapsL, \
+loading DM selection policy records failed with %d", err )
+        CleanupStack::PopAndDestroy( dnIAPRecord );
+        CleanupStack::PopAndDestroy( dnIAPRecordSet );
+        CleanupStack::PopAndDestroy( generic );
+        CleanupStack::PopAndDestroy( db );
+        return;
+        }
+
+    CCDIAPRecord*           linkedIAP;
+    CCDAccessPointRecord*   linkedAP;
+    RArray<TInt>            prevRecordIds;
+    CleanupClosePushL( prevRecordIds );
+
+    // prepare for searching APs.
+
+    for ( TInt i = 0; i < dnIAPRecordSet->iRecords.Count(); i++ )
+        {
+        linkedAP =  static_cast<CCDAccessPointRecord*>( CCDAccessPointRecord::RecordFactoryL( KCDTIdAccessPointRecord ) );
+        CleanupStack::PushL( linkedAP );
+        // Load each DN-IAP entry based on the elementId in the record set
+        // 
+        dnIAPRecord->SetElementId( GetRealElementId( dnIAPRecordSet->iRecords[i] ) );
+        dnIAPRecord->LoadL( *db );
+
+        // Find the SNAP AP pointed by DN-IAP entry
+        //
+        linkedAP->iRecordTag = (TInt)dnIAPRecord->iSNAP;
+        TBool found = linkedAP->FindL( *db );
+
+        if ( found && KErrNotFound == prevRecordIds.Find( linkedAP->RecordId() ) )
+            {
+            prevRecordIds.Append( linkedAP->RecordId() );
+            
+            // Print the DN and host name pointed by DN-IAP entry.
+            // HostName is EText field.
+            // 
+            TBuf<KMaxTextLength + 1> dn = linkedAP->iRecordName.GetL();
+            MPMLOGSTRING3( "    Snap: %d Snap Name = %s", (TInt)linkedAP->iRecordTag, dn.PtrZ() )
+            
+            // Related DN-IAP records 
+            // Get the table id from generic record
+            // 
+            CMDBGenericRecord* generic2 = static_cast<CMDBGenericRecord*>
+                ( CCDRecordBase::RecordFactoryL( 0 ) ); 
+            CleanupStack::PushL( generic2 );  
+            generic2->InitializeL( TPtrC( 
+                KCDTypeNameDataMobilitySelectionPolicy ), NULL );
+            generic2->LoadL( *db );
+            
+            // Doesn't quite work with generic records
+            // 
+            CMDBRecordSet<CCDDataMobilitySelectionPolicyRecord>* 
+                dnIAPRecordSet2 = new ( ELeave ) 
+                CMDBRecordSet<CCDDataMobilitySelectionPolicyRecord>( 
+                generic2->TableId() );
+            CleanupStack::PushL( dnIAPRecordSet2 ); 
+            
+            // Prime one record with DN 
+            // 
+            CCDDataMobilitySelectionPolicyRecord* dnIAPRecord2 = 
+                new ( ELeave ) CCDDataMobilitySelectionPolicyRecord( generic2->TableId() );
+            CleanupStack::PushL( dnIAPRecord2 );
+            dnIAPRecord2->iSNAP = (TInt)linkedAP->iRecordTag;
+            dnIAPRecordSet2->iRecords.Append( dnIAPRecord2 );
+            CleanupStack::Pop( dnIAPRecord2 );
+
+            if ( dnIAPRecordSet2->FindL( *db ) )
+                {
+                for (TInt j = 0; j < dnIAPRecordSet2->iRecords.Count(); j++)
+                    {
+                    dnIAPRecord2->SetElementId( GetRealElementId( dnIAPRecordSet2->iRecords[j] ) );
+                    dnIAPRecord2->LoadL( *db );
+
+                    if ( dnIAPRecord2->iIAP != 0 )
+                        {
+                        linkedIAP = static_cast<CCDIAPRecord*>
+                            ( LoadLinkedRecordL( *db, dnIAPRecord2->iIAP ) );
+
+                        // Remove categorised IAP from aIAPList
+                        // 
+                        TInt index = KErrNotFound;
+                        index = aIAPList.Find( linkedIAP->RecordId() );
+                        if ( index != KErrNotFound )
+                            {
+                            MPMLOGSTRING2(
+                                "        Remove categorised IAP = %i", 
+                                linkedIAP->RecordId() )
+                            aIAPList.Remove( index );
+                            }
+
+                        delete linkedIAP;
+                        dnIAPRecord2->iIAP = 0;
+                        }
+                    }
+                }
+            CleanupStack::PopAndDestroy( dnIAPRecordSet2 );
+            CleanupStack::PopAndDestroy( generic2 );
+            }
+        CleanupStack::PopAndDestroy( linkedAP );
+        }
+
+    CleanupStack::PopAndDestroy( &prevRecordIds );
+    CleanupStack::PopAndDestroy( dnIAPRecord );
+    CleanupStack::PopAndDestroy( dnIAPRecordSet );
+    CleanupStack::PopAndDestroy( generic );
+    CleanupStack::PopAndDestroy( db );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::GetIapServiceIdL
+// -----------------------------------------------------------------------------
+//
+TUint32 CMPMCommsDatAccess::GetIapServiceIdL( TUint32 aIapId )
+    {
+    TUint32 serviceId( 0 );
+    CMDBSession* db = CMDBSession::NewLC( KCDVersion1_1 );
+
+    db->SetAttributeMask( ECDHidden | ECDProtectedWrite );
+
+    // First check that IAP exists
+    // 
+    CCDIAPRecord* iap = LoadIapRecordLC( aIapId, db );
+    serviceId = iap->iService;
+    CleanupStack::PopAndDestroy( iap );
+    CleanupStack::PopAndDestroy( db );
+
+    MPMLOGSTRING3( "CMPMCommsDatAccess::GetiapServiceIdL - IAP Id: %d, service id: %d",     
+        aIapId, serviceId )
+
+    return serviceId;
+    }
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::LoadIapRecordLC
+// -----------------------------------------------------------------------------
+//
+CCDIAPRecord* CMPMCommsDatAccess::LoadIapRecordLC( const TUint32 aIapId, CMDBSession* aDb ) const
+    {
+    CCDIAPRecord* iap = static_cast<CCDIAPRecord*> ( 
+        CCDRecordBase::RecordFactoryL( KCDTIdIAPRecord ) );
+    CleanupStack::PushL( iap );
+    iap->SetRecordId( aIapId );
+    iap->LoadL( *aDb );
+    return iap;    
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::SearchAccessNetIdL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::SearchAccessNetIdL( const TUint32&  aIapId,
+                                            TUint32&        aNetId )
+    {
+    MPMLOGSTRING2( "CMPMCommsDatAccess::SearchAccessNetIdL - IAP Id: %d", 
+        aIapId )
+
+    CCommsDatabase* commsDatabase = CCommsDatabase::NewL();
+    CleanupStack::PushL(commsDatabase);
+
+    // Make hidden records visible
+    // 
+    commsDatabase->ShowHiddenRecords();
+
+    // Open IAP table view by matching IAP Id
+    //
+    CCommsDbTableView* commsDbTableView = 
+        commsDatabase->OpenViewMatchingUintLC( TPtrC( IAP ),
+                                               TPtrC( COMMDB_ID ),
+                                               aIapId );
+
+    User::LeaveIfError( commsDbTableView->GotoFirstRecord() );
+
+    commsDbTableView->ReadUintL(TPtrC( IAP_NETWORK ), aNetId );
+    MPMLOGSTRING2(
+        "CMPMCommsDatAccess::SearchAccessNetIdL - Found Access NetId: %d", 
+        aNetId )
+
+    CleanupStack::PopAndDestroy(commsDbTableView);
+    CleanupStack::PopAndDestroy(commsDatabase);
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::WlanUnderVirtualL
+// -----------------------------------------------------------------------------
+//
+TBool CMPMCommsDatAccess::WlanUnderVirtualL( const TUint32  aVirtualIapId, 
+                                             RArray<TUint>& aIapPath )
+    {
+    MPMLOGSTRING2( "CMPMCommsDatAccess::WlanUnderVirtualL: VirtualIapId: %i", 
+        aVirtualIapId )
+    // Check that this Iap has not already traversed
+    //
+    if( aIapPath.Find( aVirtualIapId ) == KErrNotFound )
+        {
+        // append this Iap to path
+        //
+        aIapPath.Append( aVirtualIapId );
+        }
+    else
+        {
+        MPMLOGSTRING( "CMPMCommsDatAccess::WlanUnderVirtualL: Error, loop\
+detected in configuration. Iap handling not continued" )
+        return EFalse;
+        }
+
+    TBool wlan( EFalse );
+
+    // Open session
+    // 
+    CMDBSession* db = CMDBSession::NewLC( KCDVersion1_1 );
+
+    db->SetAttributeMask( ECDHidden | ECDProtectedWrite );
+
+    CMDBGenericRecord * generic = static_cast<CMDBGenericRecord*>
+        ( CCDRecordBase::RecordFactoryL( 0 ) );
+    CleanupStack::PushL( generic );
+    generic->InitializeL( TPtrC( KCDTypeNameVirtualIAPNextLayer ), 
+                          NULL );
+    generic->LoadL( *db );
+
+    CCDVirtualIAPNextLayerRecord* virtualNext = new ( ELeave ) 
+        CCDVirtualIAPNextLayerRecord( generic->TableId() );
+
+    CleanupStack::PushL( virtualNext );
+    virtualNext->iIAP = aVirtualIapId;
+    if ( virtualNext->FindL( *db ) )
+        {
+        if ( virtualNext->iNextLayerSNAP != 0 )
+            {
+            // SNAP
+            // 
+            TInt snap = virtualNext->iNextLayerSNAP;
+            MPMLOGSTRING2(
+                "CMPMCommsDatAccess::WlanUnderVirtualL: SNAP: %i", snap )
+
+            // Check if SNAP contains WLAN
+            // 
+            wlan = SnapContainsWlanL( snap, aIapPath, KMPMNrWlansOne );
+            
+            }
+        else if ( virtualNext->iNextLayerIAP != 0 )
+            {
+            // IAP
+            // 
+            TInt iap = virtualNext->iNextLayerIAP;
+            MPMLOGSTRING2(
+                "CMPMCommsDatAccess::WlanUnderVirtualL: IAP: %i", iap )
+            if( CheckWlanL( iap ) != ENotWlanIap )
+                {
+                wlan = ETrue;
+                }
+        
+            // If virtual IAP, check whether it may be using WLAN
+            // 
+            if( !wlan && IsVirtualIapL( iap ) )
+                {
+                wlan = WlanUnderVirtualL( iap, aIapPath );
+                }
+            }
+        else
+            {
+            MPMLOGSTRING( "CMPMCommsDatAccess::WlanUnderVirtualL: No underlying IAP\
+ defined for virtual IapId" )
+            }
+        }
+    // Remove this Iap from path 
+    //
+    MPMLOGSTRING2( "CMPMCommsDatAccess::WlanUnderVirtualL: removing %d from iap path", 
+                aIapPath.Count() - 1 )
+    aIapPath.Remove( aIapPath.Count() - 1 );
+
+    // Release memory
+    //
+    CleanupStack::PopAndDestroy( virtualNext );
+    CleanupStack::PopAndDestroy( generic );
+    CleanupStack::PopAndDestroy( db );
+    MPMLOGSTRING2(
+                "CMPMCommsDatAccess::WlanUnderVirtualL: found: %i", wlan )
+    return wlan;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::SearchDNEntriesL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::SearchDNEntriesL( const TUint32&   aSnapId,
+                                           RArray<TNetIap>& aDestNetIds )
+    {
+    MPMLOGSTRING2( "CMPMCommsDatAccess::SearchDNEntriesL: SNAP: %d", 
+        aSnapId )
+
+    CCDAccessPointRecord* snapAPr =  static_cast<CCDAccessPointRecord*>( 
+            CCDAccessPointRecord::RecordFactoryL( KCDTIdAccessPointRecord ) );
+    
+    snapAPr->iRecordTag = aSnapId;
+    CleanupStack::PushL( snapAPr );
+
+//    CCDNetworkRecord* dnRecord = static_cast<CCDNetworkRecord*>
+//        ( CCDRecordBase::RecordFactoryL( KCDTIdNetworkRecord ) );
+//        dnRecord->SetRecordId( aSnapId );
+
+    CMDBSession* db = CMDBSession::NewLC( KCDVersion1_1 );
+
+    db->SetAttributeMask( ECDHidden | ECDProtectedWrite );
+
+//    TRAPD( err, snapAPr->LoadL( *db ) );
+//    if ( err != KErrNone )
+    if ( !snapAPr->FindL( *db ) )
+        {
+        MPMLOGSTRING("CMPMCommsDatAccess::SearchDNEntriesL: SNAP not found")
+        CleanupStack::PopAndDestroy( db );
+        CleanupStack::PopAndDestroy( snapAPr );
+        return;
+        }
+
+    // Get the table id from generic
+    // 
+    CMDBGenericRecord* generic = static_cast<CMDBGenericRecord*>
+        ( CCDRecordBase::RecordFactoryL( 0 ) );
+    CleanupStack::PushL( generic );
+    generic->InitializeL( TPtrC( KCDTypeNameDataMobilitySelectionPolicy ), 
+                          NULL );
+    generic->LoadL( *db );
+
+    // Create the DN-IAP record set
+    // 
+    CMDBRecordSet<CCDDataMobilitySelectionPolicyRecord>* dnIAPRecordSet = 
+        new ( ELeave ) CMDBRecordSet<CCDDataMobilitySelectionPolicyRecord>( generic->TableId() );
+    CleanupStack::PushL( dnIAPRecordSet );
+
+    CCDDataMobilitySelectionPolicyRecord* dnIAPRecord = new ( ELeave ) 
+        CCDDataMobilitySelectionPolicyRecord( generic->TableId() );
+    CleanupStack::PushL( dnIAPRecord );
+    dnIAPRecord->iSNAP = (TInt)snapAPr->iRecordTag;
+    dnIAPRecordSet->iRecords.Append( dnIAPRecord );
+    CleanupStack::Pop( dnIAPRecord );
+
+    if ( dnIAPRecordSet->FindL( *db ) )
+        {
+        for ( TInt i = 0; i < dnIAPRecordSet->iRecords.Count(); i++ )
+            {
+            TNetIap elem;
+            dnIAPRecord->SetElementId( GetRealElementId( dnIAPRecordSet->iRecords[i] ) );
+            dnIAPRecord->LoadL( *db );
+
+            if ( dnIAPRecord->iIAP != 0 )
+                {
+                // Add values to elem
+                // 
+                TUint32 iapElementId( dnIAPRecord->iIAP ); 
+                elem.iSnap      = aSnapId;
+                elem.iIapId     = ( iapElementId & 
+                                    KCDMaskShowRecordId ) >> KShift8;
+                elem.iRanking   = static_cast<TUint32>( dnIAPRecord->iPriority );
+                dnIAPRecord->iIAP = 0;
+                }
+            else if( dnIAPRecord->iEmbeddedSNAP != 0 )
+                {
+                // Add values to elem
+                // 
+                elem.iSnap          = aSnapId;
+                elem.iEmbeddedSnap  = dnIAPRecord->iEmbeddedSNAP;
+                elem.iRanking       = static_cast<TUint32>( dnIAPRecord->iPriority );
+                dnIAPRecord->iEmbeddedSNAP = 0;
+                }
+            else
+                {
+                // Each Snap has an initial entry in this table,
+                // where both the IAP and EmbeddedSNAP links 
+                // have null value. 
+                }
+
+            // MPM should treat IAPs with Network Weight zero as the deleted 
+            // ones. If an IAP seems to belong to a group but it has weight 
+            // zero, it means that the IAP is not actually added to the group 
+            // but an IAP from that group is deleted and a new one is created 
+            // and this new IAP has got the same access network id that used 
+            // to belong to the deleted IAP.
+            // 
+            if ( elem.iRanking > 0 )
+                {
+                // Insert elem into RArray
+                // 
+                aDestNetIds.InsertInOrderAllowRepeats(elem, TNetIap::CompareRanking);
+                }
+            else
+                {
+                if ( elem.iIapId != 0 )
+                    {
+                    MPMLOGSTRING2( "CMPMCommsDatAccess::SearchDNEntriesL: \
+IapId %i removed because ranking is zero", elem.iIapId )
+                    }
+                if ( elem.iEmbeddedSnap != 0 )
+                    {
+                    MPMLOGSTRING2( "CMPMCommsDatAccess::SearchDNEntriesL: \
+EmbeddedSnap %i removed because ranking is zero", elem.iEmbeddedSnap )
+                    }
+                }
+            }
+        }
+
+    // Release memory
+    //
+    CleanupStack::PopAndDestroy( dnIAPRecordSet );
+    CleanupStack::PopAndDestroy( generic );
+    CleanupStack::PopAndDestroy( db );
+    CleanupStack::PopAndDestroy( snapAPr );
+
+#ifdef _DEBUG
+    // Print info into the log file
+    //
+    for ( TInt j = 0; j < aDestNetIds.Count(); j++ )
+        {
+        MPMLOGSTRING2(
+            "CMPMCommsDatAccess::SearchDNEntriesL: SNAP to array     = %i", 
+            aDestNetIds[j].iSnap )
+        MPMLOGSTRING2(
+            "CMPMCommsDatAccess::SearchDNEntriesL: Embedded to array = %i", 
+            aDestNetIds[j].iEmbeddedSnap )
+        MPMLOGSTRING2(
+            "CMPMCommsDatAccess::SearchDNEntriesL: IapId to array    = %i", 
+            aDestNetIds[j].iIapId )
+        MPMLOGSTRING2(
+            "CMPMCommsDatAccess::SearchDNEntriesL: Ranking to array  = %i", 
+            aDestNetIds[j].iRanking )
+        }
+#endif // _DEBUG
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::FindRealIapL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::FindRealIapL( 
+    const TUint32               aVirtualIapId,
+    TUint32&                    aRealIapId, 
+    const RAvailableIAPList&    aAvailableIAPList,
+    CMPMServerSession&          aSession )
+    {
+    MPMLOGSTRING2( "CMPMCommsDatAccess::FindRealIapL: VirtualIapId: %i", 
+        aVirtualIapId )
+
+    // Open transaction
+    // 
+    CMDBSession* db = CMDBSession::NewLC( KCDVersion1_1 );
+
+    db->SetAttributeMask( ECDHidden | ECDProtectedWrite );
+
+    // Get IAP
+    // 
+    CCDIAPRecord* iap = LoadIapRecordLC( aVirtualIapId, db );
+
+    TDesC& type = iap->iBearerType.GetL();
+
+    if( type.Compare( TPtrC ( KCDTypeNameVirtualBearer ) ) != 0 )
+        {
+        MPMLOGSTRING( "CMPMCommsDatAccess::FindRealIapL: \
+aVirtualIapId is not virtual, return as aRealIapId" )
+
+        aRealIapId = aVirtualIapId;
+
+        // Release memory
+        //
+        CleanupStack::PopAndDestroy( iap );
+        CleanupStack::PopAndDestroy( db );
+        return;
+        }
+
+    CMDBGenericRecord * generic = static_cast<CMDBGenericRecord*>
+        ( CCDRecordBase::RecordFactoryL( 0 ) );
+    CleanupStack::PushL( generic );
+    generic->InitializeL( TPtrC( KCDTypeNameVirtualIAPNextLayer ), 
+                          NULL );
+    generic->LoadL( *db );
+
+    CCDVirtualIAPNextLayerRecord* virtualNext = new ( ELeave ) 
+        CCDVirtualIAPNextLayerRecord( generic->TableId() );
+
+    CleanupStack::PushL( virtualNext );
+    virtualNext->iIAP = iap->RecordId();
+    if ( virtualNext->FindL( *db ) )
+        {
+        if ( virtualNext->iNextLayerSNAP != 0 )
+            {
+            // SNAP
+            // 
+            TInt snap = virtualNext->iNextLayerSNAP;
+            MPMLOGSTRING2(
+                "CMPMCommsDatAccess::FindRealIapL: SNAP: %i", snap )
+            MPMLOGSTRING(
+                "CMPMCommsDatAccess::FindRealIapL: Call ChooseBestIAPL" )
+
+            TMpmConnPref tempMpmConnPref;
+            tempMpmConnPref.SetSnapId( snap );
+            aSession.IapSelectionL()->ChooseBestIAPL( tempMpmConnPref, aAvailableIAPList );
+            aRealIapId = tempMpmConnPref.IapId();
+            }
+        else if ( virtualNext->iNextLayerIAP != 0 )
+            {
+            // IAP
+            // 
+            CCDIAPRecord* iap2 = LoadIapRecordLC( virtualNext->iNextLayerIAP, db );
+            TDesC& type2 = iap2->iBearerType.GetL();
+            if( type2.Compare( TPtrC ( KCDTypeNameVirtualBearer ) ) == 0 )
+                {
+                // Virtual IAP
+                // 
+                MPMLOGSTRING2(
+                    "CMPMCommsDatAccess::FindRealIapL: Virtual IAP: %i", 
+                    iap2->RecordId() )
+                MPMLOGSTRING(
+                    "CMPMCommsDatAccess::FindRealIapL: Call FindRealIapL" )
+
+                FindRealIapL( iap2->RecordId(), 
+                              aRealIapId, 
+                              aAvailableIAPList,
+                              aSession );
+                }
+            else
+                {
+                aRealIapId = iap2->RecordId();
+
+                MPMLOGSTRING2(
+                    "CMPMCommsDatAccess::FindRealIapL: NextLayerIAP: %i", 
+                    aRealIapId )
+                }
+            // Release memory
+            //
+            CleanupStack::PopAndDestroy( iap2 );
+            }
+        else
+            {
+            MPMLOGSTRING( "CMPMCommsDatAccess::FindRealIapL: No underlying IAP\
+ defined for virtual IapId" )
+            }
+        }
+
+    // Release memory
+    //
+    CleanupStack::PopAndDestroy( virtualNext );
+    CleanupStack::PopAndDestroy( generic );
+    CleanupStack::PopAndDestroy( iap );
+    CleanupStack::PopAndDestroy( db );
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::LoadLinkedRecordL
+// -----------------------------------------------------------------------------
+//
+CCDRecordBase* CMPMCommsDatAccess::LoadLinkedRecordL( CMDBSession&  aSession, 
+                                  TMDBElementId aElementId )
+    {
+    // This is copied from commsdatSnapTests.cpp. 
+    // Loading linked records does not work currently.
+    // 
+    CCDRecordBase *record = static_cast<CCDRecordBase*>( 
+        CCDRecordBase::RecordFactoryL( aElementId ) );
+    CleanupStack::PushL( record );
+    record->LoadL( aSession );
+    CleanupStack::Pop( record );
+    return record;
+    }
+    
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::GetRealElementId
+// -----------------------------------------------------------------------------
+//
+TUint32 CMPMCommsDatAccess::GetRealElementId( CMDBRecordBase* aRecord )
+    {
+    return aRecord->ElementId() & KCDMaskShowField;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::WlanBackgroundScanIsOnL
+// -----------------------------------------------------------------------------
+//
+TBool CMPMCommsDatAccess::WlanBackgroundScanIsOnL()
+    {
+    CCommsDatabase*    commDB = NULL;
+    CCommsDbTableView* table  = NULL;
+
+    // Open commDB
+    commDB = CCommsDatabase::NewL();
+    CleanupStack::PushL( commDB );
+
+    // from connmondef.h
+    _LIT( KCmWlanDeviceSettings,        "WLANDeviceTable" );
+    _LIT( KCmWlanDeviceSettingsType,    "WlanDeviceSettingsType" );
+    _LIT( KCmBgScanInterval,            "WlanBgScanInterval" );
+    const TUint32 KCmWlanUserSettings  = 1;
+
+    table = commDB->OpenViewMatchingUintLC( KCmWlanDeviceSettings,
+                                            KCmWlanDeviceSettingsType,
+                                            KCmWlanUserSettings );
+
+    TInt err = table->GotoFirstRecord();
+
+    if ( err )
+        {
+        User::Leave( err );  
+        }
+    
+    TUint32 scanInterval;
+    table->ReadUintL( KCmBgScanInterval, scanInterval ); 
+
+    // cleanup
+    CleanupStack::PopAndDestroy( table );
+    CleanupStack::PopAndDestroy( commDB );
+    
+    return scanInterval != 0 ? ETrue : EFalse;
+    
+    }
+
+// -----------------------------------------------------------------------------
+// IsInternetSnapL
+// -----------------------------------------------------------------------------
+//
+TBool CMPMCommsDatAccess::IsInternetSnapL( TUint32 aIapId, TUint32 aSnapId )
+    {
+    MPMLOGSTRING3( 
+        "CMPMCommsDatAccess::IsInternetSnapL - aIapId = %d, aSnapId = %d", 
+        aIapId, aSnapId )
+
+    TBool ret = EFalse;
+    
+    // Open transaction
+    CMDBSession* db = CMDBSession::NewLC( KCDVersion1_1 );
+
+    if ( aSnapId )
+        {
+        // Check that snap purpose is internet
+        ret = IsInternetSnapL( *db, aSnapId );
+        }
+    else if ( aIapId )
+        {
+        RArray<TUint> snapIds;
+        
+        // Get destinations
+        FindAllSnapsL( snapIds );
+        CleanupClosePushL( snapIds );
+        
+        for (TInt index = 0; index < snapIds.Count(); index++)
+            {
+            RArray<TNetIap> ids;
+            // Get iaps belonging to this destination
+            SearchDNEntriesL( snapIds[index], ids );
+            CleanupClosePushL( ids );
+            
+            for (TInt index2 = 0; index2 < ids.Count(); index2++)
+                {
+                // Check if iap belongs to this destination
+                if (ids[index2].iIapId == aIapId)
+                    {
+                    ret = IsInternetSnapL( *db, snapIds[index] );
+
+                    if (ret)
+                        {
+                        break;
+                        }
+                    }
+                }            
+            
+            CleanupStack::PopAndDestroy( &ids );
+            
+            if (ret)
+                {
+                break;
+                }
+            }
+        
+        CleanupStack::PopAndDestroy( &snapIds );
+        }
+
+    CleanupStack::PopAndDestroy( db );
+    
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// IsInternetSnapL
+// -----------------------------------------------------------------------------
+//
+TBool CMPMCommsDatAccess::IsInternetSnapL(CMDBSession& db, TUint32 aSnapId)
+    {
+    MPMLOGSTRING( "CMPMCommsDatAccess::IsInternetSnapL" )        
+    TBool ret = EFalse;
+    
+    CCDAccessPointRecord* snapAPr =  static_cast<CCDAccessPointRecord*>( 
+            CCDAccessPointRecord::RecordFactoryL( KCDTIdAccessPointRecord ) );
+    
+    snapAPr->iRecordTag = aSnapId;
+    CleanupStack::PushL( snapAPr );
+
+    if ( !snapAPr->FindL( db ) )
+        {
+        MPMLOGSTRING("CMPMCommsDatAccess::IsInternetSnapL: SNAP not found")
+        CleanupStack::PopAndDestroy( snapAPr );
+        return ret;
+        }
+
+    // Create snap metadata record
+    CMDBRecordSet<CCDSNAPMetadataRecord>* metaSet = 
+           new ( ELeave ) CMDBRecordSet<CCDSNAPMetadataRecord>( 
+            CCDSNAPMetadataRecord::TableIdL( db ) );
+    CleanupStack::PushL( metaSet );
+
+    // Load snap metedata record
+    metaSet->LoadL( db );
+
+    for ( TInt i = 0; i < metaSet->iRecords.Count(); ++i )
+        {
+        // Get value
+        TInt meta = QUERY_INT_FIELD( metaSet->iRecords[i], 
+                                     KCDTIdSNAPMetadataMetadata );
+        
+        TInt snap = QUERY_INT_FIELD( metaSet->iRecords[i],
+                                     KCDTIdSNAPMetadataSNAP ); 
+        // Check whether internet
+        if( meta & ESnapMetadataInternet )
+            {            
+            MPMLOGSTRING("CMPMCommsDatAccess::IsInternetSnapL: Internet snap found")
+            
+            if ( snap == aSnapId )
+                {
+                MPMLOGSTRING2("CMPMCommsDatAccess::IsInternetSnapL: This is internet snap: %d",
+                              aSnapId)
+                ret = ETrue;
+                break;
+                }
+            }
+        }
+        
+    CleanupStack::PopAndDestroy( metaSet );
+    CleanupStack::PopAndDestroy( snapAPr );
+    return ret;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::GetBearerTypeL
+// -----------------------------------------------------------------------------
+//
+TMPMBearerType CMPMCommsDatAccess::GetBearerTypeL( TUint32 aIapId )
+    {
+    MPMLOGSTRING( "CMPMCommsDatAccess::GetBearerTypeL" )
+    TMPMBearerType bearerType = EMPMBearerTypeOther;
+    RArray<TUint32> wlanArray;
+    
+    CMDBSession* db = CMDBSession::NewLC( KCDVersion1_1 );
+    
+    CleanupClosePushL( wlanArray );
+    BuildWlanArrayL(*db, wlanArray);
+    
+    CCDIAPRecord* record = LoadIapRecordLC( aIapId, db );
+    
+    TBuf<KMaxTextLength> bearerTypeName( record->iBearerType.GetL() );
+    TBuf<KMaxTextLength> serviceTypeName( record->iServiceType.GetL() );
+        
+    if ( ( serviceTypeName == TPtrC( KCDTypeNameOutgoingWCDMA ) ) ||
+         ( serviceTypeName == TPtrC( KCDTypeNameIncomingWCDMA ) ) )
+        {
+        // Packet data
+        bearerType = EMPMBearerTypePacketData;
+        }
+    else if ( serviceTypeName == TPtrC( KCDTypeNameLANService ) )
+        {
+        // LAN or WLAN
+        TUint32 bearerId( record->iBearer );
+            
+        if ( ( bearerTypeName == TPtrC( KCDTypeNameLANBearer ) ) &&
+             ( IsWlanBearer( wlanArray, record->iBearer ) ) )
+            {
+            // WLAN
+            bearerType = EMPMBearerTypeWlan;
+            }
+        }
+    else if ( ( bearerTypeName == TPtrC( KCDTypeNameVirtualBearer ) ) &&
+              ( serviceTypeName == TPtrC ( KCDTypeNameVPNService ) ) )
+        {
+        // VPN
+        bearerType = EMPMBearerTypeVpn;
+        }
+    
+    CleanupStack::PopAndDestroy( record );
+    CleanupStack::PopAndDestroy( &wlanArray );
+    CleanupStack::PopAndDestroy( db );
+    
+    return bearerType;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::IsWlanBearerL
+// -----------------------------------------------------------------------------
+//
+TBool CMPMCommsDatAccess::IsWlanBearer(RArray<TUint32>& aWlanArray, TInt aBearerId)
+    {
+    MPMLOGSTRING( "CMPMCommsDatAccess::IsWlanBearer" )
+
+    TInt index = aWlanArray.Find( aBearerId );
+
+    if ( index != KErrNotFound )
+        {
+        return ETrue;
+        }
+    
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::BuildWlanArrayL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::BuildWlanArrayL(CMDBSession& aDb, 
+                                         RArray<TUint32>& aWlanArray)
+    {
+    MPMLOGSTRING( "CMPMCommsDatAccess::BuildWlanArrayL" )
+    
+    CMDBRecordSet<CCDLANBearerRecord>* ptrLanBearerRecordSet = new( ELeave )
+            CMDBRecordSet<CCDLANBearerRecord>( KCDTIdLANBearerRecord );
+    CleanupStack::PushL( ptrLanBearerRecordSet );
+    ptrLanBearerRecordSet->LoadL( aDb );
+
+    for ( TInt i = 0; i < ptrLanBearerRecordSet->iRecords.Count(); i++ )
+        {
+        TBuf<KMaxTextLength> bearerRecordName(
+                ( (CCDLANBearerRecord*)ptrLanBearerRecordSet->iRecords[i] )->iRecordName.GetL() );
+
+        // Check if bearer is WLAN
+        if ( bearerRecordName == TPtrC( KModemBearerWLAN ) )
+            {
+            aWlanArray.AppendL( ptrLanBearerRecordSet->iRecords[i]->RecordId() );
+            }
+        }
+    
+    CleanupStack::PopAndDestroy( ptrLanBearerRecordSet );    
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::AreActiveIapsInSameSnapL
+// -----------------------------------------------------------------------------
+//
+TBool CMPMCommsDatAccess::AreActiveIapsInSameSnapL ( RArray<TActiveBMConn>& aActiveBMConns,
+                                                     TUint32& aSnapId )
+    {
+    MPMLOGSTRING( "CMPMCommsDatAccess::AreActiveIapsInSameSnapL" )
+    TBool same = ETrue;
+    TUint32 snapId = 0;
+    TUint32 prevSnapId = 0;
+            
+    // Go through all active connections
+    for (TInt index = 0; index < aActiveBMConns.Count(); index++ )
+        {
+        // Do check only for active connections
+        if ( aActiveBMConns[index].iConnInfo.iState != EStarted )
+            {
+            continue;
+            }
+        
+        // Iap id must be nonzero
+        if ( aActiveBMConns[index].iConnInfo.iIapId )
+            {
+            prevSnapId = snapId;
+            // Get destination id for the iap
+            snapId = GetSnapIdL( aActiveBMConns[index].iConnInfo.iIapId );
+                        
+            // Check if previous iap's destination is different
+            if ( ( ( prevSnapId != snapId ) && prevSnapId && snapId ) ||
+                 !snapId )
+                {
+                // Set return value to false and leave loop
+                same = EFalse;
+                break;
+                }
+            }
+        }
+    
+    // Return destId for later use
+    aSnapId = snapId;
+    
+    return same;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::SelectActiveConnectionL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::SelectActiveConnectionL ( const TUint32 aSnapId,
+                                                   RArray<TActiveBMConn>& aActiveBMConns,
+                                                   TUint32& aActiveIapId,
+                                                   TUint32& aActiveSnapId,
+                                                   TMPMBearerType& aActiveBearerType,
+                                                   CMPMServerSession& aSession )
+    {
+    MPMLOGSTRING( "CMPMCommsDatAccess::SelectActiveConnectionL" )
+    RArray<TUint32> activeIaps;
+    RArray<TNetIap> iapIds;
+    
+    // Reset output parameters
+    aActiveIapId = 0;
+    aActiveSnapId = 0;
+    aActiveBearerType = EMPMBearerTypeNone;
+
+    CleanupClosePushL( activeIaps );
+        
+    for (TInt index = 0; index < aActiveBMConns.Count(); index++ )
+        {
+        // Add only started iaps to array
+        if ( aActiveBMConns[index].iConnInfo.iState == EStarted )
+            {
+            activeIaps.AppendL ( aActiveBMConns[index].iConnInfo.iIapId );
+            }
+        }
+        
+    CleanupClosePushL( iapIds );
+    SearchDNEntriesL( aSnapId, iapIds );
+    
+    // Remove any deactived IAP from iapIds
+    TInt ret        = KErrNotFound;
+    TInt destCount  = iapIds.Count();
+    
+    // Decrement by one, because count is n, 
+    // but indexes in array are 0 .. n-1.
+    // 
+    destCount--;
+
+    // This time we are browsing the array from the end to the beginning, 
+    // because removing one element from array affects index numbering.
+    for ( TInt k = destCount; k >= 0; k-- )
+        {
+        ret = activeIaps.Find( iapIds[k].iIapId );
+        if ( ret == KErrNotFound )
+            {
+            MPMLOGSTRING2( "CMPMCommsDatAccess::SelectActiveConnectionL: \
+Remove deactived IAP = %i", iapIds[k].iIapId )
+            iapIds.Remove( k );
+            }
+        }
+
+    // Determine the actual priorities for IAPs
+    DeterminePrioritiesL( iapIds, activeIaps, aSession );
+
+    // Check if a matching available IAP is found.
+    if( iapIds.Count() )
+        {
+        // Go through all iaps
+        for ( TInt index = 0; index < iapIds.Count(); index++ )
+            {
+            // Get bearer type
+            TMPMBearerType bearerType = GetBearerTypeL( iapIds[index].iIapId );
+        
+            // If iap is not vpn, wlan or packet then skip it
+            if ( bearerType == EMPMBearerTypeOther )
+                {
+                continue;
+                }
+            
+            // Set bearer type, iap id and snap id
+            for (TInt index2 = 0; index2 < aActiveBMConns.Count(); index2++ )
+                {
+                if ( ( aActiveBMConns[index2].iConnInfo.iIapId ==
+                       iapIds[index].iIapId ) )
+                    {
+                    if ( aSession.MyServer().DedicatedClients().Find(
+                         aActiveBMConns[index2].iConnInfo.iAppUid ) != KErrNone )
+                        {
+                        aActiveSnapId = aActiveBMConns[index2].iConnInfo.iSnap;
+                        aActiveIapId = aActiveBMConns[index2].iConnInfo.iIapId;
+                        aActiveBearerType = bearerType;
+                        }
+                    break;
+                    }
+                }
+            
+            break;
+            }
+        }
+
+    MPMLOGSTRING4(
+        "CMPMCommsDatAccess::SelectActiveConnectionL: Iap id = %i, Snap id = %i, \
+Bearer type = %i",
+        aActiveIapId, aActiveSnapId, aActiveBearerType )
+    
+    CleanupStack::PopAndDestroy( &iapIds );
+    CleanupStack::PopAndDestroy( &activeIaps );
+    }
+    
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::GetSnapIdL
+// -----------------------------------------------------------------------------
+//
+TUint32 CMPMCommsDatAccess::GetSnapIdL( TUint32 aIapId )
+    {
+    MPMLOGSTRING( "CMPMCommsDatAccess::GetSnapIdL" )
+    TUint32 snapId = 0;
+    RArray<TUint> snapIds;
+        
+    CleanupClosePushL( snapIds );
+    // Get destinations
+    FindAllSnapsL( snapIds );
+
+    for (TInt index = 0; index < snapIds.Count(); index++)
+        {
+        RArray<TNetIap> ids;
+        // Get iaps belonging to this snap
+        CleanupClosePushL( ids );
+        SearchDNEntriesL( snapIds[index], ids );
+            
+        for (TInt index2 = 0; index2 < ids.Count(); index2++)
+            {
+            // Check if iap belongs to this destination
+            if (ids[index2].iIapId == aIapId)
+                {
+                snapId = snapIds[index];
+                CleanupStack::PopAndDestroy( &ids );                    
+                CleanupStack::PopAndDestroy( &snapIds );
+                return snapId;
+                }
+            }
+        
+        CleanupStack::PopAndDestroy( &ids );
+        }
+
+    CleanupStack::PopAndDestroy( &snapIds );
+    
+    return snapId;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::IsSnapEmptyL
+// -----------------------------------------------------------------------------
+//
+TBool CMPMCommsDatAccess::IsSnapEmptyL( TUint32 aSnapId )
+    {
+    MPMLOGSTRING( "CMPMCommsDatAccess::IsSnapEmptyL" )
+    TBool empty = ETrue;
+    
+    RArray<TNetIap> ids;
+    // Get iaps belonging to this snap
+    CleanupClosePushL( ids );
+    SearchDNEntriesL( aSnapId, ids );
+    
+    if ( ids.Count() )
+        {
+        empty = EFalse;
+        }
+    
+    CleanupStack::PopAndDestroy( &ids );    
+    
+    return empty;
+    }
+        
+// -----------------------------------------------------------------------------
+// VerifyIapExistsL
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::VerifyIapExistsL( TUint32 aIapId )
+    {
+    MPMLOGSTRING2( "CMPMCommsDatAccess::VerifyIapExistsL: aIapId %d", aIapId )
+    CMDBSession* db = CMDBSession::NewLC( KCDVersion1_1 );
+    db->SetAttributeMask( ECDProtectedWrite );
+    CCDIAPRecord* iapRecord = LoadIapRecordLC( aIapId, db );
+    CleanupStack::PopAndDestroy( iapRecord );
+    CleanupStack::PopAndDestroy( db );
+    }
+
+// -----------------------------------------------------------------------------
+// ForcedRoamingL
+// -----------------------------------------------------------------------------
+//
+TCmUsageOfWlan CMPMCommsDatAccess::ForcedRoamingL() const
+    {
+    TCmGenConnSettings cmGenConnSettings;
+    RCmManager rCmManager;
+    
+    rCmManager.CreateTablesAndOpenL();
+    CleanupClosePushL( rCmManager ); 
+    rCmManager.ReadGenConnSettingsL( cmGenConnSettings );
+    CleanupStack::PopAndDestroy( &rCmManager );
+    
+    return cmGenConnSettings.iUsageOfWlan;
+    }
+
+// -----------------------------------------------------------------------------
+// MapAPRecIdtoSnapAPL
+// -----------------------------------------------------------------------------
+//
+TInt CMPMCommsDatAccess::TierLinktoTagIdL( CMDBSession* aDbs, TUint32 aElementId )
+    {
+    ASSERT(aDbs);
+    
+    // declare tier record
+    CCDTierRecord* tier = static_cast<CCDTierRecord*>( 
+            CCDTierRecord::RecordFactoryL( KCDTIdTierRecord ) );
+    
+    CleanupStack::PushL( tier );
+    
+    tier->SetElementId( aElementId );
+    tier->LoadL( *aDbs );
+    TInt tag = tier->iRecordTag;
+
+    CleanupStack::PopAndDestroy( tier );
+    return  tag;
+    }
+
+// -----------------------------------------------------------------------------
+// MapAPRecIdtoSnapAPL
+// -----------------------------------------------------------------------------
+//
+TInt CMPMCommsDatAccess::MapAPRecIdtoSnapAPL( TInt aApRecId )
+    {
+    CMDBSession* dbs = CMDBSession::NewLC( KCDVersion1_1 );
+        
+    CCDAccessPointRecord* ipt =  static_cast<CCDAccessPointRecord*>( 
+            CCDAccessPointRecord::RecordFactoryL( KCDTIdAccessPointRecord ) );
+
+    CleanupStack::PushL( ipt );
+
+    ipt->SetElementId( aApRecId );
+    
+    TBool found = ipt->FindL( *dbs );
+    if ( !found )
+        User::Leave( KErrNotFound );
+    
+    if ( TierLinktoTagIdL( dbs, ipt->iTier ) == KAfInet )  // ipprototm = 271064560 , iptm = 271064536
+        {
+        User::Leave( KErrArgument );
+        }
+
+    TInt ap = ipt->iRecordTag;
+    
+    CleanupStack::PopAndDestroy( ipt );
+    CleanupStack::PopAndDestroy( dbs );
+
+    return ap;
+    }
+
+// -----------------------------------------------------------------------------
+// MapNetIdtoSnapAPL
+// -----------------------------------------------------------------------------
+//
+TInt CMPMCommsDatAccess::MapNetIdtoSnapAPL( TInt aNetId )
+    {
+    CMDBSession* dbs = CMDBSession::NewLC( KCDVersion1_1 );
+        
+    CCDAccessPointRecord* ipt =  static_cast<CCDAccessPointRecord*>( 
+            CCDAccessPointRecord::RecordFactoryL( KCDTIdAccessPointRecord ) );
+
+    CleanupStack::PushL( ipt );
+    ipt->iCustomSelectionPolicy = aNetId;
+
+    TBool found = ipt->FindL( *dbs );
+    if ( !found )
+        User::Leave( KErrNotFound );
+    
+    if ( TierLinktoTagIdL( dbs, ipt->iTier ) == KAfInet )  // ipprototm = 271064560 , iptm = 271064536
+        {
+        User::Leave( KErrArgument );
+        }
+
+    TInt ap = ipt->iRecordTag;
+    
+    CleanupStack::PopAndDestroy( ipt );
+    CleanupStack::PopAndDestroy( dbs );
+
+    return ap;
+    }
+
+// -----------------------------------------------------------------------------
+// MapSnapAPtoNetIdL
+// -----------------------------------------------------------------------------
+//
+TInt CMPMCommsDatAccess::MapSnapAPtoNetIdL( TInt aAP )
+    {
+    CMDBSession* dbs = CMDBSession::NewLC( KCDVersion1_1 );
+        
+    CCDAccessPointRecord* ipt =  static_cast<CCDAccessPointRecord*>( 
+            CCDAccessPointRecord::RecordFactoryL( KCDTIdAccessPointRecord ) );
+    CleanupStack::PushL( ipt );
+    ipt->iRecordTag = aAP;
+    TBool found = ipt->FindL( *dbs );
+    if ( !found )
+        User::Leave( KErrNotFound );
+    
+    if ( TierLinktoTagIdL( dbs, ipt->iTier ) == KAfInet )  // ipprototm = 271064560 , iptm = 271064536
+        {
+        User::Leave( KErrArgument );
+        }
+
+    TInt netid = ipt->iSelectionPolicy;
+    
+    CleanupStack::PopAndDestroy( ipt );
+    CleanupStack::PopAndDestroy( dbs );
+
+    return netid;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::ReadGenConnSettings
+// -----------------------------------------------------------------------------
+//
+TCmGenConnSettings CMPMCommsDatAccess::ReadGenConnSettingsL() const
+    {
+    TCmGenConnSettings cmGenConnSettings;
+    RCmManager rCmManager;
+    
+    rCmManager.CreateTablesAndOpenL();
+    CleanupClosePushL( rCmManager ); 
+    rCmManager.ReadGenConnSettingsL( cmGenConnSettings );
+    CleanupStack::PopAndDestroy( &rCmManager );
+    
+    return cmGenConnSettings;
+    }
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::WriteGenConnSettings
+// -----------------------------------------------------------------------------
+//
+void CMPMCommsDatAccess::WriteGenConnSettingsL(TCmGenConnSettings& aGenConnSettings )
+    {
+    RCmManager rCmManager;
+    rCmManager.CreateTablesAndOpenL();
+    CleanupClosePushL( rCmManager ); 
+    rCmManager.WriteGenConnSettingsL( aGenConnSettings );
+    CleanupStack::PopAndDestroy( &rCmManager );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMPMCommsDatAccess::DestinationIdL
+// -----------------------------------------------------------------------------
+//
+TUint32 CMPMCommsDatAccess::DestinationIdL( CMManager::TSnapPurpose aSnapPurpose )
+    {
+    MPMLOGSTRING( "CMPMCommsDatAccess::DestinationIdL" )
+    TUint32 destinationId = 0;
+    TInt snapMetadata = 0;
+    
+    RArray<TUint32> snapIds;    
+    CleanupClosePushL( snapIds );
+
+    RCmManager rCmManager;
+    CleanupClosePushL( rCmManager ); 
+    rCmManager.CreateTablesAndOpenL();
+
+    rCmManager.AllDestinationsL( snapIds );
+
+    for ( TInt index = 0; index < snapIds.Count(); index++ )
+         {
+         RCmDestination dest;
+         CleanupClosePushL( dest );
+
+         dest = rCmManager.DestinationL( snapIds[index] );
+         
+         snapMetadata = dest.MetadataL( CMManager::ESnapMetadataPurpose );
+         
+         if ( snapMetadata == aSnapPurpose )
+             {
+             destinationId = snapIds[index];
+             CleanupStack::PopAndDestroy( &dest );
+             break;
+             }        
+         CleanupStack::PopAndDestroy( &dest );
+         }
+    
+    CleanupStack::PopAndDestroy( &rCmManager );
+    CleanupStack::PopAndDestroy( &snapIds );
+
+    if (!destinationId)
+        {
+        User::Leave(KErrNotFound);
+        }
+    
+    return destinationId;
+    }
+
+//  End of File