menucontentsrv/srvsrc/menusrvsession.cpp
changeset 0 79c6a41cd166
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/menucontentsrv/srvsrc/menusrvsession.cpp	Thu Dec 17 08:54:17 2009 +0200
@@ -0,0 +1,731 @@
+/*
+* Copyright (c) 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:
+*
+*/
+#include "menusrvsession.h"
+#include "menusrvstream.h"
+#include "menusrvoperation.h"
+#include "menusrvobjectfilter.h"
+#include "mcsmenunotifier.h" // for the notifier events
+#include "menusrvnotifier.h"
+#include "menusrvbuf.h"
+#include "menumsg.h"
+#include "menusrvdef.h"
+#include "mcsmenuitem.h"
+#include "mcsmenufilter.h"
+#include "menuutil.h"
+#include "menueng.h"
+#include "menusrveng.h"
+#include "menuengobject.h"
+#include <s32buf.h>
+#include <s32strm.h>
+
+
+const TInt KParamIndAttrName = 1;
+const TInt KParamIndAttrEx = 2;
+const TInt KParamIndAttrVal = 3;
+const TInt KParamIndBuf = 2;
+const TInt KParamIndStream = 3;
+const TInt KParamIndOp = 3;
+const TInt KParamIndNotif = 3;
+
+const TInt KGetListDescriptorPos = 0;
+const TInt KGetListReturnPos = 1;
+
+//const TInt KIconSize = 74;
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CMenuSrvSession::~CMenuSrvSession
+// ---------------------------------------------------------
+//
+CMenuSrvSession::~CMenuSrvSession()
+    {
+    delete iNotifierIx;
+    delete iStreamIx;
+    delete iOperationIx;
+    iMenuSrv.RemoveContainer( iObjectCon );
+    if ( iSharedEng )
+        {
+        iSharedEng->RemoveSession( this ); // Ownership release.
+        }
+    }
+
+// ---------------------------------------------------------
+// CMenuSrvSession::NewL
+// ---------------------------------------------------------
+//
+CMenuSrvSession* CMenuSrvSession::NewL( CMenuSrv& aMenuSrv )
+    {
+    CMenuSrvSession* sess = new (ELeave) CMenuSrvSession( aMenuSrv );
+    CleanupStack::PushL( sess );
+    sess->ConstructL();
+    CleanupStack::Pop( sess );
+    return sess;
+    }
+
+// ---------------------------------------------------------
+// CMenuSrvSession::CMenuSrvSession
+// ---------------------------------------------------------
+//
+CMenuSrvSession::CMenuSrvSession( CMenuSrv& aMenuSrv )
+: iMenuSrv( aMenuSrv )
+    {
+    }
+
+// ---------------------------------------------------------
+// CMenuSrvSession::ConstructL
+// ---------------------------------------------------------
+//
+void CMenuSrvSession::ConstructL()
+    {
+    iObjectCon = iMenuSrv.NewContainerL();
+    iNotifierIx = CObjectIx::NewL();
+    iStreamIx = CObjectIx::NewL();
+    iOperationIx = CObjectIx::NewL();
+    }
+
+// ---------------------------------------------------------
+// CMenuSrvSession::CountResources
+// ---------------------------------------------------------
+//
+TInt CMenuSrvSession::CountResources()
+    {
+    return iObjectCon->Count();
+    }
+
+// ---------------------------------------------------------
+// CMenuSrvSession::ServiceL
+// ---------------------------------------------------------
+//
+void CMenuSrvSession::ServiceL( const RMessage2& aMessage )
+    {
+    if( !ServiceCapabilityTestL( aMessage ) )
+    	{
+        // The rest of the functions does not work with a dead engine.
+        if ( iEngineDead )
+            {
+            User::Leave( KErrDisconnected );
+            }
+        
+        if( !ServiceCapReadL( aMessage ) )
+        	{
+        	if( !ServiceCapWriteL( aMessage) )
+        		{
+    			//Function was not serviced
+        		aMessage.Complete( KErrNotSupported ); // Sync request -> complete it now.
+        		}
+        	}
+    	}
+    }
+
+// ---------------------------------------------------------
+// CMenuSrvSession::ServiceCapabilityTestL
+// Handles functions with test capability
+// ---------------------------------------------------------
+//
+TBool CMenuSrvSession::ServiceCapabilityTestL( const RMessage2& aMessage )
+	{
+	// These debug functions work even with a dead engine.
+	TBool serviced = ETrue;
+	switch( aMessage.Function() )
+	    {
+	    case EMenuResourceMarkStart:
+	        {
+	        ResourceCountMarkStart();
+	        aMessage.Complete( KErrNone );
+	        break;
+	        }
+	
+	    case EMenuResourceMarkEnd:
+	        {
+	        ResourceCountMarkEnd( aMessage );
+	        aMessage.Complete( KErrNone );
+	        break;
+	        }
+	
+	    case EMenuResourceCount:
+	        {
+	        aMessage.Complete( CountResources() );
+	        break;
+	        }
+	
+	    case EMenuSetHeapFailure:
+	        {
+	        User::__DbgSetAllocFail
+	            (
+	            RAllocator::EUser,
+	            STATIC_CAST( RAllocator::TAllocFail, aMessage.Int0() ),
+	            aMessage.Int1()
+	            );
+	        aMessage.Complete( KErrNone );
+	        break;
+	        }
+	
+	    default:
+	        {
+	        // Not a debug function.
+	        serviced = EFalse;
+	        break;
+	        }
+	    }
+	return serviced;
+	}
+
+// ---------------------------------------------------------
+// CMenuSrvSession::ServiceCapReadWriteL
+// Handles functions with read device data capability
+// ---------------------------------------------------------
+//
+TBool CMenuSrvSession::ServiceCapReadL( const RMessage2& aMessage )
+	{
+	TBool serviced = ETrue;
+	switch( aMessage.Function() )
+        {
+		case EMenuConstructSession:
+            {
+            __ASSERT_ALWAYS( !iSharedEng, PanicClientL( aMessage ) );
+            RBuf name;
+            name.CreateL( aMessage.GetDesLengthL( 0 ) );
+            CleanupClosePushL( name );
+            aMessage.ReadL( 0, name );
+            // Get the shared engine and open it.
+            CMenuSrvEng* sharedEng = iMenuSrv.GetEngineL( name );
+            CleanupClosePushL( *sharedEng );
+            sharedEng->AddSessionL( this ); // Ownership transfer.
+            // No leaving after this point.
+            CleanupStack::Pop( sharedEng );
+            iSharedEng = sharedEng;
+            CleanupStack::PopAndDestroy( &name );
+            break;
+            };
+
+        case EMenuRootFolder:
+            {
+            __ASSERT_ALWAYS( iSharedEng, PanicClientL( aMessage ) );
+            TPckgBuf<TInt> root;
+            TInt id;
+            iSharedEng->Engine().RootFolderL( id );
+            root() = id;
+            aMessage.WriteL( 0, root );
+            break;
+            }
+
+        case EMenuStreamClose:
+            {
+            TInt handle = aMessage.Int3();
+            StreamL( handle ); // Check that handle is valid.
+            iStreamIx->Remove( handle );
+            break;
+            };
+
+        case EMenuStreamOpen:
+            {
+            NewStreamL( *(HMenuSrvBuf::NewL()), aMessage );
+            break;
+            }
+
+        case EMenuStreamRead:
+            {
+            TInt handle = aMessage.Int3();
+            TInt len;
+            StreamL( handle ).ReadL( aMessage, len );
+            break;
+            }
+
+        case EMenuStreamWrite:
+            {
+            TInt handle = aMessage.Int3();
+            StreamL( handle ).WriteL( aMessage );
+            break;
+            }
+
+        case EMenuGetHdr:
+            {
+            __ASSERT_ALWAYS( iSharedEng, PanicClientL( aMessage ) );
+            TInt id = aMessage.Int0();
+            TPckgBuf<TMenuItem> hdr;
+            iSharedEng->Engine().GetItemL( id, hdr() );
+            aMessage.WriteL( 1, hdr );
+            break;
+            }
+
+        case EMenuGetItems:
+            {
+            __ASSERT_ALWAYS( iSharedEng, PanicClientL( aMessage ) );
+            HMenuSrvBuf* streamBuf = HMenuSrvBuf::NewLC();
+            RWriteStream stream( streamBuf );
+            TInt folder = aMessage.Int0();
+            TBool recursive = aMessage.Int1();
+            RArray<TMenuItem> items;
+            CleanupClosePushL( items );
+            iSharedEng->Engine().GetItemsL( items, folder, NULL, recursive );
+            MenuUtil::ExternalizeL( items, stream );
+            stream.CommitL();
+            CleanupStack::PopAndDestroy( &items );
+            CleanupStack::Pop( streamBuf );
+            NewStreamL( *(stream.Sink()), aMessage );
+            break;
+            }
+
+        case EMenuGetRunningApps:
+            {
+            __ASSERT_ALWAYS( iSharedEng, PanicClientL( aMessage ) );
+            HMenuSrvBuf* streamBuf = HMenuSrvBuf::NewLC();
+            RWriteStream stream( streamBuf );
+            RArray<TUid> items;
+            CleanupClosePushL( items );
+            iSharedEng->GetRunningAppsL( items );
+            MenuUtil::ExternalizeL( items, stream );
+            stream.CommitL();
+            CleanupStack::PopAndDestroy( &items );
+            CleanupStack::Pop( streamBuf );
+            NewStreamL( *(stream.Sink()), aMessage );
+            break;
+            }            
+            
+        case EMenuGetItemsFiltered:
+            {
+            __ASSERT_ALWAYS( iSharedEng, PanicClientL( aMessage ) );
+            TInt folder = aMessage.Int0();
+            TBool recursive = aMessage.Int1();
+            TInt bufHandle = aMessage.Int2();
+            RArray<TMenuItem> items;
+            CleanupClosePushL( items );
+            MStreamBuf& buf = StreamL( bufHandle ).Host();
+            RReadStream rs( &buf );
+            CMenuFilter* filter = CMenuFilter::NewLC();
+            filter->InternalizeL( rs );
+            TMenuSrvObjectFilter engFilter( *filter );
+            iSharedEng->Engine().GetItemsL
+                ( items, folder, &engFilter, recursive );
+            CleanupStack::PopAndDestroy( filter );
+            RWriteStream stream( &buf );
+            MenuUtil::ExternalizeL( items, stream );
+            stream.CommitL();
+            CleanupStack::PopAndDestroy( &items );
+            break;
+            }
+            
+        case EMenuGetListSize:
+            {
+            __ASSERT_ALWAYS( iSharedEng, PanicClientL( aMessage ) );
+            TInt deslen = aMessage.GetDesLength( KGetListDescriptorPos );
+            HBufC8* buffer = HBufC8::NewLC( deslen );
+            TPtr8 tempDes = buffer->Des( );
+            aMessage.Read( KGetListDescriptorPos, tempDes );
+            TInt size = iSharedEng->GetListSizeL( *buffer );
+            TPckg<TInt> sizeDes( size );
+            aMessage.WriteL( KGetListReturnPos, sizeDes );
+            CleanupStack::PopAndDestroy( buffer );
+            break;
+            }   
+
+        case EMenuGetListData:
+            {
+            __ASSERT_ALWAYS( iSharedEng, PanicClientL( aMessage ) );
+            aMessage.WriteL( KGetListDescriptorPos, 
+            		iSharedEng->GetListDataL() );
+            iSharedEng->CloseOutputBuffer();
+            break;
+            }              
+                        
+            
+        case EMenuItemGetAttribute:
+            {
+            __ASSERT_ALWAYS( iSharedEng, PanicClientL( aMessage ) );
+            TInt id = aMessage.Int0();
+            RBuf name;
+            name.CreateL( aMessage.GetDesLengthL( KParamIndAttrName ) );
+            CleanupClosePushL( name );
+            aMessage.ReadL( KParamIndAttrName, name );
+            TPckgBuf<TBool> attrExistsBuf;
+            TBool attrExists(EFalse);
+        	RBuf attrVal;
+        	attrVal.CleanupClosePushL();
+        	attrVal.CreateL(KMenuMaxAttrValueLen);
+        	iSharedEng->GetAttributeL( id, name, attrExists, attrVal);
+            attrExistsBuf() = attrExists;
+            aMessage.WriteL( KParamIndAttrEx, attrExistsBuf );
+            
+            if ( attrExists )
+                {
+                aMessage.WriteL( KParamIndAttrVal, attrVal );
+                }
+        	CleanupStack::PopAndDestroy( &attrVal );
+            CleanupStack::PopAndDestroy( &name );
+            break;
+            }
+            
+        case EMenuItemGetAttributeList:
+            {
+            __ASSERT_ALWAYS( iSharedEng, PanicClientL( aMessage ) );
+            TInt id = aMessage.Int0();
+            TInt bufHandle = aMessage.Int2();
+            HMenuSrvBuf* streamBuf = HMenuSrvBuf::NewLC();
+            RWriteStream ws( streamBuf );
+            RArray<TPtrC> attributeList;
+        	CleanupClosePushL(attributeList);
+            
+            iSharedEng->GetAttributeListL( id, attributeList );
+
+            for ( TInt ndx = 0; ndx < attributeList.Count(); ndx++ )
+                {
+                TPtrC name;
+                name.Set( attributeList[ndx] );
+                ws.WriteInt32L( name.Length() );
+                ws.WriteL( name );
+                }
+            ws.WriteInt32L( 0 );
+            ws.CommitL();
+
+        	CleanupStack::PopAndDestroy(&attributeList);
+            CleanupStack::Pop( streamBuf );
+            NewStreamL( *(ws.Sink()), aMessage );
+
+            break;
+            }
+
+        case EMenuNotifierClose:
+            {
+            TInt handle = aMessage.Int3();
+            NotifierL( handle ); // Check that handle is valid.
+            iNotifierIx->Remove( handle );
+            break;
+            };
+
+        case EMenuNotifierOpen:
+            {
+            NewNotifierL( aMessage );
+            break;
+            }
+
+        case EMenuNotifierNotify:
+            {
+            TInt handle = aMessage.Int3();
+            CMenuSrvNotifier& notifier( NotifierL( handle ) );
+            notifier.NotifyL( aMessage.Int0(), aMessage.Int1(), aMessage );
+            // No leaving after this point!
+            return ETrue; // Async request -> the object will complete it.
+            }
+
+        case EMenuNotifierNotifyCancel:
+            {
+            TInt handle = aMessage.Int3();
+            NotifierL( handle ).Cancel();
+            break;
+            }
+            
+	    default:
+	        {
+	        serviced = EFalse;
+	        break;
+	        }
+        }
+	if( serviced )
+		{
+		aMessage.Complete( KErrNone );// Sync request -> complete it now.
+		}
+	return serviced;
+	}
+
+// ---------------------------------------------------------
+// CMenuSrvSession::ServiceCapWriteL
+// Handles functions with write device data capability
+// ---------------------------------------------------------
+//
+TBool CMenuSrvSession::ServiceCapWriteL( const RMessage2& aMessage )
+	{
+	TBool serviced = ETrue;
+	switch( aMessage.Function() )
+        {
+        case EMenuOperationClose:
+            {
+            TInt handle = aMessage.Int3();
+            OperationL( handle ); // Check that handle is valid.
+            iOperationIx->Remove( handle );
+            break;
+            };
+
+        case EMenuOperationCreateRemove:
+            {
+            __ASSERT_ALWAYS( iSharedEng, PanicClientL( aMessage ) );
+            CMenuSrvOperation* op = new (ELeave) CMenuSrvRemoveOperation
+                ( iSharedEng->Engine(), aMessage.Int0() );
+            AddOperationL( op, aMessage ); // Ownership taken before adding.
+            break;
+            }
+
+        case EMenuOperationCreateMoveToFolder:
+            {
+            __ASSERT_ALWAYS( iSharedEng, PanicClientL( aMessage ) );
+            TInt bufHandle = aMessage.Int0();
+            MStreamBuf& buf = StreamL( bufHandle ).Host();
+            RReadStream rs( &buf );
+            CMenuSrvOperation* op = CMenuSrvMoveToFolderOperation::NewL
+                ( iSharedEng->Engine(), rs, aMessage.Int1(), aMessage.Int2() );
+            AddOperationL( op, aMessage ); // Ownership taken before adding.
+            break;
+            }
+
+        case EMenuOperationCreateReorder:
+            {
+            __ASSERT_ALWAYS( iSharedEng, PanicClientL( aMessage ) );
+            CMenuSrvOperation* op = new (ELeave) CMenuSrvReorderOperation
+                ( iSharedEng->Engine(), aMessage.Int0(), aMessage.Int1() );
+            AddOperationL( op, aMessage ); // Ownership taken before adding.
+            break;
+            }
+
+        case EMenuOperationCreateAdd:
+            {
+            __ASSERT_ALWAYS( iSharedEng, PanicClientL( aMessage ) );
+            TBuf<KMenuMaxTypeLen> type;
+            __ASSERT_ALWAYS( aMessage.GetDesLength( 0 ) <= type.MaxLength(), \
+                User::Leave( KErrBadDescriptor ) ); // Panic the client.
+            aMessage.ReadL( 0, type );
+            TInt bufHandle = aMessage.Int1();
+            MStreamBuf& buf = StreamL( bufHandle ).Host();
+            RReadStream rs( &buf );
+            CMenuSrvAddOperation* op = CMenuSrvAddOperation::NewL
+                ( iSharedEng->Engine(), type, rs );
+            CleanupStack::PushL( op ); // Leaving calls before AddOperationL.
+            // Send the ID back. Object not yet added to engine!
+            TPckgBuf<TInt> id;
+            id() = op->ObjectId();
+            __ASSERT_DEBUG( id(), User::Invariant() ); // We must have the ID already!
+            aMessage.WriteL( 2, id );
+            CleanupStack::Pop( op );
+            AddOperationL( op, aMessage ); // Ownership taken before adding.
+            break;
+            }
+
+        case EMenuOperationCreateUpdate:
+            {
+            __ASSERT_ALWAYS( iSharedEng, PanicClientL( aMessage ) );
+            TInt bufHandle = aMessage.Int1();
+            MStreamBuf& buf = StreamL( bufHandle ).Host();
+            RReadStream rs( &buf );
+            CMenuSrvOperation* op = CMenuSrvUpdateOperation::NewL
+                ( iSharedEng->Engine(), aMessage.Int0(), rs );
+            AddOperationL( op, aMessage ); // Ownership taken before adding.
+            break;
+            }
+
+        case EMenuOperationCancel:
+            {
+            TInt handle = aMessage.Int3();
+            OperationL( handle ).Cancel();
+            break;
+            }
+
+        case EMenuOperationStart:
+            {
+            TInt handle = aMessage.Int3();
+            OperationL( handle ).StartL( aMessage );
+            // No leaving after this point!
+            return ETrue; // Async request -> the object will complete it.
+            }
+        default:
+            {
+            serviced = EFalse;
+            break;
+            }
+        }
+	if( serviced )
+		{
+		aMessage.Complete( KErrNone );// Sync request -> complete it now.
+		}
+	return serviced;
+	}
+
+// ---------------------------------------------------------
+// CMenuSrvSession::ServiceError
+// ---------------------------------------------------------
+//
+void CMenuSrvSession::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 )
+        {
+        aMessage.Panic( KMenuSrvName, aError );
+        }
+    if ( aError == KErrNoMemory )
+    	{
+    	iSharedEng->CloseOutputBuffer();
+    	iSharedEng->CleanAttributeCache();
+    	}
+    CSession2::ServiceError( aMessage, aError );
+    }
+
+// ---------------------------------------------------------
+// CMenuSrvSession::EngineEvents
+// ---------------------------------------------------------
+//
+void CMenuSrvSession::EngineEvents( TInt aFolder, TInt aEvents )
+    {
+    for ( TInt i = 0; i < iNotifierIx->Count(); i++ )
+        {
+        CMenuSrvNotifier* notif = (CMenuSrvNotifier*)(*iNotifierIx)[i];
+        notif->HandleEvents( aFolder, aEvents );
+        }
+    }
+
+// ---------------------------------------------------------
+// CMenuSrvSession::EngineError
+// ---------------------------------------------------------
+//
+void CMenuSrvSession::EngineError( TInt /*aErr*/ )
+    {
+    // Unrecoverable engine error. The engine is dead and will be deleted.
+    // This session has already been removed from the shared engine's list.
+    // This session became useless now; it rejects all messages and is
+    // waiting to be closed.
+    iSharedEng = NULL;
+    iEngineDead = ETrue;
+    }
+// ---------------------------------------------------------
+// CMenuSrvSession::NewStreamL
+// ---------------------------------------------------------
+//
+void CMenuSrvSession::NewStreamL
+( MStreamBuf& aHost, const RMessage2& aMessage )
+    {
+    aHost.PushL();
+    TInt len = Min( aHost.SizeL(), KMenuStreamBufSize );
+    if ( len )
+        {
+        // We already have some data; send it.
+        TPckgBuf<TMenuBuf> buf;
+        aHost.ReadL( buf().iData, len );
+        buf().iLen = len;
+        aMessage.WriteL( KParamIndBuf, buf );
+        }
+    // Create the stream, it takes ownership of aHost.
+    CMenuSrvStream* obj = new (ELeave) CMenuSrvStream( aHost );
+    CleanupStack::Pop( &aHost );
+    CleanupStack::PushL( obj );
+    iObjectCon->AddL( obj );
+    TInt handle = iStreamIx->AddL( obj );
+    CleanupStack::Pop( obj ); // Now we manage the stream by handle.
+    TPckgC<TInt> handlePckg( handle );
+    TInt err = aMessage.Write( KParamIndStream, handlePckg );
+    if ( err )
+        {
+        iStreamIx->Remove( handle );
+        User::Leave( err );
+        }
+    }
+
+// ---------------------------------------------------------
+// CMenuSrvSession::StreamL
+// ---------------------------------------------------------
+//
+CMenuSrvStream& CMenuSrvSession::StreamL( TInt aHandle )
+    {
+    CMenuSrvStream* obj = (CMenuSrvStream*)iStreamIx->AtL( aHandle );
+    if ( !obj )
+        {
+        User::Leave( KErrBadHandle );
+        }
+    return *obj;
+    }
+
+// ---------------------------------------------------------
+// CMenuSrvSession::AddOperationL
+// ---------------------------------------------------------
+//
+void CMenuSrvSession::AddOperationL
+( CMenuSrvOperation* aOperation, const RMessage2& aMessage )
+    {
+    CleanupStack::PushL( aOperation );
+    iObjectCon->AddL( aOperation );
+    TInt handle = iOperationIx->AddL( aOperation );
+    CleanupStack::Pop( aOperation ); // Now we manage the operation by handle.
+    TPckgC<TInt> handlePckg( handle );
+    TInt err = aMessage.Write( KParamIndOp, handlePckg );
+    if ( err )
+        {
+        iOperationIx->Remove( handle ); // Deletes the operation.
+        User::Leave( err );
+        }
+    }
+
+// ---------------------------------------------------------
+// CMenuSrvSession::OperationL
+// ---------------------------------------------------------
+//
+CMenuSrvOperation& CMenuSrvSession::OperationL( TInt aHandle )
+    {
+    CMenuSrvOperation* obj = (CMenuSrvOperation*)iOperationIx->AtL( aHandle );
+    if ( !obj )
+        {
+        User::Leave( KErrBadHandle );
+        }
+    return *obj;
+    }
+
+// ---------------------------------------------------------
+// CMenuSrvSession::NewNotifierL
+// ---------------------------------------------------------
+//
+void CMenuSrvSession::NewNotifierL( const RMessage2& aMessage )
+    {
+    CMenuSrvNotifier* obj = new (ELeave) CMenuSrvNotifier;
+    CleanupStack::PushL( obj );
+    iObjectCon->AddL( obj );
+    TInt handle = iNotifierIx->AddL( obj );
+    CleanupStack::Pop( obj ); // Now we manage the notifier by handle.
+    TPckgC<TInt> handlePckg( handle );
+    TInt err = aMessage.Write( KParamIndNotif, handlePckg );
+    if ( err )
+        {
+        iNotifierIx->Remove( handle );
+        User::Leave( err );
+        }
+    }
+
+// ---------------------------------------------------------
+// CMenuSrvSession::NotifierL
+// ---------------------------------------------------------
+//
+CMenuSrvNotifier& CMenuSrvSession::NotifierL( TInt aHandle )
+    {
+    CMenuSrvNotifier* obj = (CMenuSrvNotifier*)iNotifierIx->AtL( aHandle );
+    if ( !obj )
+        {
+        User::Leave( KErrBadHandle );
+        }
+    return *obj;
+    }
+
+// ---------------------------------------------------------
+// CMenuSrvSession::PanicClientL
+// ---------------------------------------------------------
+//
+void CMenuSrvSession::PanicClientL( const RMessage2& aMessage )
+    {
+    // Client error. Panic client and leave.
+    // Use an error code (KErrGeneral) which does not cause ServiceError
+    // to panic the client again!
+    aMessage.Panic( KMenuSrvName, KErrGeneral );
+    User::Leave( KErrGeneral );
+    }
+
+//  End of File