--- /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