--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emailservices/emailstore/message_store/client/src/RMessageStoreSession.cpp Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,1827 @@
+/*
+* 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 client implementation.
+*
+*/
+
+
+
+// ========
+// INCLUDES
+// ========
+
+#include <s32mem.h> // for descriptor read/write streams
+#include <f32file.h>
+
+#include "RMessageStoreSession.h"
+
+#include "EmailStoreUids.hrh"
+#include "MessageStoreClientServer.h"
+#include "RMessageStoreSession.h"
+//<cmail>
+#include "MsgStoreAccount.h"
+#include "AccountsSerializer.h"
+#include "MsgStoreSortCriteria.h"
+#include "MsgStoreSearchCriteria.h"
+#include "MsgStoreAddress.h"
+//</cmail>
+
+// =========
+// CONSTANTS
+// =========
+
+const TUint KInitialChildrenIdsTransferBufferLength = 5000;
+const TUint KInitialPropertiesTransferBufferLength = 10000;
+const TUint KInitialPropertiesListTransferBufferLength = 15000;
+const TUint KInitialAccountsTransferBufferLength = 10000; //shoud be more than enouth
+const TUint KInitialSortedListTransferBufferLength = 30000;
+const TUint KInitialSortedIdsAndFlagsBufferLength = 65536; //shoud be more than enouth
+
+// This will try to connect to the server for a maximum of 20 seconds.
+const TUint KMaxServerConnectRetries = 20;
+const TUint KServerRetryIntervalMicroSeconds = 1000000;
+
+const TUint KNumSlots = 3;
+
+const TUint KIpcArgsIndex2 = 2;
+const TUint KIpcArgsIndex3 = 3;
+
+// ======================
+// METHOD IMPLEMENTATIONS
+// ======================
+
+// ==========================================================================
+// FUNCTION: Constructor
+// ==========================================================================
+RMessageStoreSession::RMessageStoreSession()
+ {
+ __LOG_CONSTRUCT( "MsgClient", "RMessageStoreSession" )
+ } // end constructor
+
+// ==========================================================================
+// FUNCTION: Destructor
+// ==========================================================================
+RMessageStoreSession::~RMessageStoreSession()
+ {
+ __LOG_DESTRUCT
+ } // end destructor
+
+// ==========================================================================
+// FUNCTION: Connect
+// ==========================================================================
+TInt RMessageStoreSession::Connect( TBool aLaunchServerIfNeeded, TBool aRetryIndefinitely )
+ {
+ __LOG_ENTER( "Connect" )
+
+ // This flag should only be used in the case where the message store server is being launched as a separate
+ // thread within some other process. In that case, the flag is used to control exactly which process the
+ // server will be launched in. Otherwise, always launch the server on reference.
+ aLaunchServerIfNeeded = ETrue;
+
+ TBool again = ETrue;
+ TInt returnValue;
+ TInt retry = KMaxServerConnectRetries;
+
+ while( again )
+ {
+ returnValue = CreateSession( KMsgStoreServerName, TVersion(KMsgStoreMajorVersion, KMsgStoreMinorVersion, KMsgStoreBuild), KNumSlots );
+
+ if( returnValue == KErrNone )
+ {
+ // No need to retry.
+ again = EFalse;
+ }
+ else
+ {
+ __LOG_WRITE8_FORMAT1_ERROR( "CreateSession failed %i", returnValue )
+
+ if( !aRetryIndefinitely )
+ {
+ retry--;
+ } // end if
+
+ if( retry == 0 )
+ {
+ // Do not retry again.
+ again = EFalse;
+ }
+ else if( (returnValue == KErrNotFound) && aLaunchServerIfNeeded )
+ {
+ // Start the server as a thread within the current process.
+ returnValue = StartServer();
+ }
+ else
+ {
+ __LOG_WRITE_ERROR( "waiting between retries" )
+
+ // Wait before trying again.
+ User::After( KServerRetryIntervalMicroSeconds );
+
+ } // end if
+
+ } // end if
+
+ } // end if
+
+ __LOG_WRITE8_FORMAT1_DEBUG3( "returnValue=%i", returnValue )
+ __LOG_EXIT
+ return returnValue;
+
+ } // end Connect
+
+// ==========================================================================
+// FUNCTION: StartServer
+// ==========================================================================
+TInt RMessageStoreSession::StartServer()
+ {
+ __LOG_ENTER( "StartServer" )
+
+ TInt err = KErrNone;
+
+ // Launch the server executable (i.e. in it its own process).
+ __LOG_WRITE_INFO( "Launching server process" )
+
+ // Create a new server process. Simultaneous launching of two such processes
+ // should be detected when the second one attempts to create the server
+ // object, failing with KErrAlreadyExists.
+ _LIT( KMsgStoreExeName, "MessageStoreExe" );
+ RProcess server;
+ err = server.Create( KMsgStoreExeName, KNullDesC );
+
+ if( err == KErrNone )
+ {
+ TRequestStatus stat;
+ server.Rendezvous( stat );
+
+ if( stat != KRequestPending )
+ {
+ server.Kill( 0 ); // abort startup
+ }
+ else
+ {
+ server.Resume(); // logon OK - start the server thread
+ } // end if
+
+ __LOG_WRITE_INFO( "Started" )
+ User::WaitForRequest( stat ); // wait for start or death
+
+ __LOG_WRITE8_FORMAT1_INFO( "stat.Int(() = %i", stat.Int() );
+ __LOG_WRITE8_FORMAT1_INFO( "ExitReason() = %i", server.ExitReason() );
+
+ TExitCategoryName exitCategory;
+ exitCategory = server.ExitCategory();
+ __LOG_WRITE_FORMAT1_INFO( "ExitCategory() = %S", &exitCategory );
+
+ // we can't use the 'exit reason' if the server panicked as this
+ // is the panic 'reason' and may be '0' which cannot be distinguished
+ // from KErrNone
+ err = ( server.ExitType() == EExitPanic ) ? KErrGeneral : stat.Int();
+ server.Close();
+ }
+ else
+ {
+ __LOG_WRITE8_FORMAT1_ERROR( "failed to launch server, err=%i", err )
+ } // end if
+
+ __LOG_WRITE8_FORMAT1_DEBUG3( "err=%i", err )
+ __LOG_EXIT
+ return err;
+
+ } // end StartServer
+
+// ==========================================================================
+// FUNCTION: Close
+// ==========================================================================
+void RMessageStoreSession::Close()
+ {
+ __LOG_ENTER( "Close" )
+
+ RSessionBase::Close(); //basecall
+
+ __LOG_EXIT
+ } // end Close
+
+// ==========================================================================
+// FUNCTION: EnableEncryptionL
+// ==========================================================================
+void RMessageStoreSession::EnableEncryptionL()
+ {
+ __LOG_ENTER( "EnableEncryptionL" )
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdEnableEncryption ) );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: DisableEncryptionL
+// ==========================================================================
+void RMessageStoreSession::DisableEncryptionL()
+ {
+ __LOG_ENTER( "DisableEncryptionL" )
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdDisableEncryption ) );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: AuthenticatedL
+// ==========================================================================
+TBool RMessageStoreSession::AuthenticatedL()
+ {
+ __LOG_ENTER( "AuthenticatedL" )
+
+ TPckgBuf<TBool> resultPckg( EFalse );
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdAuthenticated, TIpcArgs( &resultPckg ) ) );
+
+ __LOG_WRITE8_FORMAT1_DEBUG3( "result=%i", resultPckg() )
+ __LOG_EXIT
+
+ return resultPckg();
+
+ } // end AuthenticatedL
+
+// ==========================================================================
+// FUNCTION: AuthenticateL
+// ==========================================================================
+TBool RMessageStoreSession::AuthenticateL( const TDesC& aPassword )
+ {
+ __LOG_ENTER( "AuthenticateL" )
+
+ TPckgBuf<TBool> resultPckg( EFalse );
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdAuthenticate, TIpcArgs( &resultPckg, &aPassword ) ) );
+
+ __LOG_WRITE8_FORMAT1_DEBUG3( "result=%i", resultPckg() )
+ __LOG_EXIT
+
+ return resultPckg();
+
+ } // end AuthenticateL
+
+// ==========================================================================
+// FUNCTION: ClearAuthenticationL
+// ==========================================================================
+void RMessageStoreSession::ClearAuthenticationL()
+ {
+ __LOG_ENTER( "ClearAuthenticationL" )
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdClearAuthentication ) );
+
+ __LOG_EXIT
+ } // end ClearAuthenticationL
+
+// ==========================================================================
+// FUNCTION: HasPasswordL
+// ==========================================================================
+TBool RMessageStoreSession::HasPasswordL()
+ {
+ __LOG_ENTER( "HasPasswordL" )
+
+ TPckgBuf<TBool> resultPckg( EFalse );
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdHasPassword, TIpcArgs( &resultPckg ) ) );
+
+ __LOG_WRITE8_FORMAT1_DEBUG3( "result=%i", resultPckg() )
+ __LOG_EXIT
+
+ return resultPckg();
+
+ } // end HasPasswordL
+
+// ==========================================================================
+// FUNCTION: SetPasswordL
+// ==========================================================================
+void RMessageStoreSession::SetPasswordL( const TDesC& aPassword )
+ {
+ __LOG_ENTER( "SetPasswordL" )
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdSetPassword, TIpcArgs( &aPassword ) ) );
+
+ __LOG_EXIT
+ } // end SetPasswordL
+
+// ==========================================================================
+// FUNCTION: ChangePasswordL
+// ==========================================================================
+TBool RMessageStoreSession::ChangePasswordL( const TDesC& aOldPassword, const TDesC& aNewPassword )
+ {
+ __LOG_ENTER( "ChangePasswordL" )
+
+ TPckgBuf<TBool> resultPckg( EFalse );
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdChangePassword, TIpcArgs( &resultPckg, &aOldPassword, &aNewPassword ) ) );
+
+ __LOG_WRITE8_FORMAT1_DEBUG3( "result=%i", resultPckg() )
+ __LOG_EXIT
+
+ return resultPckg();
+
+ } // end ChangePasswordL
+
+//account management
+// ==========================================================================
+// FUNCTION: CreateAccountL
+// ==========================================================================
+TMsgStoreId RMessageStoreSession::CreateAccountL( const CMsgStoreAccount& aAccount, const TDesC8& aProperties )
+ {
+ __LOG_ENTER( "CreateAccountL" )
+
+ TPckgBuf<TMsgStoreId> resultPckg( KMsgStoreInvalidId );
+
+ TInt32 ownerId = aAccount.Owner();
+ const TDesC& name = aAccount.Name();
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdCreateAccount, TIpcArgs( &resultPckg, ownerId, &name, &aProperties ) ) );
+
+ __LOG_WRITE8_FORMAT1_DEBUG3( "result=%u", resultPckg() )
+ __LOG_EXIT
+
+ return resultPckg();
+ }
+
+// ==========================================================================
+// FUNCTION: OpenAccountL
+// ==========================================================================
+TMsgStoreId RMessageStoreSession::OpenAccountL( const CMsgStoreAccount& aAccount, RBuf8& aBuffer )
+ {
+ __LOG_ENTER( "OpenAccountL" )
+
+ TUint result = 1;
+ TPckg<TUint> resultPckg( result );
+
+ TMsgStoreOpenAccountCmdParams params;
+ TPckg<TMsgStoreOpenAccountCmdParams> paramsPckg( params );
+
+ params.iOwnerId = aAccount.Owner();
+
+ const TDesC& name = aAccount.Name();
+
+ aBuffer.CreateL( KInitialPropertiesTransferBufferLength );
+
+ while( result != 0 )
+ {
+ User::LeaveIfError( SendReceive( EMsgStoreCmdOpenAccount, TIpcArgs( &resultPckg, ¶msPckg, &name, &aBuffer ) ) );
+
+ // The buffer was too small. Reallocate.
+ if( result != 0 )
+ {
+ __LOG_WRITE8_FORMAT1_INFO( "growing buffer to %i", result );
+ aBuffer.ReAllocL( result );
+ }
+ } // end while
+
+ __LOG_WRITE8_FORMAT1_DEBUG3( "result=%u", resultPckg() )
+ __LOG_EXIT
+
+ return params.iMailBoxId;
+ }
+
+// ==========================================================================
+// FUNCTION: DeleteAccountL
+// ==========================================================================
+void RMessageStoreSession::DeleteAccountL( const CMsgStoreAccount& aAccount )
+ {
+ __LOG_ENTER( "DeleteAccountL" )
+
+ TInt32 ownerId = aAccount.Owner();
+ const TDesC& name = aAccount.Name();
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdDeleteAccount, TIpcArgs( ownerId, &name ) ) );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: RenameAccountL
+// ==========================================================================
+void RMessageStoreSession::RenameAccountL( TInt32 aOwnerId, const TDesC& aOldName, const TDesC& aNewName )
+ {
+ __LOG_ENTER( "RenameAccountL" )
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdRenameAccount, TIpcArgs( aOwnerId, &aOldName, &aNewName ) ) );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: AccountsL
+// ==========================================================================
+void RMessageStoreSession::AccountsL( RPointerArray<CMsgStoreAccount>& aAccounts )
+ {
+ __LOG_ENTER( "AccountsL" )
+
+ RBuf8 resultBuf;
+ CleanupClosePushL( resultBuf );
+ resultBuf.CreateL( KInitialAccountsTransferBufferLength );
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdListAccounts, TIpcArgs( &resultBuf ) ) );
+
+ CAccountsSerializer* serializer = new(ELeave)CAccountsSerializer();
+ CleanupStack::PushL( serializer );
+
+ serializer->DeserializeL( resultBuf );
+
+ TInt count = serializer->Count();
+ RArray<TInt32>& ownerIds = serializer->OwnerIds();
+ RPointerArray<HBufC>& names = serializer->NamesArray();
+
+ for ( int i = 0 ; i < count ; i++ )
+ {
+ CMsgStoreAccount* account = CMsgStoreAccount::NewL( ownerIds[i], *(names[i]) );
+ aAccounts.Append( account );
+ }
+ CleanupStack::PopAndDestroy( serializer );
+ CleanupStack::PopAndDestroy( &resultBuf );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: StartObservingL
+// ==========================================================================
+void RMessageStoreSession::StartObservingL()
+ {
+ __LOG_ENTER( "StartObservingL" )
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdStartObserving ) );
+
+ __LOG_EXIT
+ } // end StartObservingL
+
+// ==========================================================================
+// FUNCTION: GetEvents
+// ==========================================================================
+void RMessageStoreSession::GetEvents( TRequestStatus& aStatus, TDes8& aBuffer )
+ {
+ __LOG_ENTER( "GetEvents" )
+
+ aBuffer.SetLength( 0 );
+ SendReceive( EMsgStoreCmdGetEvents, TIpcArgs( &aBuffer ), aStatus );
+
+ __LOG_EXIT
+ } // end GetEvents
+
+// ==========================================================================
+// FUNCTION: StopObserving
+// ==========================================================================
+void RMessageStoreSession::StopObserving()
+ {
+ __LOG_ENTER( "StopObserving" )
+
+ SendReceive( EMsgStoreCmdStopObserving );
+
+ __LOG_EXIT
+ } // end StopObserving
+
+// ==========================================================================
+// FUNCTION: CreateContainerL
+// ==========================================================================
+TMsgStoreId RMessageStoreSession::CreateContainerL( TMsgStoreId aParentId,
+ TMsgStoreId aGrandparentId,
+ TMsgStoreId aMailBoxId,
+ TMsgStoreContainerMasks aType,
+ const TDesC8& aProperties,
+ TBool aCommitContainer,
+ const TDesC& aContentFilename )
+ {
+ __LOG_ENTER( "CreateContainerL" )
+
+ TMsgStoreCreateContainerCmdParams params;
+ TPckg<TMsgStoreCreateContainerCmdParams> paramsPckg( params );
+
+ params.iParentId = aParentId;
+ params.iGrandparentId = aGrandparentId;
+ params.iMailBoxId = aMailBoxId;
+ params.iCommitContainer = aCommitContainer;
+ params.iType = aType;
+ params.iHasContent = ( aContentFilename.Length() > 0 );
+
+ TIpcArgs ipcArgs( ¶msPckg, &aProperties );
+
+ // Platform security documentation recommends using different file system session for
+ // each file handle that is transferred between processes.
+ RFs fs;
+ CleanupClosePushL( fs );
+
+ RFile file;
+ CleanupClosePushL( file );
+
+ if( params.iHasContent )
+ {
+ User::LeaveIfError( fs.Connect() );
+ fs.ShareProtected();
+
+ User::LeaveIfError( file.Open( fs, aContentFilename, EFileRead | EFileShareAny ) );
+ User::LeaveIfError( file.TransferToServer( ipcArgs, KIpcArgsIndex2, KIpcArgsIndex3 ) );
+ } // end if
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdCreateContainer, ipcArgs ) );
+
+ CleanupStack::PopAndDestroy( &file );
+ CleanupStack::PopAndDestroy( &fs );
+
+ __LOG_WRITE8_FORMAT1_DEBUG3( "id=%x", params.iId )
+ __LOG_EXIT
+
+ return params.iId;
+
+ } // end CreateContainerL
+
+
+// ==========================================================================
+// FUNCTION: CreateContainerL
+// ==========================================================================
+TMsgStoreId RMessageStoreSession::CreateContainerL( TMsgStoreId aParentId,
+ TMsgStoreId aGrandparentId,
+ TMsgStoreId aMailBoxId,
+ TMsgStoreContainerMasks aType,
+ const TDesC8& aProperties,
+ TBool aCommitContainer,
+ RFile& aFile )
+ {
+ __LOG_ENTER( "CreateContainerL" )
+
+ TMsgStoreCreateContainerCmdParams params;
+ TPckg<TMsgStoreCreateContainerCmdParams> paramsPckg( params );
+
+ CleanupClosePushL( aFile );
+
+ params.iParentId = aParentId;
+ params.iGrandparentId = aGrandparentId;
+ params.iMailBoxId = aMailBoxId;
+ params.iCommitContainer = aCommitContainer;
+ params.iType = aType;
+ params.iHasContent = ETrue;
+
+ TIpcArgs ipcArgs( ¶msPckg, &aProperties );
+
+ User::LeaveIfError( aFile.TransferToServer( ipcArgs, 2, 3 ) );
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdCreateContainer, ipcArgs ) );
+
+ CleanupStack::PopAndDestroy( &aFile );
+
+ __LOG_WRITE8_FORMAT1_DEBUG3( "id=%x", params.iId )
+ __LOG_EXIT
+
+ return params.iId;
+
+ } // end CreateContainerL
+
+// ==========================================================================
+// FUNCTION: CommitContainerL
+// ==========================================================================
+void RMessageStoreSession::CommitContainerL( TMsgStoreId aId,
+ TMsgStoreId aDestinationId,
+ TMsgStoreId aMailBoxId)
+ {
+ __LOG_ENTER( "CommitContainerL" )
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdCommitContainer, TIpcArgs( aId, aDestinationId, aMailBoxId ) ) );
+
+ __LOG_EXIT
+ } // end CommitContainerL
+
+// ==========================================================================
+// FUNCTION: AbandonContainerL
+// ==========================================================================
+void RMessageStoreSession::AbandonContainerL( TMsgStoreId aId )
+ {
+ __LOG_ENTER( "AbandonContainerL" )
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdAbandonContainer, TIpcArgs( aId ) ) );
+
+ __LOG_EXIT
+ } // end AbandonContainerL
+
+// ==========================================================================
+// FUNCTION: MoveContainerL
+// ==========================================================================
+void RMessageStoreSession::MoveContainerL( TMsgStoreId aId,
+ TMsgStoreId aSourceId,
+ TMsgStoreId aDestinationId )
+ {
+ __LOG_ENTER( "MoveContainerL" )
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdMoveContainer, TIpcArgs( aId, aSourceId, aDestinationId ) ) );
+
+ __LOG_EXIT
+ } // end MoveContainerL
+
+// ==========================================================================
+// FUNCTION: CopyContainerL
+// ==========================================================================
+TMsgStoreId RMessageStoreSession::CopyContainerL( TMsgStoreId aId,
+ TMsgStoreId aSourceId,
+ TMsgStoreId aSourceParentId,
+ TMsgStoreId aDestinationId,
+ TMsgStoreId aDestinationParentId,
+ TMsgStoreId aMailBoxId)
+ {
+ __LOG_ENTER( "CopyContainerL" )
+
+ TPckgBuf<TMsgStoreId> idPckg;
+
+ TMsgStoreCopyContainerCmdParams params;
+ TPckg<TMsgStoreCopyContainerCmdParams> paramsPckg( params );
+
+ params.iId = aId;
+ params.iSourceId = aSourceId,
+ params.iSourceParentId = aSourceParentId,
+ params.iDestinationId = aDestinationId;
+ params.iDestinationParentId = aDestinationParentId;
+ params.iMailBoxId = aMailBoxId;
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdCopyContainer, TIpcArgs( ¶msPckg, &idPckg ) ) );
+
+ __LOG_WRITE8_FORMAT1_DEBUG3( "id=%x", idPckg() )
+ __LOG_EXIT
+
+ return idPckg();
+
+ } // end CopyContainerL
+
+// ==========================================================================
+// FUNCTION: ContainerPropertiesL
+// ==========================================================================
+void RMessageStoreSession::ContainerPropertiesL( TMsgStoreId aId, TMsgStoreId& aParentId, TMsgStoreId aGrandparentId, RBuf8& aBuffer, TMsgStoreId aMailboxId )
+ {
+ __LOG_ENTER( "ContainerPropertiesL" )
+
+ //TMsgStoreId originalParentId = aParentId;
+
+ TMsgStoreFetchPropertiesCmdParams params;
+ TPckg<TMsgStoreFetchPropertiesCmdParams> paramsPckg( params );
+
+ params.iId = aId;
+ params.iGrandparentId = aGrandparentId;
+ params.iMailboxId = aMailboxId;
+
+ TPckg<TMsgStoreId> parentIdPckg( aParentId );
+
+ TUint result = 1;
+ TPckg<TUint> resultPckg( result );
+
+ aBuffer.CreateL( KInitialPropertiesTransferBufferLength );
+
+ while( result != 0 )
+ {
+ User::LeaveIfError( SendReceive( EMsgStoreCmdFetchProperties, TIpcArgs( ¶msPckg, &parentIdPckg, &aBuffer, &resultPckg ) ) );
+
+ // The buffer was too small. Reallocate.
+ if( result != 0 )
+ {
+ __LOG_WRITE8_FORMAT1_INFO( "growing buffer to %i", result );
+ aBuffer.ReAllocL( result );
+ }
+ } // end while
+
+ __LOG_EXIT
+ } // end ContainerPropertiesL
+
+// ==========================================================================
+// FUNCTION: DeleteContainerL
+// ==========================================================================
+void RMessageStoreSession::DeleteContainerL( TMsgStoreId aId, TMsgStoreId aParentId, TMsgStoreId aGrandparentId, TMsgStoreId aMailBoxId )
+ {
+ __LOG_ENTER( "DeleteContainerL" )
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdDeleteContainer, TIpcArgs( aId, aParentId, aGrandparentId, aMailBoxId ) ) );
+
+ __LOG_EXIT
+ } // end DeleteContainerL
+
+// ==========================================================================
+// FUNCTION: ChildrenCountsL
+// ==========================================================================
+void RMessageStoreSession::ChildrenCountsL( TMsgStoreId aId, TUint& aMessageCount, TUint& aUnreadCount )
+ {
+ __LOG_ENTER( "ChildrenCountsL" )
+
+ TMsgStoreCounts counts;
+ TPckg<TMsgStoreCounts> countsPckg( counts );
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdChildrenCounts, TIpcArgs( aId, &countsPckg ) ) );
+
+ aMessageCount = counts.iMessagesCount;
+ aUnreadCount = counts.iUnreadCount;
+
+ __LOG_EXIT
+ } // end ChildrenCountsL
+
+// ==========================================================================
+// FUNCTION: TotalCountsL
+// ==========================================================================
+void RMessageStoreSession::TotalCountsL( TMsgStoreId aMailBoxId, TUint& aMessageCount, TUint& aUnreadCount )
+ {
+ __LOG_ENTER( "TotalCountsL" )
+
+ TMsgStoreCounts counts;
+ TPckg<TMsgStoreCounts> countsPckg( counts );
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdTotalCounts, TIpcArgs( aMailBoxId, &countsPckg ) ) );
+
+ aMessageCount = counts.iMessagesCount;
+ aUnreadCount = counts.iUnreadCount;
+
+ __LOG_EXIT
+ } // end TotalCountsL
+
+// ==========================================================================
+// FUNCTION: ChildrenIdsL
+// ==========================================================================
+void RMessageStoreSession::ChildrenIdsL( TMsgStoreId aId, TMsgStoreContainerMasks aType, RArray<TMsgStoreId>& aChildrenIds )
+ {
+ __LOG_ENTER( "ChildrenIdsL" )
+
+ RBuf8 childrenBuf;
+ childrenBuf.CreateL( KInitialChildrenIdsTransferBufferLength );
+ CleanupClosePushL( childrenBuf );
+
+ TUint result = 1;
+ TPckg<TUint> resultPckg( result );
+
+ while( result != 0 )
+ {
+ User::LeaveIfError( SendReceive( EMsgStoreCmdChildrenIds, TIpcArgs( aId, aType, &childrenBuf, &resultPckg ) ) );
+
+ if( result != 0 )
+ {
+ // Overflow!
+ __LOG_WRITE8_FORMAT1_INFO( "growing transfer buffer to %i", result )
+
+ childrenBuf.ReAllocL( result );
+ } // end if
+
+ } // end while
+
+ RDesReadStream readStream( childrenBuf );
+ CleanupClosePushL( readStream );
+
+ aChildrenIds.Reset();
+ const TUint KDivider = 4;
+ for( TInt count = 0; count < childrenBuf.Length() / KDivider; count++ )
+ {
+ aChildrenIds.Append( readStream.ReadUint32L() );
+ } // end for
+
+ CleanupStack::PopAndDestroy( &readStream );
+ CleanupStack::PopAndDestroy( &childrenBuf );
+
+ __LOG_EXIT
+ } // end ChildrenIdsL
+
+// ==========================================================================
+// FUNCTION: UpdatePropertiesL
+// ==========================================================================
+void RMessageStoreSession::UpdatePropertiesL( TMsgStoreId aId,
+ TMsgStoreId aParentId,
+ TMsgStoreId aMailBoxId,
+ const TDesC8& aProperties )
+ {
+ __LOG_ENTER( "UpdatePropertiesL" )
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdUpdateProperties, TIpcArgs( aId, aParentId, aMailBoxId, &aProperties ) ) );
+
+ __LOG_EXIT
+ } // end UpdatePropertiesL
+
+// ==========================================================================
+// FUNCTION: UpdatePropertyL
+// ==========================================================================
+void RMessageStoreSession::UpdatePropertyL( TMsgStoreId aId,
+ TMsgStoreId aParentId,
+ TMsgStoreId aMailBoxId,
+ const TDesC8& aName,
+ TMsgStorePropertyValueType aType,
+ const TDesC8& aValue )
+ {
+ __LOG_ENTER( "UpdatePropertyL" )
+
+ TMsgStoreUpdatePropertyCmdParams params;
+ TPckg<TMsgStoreUpdatePropertyCmdParams> paramsPckg( params );
+
+ params.iId = aId;
+ params.iParentId = aParentId;
+ params.iMailBoxId = aMailBoxId;
+ params.iType = aType;
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdUpdateProperty, TIpcArgs( ¶msPckg, &aName, &aValue ) ) );
+
+ __LOG_EXIT
+ } // end UpdatePropertyL
+
+// ==========================================================================
+// FUNCTION: WipeEverything
+// ==========================================================================
+void RMessageStoreSession::WipeEverythingL()
+ {
+ __LOG_ENTER( "WipeEverything" )
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdWipeEverything ) );
+
+ __LOG_EXIT
+ } // end WipeEverything
+
+// ==========================================================================
+// FUNCTION: ContentLengthL
+// ==========================================================================
+TUint RMessageStoreSession::ContentLengthL( TMsgStoreId aId, TMsgStoreId aParentId )
+ {
+ __LOG_ENTER( "ContentLengthL" )
+
+ TPckgBuf<TUint> lengthPckg;
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdContentLength, TIpcArgs( aId, aParentId, &lengthPckg ) ) );
+
+ __LOG_WRITE8_FORMAT1_DEBUG3( "length=%i", lengthPckg() )
+ __LOG_EXIT
+
+ return lengthPckg();
+
+ } // end ContentLengthL
+
+// ==========================================================================
+// FUNCTION: FetchContentL
+// ==========================================================================
+void RMessageStoreSession::FetchContentL( TMsgStoreId aId, TMsgStoreId aParentId, TDes8& aBuffer, TUint aStartOffset )
+ {
+ __LOG_ENTER( "FetchContentL(1)" )
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdFetchContentToBuffer, TIpcArgs( aId, aParentId, &aBuffer, aStartOffset ) ) );
+
+ __LOG_EXIT
+ } // end FetchContentL
+
+// ==========================================================================
+// FUNCTION: FetchContentL
+// ==========================================================================
+void RMessageStoreSession::FetchContentL( TMsgStoreId aId, TMsgStoreId aParentId, const TDesC& aFilename )
+ {
+ __LOG_ENTER( "FetchContentL(2)" )
+
+ // Platform security documentation recommends using different file system session for
+ // each file handle that is transferred between processes.
+ RFs fs;
+ User::LeaveIfError( fs.Connect() );
+ CleanupClosePushL( fs );
+ fs.ShareProtected();
+
+ RFile file;
+ User::LeaveIfError( file.Replace( fs, aFilename, EFileWrite | EFileShareAny ) );
+ CleanupClosePushL( file );
+
+ TIpcArgs ipcArgs;
+
+ ipcArgs.Set( 0, aId );
+ ipcArgs.Set( 1, aParentId );
+
+ User::LeaveIfError( file.TransferToServer( ipcArgs, KIpcArgsIndex2, KIpcArgsIndex3 ) );
+
+ TInt result = SendReceive( EMsgStoreCmdFetchContentToFile, ipcArgs );
+
+ CleanupStack::PopAndDestroy( &file );
+
+ if( result != KErrNone )
+ {
+ // Something went wrong. Cleanup file.
+ fs.Delete( aFilename );
+ User::Leave( result );
+ } // end if
+
+ CleanupStack::PopAndDestroy( &fs );
+
+ __LOG_EXIT
+ } // end FetchContentL
+
+// ==========================================================================
+// FUNCTION: ReplaceContentL
+// ==========================================================================
+void RMessageStoreSession::ReplaceContentL( TMsgStoreId aId, TMsgStoreId aParentId, const TDesC8& aContent )
+ {
+ __LOG_ENTER( "ReplaceContentL" )
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdReplaceContentWithBuffer, TIpcArgs( aId, aParentId, &aContent ) ) );
+
+ __LOG_EXIT
+ } // end ReplaceContentL
+
+// ==========================================================================
+// FUNCTION: ReplaceContentL
+// ==========================================================================
+void RMessageStoreSession::ReplaceContentWithFileL( TMsgStoreId aId, TMsgStoreId aParentId, const TDesC& aFilename )
+ {
+ __LOG_ENTER( "ReplaceContentWithFileL" )
+
+ TIpcArgs ipcArgs( aId, aParentId );
+
+ // Platform security documentation recommends using different file system session for
+ // each file handle that is transferred between processes.
+ RFs fs;
+ User::LeaveIfError( fs.Connect() );
+ CleanupClosePushL( fs );
+ fs.ShareProtected();
+
+ RFile file;
+ User::LeaveIfError( file.Open( fs, aFilename, EFileRead ) );
+ CleanupClosePushL( file );
+ User::LeaveIfError( file.TransferToServer( ipcArgs, KIpcArgsIndex2, KIpcArgsIndex3 ) );
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdReplaceContentWithFile, ipcArgs ) );
+
+ CleanupStack::PopAndDestroy( &file );
+ CleanupStack::PopAndDestroy( &fs );
+
+ __LOG_EXIT
+ } // end ReplaceContentL
+
+// ==========================================================================
+// FUNCTION: AppendToContentL
+// ==========================================================================
+void RMessageStoreSession::AppendToContentL( TMsgStoreId aId, TMsgStoreId aParentId, const TDesC8& aContent )
+ {
+ __LOG_ENTER( "AppendToContentL" )
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdAppendToContent, TIpcArgs( aId, aParentId, &aContent ) ) );
+
+ __LOG_EXIT
+ } // end AppendToContentL
+
+// ==========================================================================
+// FUNCTION: PrependToContentL
+// ==========================================================================
+void RMessageStoreSession::PrependToContentL( TMsgStoreId aId, TMsgStoreId aParentId, const TDesC8& aContent )
+ {
+ __LOG_ENTER( "PrependToContentL" )
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdPrependToContent,
+ TIpcArgs( aId, aParentId, &aContent ) ) );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: RemoveContentL
+// ==========================================================================
+void RMessageStoreSession::RemoveContentL( TMsgStoreId aId, TMsgStoreId aParentId )
+ {
+ __LOG_ENTER( "RemoveContentL" )
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdRemoveContent, TIpcArgs( aId, aParentId ) ) );
+
+ __LOG_EXIT
+ } // end RemoveContentL
+
+// ==========================================================================
+// FUNCTION: OpenOriginalContentFileL
+// ==========================================================================
+void RMessageStoreSession::OpenOriginalContentFileL( TMsgStoreId aId, TMsgStoreId aParentId, RFile& aFile )
+ {
+ __LOG_ENTER( "OpenOriginalContentFileL" )
+
+ // Retrieve the RFs and RFile handles from the server
+ TInt fsh; // session (RFs) handle
+ TPckgBuf<TInt> fh; // sub-session (RFile) handle
+
+ fsh = SendReceive( EMsgStoreCmdOpenContentFile, TIpcArgs( aId, aParentId, &fh ) );
+ User::LeaveIfError( fsh );
+
+ User::LeaveIfError( aFile.AdoptFromServer( fsh, fh() ) );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: ChildrenPropertiesL
+// ==========================================================================
+void RMessageStoreSession::ChildrenPropertiesL( TMsgStoreId aId,
+ TMsgStoreId aParentId,
+ TMsgStoreContainerMasks aType,
+ TBool aQuickProperties,
+ TBool aRecursive,
+ MPropertiesArray& aPropertiesArray )
+ {
+ __LOG_ENTER( "ChildrenPropertiesL" )
+
+ TMsgStorePropertiesListCmdParams params;
+
+ params.iUseQuery = ETrue;
+ params.iQuickProperties = aQuickProperties;
+
+ TMsgStorePropertiesListQueryParams queryParams;
+
+ queryParams.iId = aId;
+ queryParams.iParentId = aParentId;
+ queryParams.iType = aType;
+ queryParams.iRecursive = aRecursive;
+
+ TPckg<TMsgStorePropertiesListQueryParams> queryParamsPckg( queryParams );
+ TBuf8<1> emptyBuf;
+
+ DoPropertiesListL( params, queryParamsPckg, emptyBuf, aPropertiesArray );
+
+ __LOG_EXIT
+ } // end ChildrenPropertiesL
+
+// ==========================================================================
+// FUNCTION: DoPropertiesListL
+// ==========================================================================
+void RMessageStoreSession::DoPropertiesListL( TMsgStorePropertiesListCmdParams& aParams,
+ const TDesC8& aIdBuffer,
+ const TDesC8& aSerializedPropertyNames,
+ MPropertiesArray& aPropertiesArray )
+ {
+ __LOG_ENTER( "DoPropertiesListL" )
+
+ TPckg<TMsgStorePropertiesListCmdParams> paramsPckg( aParams );
+
+ RBuf8 serializedBuf;
+ serializedBuf.CreateL( KInitialPropertiesListTransferBufferLength );
+ CleanupClosePushL( serializedBuf );
+
+ TMsgStoreId id;
+ TPckg<TMsgStoreId> idPckg( id );
+
+ TMsgStoreId parentId;
+ TPckg<TMsgStoreId> parentIdPckg( parentId );
+
+ TUint32 length32;
+ TPckg<TUint32> length32Pckg( length32 );
+
+ aParams.iStartOver = ETrue;
+ aParams.iMoreProperties = ETrue;
+
+ while( aParams.iMoreProperties )
+ {
+ __LOG_WRITE_INFO( "getting next chunk" )
+
+ serializedBuf.SetLength( 0 );
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdPropertiesList,
+ TIpcArgs( ¶msPckg,
+ &aIdBuffer,
+ &aSerializedPropertyNames,
+ &serializedBuf ) ) );
+
+ __LOG_WRITE_INFO( "handling chunk" )
+
+ if( aParams.iClearExisting )
+ {
+ __LOG_WRITE_INFO( "resetting local buffer" )
+ aPropertiesArray.Reset();
+ } // end if
+
+ const TUint8* pointer = serializedBuf.Ptr();
+
+ // Deserialize data until the current buffer is exhausted.
+ while( pointer < serializedBuf.Ptr() + serializedBuf.Length() )
+ {
+ idPckg.Copy( pointer, idPckg.Length() );
+ pointer += idPckg.Length();
+
+ parentIdPckg.Copy( pointer, parentIdPckg.Length() );
+ pointer += parentIdPckg.Length();
+
+ length32Pckg.Copy( pointer, length32Pckg.Length() );
+ pointer += length32Pckg.Length();
+
+ TPtrC8 propertiesBuf( pointer, length32 );
+ pointer += length32;
+
+ aPropertiesArray.AddElementL( id, parentId, propertiesBuf );
+ } // end while
+
+ serializedBuf.SetLength( 0 );
+
+ if( aParams.iNewBufferSize > 0 )
+ {
+ __LOG_WRITE8_FORMAT1_INFO( "growing buffer to %i", aParams.iNewBufferSize );
+ serializedBuf.ReAllocL( aParams.iNewBufferSize );
+ } // end if
+
+ aParams.iStartOver = EFalse;
+
+ } // end while
+
+ __LOG_WRITE_INFO( "done" );
+
+ CleanupStack::PopAndDestroy( &serializedBuf );
+
+ __LOG_EXIT
+ } // end DoPropertiesListL
+
+// ==========================================================================
+// FUNCTION: SortL
+// ==========================================================================
+TMsgStoreId RMessageStoreSession::SortL( RMsgStoreSortCriteria& aSortCriteria, TMsgStoreId aMailBoxId, TBool aInMemorySort )
+ {
+ __LOG_ENTER( "SortL" )
+
+ TPckgBuf<TMsgStoreId> resultPckg( KMsgStoreInvalidId );
+
+ TMsgStoreSortCriteria params;
+ TPckg<TMsgStoreSortCriteria> paramsPckg( params );
+
+ params.iMailBoxId = aMailBoxId;
+ params.iFolderId = aSortCriteria.iFolderId;
+ params.iSortBy = aSortCriteria.iSortBy;
+ params.iSortOrder = aSortCriteria.iSortOrder;
+ params.iSecondarySortOrder = aSortCriteria.iSecondarySortOrder;
+
+ // Serialize property names.
+ TUint16 nameLength;
+ TPckg<TUint16> nameLengthPckg( nameLength );
+
+ const RPointerArray<TDesC8>& aPropertyNames = aSortCriteria.PropertyKeys();
+
+ TInt totalLength = 0;
+ for( TInt i = 0; i < aPropertyNames.Count(); i++ )
+ {
+ totalLength += (aPropertyNames[i]->Length() + nameLengthPckg.Length());
+ } // end for
+
+ RBuf8 propertyNamesBuffer;
+ CleanupClosePushL( propertyNamesBuffer );
+ propertyNamesBuffer.CreateL( totalLength );
+
+ for( TInt i = 0; i < aPropertyNames.Count(); i++ )
+ {
+ nameLength = aPropertyNames[i]->Length();
+ propertyNamesBuffer.Append( nameLengthPckg );
+ propertyNamesBuffer.Append( *aPropertyNames[i] );
+ } // end for
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdStartSorting, TIpcArgs( &resultPckg, ¶msPckg, &propertyNamesBuffer, aInMemorySort ) ) );
+
+ CleanupStack::PopAndDestroy( &propertyNamesBuffer );
+
+ __LOG_EXIT
+
+ return resultPckg();
+ }
+
+// ==========================================================================
+// FUNCTION: GetSortedRowsL
+// ==========================================================================
+TBool RMessageStoreSession::GetSortedRowsL( TMsgStoreId aSortSessionId,
+ TMsgStoreId aCurrentMessageId,
+ TMsgStoreIteratorDirection aDirection,
+ TUint aCount,
+ MPropertiesArray& aPropertiesArray,
+ const TDesC& aStartWith,
+ TBool aSkipCurrentGroup )
+ {
+ __LOG_ENTER( "GetSortedRowsL" )
+
+ TUint result = 1;
+ TPckg<TUint> resultPckg( result );
+
+ TMsgStoreGetSortedRowsCmdParams params;
+ TPckg<TMsgStoreGetSortedRowsCmdParams> paramsPckg( params );
+
+ params.iSortSessionId = aSortSessionId;
+ params.iStartingMessageId = aCurrentMessageId;
+ params.iDirection = aDirection;
+ params.iRowsToRetrieve = aCount;
+ params.iHasStartWith = aStartWith != KNullDesC;
+ params.iSkipCurrentGroup = aSkipCurrentGroup;
+ params.iHasMoreRows = EFalse;
+
+ RBuf8 serializedBuf;
+ CleanupClosePushL( serializedBuf );
+ serializedBuf.CreateL( KInitialSortedListTransferBufferLength );
+
+ while( result != 0 )
+ {
+ if ( aStartWith == KNullDesC )
+ {
+ User::LeaveIfError( SendReceive( EMsgStoreCmdGetSortedRows, TIpcArgs( &resultPckg, ¶msPckg, &serializedBuf ) ) );
+ }
+ else
+ {
+ User::LeaveIfError( SendReceive( EMsgStoreCmdGetSortedRows, TIpcArgs( &resultPckg, ¶msPckg, &serializedBuf, &aStartWith ) ) );
+ }
+
+ // The buffer was too small. Reallocate.
+ if( result != 0 )
+ {
+ __LOG_WRITE8_FORMAT1_INFO( "growing buffer to %i", result );
+ serializedBuf.ReAllocL( result );
+ }
+ } // end while
+
+ // Deserialize data until the current buffer is exhausted.
+ TMsgStoreId id;
+ TPckg<TMsgStoreId> idPckg( id );
+
+ TMsgStoreId parentId;
+ TPckg<TMsgStoreId> parentIdPckg( parentId );
+
+ TUint32 length32;
+ TPckg<TUint32> length32Pckg( length32 );
+
+ const TUint8* pointer = serializedBuf.Ptr();
+
+ while( pointer < serializedBuf.Ptr() + serializedBuf.Length() )
+ {
+ idPckg.Copy( pointer, idPckg.Length() );
+ pointer += idPckg.Length();
+
+ parentIdPckg.Copy( pointer, parentIdPckg.Length() );
+ pointer += parentIdPckg.Length();
+
+ length32Pckg.Copy( pointer, length32Pckg.Length() );
+ pointer += length32Pckg.Length();
+
+ TPtrC8 propertiesBuf( pointer, length32 );
+ pointer += length32;
+
+ aPropertiesArray.AddElementL( id, parentId, propertiesBuf );
+ } // end while
+
+ __LOG_EXIT
+
+ CleanupStack::PopAndDestroy( &serializedBuf );
+
+ return params.iHasMoreRows;
+ }
+
+// ==========================================================================
+// FUNCTION: SortIteratorGroupCountL
+// ==========================================================================
+TInt RMessageStoreSession::SortIteratorGroupCountL( TMsgStoreId aSortSessionId, RArray<TUint>& aItemsInGroup )
+ {
+ __LOG_ENTER("SortIteratorGroupCountL")
+
+ TInt result = 0;
+ TPckg<TInt> resultPckg( result );
+
+ RBuf8 countsBuf;
+ CleanupClosePushL( countsBuf );
+ countsBuf.CreateL( KInitialSortedListTransferBufferLength );
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdGetIteratorGroupCount, TIpcArgs( aSortSessionId, &resultPckg, &countsBuf ) ) );
+
+ TUint count;
+ TPckg<TUint> countPckg( count );
+ const TUint8* pointer = countsBuf.Ptr();
+
+ if ( result > 0 )
+ {
+ while( pointer < countsBuf.Ptr() + countsBuf.Length() )
+ {
+ countPckg.Copy( pointer, countPckg.Length() );
+ pointer += countPckg.Length();
+
+ aItemsInGroup.Append( count );
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &countsBuf );
+
+ __LOG_EXIT
+
+ return result;
+ }
+
+// ==========================================================================
+// FUNCTION: SortedIdsAndFlagsL
+// ==========================================================================
+void RMessageStoreSession::SortedIdsAndFlagsL( TMsgStoreId aSortSessionId, RArray<TMsgStoreIdAndFlag>& aIdsAndFlags )
+ {
+ __LOG_ENTER("SortedIdsAndFlagsL")
+
+ TInt count = 0;
+ TPckg<TInt> countPckg( count );
+
+ RBuf8 resultBuf;
+ CleanupClosePushL( resultBuf );
+ resultBuf.CreateL( KInitialSortedIdsAndFlagsBufferLength );
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdGetIteratorIdsAndFlags, TIpcArgs( aSortSessionId, &countPckg, &resultBuf ) ) );
+
+ TMsgStoreId id;
+ TPckg<TMsgStoreId> idPckg( id );
+
+ TUint32 flag;
+ TPckg<TUint32> flagPckg( flag );
+
+ const TUint8* pointer = resultBuf.Ptr();
+
+ if ( count > 0 )
+ {
+ while( pointer < resultBuf.Ptr() + resultBuf.Length() )
+ {
+ idPckg.Copy( pointer, idPckg.Length() );
+ pointer += idPckg.Length();
+
+ flagPckg.Copy( pointer, flagPckg.Length() );
+ pointer += flagPckg.Length();
+
+ aIdsAndFlags.Append( TMsgStoreIdAndFlag( id, flag ) );
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &resultBuf );
+
+ __LOG_EXIT
+ }
+
+
+// ==========================================================================
+// FUNCTION: SortedIndexOfL
+// ==========================================================================
+TInt RMessageStoreSession::SortedIndexOfL( TMsgStoreId aSortSessionId, TMsgStoreId aMessageId )
+ {
+ __LOG_ENTER("SortedIndexOfL")
+
+ TInt index = 0;
+ TPckg<TInt> indexPckg( index );
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdSortedIndexOf, TIpcArgs( aSortSessionId, aMessageId, &indexPckg ) ) );
+
+ __LOG_EXIT
+
+ return index;
+ }
+
+// ==========================================================================
+// FUNCTION: SortedIdsL
+// ==========================================================================
+void RMessageStoreSession::SortedIdsL( TMsgStoreId aSortSessionId, RArray<TMsgStoreId>& aMessageIds )
+ {
+ __LOG_ENTER("SortedIdsL")
+
+ TInt count = 0;
+ TPckg<TInt> countPckg( count );
+
+ RBuf8 resultBuf;
+ CleanupClosePushL( resultBuf );
+ resultBuf.CreateL( KInitialSortedIdsAndFlagsBufferLength );
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdGetIteratorIds, TIpcArgs( aSortSessionId, &countPckg, &resultBuf ) ) );
+
+ TMsgStoreId id;
+ TPckg<TMsgStoreId> idPckg( id );
+
+ const TUint8* pointer = resultBuf.Ptr();
+
+ if ( count > 0 )
+ {
+ while( pointer < resultBuf.Ptr() + resultBuf.Length() )
+ {
+ idPckg.Copy( pointer, idPckg.Length() );
+ pointer += idPckg.Length();
+
+ aMessageIds.Append( id );
+ }
+ }
+
+ CleanupStack::PopAndDestroy( &resultBuf );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: IdsAndGroupCountL
+// ==========================================================================
+void RMessageStoreSession::IdsAndGroupCountL( TMsgStoreId aSortSessionId, RArray<TMsgStoreId>& aMessageIds, RArray<TUint>& aItemsInGroup )
+ {
+ __LOG_ENTER("IdsAndGroupCountL")
+
+ TInt idCount = 0;
+ TPckg<TInt> idCountPckg( idCount );
+ TInt groupCount = 0;
+ TPckg<TInt> groupCountPckg( groupCount );
+
+ RBuf8 resultBuf;
+ CleanupClosePushL( resultBuf );
+ resultBuf.CreateL( KInitialSortedIdsAndFlagsBufferLength );
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdGetIteratorIdsAndGroupCount, TIpcArgs( aSortSessionId, &idCountPckg, &groupCountPckg, &resultBuf ) ) );
+
+ //get the ID array
+ TMsgStoreId id;
+ TPckg<TMsgStoreId> idPckg( id );
+
+ const TUint8* pointer = resultBuf.Ptr();
+
+ while( (pointer < resultBuf.Ptr() + resultBuf.Length() ) && (idCount > 0) )
+ {
+ idPckg.Copy( pointer, idPckg.Length() );
+ pointer += idPckg.Length();
+
+ aMessageIds.Append( id );
+ --idCount;
+ }
+
+ //get the count array
+ TUint count;
+ TPckg<TUint> countPckg( count );
+ while( ( pointer < resultBuf.Ptr() + resultBuf.Length() ) && (groupCount > 0) )
+ {
+ countPckg.Copy( pointer, countPckg.Length() );
+ pointer += countPckg.Length();
+
+ aItemsInGroup.Append( count );
+ --groupCount;
+ }
+
+ CleanupStack::PopAndDestroy( &resultBuf );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: EndSortL
+// ==========================================================================
+void RMessageStoreSession::EndSortL( TMsgStoreId aSortSessionId )
+ {
+ __LOG_ENTER("EndSortL")
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdEndSorting, TIpcArgs( aSortSessionId ) ) );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: PrepareSearchL
+// ==========================================================================
+void RMessageStoreSession::PrepareSearchL( RMsgStoreSearchCriteria& aSearchCriteria )
+ {
+ __LOG_ENTER( "PrepareSearchL" )
+
+ TMsgStoreSearchCmdParams params;
+ TPckg<TMsgStoreSearchCmdParams> paramsPckg( params );
+
+ params.iSearchFields = aSearchCriteria.iSearchFields;
+ params.iSortBy = aSearchCriteria.iSortBy;
+ params.iSortOrder = aSearchCriteria.iSortOrder;
+ params.iSecondarySortOrder = aSearchCriteria.iSecondarySortOrder;
+
+ // Serialize ID list.
+ TMsgStoreId id;
+ TPckg<TMsgStoreId> idPckg( id );
+
+ RArray<TMsgStoreId>& aIds = aSearchCriteria.FolderIds();
+
+ RBuf8 idBuffer;
+ idBuffer.CreateL( aIds.Count() * idPckg.Length() );
+ CleanupClosePushL( idBuffer );
+
+ for( TInt i = 0; i < aIds.Count(); i++ )
+ {
+ id = aIds[i];
+ idBuffer.Append( idPckg );
+ } // end for
+
+ //serialize the search names
+ TUint16 searchStringLen;
+ TPckg<TUint16> searchStringLenPckg( searchStringLen );
+
+ const RPointerArray<TDesC>& searchStrings = aSearchCriteria.SearchStrings();
+
+ TInt totalLength = 0;
+ for( TInt i = 0; i < searchStrings.Count(); i++ )
+ {
+ totalLength += (searchStrings[i]->Length() * 2 + searchStringLenPckg.Length());
+ } // end for
+
+ RBuf8 searchStringsBuffer;
+ searchStringsBuffer.CreateL( totalLength );
+ CleanupClosePushL( searchStringsBuffer );
+
+ for( TInt i = 0; i < searchStrings.Count(); i++ )
+ {
+ TDesC& val = *searchStrings[i];
+ searchStringLen = val.Length() * 2;
+ searchStringsBuffer.Append( searchStringLenPckg );
+
+ const TUint8* valuePtr = reinterpret_cast<const TUint8*>( val.Ptr() );
+ TPtrC8 valueDes8( valuePtr, searchStringLen );
+ searchStringsBuffer.Append( valueDes8 );
+ } // end for
+
+ // Serialize property names.
+ TUint16 nameLength;
+ TPckg<TUint16> nameLengthPckg( nameLength );
+
+ const RPointerArray<TDesC8>& aPropertyNames = aSearchCriteria.PropertyKeys();
+
+ totalLength = 0;
+ for( TInt i = 0; i < aPropertyNames.Count(); i++ )
+ {
+ totalLength += (aPropertyNames[i]->Length() + nameLengthPckg.Length());
+ } // end for
+
+ RBuf8 propertyNamesBuffer;
+ propertyNamesBuffer.CreateL( totalLength );
+ CleanupClosePushL( propertyNamesBuffer );
+
+ for( TInt i = 0; i < aPropertyNames.Count(); i++ )
+ {
+ nameLength = aPropertyNames[i]->Length();
+ propertyNamesBuffer.Append( nameLengthPckg );
+ propertyNamesBuffer.Append( *aPropertyNames[i] );
+ } // end for
+
+ User::LeaveIfError( SendReceive( EMsgStoreCmdPrepareSearch, TIpcArgs( ¶msPckg, &searchStringsBuffer, &idBuffer, &propertyNamesBuffer ) ) );
+
+ CleanupStack::PopAndDestroy( &propertyNamesBuffer );
+ CleanupStack::PopAndDestroy( &searchStringsBuffer );
+ CleanupStack::PopAndDestroy( &idBuffer );
+
+ __LOG_EXIT
+ } // end PrepareSearchL
+
+// ==========================================================================
+// FUNCTION: GetMatchesL
+// ==========================================================================
+
+void RMessageStoreSession::GetMatchesL( TRequestStatus& aStatus, TDes8& aBuffer )
+ {
+ __LOG_ENTER( "GetMatchesL" )
+
+ aBuffer.SetLength( 0 );
+ SendReceive( EMsgStoreCmdGetMatches, TIpcArgs( &aBuffer ), aStatus );
+
+ __LOG_EXIT
+ } // end GetMatchesL
+
+// ==========================================================================
+// FUNCTION: CancelSearch
+// ==========================================================================
+void RMessageStoreSession::CancelSearch()
+ {
+ __LOG_ENTER( "CancelSearch" )
+
+ SendReceive( EMsgStoreCmdCancelSearch );
+
+ __LOG_EXIT
+ } // end CancelSearch
+
+// ==========================================================================
+// FUNCTION: CleanupSearchResultCache
+// ==========================================================================
+void RMessageStoreSession::ClearSearchResultCache()
+ {
+ __LOG_ENTER( "CleanupSearchResultCache" )
+
+ SendReceive( EMsgStoreCmdClearSearchResultCache );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: SetMaxMruAddressCountL
+// ==========================================================================
+void RMessageStoreSession::SetMaxMruAddressCountL( TInt aMaxCount )
+ {
+ __LOG_ENTER( "SetMaxMruAddressCountL" )
+
+ SendReceive( EMsgStoreCmdSetMaxMruAddressCount, TIpcArgs( aMaxCount ) );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: AddMruAddressesL
+// ==========================================================================
+void RMessageStoreSession::AddMruAddressesL( TMsgStoreId aMailBoxId, RPointerArray<CMsgStoreAddress>& aAddressArray )
+ {
+ __LOG_ENTER( "AddMruAddressesL" )
+
+ //find out the size needed for serializing the addresses
+ TInt totalSize = 0 ;
+ TInt count = aAddressArray.Count();
+ TInt sizeOfLengthFields = sizeof( TUint16 ) * 2; //two lengths
+ for ( TInt i = 0 ; i < count ; i++ )
+ {
+ totalSize += sizeOfLengthFields;
+ CMsgStoreAddress* address = aAddressArray[i];
+ totalSize += (address->EmailAddress().Length() * 2);
+ totalSize += (address->DisplayName().Length() * 2);
+ }
+
+ TUint16 length;
+ TPckg<TUint16> lengthPckg( length );
+
+ RBuf8 serializedBuf;
+ CleanupClosePushL( serializedBuf );
+ serializedBuf.Create( totalSize );
+
+ for( TInt i = 0 ; i < count ; i++ )
+ {
+ CMsgStoreAddress* address = aAddressArray[i];
+
+ //write the email address
+ //length first
+ length = address->EmailAddress().Length() * 2;
+ serializedBuf.Append( lengthPckg );
+
+ //convert the 16 bit descriptor to 8 bit descriptor
+ const TUint8* addressPtr = reinterpret_cast<const TUint8*>( address->EmailAddress().Ptr() );
+ TPtrC8 addressDes( addressPtr, length );
+ serializedBuf.Append( addressDes );
+
+ //write the displayName
+ //length first
+ length = address->DisplayName().Length() * 2;
+ serializedBuf.Append( lengthPckg );
+
+ //convert the 16 bit descriptor to 8 bit descriptor
+ const TUint8* namePtr = reinterpret_cast<const TUint8*>( address->DisplayName().Ptr() );
+ TPtrC8 nameDes( namePtr, length );
+ serializedBuf.Append( nameDes );
+ }
+ SendReceive( EMsgStoreCmdSetMruAddressList, TIpcArgs( aMailBoxId, &serializedBuf ) );
+
+ CleanupStack::PopAndDestroy( &serializedBuf );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: MruAddressesL
+// ==========================================================================
+void RMessageStoreSession::MruAddressesL( TMsgStoreId aMailBoxId, RPointerArray<CMsgStoreAddress>& aAddressArray )
+ {
+ __LOG_ENTER( "MruAddressesL" )
+
+ TUint result = 1;
+ TPckg<TUint> resultPckg( result );
+
+ RBuf8 serializedBuf;
+ CleanupClosePushL( serializedBuf );
+ serializedBuf.CreateL( KInitialPropertiesTransferBufferLength );
+
+ while( result != 0 )
+ {
+ User::LeaveIfError( SendReceive( EMsgStoreCmdGetMruAddressList, TIpcArgs( aMailBoxId, &resultPckg, &serializedBuf ) ) );
+
+ // The buffer was too small. Reallocate.
+ if( result != 0 )
+ {
+ __LOG_WRITE8_FORMAT1_INFO( "growing buffer to %i", result );
+ serializedBuf.ReAllocL( result );
+ }
+ } // end while
+
+ TUint16 length;
+ TPckg<TUint16> lengthPckg( length );
+
+ const TUint8* pointer = serializedBuf.Ptr();
+ const TUint8* endPointer = serializedBuf.Ptr() + serializedBuf.Length();
+
+ // Deserialize data until the current buffer is exhausted.
+ while( pointer < endPointer )
+ {
+ //get the length of email address
+ lengthPckg.Copy( pointer, lengthPckg.Length() );
+ pointer += lengthPckg.Length();
+
+ //get the 16 bit email address
+ const TUint16* addrPtr16 = reinterpret_cast<const TUint16*>( pointer );
+ TPtrC16 addrDes16( addrPtr16, length/2 );
+ pointer += length;
+
+ //get the length of display name
+ lengthPckg.Copy( pointer, lengthPckg.Length() );
+ pointer += lengthPckg.Length();
+
+ //get the 16 bit display name
+ const TUint16* namePtr16 = reinterpret_cast<const TUint16*>( pointer );
+ TPtrC16 nameDes16( namePtr16, length/2 );
+ pointer += length;
+
+ //create the address object and add it to the output array
+ CMsgStoreAddress *address = CMsgStoreAddress::NewL( addrDes16, nameDes16 );
+ aAddressArray.Append( address );
+ } // end while
+
+ CleanupStack::PopAndDestroy( &serializedBuf );
+
+ __LOG_EXIT
+ }
+
+
+// ==========================================================================
+// FUNCTION: ContainerTypeById
+// ==========================================================================
+TMsgStoreContainerType RMessageStoreSession::ContainerTypeById( TMsgStoreId aId )
+ {
+
+ TMsgStoreContainerType resultType = EMsgStoreUnknownContainer;
+
+ TMsgStoreId type = aId & EMsgStoreContainerMask;
+
+ switch( type )
+ {
+ case EMsgStoreMailBoxBits:
+ resultType = EMsgStoreMailboxContainer;
+ break;
+
+ case EMsgStoreFolderBits:
+ resultType = EMsgStoreFolderContainer;
+ break;
+
+ case EMsgStoreMessageBits:
+ resultType = EMsgStoreMessageContainer;
+ break;
+
+ case EMsgStorePartBits:
+ resultType = EMsgStorePartContainer;
+ break;
+ }
+
+ return resultType;
+ }
+
+
+// ==========================================================================
+// FUNCTION: PropertiesL
+// ==========================================================================
+void RMessageStoreSession::PropertiesL( const RArray<TMsgStoreId>& aIds,
+ const RPointerArray<TDesC8>& aPropertyNames,
+ MPropertiesArray& aPropertiesArray )
+ {
+ __LOG_ENTER( "PropertiesL" )
+
+ TMsgStorePropertiesListCmdParams params;
+
+ params.iUseQuery = EFalse;
+ params.iQuickProperties = EFalse;
+
+ // Serialize ID list.
+ TMsgStoreId id;
+ TPckg<TMsgStoreId> idPckg( id );
+
+ RBuf8 idBuffer;
+ idBuffer.CreateL( aIds.Count() * idPckg.Length() );
+ CleanupClosePushL( idBuffer );
+
+ for( TInt i = 0; i < aIds.Count(); i++ )
+ {
+ id = aIds[i];
+ idBuffer.Append( idPckg );
+ } // end for
+
+ // Serialize property names.
+ TUint16 nameLength;
+ TPckg<TUint16> nameLengthPckg( nameLength );
+
+ TInt totalLength = 0;
+ for( TInt i = 0; i < aPropertyNames.Count(); i++ )
+ {
+ totalLength += (aPropertyNames[i]->Length() + nameLengthPckg.Length());
+ } // end for
+
+ RBuf8 propertyNamesBuffer;
+ propertyNamesBuffer.CreateL( totalLength );
+ CleanupClosePushL( propertyNamesBuffer );
+
+ for( TInt i = 0; i < aPropertyNames.Count(); i++ )
+ {
+ nameLength = aPropertyNames[i]->Length();
+ propertyNamesBuffer.Append( nameLengthPckg );
+ propertyNamesBuffer.Append( *aPropertyNames[i] );
+ } // end for
+
+ // Call server.
+ DoPropertiesListL( params, idBuffer, propertyNamesBuffer, aPropertiesArray );
+
+ CleanupStack::PopAndDestroy( &propertyNamesBuffer );
+ CleanupStack::PopAndDestroy( &idBuffer );
+
+ __LOG_EXIT
+ } // end PropertiesL
+
+/**
+ *
+ */
+void RMessageStoreSession::BeginBatchInsertL()
+ {
+ User::LeaveIfError( SendReceive( EMsgStoreCmdBeginBatchInsert ) );
+ }
+
+/**
+ *
+ */
+void RMessageStoreSession::FinishBatchInsertL()
+ {
+ User::LeaveIfError( SendReceive( EMsgStoreCmdFinishBatchInsert ) );
+ }