--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emailservices/emailstore/message_store/server/src/MessageStoreSession.cpp Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,2849 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Message store session implementation.
+*
+*/
+
+
+
+// ========
+// INCLUDES
+// ========
+
+#include "MsgStoreTypes.h"
+#include "MsgStorePropertyKeys.h"
+
+#include "MessageStoreSession.h"
+#include "MessageStoreServer.h"
+#include "ContainerStore.h"
+#include "PropertiesSerializer.h"
+#include "ContainerStoreMRUAddressTable.h"
+#include "bufferedmessagecreator.h"
+
+
+// =========
+// CONSTANTS
+// =========
+
+// The maximum number of observer events that will be queued up for a single session.
+const TInt KMsgStoreMaximumEventQueueDepth = 100;
+const TInt KInitialAddressBufSize = 256;
+const TInt KSortedArrayGranularity = 100;
+
+const TUint KValThree = 3;
+const TUint KGranularity25 = 25;
+const TUint KGranularity15 = 15;
+
+// ======================
+// CLASS CSearchResult
+// ======================
+// ==========================================================================
+// FUNCTION: NewL
+// ==========================================================================
+CSearchResult* CSearchResult::NewL( TContainerId aMessageId, TContainerId aFolderId, const TDesC8& aPropertyBuf )
+ {
+ CSearchResult* self = new(ELeave) CSearchResult( aMessageId, aFolderId );
+ CleanupStack::PushL( self );
+ self->ConstructL( aPropertyBuf );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+CSearchResult* CSearchResult::SearchCompleteResultL()
+ {
+ return NewL( KContainerInvalidId, KContainerInvalidId, KNullDesC8 );
+ }
+
+// ==========================================================================
+// FUNCTION: Constructor
+// ==========================================================================
+CSearchResult::CSearchResult( TContainerId aMessageId, TContainerId aFolderId )
+ : iMessageId( aMessageId ), iFolderId( aFolderId )
+ {
+ }
+
+// ==========================================================================
+// FUNCTION: ConstructL
+// ==========================================================================
+void CSearchResult::ConstructL( const TDesC8& aPropertyBuf )
+ {
+ iPropertyBuf.Create( aPropertyBuf );
+ }
+
+// ==========================================================================
+// FUNCTION: Destructor
+// ==========================================================================
+CSearchResult::~CSearchResult()
+ {
+ iPropertyBuf.Close();
+ }
+
+
+// ==========================
+// CLASS CMessageStoreSession
+// ==========================
+// ==========================================================================
+// FUNCTION: Constructor
+// ==========================================================================
+CMessageStoreSession::CMessageStoreSession(CMessageStoreServer& aMessageStoreServer) :
+ iServer(aMessageStoreServer),
+ iIds( KGranularity25 ),
+ iEventQueue( KGranularity15 ),
+ iSearchHandler( NULL )
+ {
+ __LOG_CONSTRUCT( "msg", "CMessageStoreSession" )
+ }
+
+// ==========================================================================
+// FUNCTION: CreateL
+// ==========================================================================
+void CMessageStoreSession::CreateL()
+ {
+ __LOG_ENTER( "CreateL" )
+
+ iServer.AddSession( this );
+
+ // This could leave if a session is created while the store is unavailable.
+ TRAP_IGNORE( iServer.MessageStoreL().ObserveL( this ) );
+
+ __LOG_EXIT
+ } // end CreateL
+
+// ==========================================================================
+// FUNCTION: Destructor
+// ==========================================================================
+CMessageStoreSession::~CMessageStoreSession()
+ {
+ delete iBufferedMessageCreator;
+
+ iIds.Reset();
+
+ iMruAddressArray.ResetAndDestroy();
+
+ iPropertyNames.ResetAndDestroy();
+
+ iMatchMessages.ResetAndDestroy();
+
+ iSearchStrings.ResetAndDestroy();
+
+ delete iSearchHandler;
+
+ TRAP_IGNORE( iServer.MessageStoreL().StopObserving( this ) );
+
+ //close all the sort iterators when the client exits/crashes
+ for ( TInt i = 0 ; i < iSortSessionIds.Count(); i++ )
+ {
+ TRAP_IGNORE( iServer.MessageStoreL().EndSortingL( iSortSessionIds[i] ) );
+ }
+ iSortSessionIds.Close();
+
+ iEventQueue.Close();
+
+ if( !iObserverMessage.IsNull() )
+ {
+ iObserverMessage.Complete( KErrCancel );
+ } // end if
+
+ if( !iGetMatchesMessage.IsNull() )
+ {
+ iGetMatchesMessage.Complete( KErrCancel );
+ } // end if
+
+ iServer.DropSession( this );
+
+ __LOG_DESTRUCT
+ } // end destructor
+
+// ==========================================================================
+// FUNCTION:ServiceL
+// ==========================================================================
+void CMessageStoreSession::ServiceL(const RMessage2& aMessage)
+ {
+ __LOG_ENTER_SUPPRESS( "ServiceL" )
+ __LOG_WRITE8_FORMAT1_INFO( "%d", aMessage.Function() )
+
+ // Call the appropriate message handler function, based on the message function ID.
+ switch( aMessage.Function() )
+ {
+ case EMsgStoreCmdAuthenticated:
+ DoAuthenticatedL( aMessage );
+ break;
+
+ case EMsgStoreCmdAuthenticate:
+ DoAuthenticateL( aMessage );
+ break;
+
+ case EMsgStoreCmdClearAuthentication:
+ DoClearAuthenticationL( aMessage );
+ break;
+
+ case EMsgStoreCmdHasPassword:
+ DoHasPasswordL( aMessage );
+ break;
+
+ case EMsgStoreCmdSetPassword:
+ DoSetPasswordL( aMessage );
+ break;
+
+ case EMsgStoreCmdChangePassword:
+ DoChangePasswordL( aMessage );
+ break;
+
+ case EMsgStoreCmdEnableEncryption:
+ DoEnableEncryptionL( aMessage );
+ break;
+
+ case EMsgStoreCmdDisableEncryption:
+ DoDisableEncryptionL( aMessage );
+ break;
+
+ case EMsgStoreCmdWipeEverything:
+ DoWipeEverythingL( aMessage );
+ break;
+
+ case EMsgStoreCmdStartObserving:
+ DoStartObserving( aMessage );
+ break;
+
+ case EMsgStoreCmdGetEvents:
+ DoGetEventsL( aMessage );
+ break;
+
+ case EMsgStoreCmdStopObserving:
+ DoStopObserving( aMessage );
+ break;
+
+ case EMsgStoreCmdCreateAccount:
+ DoCreateAccountL( aMessage );
+ break;
+
+ case EMsgStoreCmdOpenAccount:
+ DoOpenAccountL( aMessage );
+ break;
+
+ case EMsgStoreCmdDeleteAccount:
+ DoDeleteAccountL( aMessage );
+ break;
+
+ case EMsgStoreCmdRenameAccount:
+ DoRenameAccountL( aMessage );
+ break;
+
+ case EMsgStoreCmdListAccounts:
+ DoListAccountsL( aMessage );
+ break;
+
+ case EMsgStoreCmdCreateContainer:
+ DoCreateContainerL( aMessage );
+ break;
+
+ case EMsgStoreCmdCommitContainer:
+ DoCommitContainerL( aMessage );
+ break;
+
+ case EMsgStoreCmdAbandonContainer:
+ DoAbandonContainerL( aMessage );
+ break;
+
+ case EMsgStoreCmdMoveContainer:
+ DoMoveContainerL( aMessage );
+ break;
+
+ case EMsgStoreCmdCopyContainer:
+ DoCopyContainerL( aMessage );
+ break;
+
+ case EMsgStoreCmdDeleteContainer:
+ DoDeleteContainerL( aMessage );
+ break;
+
+ case EMsgStoreCmdChildrenCounts:
+ DoChildrenCountsL( aMessage );
+ break;
+
+ case EMsgStoreCmdTotalCounts:
+ DoTotalCountsL( aMessage );
+ break;
+
+ case EMsgStoreCmdChildrenIds:
+ DoChildrenIdsL( aMessage );
+ break;
+
+ case EMsgStoreCmdPropertiesList:
+ DoPropertiesListL( aMessage );
+ break;
+
+ case EMsgStoreCmdFetchProperties:
+ DoFetchPropertiesL( aMessage );
+ break;
+
+ case EMsgStoreCmdUpdateProperties:
+ DoUpdatePropertiesL( aMessage );
+ break;
+
+ case EMsgStoreCmdUpdateProperty:
+ DoUpdatePropertyL( aMessage );
+ break;
+
+ case EMsgStoreCmdContentLength:
+ DoContentLengthL( aMessage );
+ break;
+
+ case EMsgStoreCmdFetchContentToBuffer:
+ DoFetchContentToBufferL( aMessage );
+ break;
+
+ case EMsgStoreCmdFetchContentToFile:
+ DoFetchContentToFileL( aMessage );
+ break;
+
+ case EMsgStoreCmdReplaceContentWithBuffer:
+ DoReplaceContentWithBufferL( aMessage );
+ break;
+
+ case EMsgStoreCmdReplaceContentWithFile:
+ DoReplaceContentWithFileL( aMessage );
+ break;
+
+ case EMsgStoreCmdAppendToContent:
+ DoAppendToContentL( aMessage );
+ break;
+
+ case EMsgStoreCmdPrependToContent:
+ DoPrependToContentL( aMessage );
+ break;
+
+ case EMsgStoreCmdRemoveContent:
+ DoRemoveContentL( aMessage );
+ break;
+
+ case EMsgStoreCmdOpenContentFile:
+ DoOpenContentFileL( aMessage );
+ break;
+
+ case EMsgStoreCmdPrepareSearch:
+ DoPrepareSearchL( aMessage );
+ break;
+
+ case EMsgStoreCmdGetMatches:
+ DoGetMatches( aMessage );
+ break;
+
+ case EMsgStoreCmdCancelSearch:
+ DoCancelSearch( aMessage );
+ break;
+
+ case EMsgStoreCmdClearSearchResultCache:
+ DoClearSearchResultCache( aMessage );
+ break;
+
+ case EMsgStoreCmdStartSorting:
+ DoStartSortingL( aMessage );
+ break;
+
+ case EMsgStoreCmdEndSorting:
+ DoEndSortingL( aMessage );
+ break;
+
+ case EMsgStoreCmdGetSortedRows:
+ DoGetSortedRowsL( aMessage );
+ break;
+
+ case EMsgStoreCmdGetIteratorGroupCount:
+ DoGetIteratorGroupCountL( aMessage );
+ break;
+
+ case EMsgStoreCmdGetIteratorIdsAndFlags:
+ DoGetSortedIdsAndFlagsL( aMessage );
+ break;
+
+ case EMsgStoreCmdSortedIndexOf:
+ DoGetSortedIndexOfL( aMessage );
+ break;
+
+ case EMsgStoreCmdGetIteratorIds:
+ DoGetSortedIdsL( aMessage );
+ break;
+
+ case EMsgStoreCmdGetIteratorIdsAndGroupCount:
+ DoGetSortedIdsAndGroupCountL( aMessage );
+ break;
+
+ case EMsgStoreCmdSetMaxMruAddressCount:
+ DoSetMaxMruAdressCountL( aMessage );
+ break;
+
+ case EMsgStoreCmdSetMruAddressList:
+ DoSetMruAddressListL( aMessage );
+ break;
+
+ case EMsgStoreCmdGetMruAddressList:
+ DoGetMruAddressListL( aMessage );
+ break;
+
+ case EMsgStoreCmdBeginBatchInsert:
+ DoBeginBatchInsertL( aMessage );
+ break;
+
+ case EMsgStoreCmdFinishBatchInsert:
+ DoFinishBatchInsertL( aMessage );
+ break;
+
+#ifdef _DEBUG
+
+ case EMsgStoreCmdInjectBackupRestoreEvent:
+ DoInjectBackupRestoreEventL( aMessage );
+ break;
+ case EMsgStoreCmdInjectPointSecEvent:
+ DoInjectPointSecEvent( aMessage );
+ break;
+ case EMsgStoreCmdSimulateLowDiskSpace:
+ DoSimulateLowDiskSpaceL( aMessage );
+ break;
+ case EMsgStoreCmdGetEncryptionState:
+ DoGetEncryptionStateL( aMessage );
+ break;
+ case EMsgStoreCmdShutdownServer:
+ DoShutdownServer( aMessage );
+ break;
+
+#endif
+
+ default:
+ __LOG_WRITE_ERROR( "Illegal function!" )
+ PanicClient( aMessage, EPanicIllegalFunction );
+ break;
+ } // end switch
+
+ __LOG_EXIT
+ } // end ServiceL
+
+// ==========================================================================
+// FUNCTION: ServiceError
+// ==========================================================================
+void CMessageStoreSession::ServiceError(const RMessage2& aMessage, TInt aError)
+ {
+ __LOG_ENTER_SUPPRESS( "ServiceError" )
+ __LOG_WRITE8_FORMAT1_ERROR( "ServiceError %d", aError)
+ CSession2::ServiceError( aMessage, aError );
+ } // end ServiceError
+
+// ==========================================================================
+// FUNCTION: ContainerStoreUnavailable
+// ==========================================================================
+void CMessageStoreSession::ContainerStoreUnavailable()
+ {
+ // Cancel any ongoing searches.
+ delete iSearchHandler;
+ iSearchHandler = NULL;
+ iMatchMessages.ResetAndDestroy();
+
+ TRAP_IGNORE( iServer.MessageStoreL().StopObserving( this ) );
+ } // end ContainerStoreUnavailable
+
+// ==========================================================================
+// FUNCTION: ContainerStoreAvailable
+// ==========================================================================
+void CMessageStoreSession::ContainerStoreAvailable()
+ {
+ TRAP_IGNORE( iServer.MessageStoreL().ObserveL( this ) );
+ } // end ContainerStoreAvailable
+
+// ----------------------
+// OBSERVER FUNCTIONALITY
+// ----------------------
+
+// ==========================================================================
+// FUNCTION: DoStartObserving
+// ==========================================================================
+void CMessageStoreSession::DoStartObserving( const RMessage2& aMessage )
+ {
+ iIsObserving = ETrue;
+
+ aMessage.Complete( KErrNone );
+ } // end DoStartObserving
+
+// ==========================================================================
+// FUNCTION: DoStopObserving
+// ==========================================================================
+void CMessageStoreSession::DoStopObserving( const RMessage2& aMessage )
+ {
+ iIsObserving = EFalse;
+
+ iEventQueue.Reset();
+
+ if( !iObserverMessage.IsNull() )
+ {
+ iObserverMessage.Complete( KErrCancel );
+ } // end if
+
+ aMessage.Complete( KErrNone );
+ } // end DoStopObserving
+
+// ==========================================================================
+// FUNCTION: DoCreateAccountL
+// ==========================================================================
+void CMessageStoreSession::DoCreateAccountL( const RMessage2& aMessage )
+ {
+ TInt32 ownerId = aMessage.Int1();
+
+ RBuf name;
+ CleanupClosePushL( name );
+ name.CreateL( aMessage.GetDesLengthL( 2 ) );
+
+ aMessage.ReadL( 2, name );
+
+ RBuf8 propertiesBuf;
+ CleanupClosePushL( propertiesBuf );
+ propertiesBuf.CreateL( aMessage.GetDesLengthL( KValThree ) );
+ aMessage.ReadL( KValThree, propertiesBuf );
+
+ TContainerId mbId = iServer.MessageStoreL().CreateAccountL( ownerId, name, this, propertiesBuf );
+
+ TPckg<TContainerId> mbIdPckg( mbId );
+ aMessage.WriteL( 0, mbIdPckg );
+
+ CleanupStack::PopAndDestroy( &propertiesBuf );
+ CleanupStack::PopAndDestroy( &name );
+
+ aMessage.Complete( KErrNone );
+ }
+
+// ==========================================================================
+// FUNCTION: DoOpenAccountL
+// ==========================================================================
+void CMessageStoreSession::DoOpenAccountL( const RMessage2& aMessage )
+ {
+ __LOG_ENTER_SUPPRESS("DoOpenAccountL")
+
+ //parameter 0 - result
+ TUint result;
+ TPckg<TUint> resultPckg( result );
+
+ //parameter 1 - params
+ TMsgStoreOpenAccountCmdParams params;
+ TPckg<TMsgStoreOpenAccountCmdParams> paramsPckg( params );
+ aMessage.ReadL( 1, paramsPckg );
+
+ TInt32 ownerId = params.iOwnerId;
+
+ //parameter 2 - account anme
+ RBuf name;
+ CleanupClosePushL( name );
+ name.CreateL( aMessage.GetDesLengthL( 2 ) );
+ aMessage.ReadL( 2, name );
+
+ //parameter 3 - property buf
+ RBuf8 propertiesBuf;
+ CleanupClosePushL( propertiesBuf );
+
+ params.iMailBoxId = iServer.MessageStoreL().OpenAccountL( ownerId, name, propertiesBuf );
+
+ if( propertiesBuf.Length() > aMessage.GetDesMaxLengthL( KValThree ) )
+ {
+ // Overflow!
+ __LOG_WRITE8_FORMAT1_ERROR( "property buffer too long (%i)", propertiesBuf.Length() );
+
+ // Write the required length to the result parameter, to indicate to the client that the
+ // buffer must be increased to the given size.
+ result = propertiesBuf.Length();
+ aMessage.WriteL( 0, resultPckg );
+ }
+ else
+ {
+ result = 0;
+ aMessage.WriteL( 0, resultPckg );
+
+ aMessage.WriteL( 1, paramsPckg );
+
+ aMessage.WriteL( KValThree, propertiesBuf );
+
+ } // end if
+
+ CleanupStack::PopAndDestroy( &propertiesBuf );
+ CleanupStack::PopAndDestroy( &name );
+
+ aMessage.Complete( KErrNone );
+ }
+
+// ==========================================================================
+// FUNCTION: DoRenameAccountL
+// ==========================================================================
+void CMessageStoreSession::DoRenameAccountL( const RMessage2& aMessage )
+ {
+ TInt32 ownerId = aMessage.Int0();
+
+ RBuf oldName;
+ CleanupClosePushL( oldName );
+ oldName.CreateL( aMessage.GetDesLengthL( 1 ) );
+ aMessage.ReadL( 1, oldName );
+
+ RBuf newName;
+ CleanupClosePushL( newName );
+ newName.CreateL( aMessage.GetDesLengthL( 2 ) );
+ aMessage.ReadL( 2, newName );
+
+ iServer.MessageStoreL().RenameAccountL( ownerId, oldName, newName, this );
+
+ CleanupStack::PopAndDestroy( &newName );
+ CleanupStack::PopAndDestroy( &oldName );
+
+ aMessage.Complete( KErrNone );
+ }
+
+// ==========================================================================
+// FUNCTION: DoDeleteAccountL
+// ==========================================================================
+void CMessageStoreSession::DoDeleteAccountL( const RMessage2& aMessage )
+ {
+ TInt32 ownerId = aMessage.Int0();
+
+ RBuf name;
+ CleanupClosePushL( name );
+ name.CreateL( aMessage.GetDesLengthL( 1 ) );
+ aMessage.ReadL( 1, name );
+
+ iServer.MessageStoreL().DeleteAccountL( ownerId, name, this );
+
+ CleanupStack::PopAndDestroy( &name );
+
+ aMessage.Complete( KErrNone );
+ }
+
+// ==========================================================================
+// FUNCTION: DoListAccountsL
+// ==========================================================================
+void CMessageStoreSession::DoListAccountsL( const RMessage2& aMessage )
+ {
+ RBuf8 resultBuf;
+ CleanupClosePushL( resultBuf );
+ resultBuf.CreateL( aMessage.GetDesMaxLength(0) );
+
+ iServer.MessageStoreL().ListAccountsL( resultBuf );
+
+ aMessage.WriteL( 0, resultBuf );
+
+ CleanupStack::PopAndDestroy( &resultBuf );
+
+ aMessage.Complete( KErrNone );
+ }
+
+// ==========================================================================
+// FUNCTION: DoGetEventsL
+// ==========================================================================
+void CMessageStoreSession::DoGetEventsL( const RMessage2& aMessage )
+ {
+ // If there are any queued events then send them right away, otherwise
+ // save the message until events become avaialable.
+ if( iEventQueue.Count() > 0 )
+ {
+ TUint desLength = aMessage.GetDesMaxLengthL( 0 );
+
+ TUint position = 0;
+
+ while( iEventQueue.Count() > 0 && position < desLength )
+ {
+ TPckg<TMsgStoreEvent> eventPckg( iEventQueue[0] );
+ aMessage.WriteL( 0, eventPckg, position );
+
+ position += sizeof( TMsgStoreEvent );
+ iEventQueue.Remove( 0 );
+ } // end while
+
+ aMessage.Complete( KErrNone );
+ }
+ else
+ {
+ iObserverMessage = aMessage;
+ } // end if
+
+ } // end DoGetEventsL
+
+// ==========================================================================
+// FUNCTION: SendEventToObserver
+// ==========================================================================
+void CMessageStoreSession::SendEventToObserver( TMsgStoreEvent aEvent )
+ {
+ __LOG_ENTER( "SendEventToObserver" )
+
+ // If there is no observer message pending then queue up the message,
+ // otherwise send it immediately.
+
+ if( iObserverMessage.IsNull() )
+ {
+ if( iEventQueue.Count() > KMsgStoreMaximumEventQueueDepth )
+ {
+ __LOG_WRITE_ERROR( "EVENT QUEUE OVERFLOW" );
+ iEventQueue.Reset();
+
+ TMsgStoreEvent event;
+ event.iType = EObserverEventQueueOverflow;
+ event.iId = KMsgStoreInvalidId;
+ event.iParentId = KMsgStoreInvalidId;
+ event.iOtherId = KMsgStoreInvalidId;
+ event.iFlags = KMsgStoreFlagsNotFound;
+
+ iEventQueue.Append( event );
+ }
+ else
+ {
+ __LOG_WRITE_INFO( "event queued" )
+ iEventQueue.Append( aEvent );
+ } // end if
+ }
+ else
+ {
+ __LOG_WRITE_INFO( "Sending event now" )
+
+ TPckg<TMsgStoreEvent> eventPckg( aEvent );
+
+ TRAPD( result, iObserverMessage.WriteL( 0, eventPckg ) );
+
+ iObserverMessage.Complete( result );
+ } // end if
+
+ __LOG_EXIT
+ } // end SendEventToObserver
+
+// ==========================================================================
+// FUNCTION: ContainerModified
+// ==========================================================================
+void CMessageStoreSession::ContainerModified(
+ TOperation aOperation,
+ const RArray<TContainerId>& aHierarchy,
+ TContainerId aNewParentId,
+ const TDesC8& aQuickProperties )
+ {
+ // If the children IDs array is not empty then a series of EMsgStoreCmdChildrenProperties
+ // messages are in progress, and a modified container could affect the data being streamed.
+
+ if( iIds.Count() > 0 )
+ {
+ // The following event types could affect the properties that are being streamed to the client.
+ // Reset the ID list to indicate that the streaming operation should be restarted.
+
+ if ( ( iUsingQuery ) && ( aHierarchy.Count() > 1 ) )
+ {
+ // If this is a query based list then the current change only affects the list if the
+ // query was for all types or if the type match.
+ if( (iQueryParams.iType == KContainerTypeAny) || (iQueryParams.iType == (aHierarchy[0] & KContainerTypeMask )) )
+ {
+ switch( aOperation )
+ {
+ case EAdd:
+ case EMove:
+ case EDelete:
+ case EUpdateProperties:
+
+ // The current change only affects the list if the query was recursive or
+ // if the modified container has the same parent as used in the query.
+ if( iQueryParams.iRecursive || (iQueryParams.iId == aHierarchy[1]) )
+ {
+ iIds.Reset();
+ } // end if
+ break;
+
+ } // end switch
+
+ } // end if
+ }
+ else
+ {
+ // Only deletes and property updates can affect the provided list of IDs. Adds and
+ // moves do not affect this operation.
+ switch( aOperation )
+ {
+ case EDelete:
+ case EUpdateProperties:
+
+ iIds.Reset();
+ break;
+
+ } // end switch
+
+ } // end if
+
+ } // end if
+
+ // If the client session is currently observing then create an observer event.
+
+ if( iIsObserving )
+ {
+ TMsgStoreEvent event;
+
+ switch( aOperation )
+ {
+ case EAdd:
+ event.iType = EMsgStoreAdd;
+ break;
+ case EMove:
+ event.iType = EMsgStoreMove;
+ break;
+ case EDelete:
+ event.iType = EMsgStoreDelete;
+ break;
+ case EUpdateProperties:
+ event.iType = EMsgStoreUpdateProperties;
+ break;
+ case EUpdateContent:
+ event.iType = EMsgStoreUpdateContent;
+ break;
+ case ERemoveContent:
+ event.iType = EMsgStoreRemoveContent;
+ break;
+ default:
+ // This shouldn't happen.
+ event.iType = 0;
+ break;
+ } // end switch
+
+ event.iId = aHierarchy[0];
+
+ if( aHierarchy.Count() > 1 )
+ {
+ event.iParentId = aHierarchy[1];
+ }
+ else
+ {
+ event.iParentId = KContainerInvalidId;
+ } // end if
+
+ if( aNewParentId != KContainerInvalidId )
+ {
+ // Use the new parent Id for the "other" id.
+ event.iOtherId = aNewParentId;
+ }
+ else if( aHierarchy.Count() > 2 )
+ {
+ // Use the grandparent ID for the "other" ID.
+ event.iOtherId = aHierarchy[2];
+ }
+ else
+ {
+ event.iOtherId = KContainerInvalidId;
+ } // end if
+
+ //Get the MailBoxId from the buttom of the Hierarchy
+ if ( aHierarchy.Count() > 1 )
+ {
+ event.iMailBoxId = aHierarchy[ aHierarchy.Count() - 2 ];
+ }
+ else
+ {
+ //this should not happen
+ event.iMailBoxId = KContainerInvalidId;
+ }
+
+ // Find the value of the flags property.
+
+ event.iFlags = KMsgStoreFlagsNotFound;
+ if( aQuickProperties.Length() > 0 )
+ {
+ TPropertiesDeserializer deserializer( aQuickProperties );
+
+ if( deserializer.Find( KMsgStorePropertyFlags ) && deserializer.Type() == EMsgStoreTypeUint32 )
+ {
+ TPckgBuf<TUint32> flagsPckg;
+ flagsPckg.Copy( deserializer.Value() );
+
+ event.iFlags = flagsPckg();
+ } // end if
+
+ } // end if
+
+ //initialize the names which are not used
+ event.iAccountName.SetLength( 0 );
+ event.iNewAccountName.SetLength( 0 );
+
+ SendEventToObserver( event );
+
+ } // end if
+
+ } // end ContainerModified
+
+// ==========================================================================
+// FUNCTION: AuthenticationChanged
+// ==========================================================================
+void CMessageStoreSession::AuthenticationChanged( TBool aAuthenticated )
+ {
+ if( iIsObserving )
+ {
+ TMsgStoreEvent event;
+
+ if( aAuthenticated )
+ {
+ event.iType = EMsgStoreAuthenticated;
+ }
+ else
+ {
+ event.iType = EMsgStoreNotAuthenticated;
+ } // end if
+
+ event.iMailBoxId = KMsgStoreInvalidId;
+ event.iId = KMsgStoreInvalidId;
+ event.iParentId = KMsgStoreInvalidId;
+ event.iOtherId = KMsgStoreInvalidId;
+ event.iFlags = KMsgStoreFlagsNotFound;
+
+ //initialize the names which are not used
+ event.iAccountName.SetLength( 0 );
+ event.iNewAccountName.SetLength( 0 );
+
+ SendEventToObserver( event );
+ } // end if
+
+ } // end AuthenticationChanged
+
+// ==========================================================================
+// FUNCTION: AccountModified
+// ==========================================================================
+void CMessageStoreSession::AccountModified( TOperation aOperation, TInt32 aOwnerId, const TDesC8& aName, const TDesC8& aNewName, TContainerId aMailboxId )
+ {
+ if( iIsObserving )
+ {
+ TMsgStoreEvent event;
+
+ switch( aOperation )
+ {
+ case EAdd:
+ event.iType = EMsgStoreAccountCreated;
+ break;
+ case EDelete:
+ event.iType = EMsgStoreAccountDeleted;
+ break;
+ case ERenameAccount:
+ event.iType = EMsgStoreAccountRenamed;
+ break;
+ default:
+ // This shouldn't happen.
+ event.iType = 0;
+ break;
+ } // end switch
+
+ event.iMailBoxId = aMailboxId;
+ event.iId = aOwnerId;
+ event.iParentId = KMsgStoreInvalidId;
+ event.iOtherId = KMsgStoreInvalidId;
+ event.iFlags = KMsgStoreFlagsNotFound;
+
+ //initialize the names which are not used
+ event.iAccountName.Copy( aName );
+ event.iNewAccountName.Copy( aNewName );
+
+ SendEventToObserver( event );
+ } // end if
+
+ }
+
+
+// --------------------
+// SEARCH FUNCTIONALITY
+// --------------------
+
+// ==========================================================================
+// FUNCTION: DoPrepareSearchL
+// ==========================================================================
+void CMessageStoreSession::DoPrepareSearchL( const RMessage2& aMessage )
+ {
+ //param 0 (search cmd param)
+ TMsgStoreSearchCmdParams params;
+ TPckg<TMsgStoreSearchCmdParams> paramsPckg( params );
+ aMessage.ReadL( 0, paramsPckg );
+
+ //param 1 (search string)
+ ReadString16ArrayL( aMessage, 1, iSearchStrings );
+
+ //param 2 (folder IDs)
+ ReadIdArrayL( aMessage, 2, iIds );
+
+ //param 3 (property keys)
+ // Deserialize the property names list.
+ ReadString8ArrayL( aMessage, KValThree, iPropertyNames );
+
+ iMatchMessages.ResetAndDestroy();
+
+ if ( iSearchHandler )
+ {
+ if ( iSearchHandler->IsSameSearchCriteriaL( iSearchStrings ) )
+ {
+ iSearchHandler->RestartL( params, iIds, iPropertyNames );
+ }
+ else
+ {
+ delete iSearchHandler;
+ iSearchHandler = NULL;
+ }
+ }
+
+ if ( !iSearchHandler )
+ {
+ // Create an asynchronous search handler and start it.
+ iSearchHandler = iServer.MessageStoreL().SearchL( EMsgStoreMessageBits, params, iSearchStrings, iIds, iPropertyNames, *this );
+ iSearchHandler->StartL();
+ }
+
+ aMessage.Complete( KErrNone );
+ } // end DoPrepareSearchL
+
+// ==========================================================================
+// FUNCTION: DoGetMatchesL
+// ==========================================================================
+void CMessageStoreSession::DoGetMatches( const RMessage2& aMessage )
+ {
+ // TIpcArgs( &aMatchBuffer )
+
+ iGetMatchesMessage = aMessage;
+
+ // Always send the search results if the search has completed, even if there are not results found.
+ // The end of the search is indicated by a null search handler pointer.
+ TBool searchInProgress = EFalse;
+ if ( iSearchHandler )
+ {
+ searchInProgress = iSearchHandler->IsSearchInProgress();
+ }
+
+ SendMatchesToClient( !searchInProgress );
+ }
+
+// ==========================================================================
+// FUNCTION: DoCancelSearch
+// ==========================================================================
+void CMessageStoreSession::DoCancelSearch( const RMessage2& aMessage )
+ {
+ iMatchMessages.ResetAndDestroy();
+
+ if( iSearchHandler )
+ {
+ //do not delete the search handler
+ iSearchHandler->CancelSearch();
+ } // end if
+
+ if( !iGetMatchesMessage.IsNull() )
+ {
+ iGetMatchesMessage.Complete( KErrCancel );
+ } // end if
+
+ iMatchMessages.ResetAndDestroy();
+
+ aMessage.Complete( KErrNone );
+ } // end DoCancelSearch
+
+// ==========================================================================
+// FUNCTION: DoClearSearchResultCache
+// ==========================================================================
+void CMessageStoreSession::DoClearSearchResultCache( const RMessage2& aMessage )
+ {
+ delete iSearchHandler;
+ iSearchHandler = NULL;
+
+ aMessage.Complete( KErrNone );
+ }
+
+// ==========================================================================
+// FUNCTION: MatchFound
+// ==========================================================================
+void CMessageStoreSession::MatchFound( TContainerId aMessageId, TContainerId aFolderId, const TDesC8& aPropertyBuf )
+ {
+ TRAP_IGNORE( DoMatchFoundL( aMessageId, aFolderId, aPropertyBuf ) );
+ } // end MatchFound
+
+// ==========================================================================
+// FUNCTION: DoMatchFoundL
+// ==========================================================================
+void CMessageStoreSession::DoMatchFoundL( TContainerId aMessageId, TContainerId aFolderId, const TDesC8& aPropertyBuf )
+ {
+ CSearchResult* result = CSearchResult::NewL( aMessageId, aFolderId, aPropertyBuf );
+ iMatchMessages.Append( result );
+
+ SendMatchesToClient();
+ } // end MatchFound
+
+// ==========================================================================
+// FUNCTION: SearchComplete
+// ==========================================================================
+void CMessageStoreSession::SearchComplete( TInt /*aStatus*/ )
+ {
+ //do not delete the search handler
+
+ // Always send the search results if the search has completed, even if there are not results found.
+ SendMatchesToClient( ETrue );
+ } // end SearchComplete
+
+// ==========================================================================
+// FUNCTION: SendMatchesToClientL
+// ==========================================================================
+void CMessageStoreSession::SendMatchesToClient( TBool aAlwaysSend )
+ {
+ // If there is a pending GetMatches message and either aAlwaysSend is true or matches were found
+ // then build a nuffer of matching IDs and send to the client.
+
+ if( !iGetMatchesMessage.IsNull() && (aAlwaysSend || iMatchMessages.Count() > 0 ) )
+ {
+ TRAPD( result, DoWriteMatchesToMessageL() );
+ iGetMatchesMessage.Complete( result );
+ } // end if
+
+ } // end SendMatchesToClient
+
+
+// ==========================================================================
+// FUNCTION: DoWriteMatchesToMessageL
+// ==========================================================================
+void CMessageStoreSession::DoWriteMatchesToMessageL()
+ {
+ __LOG_ENTER_SUPPRESS( "DoWriteMatchesToMessageL" )
+
+ TUint desLength = iGetMatchesMessage.GetDesMaxLengthL( 0 );
+ TUint offset = 0;
+
+ TUint fixedLength = sizeof(TContainerId)*2 + sizeof(TUint); //fixed size: 2 ids and a length
+
+ TInt msgWritten = 0;
+
+ while( iMatchMessages.Count() > 0 && offset < desLength )
+ {
+ CSearchResult* result = iMatchMessages[0];
+ TUint length = result->PropertyBuf().Length();
+ TPckgBuf<TUint> lengthPkg( length );
+
+ if ( desLength - offset >= fixedLength + length )
+ {
+ //write the message id
+ TPckgBuf<TContainerId> idPkg( result->MessageId() );
+ iGetMatchesMessage.WriteL( 0, idPkg, offset );
+ offset += sizeof( TContainerId );
+
+ //write the folder id
+ TPckgBuf<TContainerId> folderIddPkg( result->FolderId() );
+ iGetMatchesMessage.WriteL( 0, folderIddPkg, offset );
+ offset += sizeof( TContainerId );
+
+ //write the length
+ iGetMatchesMessage.WriteL( 0, lengthPkg, offset );
+ offset += sizeof( TUint );
+
+ if ( length > 0 )
+ {
+ iGetMatchesMessage.WriteL( 0, result->PropertyBuf(), offset );
+ offset += length;
+ }
+ delete result;
+ iMatchMessages.Remove( 0 );
+ msgWritten++;
+ }
+ else
+ {
+ if ( msgWritten == 0 )
+ {
+ __LOG_WRITE_ERROR("ERR: Client buffer size too small, not enough for even 1 message")
+ User::Leave( KErrOverflow );
+ }
+ break;
+ }
+ } // end while
+
+ } // end DoWriteMatchesToMessageL
+
+// -------------------------
+// MESSAGE HANDLER FUNCTIONS
+// -------------------------
+
+// ==========================================================================
+// FUNCTION: DoAuthenticatedL
+// ==========================================================================
+void CMessageStoreSession::DoAuthenticatedL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( &resultPckg )
+
+ TBool authenticated = iServer.MessageStoreL().Authenticated();
+
+ TPckg<TBool> authenticatedPckg( authenticated );
+ aMessage.WriteL( 0, authenticatedPckg );
+
+ aMessage.Complete( KErrNone );
+ } // end DoAuthenticatedL
+
+// ==========================================================================
+// FUNCTION: DoAuthenticateL
+// ==========================================================================
+void CMessageStoreSession::DoAuthenticateL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( &resultPckg, &aPassword )
+
+ RBuf password;
+ CleanupClosePushL( password );
+ password.CreateL( aMessage.GetDesLengthL( 1 ) );
+ aMessage.ReadL( 1, password );
+
+ TBool result = iServer.MessageStoreL().AuthenticateL( password );
+
+ CleanupStack::PopAndDestroy( &password );
+
+ TPckg<TBool> resultPckg( result );
+ aMessage.WriteL( 0, resultPckg );
+
+ aMessage.Complete( KErrNone );
+ } // end DoAuthenticateL
+
+// ==========================================================================
+// FUNCTION: DoClearAuthenticationL
+// ==========================================================================
+void CMessageStoreSession::DoClearAuthenticationL( const RMessage2& aMessage )
+ {
+ // No arguments
+
+ iServer.MessageStoreL().ClearAuthentication();
+
+ aMessage.Complete( KErrNone );
+ } // end DoClearAuthenticationL
+
+// ==========================================================================
+// FUNCTION: DoHasPasswordL
+// ==========================================================================
+void CMessageStoreSession::DoHasPasswordL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( &resultPckg )
+
+ TBool result = iServer.MessageStoreL().HasPasswordL();
+
+ TPckg<TBool> resultPckg( result );
+ aMessage.WriteL( 0, resultPckg );
+
+ aMessage.Complete( KErrNone );
+ } // end DoHasPasswordL
+
+// ==========================================================================
+// FUNCTION: DoSetPasswordL
+// ==========================================================================
+void CMessageStoreSession::DoSetPasswordL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( &aPassword )
+
+ RBuf password;
+ CleanupClosePushL( password );
+ password.CreateL( aMessage.GetDesLengthL( 0 ) );
+ aMessage.ReadL( 0, password );
+
+ iServer.MessageStoreL().SetPasswordL( password );
+
+ CleanupStack::PopAndDestroy( &password );
+
+ aMessage.Complete( KErrNone );
+ } // end DoSetPasswordL
+
+// ==========================================================================
+// FUNCTION: DoChangePasswordL
+// ==========================================================================
+void CMessageStoreSession::DoChangePasswordL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( &resultPckg, &aOldPassword, &aNewPassword )
+
+ RBuf oldPassword;
+ CleanupClosePushL( oldPassword );
+ oldPassword.CreateL( aMessage.GetDesLengthL( 1 ) );
+ aMessage.ReadL( 1, oldPassword );
+
+ RBuf newPassword;
+ CleanupClosePushL( newPassword );
+ newPassword.CreateL( aMessage.GetDesLengthL( 2 ) );
+ aMessage.ReadL( 2, newPassword );
+
+ TBool result = iServer.MessageStoreL().ChangePasswordL( oldPassword, newPassword );
+
+ CleanupStack::PopAndDestroy( &newPassword );
+ CleanupStack::PopAndDestroy( &oldPassword );
+
+ TPckg<TBool> resultPckg( result );
+ aMessage.WriteL( 0, resultPckg );
+
+ aMessage.Complete( KErrNone );
+ } // end DoChangePasswordL
+
+// ==========================================================================
+// FUNCTION: DoEnableEncryptionL
+// ==========================================================================
+void CMessageStoreSession::DoEnableEncryptionL( const RMessage2& aMessage )
+ {
+ iServer.MessageStoreL().EnableEncryptionL();
+
+ aMessage.Complete( KErrNone );
+ } // end DoEnableEncryptionL
+
+// ==========================================================================
+// FUNCTION: DoDisableEncryptionL
+// ==========================================================================
+void CMessageStoreSession::DoDisableEncryptionL( const RMessage2& aMessage )
+ {
+ iServer.MessageStoreL().DisableEncryptionL();
+
+ aMessage.Complete( KErrNone );
+ } // end DoDisableEncryptionL
+
+// ==========================================================================
+// FUNCTION: DoWipeEverythingL
+// ==========================================================================
+void CMessageStoreSession::DoWipeEverythingL( const RMessage2& aMessage )
+ {
+ iServer.WipeEverythingL();
+
+ aMessage.Complete( KErrNone );
+ } // end DoWipeEverythingL
+
+
+// ==========================================================================
+// FUNCTION: DoCreateContainerL
+// ==========================================================================
+void CMessageStoreSession::DoCreateContainerL( const RMessage2& aMessage )
+ {
+ __LOG_ENTER( "DoCreateContainerL" )
+
+ TMsgStoreCreateContainerCmdParams params;
+ TPckg<TMsgStoreCreateContainerCmdParams> paramsPckg( params );
+ aMessage.ReadL( 0, paramsPckg );
+
+ RBuf8 propertiesBuf;
+ CleanupClosePushL( propertiesBuf );
+ propertiesBuf.CreateL( aMessage.GetDesLengthL( 1 ) );
+ aMessage.ReadL( 1, propertiesBuf );
+
+ RFile contentFile;
+ CleanupClosePushL( contentFile );
+ if( params.iHasContent )
+ {
+ User::LeaveIfError( contentFile.AdoptFromClient( aMessage, 2, KValThree ) );
+ }
+
+ CBufferedMessageCreator& creator = GetBufferedMessageCreatorL();
+ TBool queued = creator.EnqueueL(
+ iServer.MessageStoreL(), params, propertiesBuf );
+
+ //if the operation is queued then all subsequent and related
+ //CreateContainerL calls will be queued until the message container is
+ //committed; "related" are any direct or indirect descendants of the message
+ //container.
+
+ if ( queued )
+ {
+ if( params.iHasContent )
+ {
+ TRAPD( err, creator.ReplaceContentL(
+ iServer.MessageStoreL(), params.iId, contentFile ) );
+
+ if ( KErrNone != err )
+ {
+ creator.ResetL( iServer.MessageStoreL() );
+ User::Leave( err );
+ }
+ }
+ }
+ else
+ {
+ params.iId = iServer.MessageStoreL().CreateContainerL( params.iType,
+ params.iParentId,
+ params.iGrandparentId,
+ propertiesBuf );
+
+ if( params.iHasContent )
+ {
+ TRAPD( result, iServer.MessageStoreL().ReplaceContentL( params.iId,
+ params.iParentId,
+ contentFile,
+ NULL ) );
+
+ // Abandon the entire container if the content could not be written.
+ if( result != KErrNone )
+ {
+ __LOG_WRITE_ERROR( "failed to add content" );
+ iServer.MessageStoreL().AbandonContainerL( params.iId );
+ User::Leave( result );
+ }
+ }
+
+ if ( params.iCommitContainer )
+ {
+ iServer.MessageStoreL().CommitContainerL(
+ params.iId, params.iParentId, params.iMailBoxId, this );
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &contentFile );
+ // if queued the ownership was transferred to the message creator.
+ queued ? CleanupStack::Pop( &propertiesBuf )
+ : CleanupStack::PopAndDestroy( &propertiesBuf );
+
+ aMessage.WriteL( 0, paramsPckg );
+ aMessage.Complete( KErrNone );
+
+ __LOG_EXIT
+ } // end DoCreateContainerL
+
+// ==========================================================================
+// FUNCTION: DoCommitContainerL
+// ==========================================================================
+void CMessageStoreSession::DoCommitContainerL( const RMessage2& aMessage )
+ {
+ TMsgStoreId id = aMessage.Int0();
+ TMsgStoreId destinationId = aMessage.Int1();
+ TMsgStoreId mailBoxId = aMessage.Int2();
+
+ CBufferedMessageCreator& creator = GetBufferedMessageCreatorL();
+ if ( creator.IsContainerBuffered( id ) )
+ {
+ creator.CommitMessageL( iServer.MessageStoreL(), this );
+ }
+ else
+ {
+ iServer.MessageStoreL().CommitContainerL(
+ id, destinationId, mailBoxId, this );
+ }
+
+ aMessage.Complete( KErrNone );
+ } // end DoCommitContainerL
+
+// ==========================================================================
+// FUNCTION: DoAbandonContainerL
+// ==========================================================================
+void CMessageStoreSession::DoAbandonContainerL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( aId )
+
+ TMsgStoreId id = aMessage.Int0();
+
+ CBufferedMessageCreator& creator = GetBufferedMessageCreatorL();
+ if ( creator.IsContainerBuffered( id ) )
+ {
+ creator.AbandonMessageL( iServer.MessageStoreL(), id );
+ }
+ else
+ {
+ iServer.MessageStoreL().AbandonContainerL( id );
+ }
+
+ aMessage.Complete( KErrNone );
+ } // end DoAbandonContainerL
+
+// ==========================================================================
+// FUNCTION: DoMoveContainerL
+// ==========================================================================
+void CMessageStoreSession::DoMoveContainerL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( aId, aSourceId, aDestinationId )
+
+ TMsgStoreId id = aMessage.Int0();
+
+ TMsgStoreId sourceId = aMessage.Int1();
+
+ TMsgStoreId destinationId = aMessage.Int2();
+
+ iServer.MessageStoreL().MoveContainerL( id, sourceId, destinationId, this );
+
+ aMessage.Complete( KErrNone );
+ } // end DoMoveContainerL
+
+// ==========================================================================
+// FUNCTION: DoCopyContainerL
+// ==========================================================================
+void CMessageStoreSession::DoCopyContainerL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( ¶msPckg, &idPckg )
+
+ TMsgStoreCopyContainerCmdParams params;
+ TPckg<TMsgStoreCopyContainerCmdParams> paramsPckg( params );
+ aMessage.ReadL( 0, paramsPckg );
+
+ TUint newId = iServer.MessageStoreL().CopyContainerL( params.iId,
+ params.iSourceId,
+ params.iSourceParentId,
+ params.iDestinationId,
+ params.iDestinationParentId,
+ params.iMailBoxId,
+ this );
+
+ TPckg<TMsgStoreId> newIdPckg(newId);
+ aMessage.WriteL( 1, newIdPckg );
+
+ aMessage.Complete( KErrNone );
+ } // end DoCopyContainerL
+
+// ==========================================================================
+// FUNCTION: DoFetchPropertiesL
+// ==========================================================================
+void CMessageStoreSession::DoFetchPropertiesL( const RMessage2& aMessage )
+ {
+ __LOG_ENTER( "DoFetchPropertiesL" )
+
+ // TIpcArgs( ¶ms, &parentIdPckg, &aBuffer, &resultPckg );
+
+ TMsgStoreFetchPropertiesCmdParams params;
+ TPckg<TMsgStoreFetchPropertiesCmdParams> paramsPckg( params );
+ aMessage.ReadL( 0, paramsPckg );
+
+ TMsgStoreId parentId;
+ TPckg<TMsgStoreId> parentIdPckg( parentId );
+ aMessage.ReadL( 1, parentIdPckg );
+
+ TUint result;
+ TPckg<TUint> resultPckg( result );
+
+ RBuf8 propertiesBuf;
+ CleanupClosePushL( propertiesBuf );
+
+ iServer.MessageStoreL().FetchPropertiesL( params.iId, parentId, params.iGrandparentId, propertiesBuf, params.iMailboxId );
+
+ if( propertiesBuf.Length() > aMessage.GetDesMaxLengthL( 2 ) )
+ {
+ // Overflow!
+ __LOG_WRITE8_FORMAT1_ERROR( "property buffer too long (%i)", propertiesBuf.Length() );
+
+ // Write the required length to the result parameter, to indicate to the client that the
+ // buffer must be increased to the given size.
+ result = propertiesBuf.Length();
+ aMessage.WriteL( KValThree, resultPckg );
+ }
+ else
+ {
+ aMessage.WriteL( 1, parentIdPckg );
+
+ aMessage.WriteL( 2, propertiesBuf );
+
+ result = 0;
+ aMessage.WriteL( KValThree, resultPckg );
+ } // end if
+
+ CleanupStack::PopAndDestroy( &propertiesBuf );
+
+ aMessage.Complete( KErrNone );
+
+ __LOG_EXIT
+ } // end DoFetchPropertiesL
+
+// ==========================================================================
+// FUNCTION: DoUpdatePropertiesL
+// ==========================================================================
+void CMessageStoreSession::DoUpdatePropertiesL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( aId, aParentId, properties )
+
+ TMsgStoreId id = aMessage.Int0();
+
+ TMsgStoreId parentId = aMessage.Int1();
+
+ TMsgStoreId mailBoxId = aMessage.Int2();
+
+ TInt propertiesLength = aMessage.GetDesLengthL( KValThree );
+ RBuf8 propertiesBuf;
+ CleanupClosePushL( propertiesBuf );
+ propertiesBuf.CreateL( propertiesLength );
+ aMessage.ReadL( KValThree, propertiesBuf );
+
+ iServer.MessageStoreL().UpdatePropertiesL( id, parentId, mailBoxId, propertiesBuf, this );
+
+ CleanupStack::PopAndDestroy( &propertiesBuf );
+
+ aMessage.Complete( KErrNone );
+ } // end DoUpdatePropertiesL
+
+// ==========================================================================
+// FUNCTION: DoUpdatePropertyL
+// ==========================================================================
+void CMessageStoreSession::DoUpdatePropertyL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( ¶ms, &aName, &aValue )
+
+ TMsgStoreUpdatePropertyCmdParams params;
+ TPckg<TMsgStoreUpdatePropertyCmdParams> paramsPckg( params );
+ aMessage.ReadL( 0, paramsPckg );
+
+ RBuf8 nameBuf;
+ CleanupClosePushL( nameBuf );
+ nameBuf.CreateL( aMessage.GetDesLengthL( 1 ) );
+ aMessage.ReadL( 1, nameBuf );
+
+ RBuf8 valueBuf;
+ CleanupClosePushL( valueBuf );
+ valueBuf.CreateL( aMessage.GetDesLengthL( 2 ) );
+ aMessage.ReadL( 2, valueBuf );
+
+ iServer.MessageStoreL().UpdatePropertyL( params.iId, params.iParentId, params.iMailBoxId, nameBuf, params.iType, valueBuf, this );
+
+ CleanupStack::PopAndDestroy( &valueBuf );
+ CleanupStack::PopAndDestroy( &nameBuf );
+
+ aMessage.Complete( KErrNone );
+ } // end DoUpdatePropertyL
+
+// ==========================================================================
+// FUNCTION: DoChildrenCountsL
+// ==========================================================================
+void CMessageStoreSession::DoChildrenCountsL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( aId, &counts )
+
+ TMsgStoreId id = aMessage.Int0();
+
+ RBuf8 countsBuf;
+ CleanupClosePushL( countsBuf );
+ countsBuf.CreateL( KMsgStoreCountsLength );
+
+ iServer.MessageStoreL().ChildrenCountsL( id, countsBuf );
+
+ aMessage.WriteL( 1, countsBuf );
+
+ CleanupStack::PopAndDestroy( &countsBuf );
+
+ aMessage.Complete( KErrNone );
+ } // end DoChildrenCountsL
+
+// ==========================================================================
+// FUNCTION: DoTotalCountsL
+// ==========================================================================
+void CMessageStoreSession::DoTotalCountsL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( &counts )
+
+ TMsgStoreId mailBoxId = aMessage.Int0();
+
+ RBuf8 countsBuf;
+ CleanupClosePushL( countsBuf );
+ countsBuf.CreateL( KMsgStoreCountsLength );
+
+ iServer.MessageStoreL().TotalCountsL( mailBoxId, countsBuf );
+
+ aMessage.WriteL( 1, countsBuf );
+
+ CleanupStack::PopAndDestroy( &countsBuf );
+
+ aMessage.Complete( KErrNone );
+ } // end DoTotalCountsL
+
+// ==========================================================================
+// FUNCTION: DoChildrenIdsL
+// ==========================================================================
+void CMessageStoreSession::DoChildrenIdsL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( aId, aType, &childrenDes, &resultBuf )
+
+ __LOG_ENTER( "DoChildrenIdsL" )
+
+ TMsgStoreId id = aMessage.Int0();
+
+ TMsgStoreId type = aMessage.Int1();
+
+ RArray<TMsgStoreId> childIds( KGranularity25 );
+ CleanupClosePushL( childIds );
+
+ TUint result;
+ TPckg<TUint> resultPckg( result );
+
+ iServer.MessageStoreL().ListChildrenL( childIds, id, KMsgStoreInvalidId, type );
+
+ TUint sizeNeeded = childIds.Count() * sizeof(TMsgStoreId);
+
+ if( sizeNeeded > aMessage.GetDesMaxLengthL( 2 ) )
+ {
+ // Overflow!
+ __LOG_WRITE8_FORMAT1_ERROR( "children IDs buffer too long (%i)", sizeNeeded );
+
+ // Write the required length to the result parameter, to indicate to the client that the
+ // buffer must be increased to the given size.
+ result = sizeNeeded;
+ aMessage.WriteL( KValThree, resultPckg );
+ }
+ else
+ {
+ for( TInt count = 0; count < childIds.Count(); count++ )
+ {
+ TPckg<TMsgStoreId> currentChild( childIds[count] );
+ const TUint KFour = 4;
+ aMessage.WriteL( 2, currentChild, count*KFour );
+ } // end for
+
+ result = 0;
+ aMessage.WriteL( KValThree, resultPckg );
+ } // end if
+
+ CleanupStack::PopAndDestroy( &childIds );
+
+ aMessage.Complete( KErrNone );
+
+ __LOG_EXIT
+ } // end DoChildrenIdsL
+
+// ==========================================================================
+// FUNCTION: DoPropertiesListL
+// ==========================================================================
+void CMessageStoreSession::DoPropertiesListL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( ¶msPckg, &idList, ¶mNames, &serializedBuf )
+
+ __LOG_ENTER( "DoPropertiesList" )
+
+ TMsgStorePropertiesListCmdParams params;
+ TPckg<TMsgStorePropertiesListCmdParams> paramsPckg( params );
+ aMessage.ReadL( 0, paramsPckg );
+
+ TInt position = 0;
+
+ TMsgStoreId id;
+ TPckg<TMsgStoreId> idPckg( id );
+
+ TMsgStoreId parentId;
+ TPckg<TMsgStoreId> parentIdPckg( parentId );
+
+ TUint16 length16;
+ TPckg<TUint16> length16Pckg( length16 );
+
+ TUint32 length32;
+ TPckg<TUint32> length32Pckg( length32 );
+
+ CContainerStore& messageStore = iServer.MessageStoreL();
+
+ // Suspend compaction here, to avoid suspension and resumption of compaction for each
+ // fetch properties operation.
+ messageStore.SuspendCompactionLC();
+
+ // Populate the ids and property names lists, if needed.
+
+ // params.iStartOver means that the client wants to reset the list
+ // iIds.Count == 0 means that the container store has been modified
+ if( params.iStartOver || iIds.Count() == 0 )
+ {
+ __LOG_WRITE_INFO( "Starting over" )
+
+ iIds.Reset();
+ iPropertyNames.ResetAndDestroy();
+
+ // Indicate to the client that any existing data should be cleared.
+ params.iClearExisting = ETrue;
+
+ iUsingQuery = params.iUseQuery;
+
+ if( iUsingQuery )
+ {
+ __LOG_WRITE_INFO( "querying for children" )
+
+ TPckg<TMsgStorePropertiesListQueryParams> queryParamsPckg( iQueryParams );
+
+ aMessage.ReadL( 1, queryParamsPckg );
+
+ // Get the list of children IDs whose properties are to be retrieved.
+ messageStore.ListChildrenL( iIds,
+ iQueryParams.iId,
+ iQueryParams.iParentId,
+ iQueryParams.iType,
+ iQueryParams.iRecursive );
+ }
+ else
+ {
+ __LOG_WRITE_INFO( "deserializing ID list" )
+
+ // Deserialize the ID list from the message.
+ ReadIdArrayL( aMessage, 1, iIds );
+ } // end if
+
+ __LOG_WRITE_INFO( "deserializing property names" )
+
+ // Deserialize the property names list.
+ ReadString8ArrayL( aMessage, 2, iPropertyNames );
+ }
+ else
+ {
+ // The client should not clear any properties that have already been received.
+ params.iClearExisting = EFalse;
+ } // end if
+
+ __LOG_WRITE8_FORMAT1_INFO( "iIds.Count=%i", iIds.Count() )
+
+ RBuf8 propertiesBuf;
+ CleanupClosePushL( propertiesBuf );
+
+ const TUint overhead = idPckg.Length() + parentIdPckg.Length() + length32Pckg.Length();
+ const TUint maxLength = aMessage.GetDesMaxLengthL( 3 );
+
+ TInt result;
+ TBool bufferFull = EFalse;
+
+ position = 0;
+
+ // Continue adding properties to the buffer until there are no more properties or the buffer is full.
+ while( iIds.Count() > 0 && !bufferFull )
+ {
+ propertiesBuf.SetLength( 0 );
+ id = iIds[0];
+ parentId = KMsgStoreInvalidId;
+ if( params.iUseQuery )
+ {
+ // Use the fast fetch because the ContainerModified callback will cause the query to be
+ // reissued if a potential change to a query item has been made.
+ TRAP( result, messageStore.FastFetchPropertiesL( id,
+ params.iQuickProperties,
+ parentId,
+ propertiesBuf ) );
+ }
+ else
+ {
+ // Don't want to return properties for deleted items, so don't use the fast fetch.
+ TRAP( result, messageStore.FetchPropertiesL( id,
+ parentId,
+ KMsgStoreInvalidId,
+ propertiesBuf ) );
+ } // end if
+
+ if( result == KErrNone )
+ {
+ // Filter the properties, if needed.
+ if( iPropertyNames.Count() > 0 )
+ {
+ // Remove the properties that are not needed.
+ TPropertiesSerializer serializer( propertiesBuf );
+ TBool moreProperties = serializer.First();
+ while( moreProperties )
+ {
+ TBool found = EFalse;
+ for( TInt i = 0; !found && (i < iPropertyNames.Count()); i++ )
+ {
+ found = (iPropertyNames[i]->Compare( serializer.Name() ) == 0);
+ } // end for
+ if( found )
+ {
+ moreProperties = serializer.Next();
+ }
+ else
+ {
+ moreProperties = serializer.RemovePropertyL();
+ } // end if
+ } // end while
+ } // end if
+
+ if( position + propertiesBuf.Length() + overhead > maxLength )
+ {
+ // Insufficient room in the IPC buffer for the current set of properties.
+ bufferFull = ETrue;
+ }
+ else
+ {
+ // Write the current set of properties into the IPC buffer.
+ aMessage.WriteL( KValThree, idPckg, position );
+ position += idPckg.Length();
+
+ aMessage.WriteL( KValThree, parentIdPckg, position );
+ position += parentIdPckg.Length();
+
+ length32 = propertiesBuf.Length();
+ aMessage.WriteL( KValThree, length32Pckg, position );
+ position += length32Pckg.Length();
+
+ aMessage.WriteL( KValThree, propertiesBuf, position );
+ position += length32;
+
+ iIds.Remove( 0 );
+
+ } // end if
+ }
+ else
+ {
+ __LOG_WRITE8_FORMAT1_ERROR( "failure during DoPropertiesListL %i", result );
+
+ // This entry couldn't be read for some reason. Skip past it.
+ iIds.Remove( 0 );
+
+ } // end if
+
+ } // end for
+
+ // If the current set of properties is larger than the transfer buffer then indicate to the client
+ // that a larger transfer buffer is needed.
+ params.iNewBufferSize = propertiesBuf.Length() + overhead;
+ if( params.iNewBufferSize <= maxLength )
+ {
+ __LOG_WRITE_INFO( "larger buffer needed" )
+ params.iNewBufferSize = 0;
+ } // end if
+
+ if( iIds.Count() > 0 )
+ {
+ __LOG_WRITE_INFO( "more properties" )
+
+ // Indicate that there are more properties to stream.
+ params.iMoreProperties = ETrue;
+ }
+ else
+ {
+ __LOG_WRITE_INFO( "no more properties" )
+
+ // Indicate that there are no more properties to stream.
+ params.iMoreProperties = EFalse;
+
+ // free the memory
+ iIds.Reset();
+ iPropertyNames.ResetAndDestroy();
+ } // end if
+
+ CleanupStack::PopAndDestroy( &propertiesBuf );
+
+ messageStore.ResumeCompaction();
+
+ // Write the more flag.
+ aMessage.WriteL( 0, paramsPckg );
+
+ aMessage.Complete( KErrNone );
+
+ __LOG_EXIT
+ } // end DoPropertiesListL
+
+// ==========================================================================
+// FUNCTION: DoContentLengthL
+// ==========================================================================
+void CMessageStoreSession::DoContentLengthL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( aId, aParentId, &lengthPckg )
+
+ TMsgStoreId id = aMessage.Int0();
+
+ TMsgStoreId parentId = aMessage.Int1();
+
+ TUint length = iServer.MessageStoreL().ContentLengthL( id, parentId );
+
+ TPckg<TUint> lengthPckg( length );
+ aMessage.WriteL( 2, lengthPckg );
+
+ aMessage.Complete( KErrNone );
+ } // end DoContentLengthL
+
+// ==========================================================================
+// FUNCTION: DoFetchContentToBufferL
+// ==========================================================================
+void CMessageStoreSession::DoFetchContentToBufferL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( aId, aParentId, &aBuffer, aStartOffset )
+
+ TMsgStoreId id = aMessage.Int0();
+
+ TMsgStoreId parentId = aMessage.Int1();
+
+ RBuf8 contentBuf;
+ CleanupClosePushL( contentBuf );
+ contentBuf.CreateL( aMessage.GetDesMaxLengthL( 2 ) );
+
+ TMsgStoreId startOffset = aMessage.Int3();
+
+ iServer.MessageStoreL().FetchContentL( id, parentId, contentBuf, startOffset );
+
+ aMessage.WriteL( 2, contentBuf );
+
+ CleanupStack::PopAndDestroy( &contentBuf );
+
+ aMessage.Complete( KErrNone );
+ } // end DoFetchContentToBufferL
+
+// ==========================================================================
+// FUNCTION: DoFetchContentToFileL
+// ==========================================================================
+void CMessageStoreSession::DoFetchContentToFileL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( aId, aParentId, fs, file )
+
+ TMsgStoreId id = aMessage.Int0();
+
+ TMsgStoreId parentId = aMessage.Int1();
+
+ RFile file;
+ User::LeaveIfError( file.AdoptFromClient( aMessage, 2, KValThree ) );
+ CleanupClosePushL( file );
+
+ iServer.MessageStoreL().FetchContentL( id, parentId, file );
+
+ CleanupStack::PopAndDestroy( &file );
+
+ aMessage.Complete( KErrNone );
+ } // end DoFetchContentToFileL
+
+// ==========================================================================
+// FUNCTION: DoReplaceContentWithBufferL
+// ==========================================================================
+void CMessageStoreSession::DoReplaceContentWithBufferL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( aId, aParentId, &aBuffer )
+
+ TMsgStoreId id = aMessage.Int0();
+
+ TMsgStoreId parentId = aMessage.Int1();
+
+ RBuf8 contentBuf;
+ CleanupClosePushL( contentBuf );
+ contentBuf.CreateL( aMessage.GetDesLengthL( 2 ) );
+ aMessage.ReadL( 2, contentBuf );
+
+ CBufferedMessageCreator& creator = GetBufferedMessageCreatorL();
+ if ( creator.IsContainerBuffered( id ) )
+ {
+ creator.ReplaceContentL(
+ iServer.MessageStoreL(), id, contentBuf );
+ }
+ else
+ {
+ iServer.MessageStoreL().ReplaceContentL(
+ id, parentId, contentBuf, this );
+ }
+
+ CleanupStack::PopAndDestroy( &contentBuf );
+
+ aMessage.Complete( KErrNone );
+ } // end DoReplaceContentWithBufferL
+
+// ==========================================================================
+// FUNCTION: DoReplaceContentWithFileL
+// ==========================================================================
+void CMessageStoreSession::DoReplaceContentWithFileL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( aId, aParentId, fs, file )
+
+ TMsgStoreId id = aMessage.Int0();
+
+ TMsgStoreId parentId = aMessage.Int1();
+
+ RFile file;
+ User::LeaveIfError( file.AdoptFromClient( aMessage, 2, KValThree ) );
+ CleanupClosePushL( file );
+
+ CBufferedMessageCreator& creator = GetBufferedMessageCreatorL();
+ if ( creator.IsContainerBuffered( id ) )
+ {
+ creator.ReplaceContentL(
+ iServer.MessageStoreL(), id, file );
+ }
+ else
+ {
+ iServer.MessageStoreL().ReplaceContentL( id, parentId, file, this );
+ }
+
+ CleanupStack::PopAndDestroy( &file );
+
+ aMessage.Complete( KErrNone );
+ } // end DoReplaceContentWithFileL
+
+// ==========================================================================
+// FUNCTION: DoAppendToContentL
+// ==========================================================================
+void CMessageStoreSession::DoAppendToContentL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( aId, aParentId, &aContent )
+
+ TMsgStoreId id = aMessage.Int0();
+
+ TMsgStoreId parentId = aMessage.Int1();
+
+ RBuf8 contentBuf;
+ CleanupClosePushL( contentBuf );
+ contentBuf.CreateL( aMessage.GetDesLengthL( 2 ) );
+ aMessage.ReadL( 2, contentBuf );
+
+ CBufferedMessageCreator& creator = GetBufferedMessageCreatorL();
+ if ( creator.IsContainerBuffered( id ) )
+ {
+ creator.AppendContentL(
+ iServer.MessageStoreL(), id, contentBuf );
+ }
+ else
+ {
+ iServer.MessageStoreL().AppendContentL( id, parentId, contentBuf, this );
+ }
+
+ CleanupStack::PopAndDestroy( &contentBuf );
+
+ aMessage.Complete( KErrNone );
+ } // end DoAppendToContentL
+
+// ==========================================================================
+// FUNCTION: DoPrependToContentL
+// ==========================================================================
+void CMessageStoreSession::DoPrependToContentL( const RMessage2& aMessage )
+ {
+ TMsgStoreId id = aMessage.Int0();
+ TMsgStoreId parentId = aMessage.Int1();
+
+ RBuf8 contentBuf;
+ CleanupClosePushL( contentBuf );
+ contentBuf.CreateL( aMessage.GetDesLengthL( 2 ) );
+ aMessage.ReadL( 2, contentBuf );
+
+ CBufferedMessageCreator& creator = GetBufferedMessageCreatorL();
+ if ( creator.IsContainerBuffered( id ) )
+ {
+ creator.PrependContentL(
+ iServer.MessageStoreL(), id, contentBuf );
+ }
+ else
+ {
+ iServer.MessageStoreL().PrependContentL(
+ id, parentId, contentBuf, this );
+ }
+
+ CleanupStack::PopAndDestroy( &contentBuf );
+ aMessage.Complete( KErrNone );
+ }
+
+// ==========================================================================
+// FUNCTION: DoRemoveContentL
+// ==========================================================================
+void CMessageStoreSession::DoRemoveContentL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( aId, aParentId )
+
+ TMsgStoreId id = aMessage.Int0();
+
+ TMsgStoreId parentId = aMessage.Int1();
+
+ iServer.MessageStoreL().RemoveContentL( id, parentId, this );
+
+ aMessage.Complete( KErrNone );
+ } // end DoRemoveContentL
+
+
+// ==========================================================================
+// FUNCTION: DoOpenContentFile
+// ==========================================================================
+void CMessageStoreSession::DoOpenContentFileL( const RMessage2& aMessage )
+ {
+ TMsgStoreId id = aMessage.Int0();
+ TMsgStoreId parentId = aMessage.Int1();
+
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+ CleanupClosePushL(fs); //+fs
+
+ User::LeaveIfError(fs.ShareProtected());
+
+ RFile file;
+ CleanupClosePushL( file ); //+file
+
+ iServer.MessageStoreL().OpenContentFileL( id, parentId, fs, file );
+
+ // transfer to client: store the RFile handle into the package buffer in slot 2
+ // and complete the message with the RFs handle
+ // This assumes that if TransferToClient() return an error, then
+ // the standard CServer2::RunError() will complete the message
+ User::LeaveIfError( file.TransferToClient(aMessage, 2) );
+
+ CleanupStack::PopAndDestroy( &file );
+ CleanupStack::PopAndDestroy( &fs );
+ }
+
+// ==========================================================================
+// FUNCTION: DoDeleteContainerL
+// ==========================================================================
+void CMessageStoreSession::DoDeleteContainerL( const RMessage2& aMessage )
+ {
+ // TIpcArgs( aId, aParentId, aGrandparentId )
+
+ TMsgStoreId id = aMessage.Int0();
+
+ TMsgStoreId parentId = aMessage.Int1();
+
+ TMsgStoreId grandparentId = aMessage.Int2();
+
+ TMsgStoreId mailBoxId = aMessage.Int3();
+
+ iServer.MessageStoreL().DeleteContainerL( id, parentId, grandparentId, mailBoxId, this );
+
+ aMessage.Complete( KErrNone );
+ } // end DoDeleteContainerL
+
+
+// -------------------------
+// SORTING HANDLER FUNCTIONS
+// -------------------------
+// ==========================================================================
+// FUNCTION: DoStartSortingL
+// ==========================================================================
+void CMessageStoreSession::DoStartSortingL( const RMessage2& aMessage )
+ {
+ __LOG_ENTER( "DoStartSortingL" )
+
+ TMsgStoreSortCriteria sortCriteria;
+ TPckg<TMsgStoreSortCriteria> paramsPckg( sortCriteria );
+ aMessage.ReadL( 1, paramsPckg );
+
+ TUint16 length16;
+ TPckg<TUint16> length16Pckg( length16 );
+
+ // Deserialize the property names list.
+ ReadString8ArrayL( aMessage, 2, iPropertyNames );
+
+ //parameter 3
+ TBool inMemorySort = aMessage.Int3();
+
+ TContainerId sessionId = iServer.MessageStoreL().StartSortingL( sortCriteria, iPropertyNames, inMemorySort );
+ iSortSessionIds.Append( sessionId );
+
+ TPckg<TContainerId> sessionIdPckg( sessionId );
+ aMessage.WriteL( 0, sessionIdPckg );
+
+ aMessage.Complete( KErrNone );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: DoEndSortingL
+// ==========================================================================
+void CMessageStoreSession::DoEndSortingL( const RMessage2& aMessage )
+ {
+ __LOG_ENTER( "DoEndSortingL" )
+
+ TMsgStoreId sessionId = aMessage.Int0();
+
+ iServer.MessageStoreL().EndSortingL( sessionId );
+
+ TInt index = iSortSessionIds.Find( sessionId );
+ if ( index != KErrNotFound )
+ {
+ iSortSessionIds.Remove( index );
+ }
+
+ aMessage.Complete( KErrNone );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: GetSortedRowsL
+// ==========================================================================
+void CMessageStoreSession::DoGetSortedRowsL( const RMessage2& aMessage )
+ {
+ __LOG_ENTER( "DoGetSortedRowsL" )
+
+ //param 0
+ TUint result;
+ TPckg<TUint> resultPckg( result );
+
+ //param 1
+ TMsgStoreGetSortedRowsCmdParams params;
+ TPckg<TMsgStoreGetSortedRowsCmdParams> paramsPckg( params );
+ aMessage.ReadL( 1, paramsPckg );
+
+ //param 2
+ RBuf8 propertiesBuf;
+ CleanupClosePushL( propertiesBuf );
+
+ //param 3
+ TBool hasMore;
+ if ( params.iHasStartWith )
+ {
+ RBuf startWith;
+ CleanupClosePushL( startWith );
+
+ startWith.CreateL( aMessage.GetDesLengthL( KValThree ) );
+ aMessage.ReadL( KValThree, startWith );
+
+ hasMore = iServer.MessageStoreL().GetSortedRowsL( params, propertiesBuf, startWith );
+ CleanupStack::PopAndDestroy( &startWith );
+ }
+ else
+ {
+ hasMore = iServer.MessageStoreL().GetSortedRowsL( params, propertiesBuf );
+ }
+ params.iHasMoreRows = hasMore;
+
+ if( propertiesBuf.Length() > aMessage.GetDesMaxLengthL( 2 ) )
+ {
+ // Overflow!
+ __LOG_WRITE8_FORMAT1_ERROR( "property buffer too long (%i)", propertiesBuf.Length() );
+
+ // Write the required length to the result parameter, to indicate to the client that the
+ // buffer must be increased to the given size.
+ result = propertiesBuf.Length();
+ aMessage.WriteL( 0, resultPckg );
+ }
+ else
+ {
+ result = 0;
+ aMessage.WriteL( 0, resultPckg );
+ aMessage.WriteL( 1, paramsPckg );
+ aMessage.WriteL( 2, propertiesBuf );
+ } // end if
+
+ CleanupStack::PopAndDestroy( &propertiesBuf );
+
+ aMessage.Complete( KErrNone );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: DoGetIteratorGroupCountL
+// ==========================================================================
+void CMessageStoreSession::DoGetIteratorGroupCountL( const RMessage2& aMessage )
+ {
+ __LOG_ENTER("DoGetIteratorGroupCountL")
+
+ //param 0
+ TMsgStoreId sessionId = aMessage.Int0();
+
+ //param 1
+ TInt count;
+ TPckg<TInt> resultPckg( count );
+
+ RArray<TUint> itemsInGroup;
+ CleanupClosePushL( itemsInGroup );
+
+ count = iServer.MessageStoreL().IteratorGroupCountL( sessionId, itemsInGroup );
+ aMessage.WriteL( 1, resultPckg );
+
+ TUint items;
+ TPckg<TUint> itemsPkg( items );
+ TInt position = 0;
+
+ for ( TInt i = 0; i < count; i++ )
+ {
+ items = itemsInGroup[i];
+ aMessage.WriteL( 2, itemsPkg, position );
+ position += itemsPkg.Length();
+ }
+
+ CleanupStack::PopAndDestroy( &itemsInGroup );
+
+ aMessage.Complete( KErrNone );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: DoGetSortedIdsAndFlagsL
+// ==========================================================================
+void CMessageStoreSession::DoGetSortedIdsAndFlagsL( const RMessage2& aMessage )
+ {
+ __LOG_ENTER("DoGetSortedIdsAndFlags")
+
+ //param 0
+ TMsgStoreId sessionId = aMessage.Int0();
+
+ //param 1
+ TInt count;
+ TPckg<TInt> countPckg( count );
+
+ RArray<TContainerId> idArray( KSortedArrayGranularity );
+ CleanupClosePushL( idArray );
+
+ RArray<TUint32> flagArray ( KSortedArrayGranularity );
+ CleanupClosePushL( flagArray );
+
+ iServer.MessageStoreL().SortedIdsAndFlagsL( sessionId, idArray, flagArray );
+ if ( idArray.Count() != flagArray.Count() )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ count = idArray.Count();
+ aMessage.WriteL( 1, countPckg );
+
+ TContainerId id;
+ TPckg<TContainerId> idPkg( id );
+
+ TUint32 flag;
+ TPckg<TUint32> flagPkg( flag );
+
+ TInt position = 0;
+
+ for ( TInt i = 0; i < count; i++ )
+ {
+ id = idArray[i];
+ aMessage.WriteL( 2, idPkg, position );
+ position += idPkg.Length();
+
+ flag = flagArray[i];
+ aMessage.WriteL( 2, flagPkg, position );
+ position += flagPkg.Length();
+ }
+
+ CleanupStack::PopAndDestroy( &flagArray );
+ CleanupStack::PopAndDestroy( &idArray );
+
+ aMessage.Complete( KErrNone );
+
+ __LOG_EXIT
+ }
+
+
+// ==========================================================================
+// FUNCTION: DoGetSortedIndexOfL
+// ==========================================================================
+void CMessageStoreSession::DoGetSortedIndexOfL( const RMessage2& aMessage )
+ {
+ __LOG_ENTER("DoGetSortedIndexOfL")
+
+ //param 0
+ TContainerId sessionId = aMessage.Int0();
+
+ //param 1
+ TContainerId messageId = aMessage.Int1();
+
+ //param 2
+ TInt index;
+ TPckg<TInt> indexPckg( index );
+
+ index = iServer.MessageStoreL().SortedIndexOfL( sessionId, messageId );
+
+ aMessage.WriteL( 2, indexPckg );
+
+ aMessage.Complete( KErrNone );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: DoGetSortedIdsL
+// ==========================================================================
+void CMessageStoreSession::DoGetSortedIdsL( const RMessage2& aMessage )
+ {
+ __LOG_ENTER("DoGetSortedIdsL")
+
+ //param 0
+ TMsgStoreId sessionId = aMessage.Int0();
+
+ //param 1
+ TInt count;
+ TPckg<TInt> countPckg( count );
+
+ RArray<TContainerId> idArray( KSortedArrayGranularity );
+ CleanupClosePushL( idArray );
+
+ iServer.MessageStoreL().SortedIdsL( sessionId, idArray );
+ count = idArray.Count();
+ aMessage.WriteL( 1, countPckg );
+
+ TContainerId id;
+ TPckg<TContainerId> idPkg( id );
+
+ TInt position = 0;
+
+ for ( TInt i = 0; i < count; i++ )
+ {
+ id = idArray[i];
+ aMessage.WriteL( 2, idPkg, position );
+ position += idPkg.Length();
+ }
+
+ CleanupStack::PopAndDestroy( &idArray );
+
+ aMessage.Complete( KErrNone );
+
+ __LOG_EXIT
+ }
+
+
+// ==========================================================================
+// FUNCTION: DoGetSortedIdsAndGroupCountL
+// ==========================================================================
+void CMessageStoreSession::DoGetSortedIdsAndGroupCountL( const RMessage2& aMessage )
+ {
+ __LOG_ENTER("DoGetSortedIdsAndGroupCountL")
+
+ //param 0
+ TMsgStoreId sessionId = aMessage.Int0();
+
+ //param 1
+ TInt idCount;
+ TPckg<TInt> idCountPckg( idCount );
+
+ //param 2
+ TInt groupCount;
+ TPckg<TInt> groupCountPckg( groupCount );
+
+ RArray<TContainerId> idArray( KSortedArrayGranularity );
+ CleanupClosePushL( idArray );
+
+ RArray<TUint> itemsInGroup;
+ CleanupClosePushL( itemsInGroup );
+
+ iServer.MessageStoreL().SortedIdsAndGroupCountL( sessionId, idArray, itemsInGroup );
+
+ idCount = idArray.Count();
+ aMessage.WriteL( 1, idCountPckg );
+
+ groupCount = itemsInGroup.Count();
+ aMessage.WriteL( 2, groupCountPckg );
+
+ TContainerId id;
+ TPckg<TContainerId> idPkg( id );
+
+ TInt position = 0;
+
+ for ( TInt i = 0; i < idCount; i++ )
+ {
+ id = idArray[i];
+ aMessage.WriteL( KValThree, idPkg, position );
+ position += idPkg.Length();
+ }
+
+ TUint items;
+ TPckg<TUint> itemsPkg( items );
+
+ for ( TInt i = 0 ; i < groupCount ; i++ )
+ {
+ items = itemsInGroup[i];
+ aMessage.WriteL( KValThree, itemsPkg, position );
+ position += itemsPkg.Length();
+ }
+
+ CleanupStack::PopAndDestroy( &itemsInGroup );
+ CleanupStack::PopAndDestroy( &idArray );
+
+ aMessage.Complete( KErrNone );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: DoSetMaxMruAdressCountL
+// ==========================================================================
+void CMessageStoreSession::DoSetMaxMruAdressCountL( const RMessage2& aMessage )
+ {
+ __LOG_ENTER("DoSetMaxMruAdressCountL")
+
+ TInt maxCount = aMessage.Int0();
+
+ iServer.MessageStoreL().SetMaxMruCountL( maxCount );
+
+ aMessage.Complete( KErrNone );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: DoSetMruAddressListL
+// ==========================================================================
+void CMessageStoreSession::DoSetMruAddressListL( const RMessage2& aMessage )
+ {
+ __LOG_ENTER("DoSetMruAddressListL")
+
+ TMsgStoreId mailboxId = aMessage.Int0();
+
+ iMruAddressArray.ResetAndDestroy();
+
+ //read the address array
+ TInt bufSize = aMessage.GetDesLengthL( 1 );
+
+ TUint16 length16;
+ TPckg<TUint16> length16Pckg( length16 );
+
+ RBuf8 addressBuf;
+ CleanupClosePushL( addressBuf );
+ addressBuf.Create( KInitialAddressBufSize );
+
+ RBuf8 dispNameBuf;
+ CleanupClosePushL( dispNameBuf );
+ dispNameBuf.Create( KInitialAddressBufSize );
+
+ TInt position = 0;
+ while( position < bufSize )
+ {
+ //read the email address
+ aMessage.ReadL( 1, length16Pckg, position );
+ position += length16Pckg.Length();
+
+ if ( addressBuf.MaxLength() < length16 )
+ {
+ addressBuf.ReAlloc( length16 );
+ }
+ aMessage.ReadL( 1, addressBuf, position );
+
+ //now read convert the 8 bit descriptor to 16 descriptor
+ const TUint16* addressPtr = reinterpret_cast<const TUint16*>( addressBuf.Ptr() );
+ TPtrC addressDes( addressPtr, length16 / 2 );
+
+ position += length16;
+
+ //read the display name
+ aMessage.ReadL( 1, length16Pckg, position );
+ position += length16Pckg.Length();
+
+ if ( dispNameBuf.MaxLength() < length16 )
+ {
+ dispNameBuf.ReAlloc( length16 );
+ }
+ aMessage.ReadL( 1, dispNameBuf, position );
+
+ //now read convert the 8 bit descriptor to 16 descriptor
+ const TUint16* dispNamePtr = reinterpret_cast<const TUint16*>( dispNameBuf.Ptr() );
+ TPtrC dispNameDes( dispNamePtr, length16 / 2 );
+
+ position += length16;
+
+ CMruAddress* mruAddress = CMruAddress::NewL(0, addressDes, dispNameDes );
+
+ iMruAddressArray.Append( mruAddress );
+
+ } // end while
+
+ iServer.MessageStoreL().SetMruAddressListL( mailboxId, iMruAddressArray );
+
+ CleanupStack::PopAndDestroy( &dispNameBuf );
+ CleanupStack::PopAndDestroy( &addressBuf );
+
+ iMruAddressArray.ResetAndDestroy();
+
+ aMessage.Complete( KErrNone );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: DoGetMruAddressListL
+// ==========================================================================
+void CMessageStoreSession::DoGetMruAddressListL( const RMessage2& aMessage )
+ {
+ __LOG_ENTER("DoGetMruAddressListL")
+
+ TUint result;
+ TPckg<TUint> resultPckg( result );
+
+ TMsgStoreId mailboxId = aMessage.Int0();
+
+ const RPointerArray<CMruAddress> addressArray = iServer.MessageStoreL().MruAddressListL( mailboxId );
+
+ TUint16 length16;
+ TPckg<TUint16> length16Pckg( length16 );
+
+ //Find out the size
+ TInt totalSize = 0;
+ TInt count = addressArray.Count();
+ TInt sizeOfLengthFields = sizeof( TUint16 ) * 2; //two lengths
+ for ( TInt i = 0 ; i < count ; i++ )
+ {
+ totalSize += sizeOfLengthFields;
+ CMruAddress* address = addressArray[i];
+ totalSize += (address->EmailAddress().Length() * 2);
+ totalSize += (address->DisplayName().Length() * 2);
+ }
+
+ //now check if the client buffer is big enough
+ if ( totalSize > aMessage.GetDesMaxLengthL( 2 ) )
+ {
+ // Overflow!
+ __LOG_WRITE8_FORMAT1_ERROR( "Mru buffer too long (%i)", totalSize );
+
+ // Write the required length to the result parameter, to indicate to the client that the
+ // buffer must be increased to the given size.
+ result = static_cast<TUint>(totalSize);
+ aMessage.WriteL( 1, resultPckg );
+ }
+ else
+ {
+ //now serialize it to the buffer
+ TUint position = 0;
+
+ for ( TInt i = 0 ; i < count ; i++ )
+ {
+ CMruAddress* address = addressArray[i];
+
+ //write the email address
+ //write the length and update the cursor
+ length16 = address->EmailAddress().Length() * 2 ;
+ aMessage.Write( 2, length16Pckg, position );
+ position += length16Pckg.Length();
+
+ //convert the 16 bit descriptor to 8 bit descriptor
+ const TUint8* addressPtr = reinterpret_cast<const TUint8*>( address->EmailAddress().Ptr() );
+ TPtrC8 addressDes( addressPtr, length16 );
+
+ //write it and update the cursor
+ aMessage.Write( 2, addressDes, position );
+ position += length16;
+
+ //write the displayName
+ //write the length and update the cursor
+ length16 = address->DisplayName().Length() * 2 ;
+ aMessage.Write( 2, length16Pckg, position );
+ position += length16Pckg.Length();
+
+ //convert the 16 bit descriptor to 8 bit descriptor
+ const TUint8* namePtr = reinterpret_cast<const TUint8*>( address->DisplayName().Ptr() );
+ TPtrC8 nameDes( namePtr, length16 );
+
+ //write it and update the cursor
+ aMessage.Write( 2, nameDes, position );
+ position += length16;
+ }
+
+ result = 0;
+ aMessage.WriteL( 1, resultPckg );
+ }
+
+ aMessage.Complete( KErrNone );
+
+ __LOG_EXIT
+ }
+
+/**
+ *
+ */
+void CMessageStoreSession::DoBeginBatchInsertL( const RMessage2& aMessage )
+ {
+ CBufferedMessageCreator& creator = GetBufferedMessageCreatorL();
+ creator.BeginBatchInsertL( iServer.MessageStoreL() );
+
+ aMessage.Complete( KErrNone );
+ }
+
+/**
+ *
+ */
+void CMessageStoreSession::DoFinishBatchInsertL( const RMessage2& aMessage )
+ {
+ CBufferedMessageCreator& creator = GetBufferedMessageCreatorL();
+ creator.FinishBatchInsertL( iServer.MessageStoreL(), this );
+
+ aMessage.Complete( KErrNone );
+ }
+
+// ==========================================================================
+// FUNCTION: ReadString8ArrayL
+// ==========================================================================
+void CMessageStoreSession::ReadString8ArrayL( const RMessage2& aMessage, TInt aIndex, RPointerArray<HBufC8>& aArray )
+ {
+ TUint16 length16;
+ TPckg<TUint16> length16Pckg( length16 );
+
+ // Deserialize the property names list.
+ aArray.ResetAndDestroy();
+
+ TInt position = 0;
+ while( position < aMessage.GetDesLengthL( aIndex ) )
+ {
+ aMessage.ReadL( aIndex, length16Pckg, position );
+ position += length16Pckg.Length();
+
+ HBufC8* buf8 = HBufC8::NewL( length16 );
+ aArray.Append( buf8 );
+ TPtr8 buf8Ptr( buf8->Des() );
+ aMessage.ReadL( aIndex, buf8Ptr, position );
+ buf8->Des().SetLength( length16 );
+ position += length16;
+ } // end while
+ }
+
+// ==========================================================================
+// FUNCTION: ReadString16ArrayL
+// ==========================================================================
+void CMessageStoreSession::ReadString16ArrayL( const RMessage2& aMessage, TInt aIndex, RPointerArray<HBufC>& aArray )
+ {
+ TUint16 length16;
+ TPckg<TUint16> length16Pckg( length16 );
+
+ // Deserialize the property names list.
+ aArray.ResetAndDestroy();
+
+ RBuf8 readBuf;
+ CleanupClosePushL( readBuf );
+
+ TInt position = 0;
+ while( position < aMessage.GetDesLengthL( aIndex ) )
+ {
+ aMessage.ReadL( aIndex, length16Pckg, position );
+ position += length16Pckg.Length();
+
+ if ( readBuf.MaxLength() < length16 )
+ {
+ readBuf.ReAlloc( length16 );
+ }
+ aMessage.ReadL( aIndex, readBuf, position );
+
+ //now read convert the 8 bit descriptor to 16 descriptor
+ const TUint16* valuePtr = reinterpret_cast<const TUint16*>( readBuf.Ptr() );
+ TPtrC valueDes( valuePtr, length16 / 2 );
+
+ aArray.Append( valueDes.AllocL() );
+
+ position += length16;
+ } // end while
+
+ CleanupStack::PopAndDestroy( &readBuf );
+ }
+
+// ==========================================================================
+// FUNCTION: ReadIdArrayL
+// ==========================================================================
+void CMessageStoreSession::ReadIdArrayL( const RMessage2& aMessage, TInt aIndex, RArray<TContainerId>& aArray )
+ {
+ TMsgStoreId id;
+ TPckg<TMsgStoreId> idPckg( id );
+ TInt position = 0;
+
+ aArray.Reset();
+ for( position = 0; position < aMessage.GetDesLengthL( aIndex ); position += idPckg.Length() )
+ {
+ aMessage.ReadL( aIndex, idPckg, position );
+ aArray.Append( id );
+ } // end for
+ }
+
+/**
+ *
+ */
+/*private*/
+CBufferedMessageCreator& CMessageStoreSession::GetBufferedMessageCreatorL()
+ {
+ if ( NULL == iBufferedMessageCreator )
+ {
+ iBufferedMessageCreator = CBufferedMessageCreator::NewL(
+ iServer.MessageStoreL() );
+ }
+
+ return *iBufferedMessageCreator;
+ }
+
+// FUNCTIONS TO SUPPORT AUTOMATED UNIT TESTING
+#ifdef _DEBUG
+
+void CMessageStoreSession::DoInjectBackupRestoreEventL( const RMessage2& aMessage )
+ {
+ // parameter 1 contains the event to inject
+ TUint event = aMessage.Int0();
+ iServer.InjectBackupRestoreEventL( event );
+ aMessage.Complete( KErrNone );
+ }
+
+void CMessageStoreSession::DoInjectPointSecEvent( const RMessage2& aMessage )
+ {
+ // parameter 1 contains the event to inject
+ TUint event = aMessage.Int0();
+ iServer.InjectPointSecEvent( event );
+ aMessage.Complete( KErrNone );
+ }
+
+void CMessageStoreSession::DoSimulateLowDiskSpaceL( const RMessage2& aMessage )
+ {
+ // parameter 1 contains the number of calls to delay before indicating low disk space.
+ TUint latency = aMessage.Int0();
+ iServer.MessageStoreL().SimulateLowDiskSpace( latency );
+ aMessage.Complete( KErrNone );
+ }
+
+void CMessageStoreSession::DoGetEncryptionStateL( const RMessage2& aMessage )
+ {
+ TInt state = iServer.MessageStoreL().GetEncryptionStateL();
+
+ TPckg<TInt> statePckg( state );
+ aMessage.WriteL( 0, statePckg );
+
+ aMessage.Complete( KErrNone );
+ }
+
+void CMessageStoreSession::DoShutdownServer( const RMessage2& aMessage )
+ {
+ aMessage.Complete( KErrNone );
+ iServer.Shutdown();
+ }
+
+#endif