browserutilities/favouritesengine/ClientServer/srvsrc/FavouritesSrvSession.cpp
changeset 0 dd21522fd290
child 68 92a765b5b3e7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/browserutilities/favouritesengine/ClientServer/srvsrc/FavouritesSrvSession.cpp	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,915 @@
+/*
+* Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*      Implementation of class CFavouritesSession
+*      
+*
+*/
+
+
+// INCLUDE FILES
+
+#include "FavouritesSrvDb.h"
+#include "FavouritesSrvDbNotifier.h"
+#include "FavouritesSrvDbIncremental.h"
+#include "FavouritesSrvStream.h"
+#include "FavouritesSrvFile.h"
+#include "FavouritesSrvBuf.h"
+#include "FavouritesBuf.h"
+#include "FavouritesFilter.h"
+#include "FavouritesSrvSession.h"
+#include "FavouritesSrvSessionEntry.h"
+#include "FavouritesDef.h"
+#include "FavouritesMsg.h"
+#include "FavouritesItemImplList.h"
+#include "FavouritesUtil.h"
+#include "UidMap.h"
+#include "favouriteslogger.h"
+#include <utf.h>
+// CONSTANTS
+
+/// Object list granularity.
+LOCAL_D const TInt KFavouritesSrvSessionObjectGranularity = 4;
+/// Uid list granularity.
+LOCAL_D const TInt KFavouritesSrvSessionUidListGranularity = 4;
+/// Granularity of AP map in RFS.
+LOCAL_D const TInt KApMapGranularity = 4;
+
+// Secure policy ID of the Faveng database files.
+LOCAL_D const TUint KUidFavengDbPolicy = 0x101FD685;
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CFavouritesSession::NewL
+// ---------------------------------------------------------
+//
+CFavouritesSession* CFavouritesSession::NewL()
+    {
+    CFavouritesSession* sess = new (ELeave) CFavouritesSession();
+    CleanupStack::PushL( sess );
+    sess->ConstructL();
+    CleanupStack::Pop();
+    return sess;
+    }
+
+// ---------------------------------------------------------
+// CFavouritesSession::~CFavouritesSession
+// ---------------------------------------------------------
+//
+CFavouritesSession::~CFavouritesSession()
+    {
+    // Free all entries in reverse order:
+    // Files -> Streams -> Incrementals -> Notifiers -> Databases.
+    for ( TInt type = TFavouritesSessionEntry::EFile;
+          type > TFavouritesSessionEntry::ENone;
+          type--
+        )
+        {
+        for ( TInt i = 0; i < iNumEntries; i++ )
+            {
+            if ( STATIC_CAST( TInt, iEntries[i].Type() ) == type )
+                {
+                iEntries[i].Release();
+                }
+            }
+        }
+    delete iEntries;
+    iEntries = NULL;    // Safety code.
+    iNumEntries = 0;    // Safety code.
+    
+    // In the case of -Secure Backup is in progress- 
+    // the ActiveScheduler is not active the server does not exists at this point.
+    if(CActiveScheduler::Current() != NULL)
+    	{
+    	FLOG(( _L("Server().SessionClosed()") ));
+    	Server().SessionClosed();
+    	}
+    else
+    	{
+    	FLOG(( _L("CActiveScheduler::Current() == NULL") ));
+    	}
+    
+    iDbs.Close();
+    iFs.Close();
+    }
+
+// ---------------------------------------------------------
+// CFavouritesSession::CFavouritesSession
+// ---------------------------------------------------------
+//
+CFavouritesSession::CFavouritesSession()
+: iEntries( NULL ), iNumEntries( 0 ), iChkNum( 1 )
+    {
+    }
+
+// ---------------------------------------------------------
+// CFavouritesSession::ConstructL
+// ---------------------------------------------------------
+//
+void CFavouritesSession::ConstructL()
+    {
+    User::LeaveIfError( iFs.Connect() );
+    User::LeaveIfError( iFs.SetSessionToPrivate( EDriveC ) );
+    User::LeaveIfError( iDbs.Connect() );
+
+       }
+
+// ---------------------------------------------------------
+// CFavouritesSession::CountResources
+// ---------------------------------------------------------
+//
+TInt CFavouritesSession::CountResources()
+    {
+    TInt cnt( 0 );
+    for ( TInt i = 0; i < iNumEntries; i++ )
+        {
+        if ( iEntries[i].Type() != TFavouritesSessionEntry::ENone )
+            {
+            cnt++;
+            }
+        }
+    return cnt;
+    }
+
+// ---------------------------------------------------------
+// CFavouritesSession::ServiceL
+// ---------------------------------------------------------
+//
+void CFavouritesSession::ServiceL( const RMessage2& aMessage )
+    {
+	// Set received message in server so it can be used in cleanup when
+    // server panics.
+	Server().ReceivedMessage( aMessage );
+    TInt ret( KErrNone );
+    TFavouritesMsg msg( aMessage.Function() );
+    if ( msg.IsNull() )
+        {
+        // Null handle -> session function.
+        switch ( msg.Function() )
+            {
+            // Session functions.
+            case EFavengResourceMarkStart:
+                {
+                ResourceCountMarkStart();
+                break;
+                }
+
+            case EFavengResourceMarkEnd:
+                {
+                ResourceCountMarkEnd( aMessage );
+                break;
+                }
+
+            case EFavengResourceCount:
+                {
+                ret = CountResources();
+                break;
+                }
+
+            case EFavengDeleteDatabase:
+                {
+                TBuf<KFavouritesMaxName> name;
+                TInt len = aMessage.GetDesLength( 0 );
+                if ( len < 1 || len > KFavouritesMaxName )
+                    {
+                    User::Leave( KErrBadName );
+                    }
+                name.SetLength( len );
+                aMessage.ReadL( 0, name );
+                DatabaseDirL( name, iParse );
+                TRAPD( err, DeleteDirL( iParse ) );
+                // Map KErrPathNotFound error to KErrNotFound.
+                if ( err == KErrPathNotFound )
+                    {
+                    err = KErrNotFound;
+                    }
+                User::LeaveIfError( err );
+                break;
+                }
+
+            case EFavengSetHeapFailure:
+                {
+                User::__DbgSetAllocFail
+                    (
+                    RAllocator::EUser,
+                    STATIC_CAST( RAllocator::TAllocFail, aMessage.Int0() ),
+                    aMessage.Int1()
+                    );
+                break;
+                }
+
+            case EFavengOpenDatabase:
+                {
+                
+                // Fixed for Bug id - JJUN-78RARE (FAVENGSRV crashes under IPC attack)
+                // When client sends 8 bit descriptor input and favourite server always 
+                // will attempt  on 16 bit RMessage2 read/write. So server will leave with 
+                // KErrBadDescriptor and hence crash occurs. To avoid this crash,favourite 
+                // server will attempt to  read/write on 8bit descriptor.
+                
+                HBufC *buf = HBufC::NewLC(KFavouritesMaxName);
+                TPtr name(buf->Des());
+                TInt len = aMessage.GetDesLength( 0 );
+                if ( len < 1 || len > KFavouritesMaxName )
+                    {
+                    User::Leave( KErrBadName );
+                    }
+                name.SetLength( len );
+                TInt err =  aMessage.Read( 0, name );
+                
+                if ( KErrBadDescriptor == err)   // Mismatch between 8 bit and 16 bit descriptors
+	            {
+            	    HBufC8 *buf8 = HBufC8::NewLC(KFavouritesMaxName);
+            	    TPtr8 name8(buf8->Des());
+                	name8.SetLength( len );
+                	aMessage.ReadL( 0, name8 );
+                	CnvUtfConverter::ConvertToUnicodeFromUtf8(name,name8);
+                	CleanupStack::PopAndDestroy(/*buf8*/);
+                }
+                else
+                {
+                	User::LeaveIfError(err);
+                }
+                
+                DatabaseDirL( name, iParse );
+                TFavouritesHandle h = NewHandleL();
+                Entry( h ) = *(CFavouritesSrvDb::NewL
+                    ( iFs, iDbs, iParse.FullName(), name ));
+                ret = h;
+                CleanupStack::PopAndDestroy(/*buf*/);
+                break;
+                }
+
+            case EFavengOpenStream:
+                {
+                ret = NewStreamL( *(HFavouritesSrvBuf::NewL()), aMessage );
+                break;
+                }
+
+            default:
+                {
+                ret = KErrNotSupported;
+                break;
+                }
+            }
+        }
+    else
+        {
+        // Object based functions.
+        TFavouritesSessionEntry& e = EntryL( msg );
+
+        switch( msg.Function() )
+            {
+            // Favourites Engine functions.
+            case EFavengClose:
+                {
+                e.Release();
+                break;
+                };
+
+            case EFavengIsDamaged:
+                {
+                ret = e.Database().IsDamagedL();
+                break;
+                }
+
+            case EFavengRecover:
+                {
+                e.Database().RecoverL();
+                break;
+                }
+
+            case EFavengCompact:
+                {
+                e.Database().CompactL();
+                break;
+                }
+
+            case EFavengSize:
+                {
+                TPckgBuf<RDbDatabase::TSize> size;
+                size() = e.Database().Size();
+                aMessage.WriteL( 0, size );
+                break;
+                }
+
+            case EFavengUpdateStats:
+                {
+                e.Database().UpdateStatsL();
+                break;
+                }
+
+            case EFavengBegin:
+                {
+                if ( e.Database().InTransaction() )
+                    {
+                    Server().PanicClient( EFavouritesNestedTransaction );
+                    }
+                else
+                    {
+                    e.Database().BeginL( (TBool)aMessage.Int0() );
+                    }
+                break;
+                }
+
+            case EFavengCommit:
+                {
+                if ( e.Database().InTransaction() )
+                    {
+                    e.Database().CommitL();
+                    }
+                else
+                    {
+                    Server().PanicClient( EFavouritesNoTransaction );
+                    }
+                break;
+                }
+
+            case EFavengRollback:
+                {
+                if ( e.Database().InTransaction() )
+                    {
+                    e.Database().Rollback();
+                    }
+                else
+                    {
+                    Server().PanicClient( EFavouritesNoTransaction );
+                    }
+                break;
+                }
+
+            case EFavengGet:
+                {
+                RWriteStream stream( HFavouritesSrvBuf::NewLC() );
+                CFavouritesItemImpl* item = CFavouritesItemImpl::NewLC();
+                e.Database().GetL( aMessage.Int0(), *item );
+                item->ExternalizeL( stream );
+                stream.CommitL();
+                CleanupStack::PopAndDestroy( item );
+                CleanupStack::Pop();    // Stream buf; will be taken by stream.
+                ret = NewStreamL( *(stream.Sink()), aMessage );
+                break;
+                }
+
+            case EFavengGetAll:
+                {
+                TPckgBuf<TFavouritesFilter> filter;
+                aMessage.ReadL( 0, filter );
+                RWriteStream stream( HFavouritesSrvBuf::NewLC() );
+                CFavouritesItemImplList* list =
+                    new (ELeave) CFavouritesItemImplList();
+                CleanupStack::PushL( list );
+                e.Database().GetAllL( *list, filter() );
+                list->ExternalizeL( stream );
+                stream.CommitL();
+                CleanupStack::PopAndDestroy( list );
+                CleanupStack::Pop();    // Stream buf; will be taken by stream.
+                ret = NewStreamL( *(stream.Sink()), aMessage );
+                break;
+                }
+
+            case EFavengGetUids:
+                {
+                TPckgBuf<TFavouritesFilter> filter;
+                aMessage.ReadL( 0, filter );
+                RWriteStream stream( HFavouritesSrvBuf::NewLC() );
+                CArrayFixFlat<TInt>* list = new (ELeave) CArrayFixFlat<TInt>
+                    ( KFavouritesSrvSessionUidListGranularity );
+                CleanupStack::PushL( list );
+                e.Database().GetUidsL( *list, filter() );
+                FavouritesUtil::ExternalizeL( *list, stream );
+                stream.CommitL();
+                CleanupStack::PopAndDestroy( list );
+                CleanupStack::Pop();    // Stream buf; will be taken by stream.
+                ret = NewStreamL( *(stream.Sink()), aMessage );
+                break;
+                }
+
+            case EFavengPreferredUid:
+                {
+                TPckgBuf<TInt> uid;
+                uid() = e.Database().PreferredUidL( aMessage.Int0() );
+                aMessage.WriteL( 1, uid );
+                break;
+                }
+
+            case EFavengDelete:
+                {
+                e.Database().DeleteL( aMessage.Int0() );
+                break;
+                }
+
+            case EFavengUpdate:
+                {
+                MStreamBuf& buf = EntryL( TFavouritesHandle
+                    ( aMessage.Int0() ) ).Stream().Host();
+                RReadStream rs( &buf );
+                CFavouritesItemImpl* item = CFavouritesItemImpl::NewLC();
+                item->InternalizeL( rs );
+                e.Database().UpdateL
+                    ( *item, aMessage.Int1(), aMessage.Int2() );
+                RWriteStream ws( &buf );
+                item->ExternalizeUpdateDeltaL( ws );
+                ws.CommitL();
+                CleanupStack::PopAndDestroy( item );
+                break;
+                }
+
+            case EFavengAdd:
+                {
+                MStreamBuf& buf = EntryL( TFavouritesHandle
+                    ( aMessage.Int0() ) ).Stream().Host();
+                RReadStream rs( &buf );
+                CFavouritesItemImpl* item = CFavouritesItemImpl::NewLC();
+                item->InternalizeL( rs );
+                e.Database().AddL( *item, aMessage.Int1() );
+                RWriteStream ws( &buf );
+                item->ExternalizeUpdateDeltaL( ws );
+                ws.CommitL();
+                CleanupStack::PopAndDestroy( item );
+                break;
+                }
+
+            case EFavengSetSpecialItem:
+                {
+                MStreamBuf& buf = EntryL( TFavouritesHandle
+                    ( aMessage.Int0() ) ).Stream().Host();
+                RReadStream rs( &buf );
+                CFavouritesItemImpl* item = CFavouritesItemImpl::NewLC();
+                item->InternalizeL( rs );
+                e.Database().SetSpecialItemL( *item, aMessage.Int1() );
+                RWriteStream ws( &buf );
+                item->ExternalizeUpdateDeltaL( ws );
+                ws.CommitL();
+                CleanupStack::PopAndDestroy( item );
+                break;
+                }
+
+            case EFavengSetFactoryItem:
+                {
+                e.Database().SetFactoryItemL
+                                        ( aMessage.Int0(), aMessage.Int1() );
+                break;
+                }
+
+            case EFavengSetReadOnly:
+                {
+                e.Database().SetReadOnlyL
+                                        ( aMessage.Int0(), aMessage.Int1() );
+                break;
+                }
+
+            case EFavengSetModified:
+                {
+                e.Database().SetModifiedL( aMessage.Int0(),
+                    TTime( MAKE_TINT64( aMessage.Int1(), aMessage.Int2() ) ) );
+                break;
+                }
+
+            case EFavengSetPreferredUid:
+                {
+                e.Database().SetPreferredUidL
+                                        ( aMessage.Int0(), aMessage.Int1() );
+                break;
+                }
+
+            case EFavengItemExists:
+                {
+                ret = e.Database().ItemExistsL( aMessage.Int0() );
+                break;
+                }
+
+            case EFavengFolderExists:
+                {
+                ret = e.Database().FolderExistsL( aMessage.Int0() );
+                break;
+                }
+
+            case EFavengCount:
+                {
+                TPckgBuf<TFavouritesFilter> filter;
+                aMessage.ReadL( 0, filter );
+                ret = e.Database().CountL( filter() );
+                break;
+                }
+
+            case EFavengSetData:
+                {
+                MStreamBuf& buf = EntryL( TFavouritesHandle
+                    ( aMessage.Int0() ) ).Stream().Host();
+                e.Database().SetDataL( aMessage.Int1(), buf );
+                break;
+                }
+
+            case EFavengGetData:
+                {
+                RWriteStream stream( HFavouritesSrvBuf::NewLC() );
+                e.Database().GetDataL
+                    ( aMessage.Int0(), *(stream.Sink()) );
+                stream.CommitL();
+                CleanupStack::Pop();    // Stream buf; will be taken by stream.
+                ret = NewStreamL( *(stream.Sink()), aMessage );
+                break;
+                }
+
+            case EFavengSetBrowserData:
+                {
+                MStreamBuf& buf = EntryL( TFavouritesHandle
+                    ( aMessage.Int0() ) ).Stream().Host();
+                e.Database().SetBrowserDataL( aMessage.Int1(), buf );
+                break;
+                }
+
+            case EFavengGetBrowserData:
+                {
+                RWriteStream stream( HFavouritesSrvBuf::NewLC() );
+                e.Database().GetBrowserDataL
+                    ( aMessage.Int0(), *(stream.Sink()) );
+                stream.CommitL();
+                CleanupStack::Pop();    // Stream buf; will be taken by stream.
+                ret = NewStreamL( *(stream.Sink()), aMessage );
+                break;
+                }
+
+            case EFavengMakeUniqueName:
+                {
+                TBuf<KFavouritesMaxName> name;
+                name.SetLength( aMessage.Int1() );
+                aMessage.ReadL( 0, name );
+                e.Database().MakeUniqueNameL( name, aMessage.Int2() );
+                aMessage.WriteL( 0, name );
+                ret = name.Length();
+                break;
+                };
+
+
+            case EFavengRestoreFactorySettings:
+                {
+                TFileName refDb;
+                TInt len = aMessage.Int1();
+                if ( len > refDb.MaxLength() )
+                    {
+                    User::Leave( KErrBadName );
+                    }
+                refDb.SetLength( len );
+                aMessage.ReadL( 0, refDb );
+                RWriteStream stream( HFavouritesSrvBuf::NewLC() );
+                CUidMap* map = new (ELeave) CUidMap( KApMapGranularity );
+                CleanupStack::PushL( map );
+                e.Database().RestoreFactorySettingsL( refDb, *map );
+                map->ExternalizeL( stream );
+                stream.CommitL();
+                CleanupStack::PopAndDestroy( map );
+                CleanupStack::Pop();    // Stream buf; will be taken by stream.
+                ret = NewStreamL( *(stream.Sink()), aMessage );
+			    FLOG(( _L("restore: case EFavengRestoreFactorySettings") ));
+                break;
+                }
+
+            case EFavengSetAccessPoints:
+                {
+                MStreamBuf& buf = EntryL( TFavouritesHandle
+                    ( aMessage.Int0() ) ).Stream().Host();
+                RReadStream rs( &buf );
+                CUidMap* map = new (ELeave) CUidMap( KApMapGranularity );
+                CleanupStack::PushL( map );
+                map->InternalizeL( rs );
+                e.Database().SetAccessPointsL( *map );
+                CleanupStack::PopAndDestroy( map );
+                break;
+                }
+
+			case EFavengFileOpen:
+                {
+                TFavouritesHandle h = NewHandleL();
+                e.Database().FilenameL( aMessage.Int0(), iParse );
+                CFavouritesSrvFile* file = CFavouritesSrvFile::NewL();
+                Entry( h ) = *file;
+                file->SetName(iParse);
+            
+                ret = h;
+                break;
+                }
+                
+            case EFavengFileOpenRead:
+                {
+                CFavouritesSrvFile& file = e.File();
+                
+                file.OpenL();
+                file.TransferToClientL( aMessage );
+                
+                break;
+                }
+
+            case EFavengFileOpenWrite:
+                {
+                CFavouritesSrvFile& file = e.File();
+                
+                file.ReplaceL();
+                file.TransferToClientL( aMessage );
+                
+                break;
+                }
+
+            case EFavengFileDelete:
+                {
+                TFavouritesHandle h = NewHandleL();
+                e.Database().FilenameL( aMessage.Int0(), iParse );
+                TInt err = iFs.Delete( iParse.FullName() );
+                // Map KErrPathNotFound error to KErrNotFound.
+                if ( err == KErrPathNotFound )
+                    {
+                    err = KErrNotFound;
+                    }
+                User::LeaveIfError( err );
+                break;
+                }
+
+            case EFavengIncrementalRecover:
+                {
+                TFavouritesHandle h = NewHandleL();
+                CFavouritesSrvDbIncremental* inc =
+                    new (ELeave) CFavouritesSrvDbIncremental();
+                Entry( h ) = *inc;
+                TPckgBuf<TInt> step;
+                inc->RecoverL( e.Database(), step() );
+                aMessage.WriteL( 0, step );
+                ret = h;
+                break;
+                }
+
+            case EFavengIncrementalCompact:
+                {
+                TFavouritesHandle h = NewHandleL();
+                CFavouritesSrvDbIncremental* inc =
+                    new (ELeave) CFavouritesSrvDbIncremental();
+                Entry( h ) = *inc;
+                TPckgBuf<TInt> step;
+                inc->CompactL( e.Database(), step() );
+                aMessage.WriteL( 0, step );
+                ret = h;
+                break;
+                }
+
+            case EFavengIncrementalNext:
+                {
+                TInt step =  aMessage.Int0();
+                if ( step == e.Incremental().Step() && step > 0 )
+                    {
+                    e.Incremental().NextL( step );
+                    ret = step;
+                    }
+                else
+                    {
+                    Server().PanicClient( EFavouritesBadStep );
+                    }
+                break;
+                }
+
+            case EFavengOpenNotifier:
+                {
+                TFavouritesHandle h = NewHandleL();
+                Entry( h ) = *(CFavouritesSrvDbNotifier::NewL( e.Database() ));
+                ret = h;
+                break;
+                }
+
+            case EFavengNotifyAllEvents:
+                {
+                if ( e.Notifier().IsActive() )
+                    {
+                    Server().PanicClient( EFavouritesAlreadyOpen );
+                    }
+                else
+                    {
+                    e.Notifier().NotifyAllEvents( aMessage );
+                    return; // Notifier will complete the message.
+                    }
+                break;
+                }
+
+            case EFavengNotifyChange:
+                {
+                if ( e.Notifier().IsActive() )
+                    {
+                    Server().PanicClient( EFavouritesAlreadyOpen );
+                    }
+                else
+                    {
+                    e.Notifier().NotifyChange( aMessage );
+                    return; // Notifier will complete the message.
+                    }
+                break;
+                }
+
+            case EFavengNotifyCancel:
+                {
+                e.Notifier().Cancel();
+                break;
+                }
+
+            case EFavengStreamRead:
+                {
+                ret = e.Stream().ReadL( aMessage );
+                break;
+                }
+
+            case EFavengStreamWrite:
+                {
+                e.Stream().WriteL( aMessage );
+                break;
+                }
+
+            default:
+                {
+                ret = KErrNotSupported;
+                break;
+                }
+            }
+
+        }
+
+	// Fixed for Bug id - JJUN-78RARE (FAVENGSRV crashes under IPC attack)    
+	if ( (EFavengFileOpenRead == msg.Function()) && msg.IsNull() )
+		{
+		User::Leave(ret);	
+		}
+		
+    if ( !Server().ReceivedMessage().IsNull() &&
+    	// Special cases - file handler passed -
+    	// IPC message is transfered automatically. 
+    	msg.Function() != EFavengFileOpenRead &&
+    	msg.Function() != EFavengFileOpenWrite)
+        {
+        aMessage.Complete( ret );
+        }
+    }
+
+// ---------------------------------------------------------
+// CFavouritesSession::ServiceError
+// ---------------------------------------------------------
+//
+void CFavouritesSession::ServiceError( const RMessage2& aMessage, TInt aError )
+    {
+    // A bad descriptor / bad handle error implies a badly programmed client,
+    // so panic it; otherwise use the default handling (report the error to
+    // the client).
+    if ( aError == KErrBadDescriptor || aError == KErrBadHandle )
+        {
+        Server().PanicClient( aError );
+        }
+    CSession2::ServiceError( aMessage, aError );
+    }
+
+// ---------------------------------------------------------
+// CFavouritesSession::NewHandleL
+// ---------------------------------------------------------
+//
+TFavouritesHandle CFavouritesSession::NewHandleL()
+    {
+    TInt i;
+    for ( i = 0; i < iNumEntries; i++ )
+        {
+        if ( iEntries[i].Type() == TFavouritesSessionEntry::ENone )
+            {
+            // Found free slot; assign check number and return it.
+            iEntries[i].ChkNum() = NextChkNum();
+            return TFavouritesHandle( i, iEntries[i].ChkNum() );
+            }
+        }
+    // No free slot; expand entry list.
+    TInt newNum = iNumEntries + KFavouritesSrvSessionObjectGranularity;
+    if ( newNum > (1 << KIndexBits) )
+        {
+        // Index range exhausted.
+        User::Leave( KErrNoMemory );
+        }
+    iEntries = STATIC_CAST( TFavouritesSessionEntry*, User::ReAllocL\
+        ( iEntries, newNum * sizeof( TFavouritesSessionEntry ) ) );
+    // Initialize new entries.
+    for ( i = iNumEntries; i < newNum; i++ )
+        {
+        iEntries[i].SetNull();
+        }
+    i = iNumEntries;    // Index of first newly allocated entry.
+    iNumEntries = newNum;
+    iEntries[i].ChkNum() = NextChkNum();
+    return TFavouritesHandle( i, iEntries[i].ChkNum() );
+    }
+
+// ---------------------------------------------------------
+// CFavouritesSession::EntryL
+// ---------------------------------------------------------
+//
+TFavouritesSessionEntry& CFavouritesSession::EntryL
+( TFavouritesHandle aHandle )
+    {
+    TInt i = aHandle.Index();
+    if ( i > iNumEntries || aHandle.ChkNum() != iEntries[i].ChkNum() )
+        {
+        User::Leave( KErrBadHandle );
+        }
+    return iEntries[i];
+    }
+
+// ---------------------------------------------------------
+// CFavouritesSession::Entry
+// ---------------------------------------------------------
+//
+TFavouritesSessionEntry& CFavouritesSession::Entry
+( TFavouritesHandle aHandle )
+    {
+    TInt i = aHandle.Index();
+    if ( i > iNumEntries || aHandle.ChkNum() != iEntries[i].ChkNum() )
+        {
+        FavouritesPanic( EFavouritesInternal );
+        }
+    return iEntries[i];
+    }
+
+// ---------------------------------------------------------
+// CFavouritesSession::NextChkNum
+// ---------------------------------------------------------
+//
+TInt CFavouritesSession::NextChkNum()
+    {
+    if ( iChkNum > (1 << KChkNumBits - 1) )
+        {
+        iChkNum = 1;    // Start from 1 - we never get 0 handle.
+        }
+    return iChkNum++;
+    }
+
+// ---------------------------------------------------------
+// CFavouritesSession::NewStreamL
+// ---------------------------------------------------------
+//
+TFavouritesHandle CFavouritesSession::NewStreamL
+( MStreamBuf& aHost, const RMessage2& aMessage )
+    {
+    aHost.PushL();
+    TInt len = Min( aHost.SizeL(), KFavouritesStreamBufSize );
+    if ( len )
+        {
+        // We already have some data; send it.
+        TPckgBuf<TFavouritesBuf> buf;
+        aHost.ReadL( buf().iData, len );
+        buf().iLen = len;
+        aMessage.WriteL( 3, buf );
+        }
+    // Make a handle.
+    TFavouritesHandle h = NewHandleL();
+    TFavouritesSessionEntry& e = Entry( h );
+    // Create the stream, owner is the entry (== the session).
+    // Pass ownership to session.
+    e = *(new (ELeave) HFavouritesSrvStream( aHost ));
+    CleanupStack::Pop();    // aHost
+    return h;
+    }
+
+
+// ---------------------------------------------------------
+// CFavouritesSession::DatabaseDirL
+// ---------------------------------------------------------
+//
+void CFavouritesSession::DatabaseDirL( const TDesC& aName, TParse& aParse )
+    {
+    TDriveName cDrive = TDriveUnit( EDriveC ).Name();
+    
+    _LIT(KDbExtension, ".db");
+    
+    User::LeaveIfError( aParse.SetNoWild( aName, &cDrive, &KDbExtension() ) );
+    }
+
+    
+// ---------------------------------------------------------
+// CFavouritesSession::DeleteDirL
+// ---------------------------------------------------------
+//
+void CFavouritesSession::DeleteDirL( const TParse& aParse )
+    {
+    const TUid KDbPolicyUid = TUid::Uid(KUidFavengDbPolicy);
+
+    TPtrC path( aParse.FullName() );
+    TInt err = iDbs.DeleteDatabase( path, KDbPolicyUid );
+    
+    if ( err != KErrNone )
+        {
+        User::Leave( err );
+        }
+    }
+
+//  End of File