htiui/HtiServicePlugins/HtiMessagesServicePlugin/src/MessageMgmntHandler.cpp
changeset 0 d6fe6244b863
child 3 2703485a934c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/htiui/HtiServicePlugins/HtiMessagesServicePlugin/src/MessageMgmntHandler.cpp	Tue Feb 02 00:17:27 2010 +0200
@@ -0,0 +1,1879 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Functional implementation of HtiMessagesServicePlugin service
+*
+*/
+
+
+// INCLUDE FILES
+#include "HtiMessagesServicePlugin.h"
+#include "MessageMgmntHandler.h"
+
+#include <HtiDispatcherInterface.h>
+#include <HTILogging.h>
+#include <mtclreg.h>
+#include <smscmds.h>
+#include <smtcmtm.h>
+#include <smuthdr.h>
+#include <smsclnt.h>
+#include <utf.h>
+#include <mmsclient.h>
+#include <mmsconst.h>
+#include <miutset.h>
+#include <irmsgtypeuid.h>
+#include <btmsgtypeuid.h>
+#include <biouids.h>
+#include <apgcli.h>
+#include <apmstd.h>
+#include <bautils.h>
+#include <obexclientmtm.h>
+#include <cmsvmimeheaders.h>
+#include <mmsvattachmentmanager.h>
+
+// CONSTANTS
+_LIT8( KErrorMissingCommand,        "Command was not given - message was empty" );
+_LIT8( KErrorUnrecognizedCommand,   "Unrecognized command" );
+_LIT8( KErrorInvalidParameters,     "Invalid command parameters");
+_LIT8( KErrorTooLongSmsBody,        "Too long SMS body" );
+_LIT8( KErrorInvalidId,             "Invalid SMS id parameter" );
+_LIT8( KErrorInvalidFolder,         "Invalid folder parameter" );
+_LIT8( KErrorItemNotFound,          "Item not found" );
+_LIT8( KErrorFailedDelete,          "Failed to delete item" );
+_LIT8( KErrorNotSupported,          "Not supported" );
+_LIT8( KErrorSmsSettingNotDefined,  "SMS settings not defined" );
+_LIT8( KErrorMmsSettingNotDefined,  "MMS settings not defined" );
+_LIT8( KErrorMailboxNotDefined,     "Mailbox not defined" );
+_LIT8( KErrorMsgTypeNotFound,       "Message type module not found" );
+_LIT8( KErrorMsgStoreOpenFailed,    "Could not open message store" );
+_LIT8( KErrorRfsConnectFailed,      "Could not connect to file server session" );
+_LIT8( KErrorAttachmentNotFound,    "Attachment not found" );
+_LIT8( KErrorInvalidFolderForSmartMsg, "Only inbox allowed for smart messages" );
+
+const static TInt KAddSmsCmdMinLength        = 7;
+const static TInt KAddMmsOrEmailCmdMinLength = 8;
+const static TInt KAddObexMsgCmdMinLength    = 6;
+const static TInt KAddSmartMsgCmdMinLength   = 11;
+const static TInt KAddAudioCmdMinLength      = 10;
+
+// ----------------------------------------------------------------------------
+CMessageMgmntHandler* CMessageMgmntHandler::NewL()
+    {
+    HTI_LOG_FUNC_IN( "CMessageMgmntHandler::NewL" );
+    CMessageMgmntHandler* self = new (ELeave) CMessageMgmntHandler();
+    CleanupStack::PushL ( self );
+    self->ConstructL();
+    CleanupStack::Pop();
+    HTI_LOG_FUNC_OUT( "CMessageMgmntHandler::NewL: Done" );
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+CMessageMgmntHandler::CMessageMgmntHandler()
+    {
+    }
+
+// ----------------------------------------------------------------------------
+CMessageMgmntHandler::~CMessageMgmntHandler()
+    {
+    delete iMtmReg;
+    delete iSession;
+    }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::ConstructL()
+    {
+    HTI_LOG_FUNC_IN( "CMessageMgmntHandler::ConstructL" );
+    iSession = CMsvSession::OpenSyncL( *this );
+    iMtmReg = CClientMtmRegistry::NewL( *iSession );
+    HTI_LOG_FUNC_OUT( "CMessageMgmntHandler::ConstructL: Done" );
+    }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::SetDispatcher( MHtiDispatcher* aDispatcher )
+    {
+    iDispatcher = aDispatcher;
+    }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::ProcessMessageL( const TDesC8& aMessage,
+                                            THtiMessagePriority /*aPriority*/ )
+    {
+    HTI_LOG_FUNC_IN( "CMessageMgmntHandler::ProcessMessageL" );
+    HTI_LOG_FORMAT( "Msg length: %d", aMessage.Length() );
+
+    if ( aMessage.Length() == 0 )
+        {
+        SendErrorMessageL( KErrArgument, KErrorMissingCommand );
+        return;
+        }
+
+    switch ( aMessage[0] )
+        {
+        case CHtiMessagesServicePlugin::EAddSms:
+            HTI_LOG_TEXT( "Add SMS" );
+            HandleCreateSmsL( aMessage.Right( aMessage.Length() - 1 ) );
+            break;
+
+        case CHtiMessagesServicePlugin::EAddMms:
+        case CHtiMessagesServicePlugin::EAddAudioMsg: // special MMS sub type
+            HTI_LOG_TEXT( "Add MMS" );
+            HandleCreateMmsL( aMessage );
+            break;
+
+        case CHtiMessagesServicePlugin::EAddEmail:
+            HTI_LOG_TEXT( "Add Email" );
+            HandleCreateEmailL( aMessage );
+            break;
+
+        case CHtiMessagesServicePlugin::EAddIrMsg:
+            HTI_LOG_TEXT( "Add IR msg" );
+            HandleCreateObexMsgL( aMessage.Right( aMessage.Length() - 1 ),
+                                  TUid::Uid( KUidMsgTypeIrTInt32 ),
+                                  KUidMsgTypeIrUID );
+            break;
+
+        case CHtiMessagesServicePlugin::EAddBtMsg:
+            HTI_LOG_TEXT( "Add BT msg" );
+            HandleCreateObexMsgL( aMessage.Right( aMessage.Length() - 1 ),
+                                  TUid::Uid( KUidMsgTypeBtTInt32 ),
+                                  KUidMsgTypeBt );
+            break;
+
+        case CHtiMessagesServicePlugin::EAddSmartMsg:
+            HTI_LOG_TEXT( "Add smart msg" );
+            HandleCreateSmartMsgL( aMessage.Right( aMessage.Length() - 1 ) );
+            break;
+
+        case CHtiMessagesServicePlugin::EDeleteMessage:
+            HTI_LOG_TEXT( "Delete message" );
+            HandleDeleteMessageL( aMessage.Right( aMessage.Length() - 1 ) );
+            break;
+
+        case CHtiMessagesServicePlugin::EDeleteFolderContent:
+            HTI_LOG_TEXT( "Delete messages" );
+            HandleDeleteMessagesL( aMessage.Right( aMessage.Length() - 1 ) );
+            break;
+
+        default:
+            HTI_LOG_TEXT( "Unknown command" );
+            SendErrorMessageL( KErrUnknown, KErrorUnrecognizedCommand );
+            break;
+        }
+
+    HTI_LOG_FUNC_OUT( "CMessageMgmntHandler::ProcessMessageL: Done" );
+    }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleCreateSmsL( const TDesC8& aData )
+    {
+    HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleSmsImportFuncL" );
+
+    if ( ValidateAddSmsCommand( aData ) )
+        {
+        TInt position( 0 );
+        HBufC16* fromTo = ExtractDesLC( aData, position, 1 );
+        HBufC16* description = ExtractDesLC( aData, position, 1 );
+        HBufC16* body = ExtractDesLC( aData, position, 2 );
+        TBool isNew = (TBool)aData[position];
+        TBool isUnread = (TBool)aData[position+1];
+        TFolder folder = (TFolder)aData[position+2];
+
+        CSmsClientMtm* smsMtm = NULL;
+        TRAPD( err, smsMtm = ( CSmsClientMtm* )iMtmReg->NewMtmL(
+                KUidMsgTypeSMS ) );
+        if ( err || !smsMtm )
+            {
+            HTI_LOG_TEXT( "SMS message type module not found" );
+            SendErrorMessageL( KErrNotFound, KErrorMsgTypeNotFound );
+            CleanupStack::PopAndDestroy( body );
+            CleanupStack::PopAndDestroy( description );
+            CleanupStack::PopAndDestroy( fromTo );
+            return;
+            }
+        CleanupStack::PushL( smsMtm );
+
+        CMsvEntry* entry = CMsvEntry::NewL( *iSession,
+                                            KMsvGlobalInBoxIndexEntryId,
+                                            TMsvSelectionOrdering() );
+        CleanupStack::PushL( entry );
+
+        // get the default service
+        TMsvId defaultServiceId = 0;
+        TRAP( err, defaultServiceId = smsMtm->DefaultServiceL() );
+        if ( err )
+            {
+            HTI_LOG_FORMAT( "Could not get default service, err: %d", err );
+            SendErrorMessageL( err, KErrorSmsSettingNotDefined );
+            CleanupStack::PopAndDestroy( entry );
+            CleanupStack::PopAndDestroy( smsMtm );
+            CleanupStack::PopAndDestroy( body );
+            CleanupStack::PopAndDestroy( description );
+            CleanupStack::PopAndDestroy( fromTo );
+            return;
+            }
+
+        // map the folder parameter to folder id
+        TMsvId folderId = KMsvGlobalInBoxIndexEntryId;
+        TRAP( err, folderId = MapFolderToIdL( folder ) );
+        if ( err )
+            {
+            HTI_LOG_FORMAT( "Invalid folder: %d", folder );
+            SendErrorMessageL( err, KErrorInvalidFolder );
+            CleanupStack::PopAndDestroy( entry );
+            CleanupStack::PopAndDestroy( smsMtm );
+            CleanupStack::PopAndDestroy( body );
+            CleanupStack::PopAndDestroy( description );
+            CleanupStack::PopAndDestroy( fromTo );
+            return;
+            }
+        entry->SetEntryL( folderId );
+
+        // mtm takes ownership of entry context
+        smsMtm->SetCurrentEntryL( entry );
+        CleanupStack::Pop( entry );
+
+        // create a new message
+        smsMtm->CreateMessageL( defaultServiceId );
+
+        if ( folder == EInbox )
+            {
+            CSmsHeader* smsHeader = &( smsMtm->SmsHeader() );
+            delete smsHeader;
+            smsHeader = NULL;
+            smsHeader = CSmsHeader::NewL( CSmsPDU::ESmsDeliver, smsMtm->Body() );
+            smsHeader->SetFromAddressL( fromTo->Des() );
+            }
+        else
+            {
+            smsMtm->AddAddresseeL( fromTo->Des() );
+
+            // set delivery settings
+            CSmsSettings* sendOptions = CSmsSettings::NewL();
+            CleanupStack::PushL( sendOptions );
+            sendOptions->CopyL( smsMtm->ServiceSettings() );
+            sendOptions->SetDelivery( ESmsDeliveryImmediately );
+
+            CSmsHeader* smsHeader = &( smsMtm->SmsHeader() );
+            smsHeader->SetSmsSettingsL( *sendOptions );
+            CleanupStack::PopAndDestroy( sendOptions );
+            }
+
+
+
+        // set body
+        smsMtm->Body().Reset();
+        smsMtm->Body().InsertL( 0, *body );
+
+        // save the message
+        smsMtm->SaveMessageL();
+
+        // get the entry of the message
+        TMsvEntry tentry = smsMtm->Entry().Entry();
+
+        // set the details field
+        tentry.iDetails.Set( fromTo->Des() );
+
+        // set the description field if it is given.
+        // (with no description the beginning of the message body
+        //  is used as a description)
+        if ( description->Length() > 0 )
+            {
+            tentry.iDescription.Set( description->Des() );
+            }
+
+        // final fine tuning
+        tentry.SetAttachment( EFalse );
+        tentry.iDate.UniversalTime();
+        tentry.SetVisible( ETrue );
+        tentry.SetInPreparation( EFalse );
+        tentry.SetUnread( isUnread );
+        tentry.SetNew( isNew );
+        tentry.SetComplete( ETrue );
+        tentry.SetSendingState( KMsvSendStateWaiting );
+        tentry.iServiceId = defaultServiceId;
+        tentry.iRelatedId = 0;
+        if ( folder == EInbox )
+            {
+            tentry.SetReadOnly( ETrue );
+            }
+
+        smsMtm->Entry().ChangeL( tentry );
+
+        // send the message, if it is in outbox
+        if ( folder == EOutbox )
+            {
+            CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection;
+            CleanupStack::PushL( selection );
+            selection->AppendL( tentry.Id() );
+
+            TBuf8<1> dummyParameter;
+            CMsvOperationWait* waiter = CMsvOperationWait::NewLC();
+            CMsvOperation* op = smsMtm->InvokeAsyncFunctionL(
+                    ESmsMtmCommandScheduleCopy, *selection,
+                    dummyParameter, waiter->iStatus );
+            CleanupStack::PushL( op );
+            waiter->Start();
+            CActiveScheduler::Start();
+            CleanupStack::PopAndDestroy( op );
+            CleanupStack::PopAndDestroy( waiter );
+            CleanupStack::PopAndDestroy( selection );
+            }
+
+        CleanupStack::PopAndDestroy( smsMtm );
+        CleanupStack::PopAndDestroy( body );
+        CleanupStack::PopAndDestroy( description );
+        CleanupStack::PopAndDestroy( fromTo );
+
+        TInt32 id = tentry.Id();
+        TBuf8<8> idStr;
+        idStr.Copy( ( TUint8* )( &id ), sizeof( id ) );
+        SendOkMsgL( idStr );
+        }
+
+    HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleSmsImportFuncL: Done");
+    }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleCreateMmsL( const TDesC8& aData )
+    {
+    HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleCreateMmsL" );
+
+    if ( !ValidateAddMmsOrAddEmailCommand( aData ) )
+        {
+        // Error message has been sent from validation method.
+        return;
+        }
+
+    // parse the parameters
+    TInt position( 0 );
+    TInt cmdCode = aData[position];
+    position++;
+    HBufC16* fromTo = ExtractDesLC( aData, position, 1 );
+    HBufC16* description = ExtractDesLC( aData, position, 1 );
+    HBufC8* body = NULL;
+    if ( cmdCode == CHtiMessagesServicePlugin::EAddMms )
+        {
+        body = ExtractDes8LC( aData, position, 2 );
+        }
+    else // Audio msg does not have body text
+        {
+        body = HBufC8::NewLC( 0 );
+        }
+    HBufC16* attPath = ExtractDesLC( aData, position, 1 );
+    TBool isNew = (TBool)aData[position];
+    TBool isUnread = (TBool)aData[position+1];
+    TFolder folder = (TFolder)aData[position+2];
+
+    HTI_LOG_TEXT( "Creating MMS Client MTM" );
+    CMmsClientMtm* mmsMtm = NULL;
+    TRAPD( err , mmsMtm = ( CMmsClientMtm* )iMtmReg->NewMtmL(
+            KUidMsgTypeMultimedia ) );
+    if ( err || !mmsMtm )
+        {
+        HTI_LOG_TEXT( "MMS message type module not found" );
+        SendErrorMessageL( KErrNotFound, KErrorMsgTypeNotFound );
+        CleanupStack::PopAndDestroy( attPath );
+        CleanupStack::PopAndDestroy( body );
+        CleanupStack::PopAndDestroy( description );
+        CleanupStack::PopAndDestroy( fromTo );
+        return;
+        }
+    CleanupStack::PushL( mmsMtm );
+
+    HTI_LOG_TEXT( "Creating MMS Client MTM" );
+    CMsvEntry* entry = CMsvEntry::NewL( *iSession,
+                                        KMsvGlobalInBoxIndexEntryId,
+                                        TMsvSelectionOrdering() );
+    CleanupStack::PushL( entry );
+
+    // get the default service
+    TMsvId defaultServiceId = 0;
+    TRAP( err, defaultServiceId = mmsMtm->DefaultServiceL() );
+    if ( err )
+        {
+        HTI_LOG_FORMAT( "Could not get default service, err: %d", err );
+        SendErrorMessageL( err, KErrorMmsSettingNotDefined );
+        CleanupStack::PopAndDestroy( entry );
+        CleanupStack::PopAndDestroy( mmsMtm );
+        CleanupStack::PopAndDestroy( attPath );
+        CleanupStack::PopAndDestroy( body );
+        CleanupStack::PopAndDestroy( description );
+        CleanupStack::PopAndDestroy( fromTo );
+        return;
+        }
+
+    // map the folder parameter to folder id
+    TMsvId folderId = KMsvGlobalInBoxIndexEntryId;
+    TRAP( err, folderId = MapFolderToIdL( folder ) );
+    if ( err )
+        {
+        HTI_LOG_FORMAT( "Invalid folder: %d", folder );
+        SendErrorMessageL( err, KErrorInvalidFolder );
+        CleanupStack::PopAndDestroy( entry );
+        CleanupStack::PopAndDestroy( mmsMtm );
+        CleanupStack::PopAndDestroy( attPath );
+        CleanupStack::PopAndDestroy( body );
+        CleanupStack::PopAndDestroy( description );
+        CleanupStack::PopAndDestroy( fromTo );
+        return;
+        }
+    entry->SetEntryL( folderId );
+
+    // mtm takes ownership of entry context
+    mmsMtm->SetCurrentEntryL( entry );
+    CleanupStack::Pop( entry );
+
+    HTI_LOG_TEXT( "Creating MMS..." );
+    mmsMtm->CreateMessageL( defaultServiceId );
+    mmsMtm->SetMessageClass( EMmsClassPersonal );
+    mmsMtm->SetExpiryInterval( 86400 );
+    mmsMtm->SetDeliveryTimeInterval( 0 );
+    mmsMtm->SetMessagePriority( EMmsPriorityNormal );
+    mmsMtm->SetSenderVisibility( EMmsMaximumSenderVisibility );
+    mmsMtm->SetDeliveryReport( EMmsDeliveryReportNo );
+    mmsMtm->SetReadReply( EMmsReadReplyYes );
+
+    if ( description->Length() > 0 )
+        {
+        mmsMtm->SetSubjectL( description->Des() );
+        }
+
+    if ( folder == EInbox )
+        {
+        mmsMtm->SetSenderL( fromTo->Des() );
+        }
+    else
+        {
+        mmsMtm->AddAddresseeL( fromTo->Des() );
+        }
+
+    // get an access to the message store
+    HTI_LOG_TEXT( "Getting message store..." );
+    CMsvStore* store = NULL;
+    TRAP( err, store = entry->EditStoreL() );
+    if ( err )
+        {
+        HTI_LOG_FORMAT( "Could not get access to message store, err: %d", err );
+        SendErrorMessageL( err, KErrorMsgStoreOpenFailed );
+        CleanupStack::PopAndDestroy( mmsMtm );
+        CleanupStack::PopAndDestroy( attPath );
+        CleanupStack::PopAndDestroy( body );
+        CleanupStack::PopAndDestroy( description );
+        CleanupStack::PopAndDestroy( fromTo );
+        return;
+        }
+    CleanupStack::PushL( store );
+
+    MMsvAttachmentManager& attachMan = store->AttachmentManagerL();
+    // set body attachment only for normal MMS - audio message doesn't have body
+    if ( cmdCode == CHtiMessagesServicePlugin::EAddMms )
+        {
+        // Set the message body as attachment
+        // Use UTF-8 as charset because MMS created with MMS editor seems to
+        // save text attachments also as UTF-8.
+        HTI_LOG_TEXT( "Setting body..." );
+        CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewL();
+        CleanupStack::PushL( mimeHeaders );
+        mimeHeaders->SetContentTypeL( _L8( "text" ) );
+        mimeHeaders->SetContentSubTypeL( _L8( "plain" ) );
+        mimeHeaders->SetMimeCharset( KMmsUtf8 );
+        mimeHeaders->SetSuggestedFilenameL( _L( "body.txt" ) );
+
+        // ownership of bodyAttachment will be transferred
+        CMsvAttachment* bodyAttachment = CMsvAttachment::NewL(
+                CMsvAttachment::EMsvFile );
+        CleanupStack::PushL( bodyAttachment );
+        bodyAttachment->SetAttachmentNameL( _L( "body.txt" ) );
+        bodyAttachment->SetMimeTypeL( _L8( "text/plain" ) );
+        mimeHeaders->StoreL( *bodyAttachment );
+
+        RFile textFile;
+        CleanupClosePushL( textFile );
+        CWaiter* waiter = CWaiter::NewLC();
+        attachMan.CreateAttachmentL( _L( "body.txt" ), textFile,
+                bodyAttachment, waiter->iStatus );
+        waiter->StartAndWait();
+        CleanupStack::PopAndDestroy( waiter );
+
+        // write the UTF-8 body data to attachment file
+        textFile.Write( *body );
+        CleanupStack::PopAndDestroy(); // textFile
+        CleanupStack::Pop( bodyAttachment ); // ownership transfered
+        CleanupStack::PopAndDestroy( mimeHeaders );
+        }
+
+    // get the entry of the message
+    TMsvEntry tentry = mmsMtm->Entry().Entry();
+
+    // set the details field
+    tentry.iDetails.Set( *fromTo );
+
+    // set the description field
+    if ( description->Length() > 0 )
+        {
+        tentry.iDescription.Set( description->Left( KMmsMaxDescription ) );
+        }
+    else
+        {
+        TBuf<KMmsMaxDescription> descr;
+        CnvUtfConverter::ConvertToUnicodeFromUtf8( descr, *body );
+        tentry.iDescription.Set( descr );
+        }
+
+    // if this is audio message, set the bio type uid
+    if ( cmdCode == CHtiMessagesServicePlugin::EAddAudioMsg )
+        {
+        tentry.iBioType = KUidMsgSubTypeMmsAudioMsg.iUid;
+        }
+
+    // handle attachment
+    TBool attachmentsExist = EFalse;
+    if ( attPath->Length() > 0 )
+        {
+        HTI_LOG_TEXT( "Handling attachment..." );
+        // check that attachment exists
+        RFs fsSession;
+        if ( fsSession.Connect() != KErrNone )
+            {
+            HTI_LOG_FORMAT( "Error in connecting to file server session: %d", err );
+            SendErrorMessageL( KErrCouldNotConnect, KErrorRfsConnectFailed );
+            CleanupStack::PopAndDestroy( store );
+            CleanupStack::PopAndDestroy( mmsMtm );
+            CleanupStack::PopAndDestroy( attPath );
+            CleanupStack::PopAndDestroy( body );
+            CleanupStack::PopAndDestroy( description );
+            CleanupStack::PopAndDestroy( fromTo );
+            return;
+            }
+
+        TBool fileExists = BaflUtils::FileExists( fsSession, attPath->Des() );
+        fsSession.Close();
+        if ( !fileExists )
+            {
+            HTI_LOG_TEXT( "Attachment file not found" );
+            SendErrorMessageL( KErrPathNotFound, KErrorAttachmentNotFound );
+            store->RevertL();
+            CleanupStack::PopAndDestroy( store );
+            CleanupStack::PopAndDestroy( mmsMtm );
+            CleanupStack::PopAndDestroy( attPath );
+            CleanupStack::PopAndDestroy( body );
+            CleanupStack::PopAndDestroy( description );
+            CleanupStack::PopAndDestroy( fromTo );
+            return;
+            }
+        else
+            {
+            // save the attachment
+            TParse parser;
+            parser.Set( *attPath, NULL, NULL);
+            TFileName shortFileName = parser.NameAndExt();
+
+            // get the mime type
+            RApaLsSession ls;
+            User::LeaveIfError( ls.Connect() );
+            CleanupClosePushL( ls );
+            TUid appUid;
+            TDataType dataType;
+            ls.AppForDocument( *attPath, appUid, dataType );
+            CleanupStack::PopAndDestroy(); // ls
+            TPtrC8 mimeType = dataType.Des8();
+
+            // attachment settings
+            // ownership of attachment will be transferred
+            CMsvAttachment* attachment = CMsvAttachment::NewL(
+                    CMsvAttachment::EMsvFile );
+            attachment->SetAttachmentNameL( shortFileName );
+            attachment->SetMimeTypeL( mimeType );
+
+            // save
+            CWaiter* waiter = CWaiter::NewLC();
+            attachMan.AddAttachmentL( *attPath, attachment, waiter->iStatus );
+            waiter->StartAndWait();
+            CleanupStack::PopAndDestroy( waiter );
+            attachmentsExist = ETrue;
+            }
+        }
+
+    // save the changes made to the message store
+    store->CommitL();
+    CleanupStack::PopAndDestroy( store );
+
+    // save the message
+    mmsMtm->SaveMessageL();
+
+    // final fine tuning
+    tentry.SetAttachment( attachmentsExist );
+    tentry.iDate.UniversalTime();
+    tentry.SetVisible( ETrue );
+    tentry.SetInPreparation( EFalse );
+    if ( folder == EDrafts )
+        {
+        tentry.SetReadOnly( EFalse );
+        }
+    else
+        {
+        tentry.SetReadOnly( ETrue );
+        }
+    tentry.SetUnread( isUnread );
+    tentry.SetNew( isNew );
+    tentry.SetComplete( ETrue );
+    tentry.SetSendingState( KMsvSendStateWaiting );
+    tentry.iServiceId = defaultServiceId;
+    tentry.iRelatedId = 0;
+    tentry.iMtmData1 = KMmsMessageMRetrieveConf | KMmsMessageMobileTerminated;
+
+    mmsMtm->Entry().ChangeL( tentry );
+
+    HTI_LOG_TEXT( "MMS created and ready" );
+
+    // send the message, if it is in outbox
+    if ( folder == EOutbox )
+        {
+        HTI_LOG_TEXT( "MMS is in Outbox, sending it..." );
+
+        CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection;
+        CleanupStack::PushL( selection );
+        selection->AppendL( tentry.Id() );
+
+        CMsvOperationWait* waiter = CMsvOperationWait::NewLC();
+        CMsvOperation* op = mmsMtm->SendL( *selection,
+                                           waiter->iStatus,
+                                           tentry.iDate );
+        CleanupStack::PushL( op );
+        waiter->Start();
+        CActiveScheduler::Start();
+        CleanupStack::PopAndDestroy( op );
+        CleanupStack::PopAndDestroy( waiter );
+        CleanupStack::PopAndDestroy( selection );
+        }
+
+    HTI_LOG_TEXT( "Cleaning up" );
+    CleanupStack::PopAndDestroy( mmsMtm );
+    CleanupStack::PopAndDestroy( attPath );
+    CleanupStack::PopAndDestroy( body );
+    CleanupStack::PopAndDestroy( description );
+    CleanupStack::PopAndDestroy( fromTo );
+
+    // send the message id back
+    TInt32 id = tentry.Id();
+    TBuf8<8> idStr;
+    idStr.Copy( ( TUint8* )( &id ), sizeof( id ) );
+    SendOkMsgL( idStr );
+
+    HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleCreateMmsL: Done");
+    }
+
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleCreateEmailL( const TDesC8& aData )
+    {
+    HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleCreateEmailL" );
+
+    if ( ValidateAddMmsOrAddEmailCommand( aData ) )
+        {
+        // parse the parameters
+        TInt position( 1 ); // position 0 is command code
+        HBufC16* fromTo = ExtractDesLC( aData, position, 1 );
+        HBufC16* description = ExtractDesLC( aData, position, 1 );
+        HBufC16* body = ExtractDesLC( aData, position, 2 );
+        HBufC16* attPath = ExtractDesLC( aData, position, 1 );
+        TBool isNew = (TBool)aData[position];
+        TBool isUnread = (TBool)aData[position+1];
+        TFolder folder = (TFolder)aData[position+2];
+
+        HTI_LOG_TEXT( "Creating SMTP Client MTM" );
+        CSmtpClientMtm* smtpMtm = NULL;
+        TRAPD( err, smtpMtm = ( CSmtpClientMtm* )iMtmReg->NewMtmL(
+                KUidMsgTypeSMTP ) );
+        if ( err || !smtpMtm )
+            {
+            HTI_LOG_TEXT( "SMTP message type module not found" );
+            SendErrorMessageL( KErrNotFound, KErrorMsgTypeNotFound );
+            CleanupStack::PopAndDestroy( attPath );
+            CleanupStack::PopAndDestroy( body );
+            CleanupStack::PopAndDestroy( description );
+            CleanupStack::PopAndDestroy( fromTo );
+            return;
+            }
+        CleanupStack::PushL( smtpMtm );
+
+        HTI_LOG_TEXT( "Creating a new CMsvEntry" );
+        CMsvEntry* entry = CMsvEntry::NewL( *iSession,
+                                            KMsvGlobalInBoxIndexEntryId,
+                                            TMsvSelectionOrdering() );
+        CleanupStack::PushL( entry );
+
+        // get the default service
+        HTI_LOG_TEXT( "Getting the default service" );
+        TMsvId defaultServiceId = 0;
+        TRAP( err, defaultServiceId = smtpMtm->DefaultServiceL() );
+        if ( err )
+            {
+            HTI_LOG_FORMAT( "Could not get default service, err: %d", err );
+            SendErrorMessageL( err, KErrorMailboxNotDefined );
+            CleanupStack::PopAndDestroy( entry );
+            CleanupStack::PopAndDestroy( smtpMtm );
+            CleanupStack::PopAndDestroy( attPath );
+            CleanupStack::PopAndDestroy( body );
+            CleanupStack::PopAndDestroy( description );
+            CleanupStack::PopAndDestroy( fromTo );
+            return;
+            }
+
+        // map the folder parameter to folder id
+        HTI_LOG_TEXT( "Mapping the folder parameter to folder id" );
+        TMsvId folderId = KMsvGlobalInBoxIndexEntryId;
+        TRAP( err, folderId = MapFolderToIdL( folder ) );
+        if ( err )
+            {
+            HTI_LOG_FORMAT( "Invalid folder: %d", folder );
+            SendErrorMessageL( err, KErrorInvalidFolder );
+            CleanupStack::PopAndDestroy( entry );
+            CleanupStack::PopAndDestroy( smtpMtm );
+            CleanupStack::PopAndDestroy( attPath );
+            CleanupStack::PopAndDestroy( body );
+            CleanupStack::PopAndDestroy( description );
+            CleanupStack::PopAndDestroy( fromTo );
+            return;
+            }
+        entry->SetEntryL( folderId );
+
+        // mtm takes ownership of entry context
+        smtpMtm->SetCurrentEntryL( entry );
+        CleanupStack::Pop( entry );
+
+        // create a message and set subject and body
+        smtpMtm->CreateMessageL( defaultServiceId );
+        smtpMtm->SetSubjectL( description->Des() );
+        smtpMtm->Body().Reset();
+        smtpMtm->Body().InsertL( 0, body->Des() );
+
+        // get the entry of the message
+        TMsvEntry tentry = smtpMtm->Entry().Entry();
+
+        // add addressee
+        smtpMtm->AddAddresseeL( fromTo->Des() );
+        tentry.iDetails.Set( fromTo->Des() );
+
+        // If creating to Inbox use other than KUidMsgTypeSMTP so that the
+        // mail displays "from" field and not "to" field.
+        if ( folder == EInbox )
+            {
+            tentry.iMtm = KUidMsgTypeIMAP4;
+            }
+
+        // set the description field same as the message subject
+        tentry.iDescription.Set( description->Des() );
+
+        // save the changes done above
+        smtpMtm->Entry().ChangeL( tentry );
+
+        // get an access to the message store
+        CMsvStore* store = entry->EditStoreL();
+        CleanupStack::PushL( store );
+        CImHeader* header = CImHeader::NewLC();
+        header->RestoreL( *store );
+        TUint charset = header->Charset();
+        CleanupStack::PopAndDestroy( header );
+        CleanupStack::PopAndDestroy( store );
+
+        // handle attachment
+        TBool attachmentsExist = EFalse;
+        if ( attPath->Length() > 0 )
+            {
+            // check that attachment exists
+            RFs fsSession;
+            if ( fsSession.Connect() != KErrNone )
+                {
+                HTI_LOG_FORMAT( "Error in connecting to file server session: %d", err );
+                SendErrorMessageL( KErrCouldNotConnect, KErrorRfsConnectFailed );
+                CleanupStack::PopAndDestroy( smtpMtm );
+                CleanupStack::PopAndDestroy( attPath );
+                CleanupStack::PopAndDestroy( body );
+                CleanupStack::PopAndDestroy( description );
+                CleanupStack::PopAndDestroy( fromTo );
+                return;
+                }
+            CleanupClosePushL( fsSession );
+
+            TBool fileExists = BaflUtils::FileExists( fsSession, attPath->Des() );
+            if ( !fileExists )
+                {
+                HTI_LOG_TEXT( "Attachment file not found" );
+                SendErrorMessageL( KErrPathNotFound, KErrorAttachmentNotFound );
+                CleanupStack::PopAndDestroy(); // fsSession
+                CleanupStack::PopAndDestroy( smtpMtm );
+                CleanupStack::PopAndDestroy( attPath );
+                CleanupStack::PopAndDestroy( body );
+                CleanupStack::PopAndDestroy( description );
+                CleanupStack::PopAndDestroy( fromTo );
+                return;
+                }
+            else
+                {
+                // get the mime type
+                HTI_LOG_TEXT( "Getting the attachment's mime type" );
+                RApaLsSession ls;
+                User::LeaveIfError( ls.Connect() );
+                TUid appUid;
+                TDataType dataType;
+                ls.AppForDocument( *attPath, appUid, dataType );
+                TPtrC8 mimeType = dataType.Des8();
+
+                HTI_LOG_TEXT( "Adding the attachment" );
+                CWaiter* waiter = CWaiter::NewLC();
+                smtpMtm->AddAttachmentL( attPath->Des(), mimeType, charset,
+                        waiter->iStatus );
+                waiter->StartAndWait();
+                CleanupStack::PopAndDestroy( waiter );
+                HTI_LOG_TEXT( "Attachment added succesfully" );
+
+                attachmentsExist = ETrue;
+                }
+
+            CleanupStack::PopAndDestroy(); // fsSession
+            }
+
+        // save the message
+        smtpMtm->SaveMessageL();
+
+        // final fine tuning
+        TMsvEmailEntry temailEntry = static_cast<TMsvEmailEntry>( tentry );
+        temailEntry.SetMessageFolderType( EFolderTypeUnknown );
+        temailEntry.SetDisconnectedOperation( ENoDisconnectedOperations );
+        temailEntry.SetEncrypted( EFalse );
+        temailEntry.SetSigned( EFalse );
+        temailEntry.SetVCard( EFalse );
+        temailEntry.SetVCalendar( EFalse );
+        temailEntry.SetReceipt( EFalse );
+        temailEntry.SetMHTMLEmail( EFalse );
+        temailEntry.SetBodyTextComplete( ETrue );
+        temailEntry.SetAttachment( attachmentsExist );
+        temailEntry.iDate.UniversalTime();
+        temailEntry.SetVisible( ETrue );
+        temailEntry.SetInPreparation( EFalse );
+        temailEntry.SetSendingState( KMsvSendStateWaiting );
+        temailEntry.SetUnread( isUnread );
+        temailEntry.SetNew( isNew );
+        temailEntry.SetComplete( ETrue );
+        temailEntry.iServiceId = defaultServiceId;
+        temailEntry.iRelatedId = 0;
+
+        smtpMtm->Entry().ChangeL( temailEntry );
+
+        // get an access to the message store
+        store = entry->EditStoreL();
+        CleanupStack::PushL( store );
+
+        // set email header info
+        header = CImHeader::NewLC();
+        header->RestoreL( *store );
+        header->SetSubjectL( description->Des() );
+        header->SetFromL( fromTo->Des() );
+        header->SetReceiptAddressL( fromTo->Des() );
+        header->StoreL( *store );
+        store->CommitL();
+        CleanupStack::PopAndDestroy( header );
+        CleanupStack::PopAndDestroy( store );
+
+        // send the message, if it is in outbox
+        if ( folder == EOutbox )
+            {
+            HTI_LOG_TEXT( "E-Mail was created in outbox, marking it to be sent on next connection" );
+
+            CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection;
+            CleanupStack::PushL( selection );
+            selection->AppendL( temailEntry.Id() );
+
+            TBuf8<1> dummyParameter;
+            CMsvOperationActiveSchedulerWait* waiter =
+                    CMsvOperationActiveSchedulerWait::NewLC();
+            CMsvOperation* op = smtpMtm->InvokeAsyncFunctionL(
+                    KSMTPMTMSendOnNextConnection, *selection,
+                    dummyParameter, waiter->iStatus );
+            CleanupStack::PushL( op );
+            waiter->Start();
+            CleanupStack::PopAndDestroy( op );
+            CleanupStack::PopAndDestroy( waiter );
+            CleanupStack::PopAndDestroy( selection );
+            }
+
+        HTI_LOG_TEXT( "Cleaning up" );
+        CleanupStack::PopAndDestroy( smtpMtm );
+        CleanupStack::PopAndDestroy( attPath );
+        CleanupStack::PopAndDestroy( body );
+        CleanupStack::PopAndDestroy( description );
+        CleanupStack::PopAndDestroy( fromTo );
+
+        // send the message id back
+        TInt32 id = tentry.Id();
+        TBuf8<8> idStr;
+        idStr.Copy( ( TUint8* )( &id ), sizeof( id ) );
+        SendOkMsgL( idStr );
+        }
+
+    HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleCreateEmailL: Done");
+    }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleCreateObexMsgL( const TDesC8& aData,
+                                                 TUid aMtmUid,
+                                                 TUid aMsgTypeUid )
+    {
+    HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleCreateObexMsgL" );
+
+    if ( ValidateAddObexMsgCommand( aData ) )
+        {
+        // parse the parameters
+        TInt position( 0 );
+        HBufC16* fromTo = ExtractDesLC( aData, position, 1 );
+        HBufC16* description = ExtractDesLC( aData, position, 1 );
+        HBufC16* attPath = ExtractDesLC( aData, position, 1 );
+        TBool isNew = (TBool)aData[position];
+        TBool isUnread = (TBool)aData[position+1];
+        TFolder folder = (TFolder)aData[position+2];
+
+        // Adding Obex messages to the outbox is not allowed
+        if ( folder == EOutbox )
+            {
+            HTI_LOG_TEXT( "Outbox not supported with Obex messages" );
+            SendErrorMessageL( KErrNotSupported, KErrorNotSupported );
+            CleanupStack::PopAndDestroy( attPath );
+            CleanupStack::PopAndDestroy( description );
+            CleanupStack::PopAndDestroy( fromTo );
+            return;
+            }
+
+        CObexClientMtm* obexMtm = NULL;
+        TRAPD( err, obexMtm = ( CObexClientMtm* )iMtmReg->NewMtmL( aMtmUid ) );
+        if ( err || !obexMtm )
+            {
+            HTI_LOG_TEXT( "Obex message type module not found" );
+            SendErrorMessageL( KErrNotFound, KErrorMsgTypeNotFound );
+            CleanupStack::PopAndDestroy( attPath );
+            CleanupStack::PopAndDestroy( description );
+            CleanupStack::PopAndDestroy( fromTo );
+            return;
+            }
+        CleanupStack::PushL( obexMtm );
+
+        CMsvEntry* entry = CMsvEntry::NewL( *iSession,
+                                            KMsvGlobalInBoxIndexEntryId,
+                                            TMsvSelectionOrdering() );
+        CleanupStack::PushL( entry );
+
+        TMsvId defaultServiceId = 0;
+
+        // map the folder parameter to folder id
+        TMsvId folderId = KMsvGlobalInBoxIndexEntryId;
+        TRAP( err, folderId = MapFolderToIdL( folder ) );
+        if ( err )
+            {
+            HTI_LOG_FORMAT( "Invalid folder: %d", folder );
+            SendErrorMessageL( err, KErrorInvalidFolder );
+            CleanupStack::PopAndDestroy( entry );
+            CleanupStack::PopAndDestroy( obexMtm );
+            CleanupStack::PopAndDestroy( attPath );
+            CleanupStack::PopAndDestroy( description );
+            CleanupStack::PopAndDestroy( fromTo );
+            return;
+            }
+        entry->SetEntryL( folderId );
+
+        // mtm takes ownership of entry context
+        obexMtm->SetCurrentEntryL( entry );
+        CleanupStack::Pop( entry );
+
+        // create a new message
+        obexMtm->CreateMessageL( defaultServiceId );
+
+        // get the entry of the message
+        TMsvEntry tentry = obexMtm->Entry().Entry();
+
+        // set subject
+        obexMtm->SetSubjectL( description->Des() );
+        tentry.iDescription.Set( description->Des() );
+
+        // set body, must be empty for obex messages
+        obexMtm->Body().Reset();
+
+        // set the details field and
+        tentry.iDetails.Set( fromTo->Des() );
+
+        // set mtm
+        tentry.iMtm = aMtmUid;
+        tentry.iType = KUidMsvMessageEntry;
+        tentry.iServiceId = KMsvUnknownServiceIndexEntryId;
+
+        // save the changes done above
+        obexMtm->Entry().ChangeL( tentry );
+
+        // save the message
+        obexMtm->SaveMessageL();
+
+        // final fine tuning
+        tentry.iDate.HomeTime();
+        tentry.SetVisible( ETrue );
+        tentry.SetInPreparation( EFalse );
+        tentry.SetUnread( isUnread );
+        tentry.SetNew( isNew );
+        tentry.SetComplete( ETrue );
+        obexMtm->Entry().ChangeL( tentry );
+
+        // handle attachment
+        if ( attPath->Length() > 0 )
+            {
+            // check that attachment exists
+            RFs fsSession;
+            if ( fsSession.Connect() != KErrNone )
+                {
+                HTI_LOG_FORMAT( "Error in connecting to file server session: %d", err );
+                SendErrorMessageL( KErrCouldNotConnect, KErrorRfsConnectFailed );
+                CleanupStack::PopAndDestroy( obexMtm );
+                CleanupStack::PopAndDestroy( attPath );
+                CleanupStack::PopAndDestroy( description );
+                CleanupStack::PopAndDestroy( fromTo );
+                return;
+                }
+
+            TBool fileExists = BaflUtils::FileExists( fsSession, attPath->Des() );
+            fsSession.Close();
+            if ( !fileExists )
+                {
+                HTI_LOG_TEXT( "Attachment file not found" );
+                SendErrorMessageL( KErrPathNotFound, KErrorAttachmentNotFound );
+                CleanupStack::PopAndDestroy( obexMtm );
+                CleanupStack::PopAndDestroy( attPath );
+                CleanupStack::PopAndDestroy( description );
+                CleanupStack::PopAndDestroy( fromTo );
+                return;
+                }
+            else
+                {
+                // create a new entry for the attachment
+                TMsvEntry attachTEntry;
+                attachTEntry.iType = KUidMsvAttachmentEntry;
+                attachTEntry.iServiceId = KMsvUnknownServiceIndexEntryId;
+                attachTEntry.iMtm = aMsgTypeUid; //save as bt message
+
+                entry->CreateL( attachTEntry );
+
+                CMsvEntry* attachEntry = iSession->GetEntryL( attachTEntry.Id() );
+                obexMtm->SetCurrentEntryL( attachEntry );
+
+                // get source file
+                TFileName sourceFileName = attPath->Des();
+
+                // get the mime type
+                RApaLsSession ls;
+                User::LeaveIfError( ls.Connect() );
+                CleanupClosePushL<RApaLsSession>(ls);
+                TUid appUid;
+                TDataType mimeType;
+                ls.AppForDocument( sourceFileName, appUid, mimeType );
+                CleanupStack::PopAndDestroy(); //ls
+
+                CWaiter* waiter = CWaiter::NewLC();
+
+                // add an attachment to the current message entry
+                obexMtm->AddAttachmentL( sourceFileName, mimeType.Des8(), 0,
+                        waiter->iStatus );
+                waiter->StartAndWait();
+                CleanupStack::PopAndDestroy( waiter );
+                }
+            }
+
+        CleanupStack::PopAndDestroy( obexMtm );
+        CleanupStack::PopAndDestroy( attPath );
+        CleanupStack::PopAndDestroy( description );
+        CleanupStack::PopAndDestroy( fromTo );
+
+        // send the message id back
+        TInt32 id = tentry.Id();
+        TBuf8<8> idStr;
+        idStr.Copy( ( TUint8* )( &id ), sizeof( id ) );
+        SendOkMsgL( idStr );
+        }
+
+    HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleCreateObexMsgL: Done");
+    }
+
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleCreateSmartMsgL( const TDesC8& aData )
+    {
+    HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleCreateSmartMsgL" );
+
+    if ( ValidateAddSmartMsgCommand( aData ) )
+        {
+        TInt position( 0 );
+        HBufC16* fromTo = ExtractDesLC( aData, position, 1 );
+        HBufC16* description = ExtractDesLC( aData, position, 1 );
+        HBufC16* body = ExtractDesLC( aData, position, 2 );
+        TBool isNew = (TBool)aData[position];
+        TBool isUnread = (TBool)aData[position+1];
+        TFolder folder = (TFolder)aData[position+2];
+        TInt bioUidValue =   aData[position+3] +
+                           ( aData[position+4] << 8 ) +
+                           ( aData[position+5] << 16 ) +
+                           ( aData[position+6] << 24 );
+
+
+        // Smart messages can be created only to inbox.
+        // For sending smart messages, create a normal SMS with smart message
+        // content as a body and send it.
+        if ( folder != EInbox )
+            {
+            HTI_LOG_TEXT( "Invalid folder specified for smart message" );
+            SendErrorMessageL( KErrArgument, KErrorInvalidFolderForSmartMsg );
+            CleanupStack::PopAndDestroy( body );
+            CleanupStack::PopAndDestroy( description );
+            CleanupStack::PopAndDestroy( fromTo );
+            return;
+
+            }
+
+        CSmsClientMtm* smsMtm = NULL;
+        TRAPD( err, smsMtm = ( CSmsClientMtm* )iMtmReg->NewMtmL( KUidMsgTypeSMS ) );
+        if ( err || !smsMtm )
+            {
+            HTI_LOG_TEXT( "SMS message type module not found" );
+            SendErrorMessageL( KErrNotFound, KErrorMsgTypeNotFound );
+            CleanupStack::PopAndDestroy( body );
+            CleanupStack::PopAndDestroy( description );
+            CleanupStack::PopAndDestroy( fromTo );
+            return;
+            }
+        CleanupStack::PushL( smsMtm );
+
+        CMsvEntry* entry = CMsvEntry::NewL( *iSession,
+                KMsvGlobalInBoxIndexEntryId, TMsvSelectionOrdering() );
+        CleanupStack::PushL( entry );
+
+        // get the default service
+        TMsvId defaultServiceId = 0;
+        TRAP( err, defaultServiceId = smsMtm->DefaultServiceL() );
+        if ( err )
+            {
+            HTI_LOG_FORMAT( "Could not get default service, err: %d", err );
+            SendErrorMessageL( err, KErrorSmsSettingNotDefined );
+            CleanupStack::PopAndDestroy( entry );
+            CleanupStack::PopAndDestroy( smsMtm );
+            CleanupStack::PopAndDestroy( body );
+            CleanupStack::PopAndDestroy( description );
+            CleanupStack::PopAndDestroy( fromTo );
+            return;
+            }
+
+        // no need for folder mapping, since only inbox allowed for smart messages
+        TMsvId folderId = KMsvGlobalInBoxIndexEntryId;
+        entry->SetEntryL( folderId );
+
+        // mtm takes ownership of entry context
+        smsMtm->SetCurrentEntryL( entry );
+        CleanupStack::Pop( entry );
+
+        // create a new message
+        smsMtm->CreateMessageL( defaultServiceId );
+
+        // update the message header
+        CSmsHeader* smsHeader = &( smsMtm->SmsHeader() );
+        delete smsHeader;
+        smsHeader = NULL;
+        smsHeader = CSmsHeader::NewL( CSmsPDU::ESmsDeliver, smsMtm->Body() );
+        smsHeader->SetFromAddressL( fromTo->Des() );
+
+        // set body, the actual BIO message content
+        smsMtm->Body().Reset();
+        smsMtm->Body().InsertL( 0, body->Des() );
+
+        // get the entry of the message
+        TMsvEntry tentry = smsMtm->Entry().Entry();
+
+        // set BIO message type specific data
+        tentry.iBioType = bioUidValue;
+        smsMtm->BioTypeChangedL( TUid::Uid( bioUidValue ) );
+
+        // set details field
+        tentry.iDetails.Set( fromTo->Des() );
+
+        // set the description field
+        tentry.iDescription.Set( description->Des() );
+
+        // set correct MTM type
+        tentry.iMtm= KUidBIOMessageTypeMtm;
+
+        // final fine tuning
+        tentry.SetAttachment( EFalse );
+        tentry.iDate.UniversalTime();
+        tentry.SetVisible( ETrue );
+        tentry.SetInPreparation( EFalse );
+        tentry.SetUnread( isUnread );
+        tentry.SetNew( isNew );
+        tentry.SetComplete( ETrue );
+        tentry.SetSendingState( KMsvSendStateWaiting );
+        tentry.iServiceId = defaultServiceId;
+        tentry.iRelatedId = 0;
+
+        // save the changes done above
+        smsMtm->Entry().ChangeL( tentry );
+
+        // save the message
+        smsMtm->SaveMessageL();
+
+        CleanupStack::PopAndDestroy( smsMtm );
+        CleanupStack::PopAndDestroy( body );
+        CleanupStack::PopAndDestroy( description );
+        CleanupStack::PopAndDestroy( fromTo );
+
+        TInt32 id = tentry.Id();
+        TBuf8<8> idStr;
+        idStr.Copy( ( TUint8* )( &id ), sizeof( id ) );
+        SendOkMsgL( idStr );
+        }
+
+    HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleCreateSmartMsgL: Done");
+    }
+
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleDeleteMessageL( const TDesC8& aData )
+    {
+    HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleDeleteMessageL" );
+
+    if ( aData.Length() != 4 )
+        {
+        HTI_LOG_TEXT( "CMessageMgmntHandler: Error: wrong length of data" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidId );
+        return;
+        }
+
+    TMsvId entryId =   aData[0] +
+                     ( aData[1] << 8 ) +
+                     ( aData[2] << 16 ) +
+                     ( aData[3] << 24 );
+    HTI_LOG_FORMAT( "CMessageMgmntHandler: Deleting one message, id: %d", entryId );
+    TMsvEntry entry;
+    TMsvId service;
+    User::LeaveIfError( iSession->GetEntry( entryId, service, entry ) );
+
+    CMsvEntry* parentCEntry = iSession->GetEntryL( entry.Parent() );
+    CleanupStack::PushL( parentCEntry );
+    TRAPD( err, parentCEntry->DeleteL( entry.Id() ) );
+    CleanupStack::PopAndDestroy( parentCEntry );
+
+    if ( err == KErrNone )
+        {
+        SendOkMsgL( KNullDesC8 );
+        }
+    else if ( err == KErrNotFound )
+        {
+        SendErrorMessageL( err, KErrorItemNotFound );
+        }
+    else
+        {
+        SendErrorMessageL( err, KErrorFailedDelete );
+        }
+
+    HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleDeleteMessageL: Done");
+    }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleDeleteMessagesL( const TDesC8& aData )
+    {
+    HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleDeleteMessagesFuncL" );
+
+    if ( aData.Length() != 2 )
+        {
+        HTI_LOG_TEXT( "CMessageMgmntHandler: Error: wrong length of data" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidFolder );
+        return;
+        }
+
+    if ( aData[0] == EAllFolders )
+        {
+        HandleDeleteFromAllFoldersL( (TMessageType)aData[1] );
+        }
+    else if ( aData[1] == EAllMessageTypes )
+        {
+        HandleDeleteAllMessageTypesL( (TFolder)aData[0] );
+        }
+    else
+        {
+        HandleDeleteFromFolderByTypeL( (TFolder)aData[0],
+                                       (TMessageType)aData[1] );
+        }
+
+    SendOkMsgL( KNullDesC8 );
+    HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleDeleteMessagesFuncL: Done");
+    }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleDeleteFromAllFoldersL( TMessageType aType )
+    {
+    HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleDeleteFromAllFoldersL" );
+
+    if ( aType == EAllMessageTypes )
+        {
+        for ( TInt i = 1; i < ENumberOfFolders; i++ )
+            {
+            HandleDeleteAllMessageTypesL( (TFolder)i );
+            }
+        }
+    else
+        {
+        for ( TInt i = 1; i < ENumberOfFolders; i++ )
+            {
+            HandleDeleteFromFolderByTypeL( (TFolder)i, aType );
+            }
+        }
+
+    HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleDeleteFromAllFoldersL: Done");
+    }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleDeleteAllMessageTypesL( TFolder aFolder )
+    {
+    HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleDeleteAllMessageTypesL" );
+
+    if ( aFolder == EAllFolders )
+        {
+        for ( TInt i = 1; i < ENumberOfMessageTypes; i++ )
+            {
+            HandleDeleteFromAllFoldersL( (TMessageType)i );
+            }
+        }
+    else
+        {
+        for ( TInt i = 1; i < ENumberOfMessageTypes; i++ )
+            {
+            HandleDeleteFromFolderByTypeL( aFolder, (TMessageType)i );
+            }
+        }
+
+    HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleDeleteAllMessageTypesL: Done");
+    }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleDeleteFromFolderByTypeL( TFolder aFolder,
+                                                          TMessageType aType )
+    {
+    HTI_LOG_FUNC_IN( "CMessageMgmntHandler::HandleDeleteFromFolderByTypeL" );
+
+    TMsvId folderId = MapFolderToIdL( aFolder );
+    TUid msgTypeUid = MapMessageTypeToUidL( aType );
+
+    HTI_LOG_TEXT( "Deleting messages..." );
+    HTI_LOG_FORMAT( "Folder: %d", aFolder );
+    HTI_LOG_FORMAT( "Message type: %d", aType );
+
+    CMsvEntry* folder = CMsvEntry::NewL( *iSession,
+                                         folderId,
+                                         TMsvSelectionOrdering() );
+    CleanupStack::PushL( folder );
+    CMsvEntrySelection* sel = folder->ChildrenWithMtmL( msgTypeUid );
+
+    CleanupStack::PushL( sel );
+    HTI_LOG_FORMAT( "Found %d matching items", sel->Count() );
+
+    for ( TInt i = 0; i < sel->Count(); i++ )
+        {
+        TMsvId entryId = sel->At( i );
+        TMsvEntry entry;
+        TMsvId service;
+        User::LeaveIfError( iSession->GetEntry( entryId, service, entry ) );
+        if ( ( aType == EAudioMessage && entry.iBioType != KUidMsgSubTypeMmsAudioMsg.iUid ) ||
+                ( aType == EMMS && entry.iBioType == KUidMsgSubTypeMmsAudioMsg.iUid ) )
+            {
+            // do not delete audio messages when MMS deletion
+            // requested and vice versa
+            continue;
+            }
+        CMsvEntry* parentCEntry = iSession->GetEntryL( entry.Parent() );
+        CleanupStack::PushL( parentCEntry );
+        parentCEntry->DeleteL( entry.Id() );
+        CleanupStack::PopAndDestroy( parentCEntry );
+        }
+
+    CleanupStack::PopAndDestroy( sel );
+    CleanupStack::PopAndDestroy( folder );
+
+    if ( aType == EEmail )
+        {
+        HandleDeleteFromFolderByTypeL( aFolder, EEmailPOP3 );
+        HandleDeleteFromFolderByTypeL( aFolder, EEmailIMAP4 );
+        }
+
+    HTI_LOG_FUNC_OUT("CMessageMgmntHandler::HandleDeleteFromFolderByTypeL: Done");
+    }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::SendOkMsgL( const TDesC8& aData )
+    {
+    HTI_LOG_FUNC_IN("CMessageMgmntHandler::SendOkMsgL: Starting");
+
+    User::LeaveIfNull( iDispatcher );
+
+    HBufC8* temp = HBufC8::NewL( aData.Length() + 1 );
+    TPtr8 response = temp->Des();
+    response.Append( (TChar) CHtiMessagesServicePlugin::EResultOk );
+    response.Append( aData );
+    User::LeaveIfError( iDispatcher->DispatchOutgoingMessage(
+        temp, KHtiMessagesServiceUid ) );
+
+    HTI_LOG_FUNC_OUT("CMessageMgmntHandler::SendOkMsgL: Done");
+    }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::SendErrorMessageL( TInt aError,
+                                              const TDesC8& aDescription )
+    {
+    HTI_LOG_FUNC_IN("CMessageMgmntHandler::SendErrorMessageL: Starting");
+    User::LeaveIfNull( iDispatcher );
+    User::LeaveIfError( iDispatcher->DispatchOutgoingErrorMessage(
+        aError, aDescription, KHtiMessagesServiceUid ) );
+    HTI_LOG_FUNC_OUT("CMessageMgmntHandler::SendErrorMessageL: Done");
+    }
+
+// ----------------------------------------------------------------------------
+TBool CMessageMgmntHandler::ValidateAddSmsCommand( const TDesC8& aData )
+    {
+    if ( aData.Length() < KAddSmsCmdMinLength )
+        {
+        HTI_LOG_TEXT( "ValidateAddSmsCommand: Error: missing data" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+        return EFalse;
+        }
+
+    TInt offset = 0;
+    TInt fromLength = aData[offset];
+
+    offset = 1 + fromLength;
+    if ( offset > aData.Length() - 1 )
+        {
+        HTI_LOG_TEXT( "ValidateAddSmsCommand: Error: wrong length of data" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+        return EFalse;
+        }
+    TInt descrLength = aData[offset];
+
+    offset = offset + 1 + descrLength;
+    if ( offset > aData.Length() - 2 ) // body length in two bytes
+        {
+        HTI_LOG_TEXT( "ValidateAddSmsCommand: Error: wrong length of data" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+        return EFalse;
+        }
+    TInt bodyLength = aData[offset] + ( aData[offset+1] << 8 );
+
+    TInt wholeLength = 1 + fromLength +
+                       1 + descrLength +
+                       2 + bodyLength +
+                       1 + // is new
+                       1 + // is unread
+                       1;  // folder
+
+    if ( wholeLength != aData.Length() )
+        {
+        HTI_LOG_TEXT( "ValidateAddSmsCommand: Error: wrong length of data" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+        return EFalse;
+        }
+
+    if ( bodyLength > 160 )
+        {
+        HTI_LOG_TEXT( "ValidateAddSmsCommand: Error: too long SMS body" );
+        SendErrorMessageL( KErrOverflow, KErrorTooLongSmsBody );
+        return EFalse;
+        }
+
+    return ETrue;
+    }
+
+
+// ----------------------------------------------------------------------------
+TBool CMessageMgmntHandler::ValidateAddMmsOrAddEmailCommand( const TDesC8& aData )
+    {
+    HTI_LOG_FUNC_IN( "CMessageMgmntHandler::ValidateAddMmsOrAddEmailCommand" );
+    if ( aData.Length() < KAddMmsOrEmailCmdMinLength + 1 ) // +1 = cmd code
+        {
+        HTI_LOG_TEXT( "Error: missing data" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+        return EFalse;
+        }
+
+    if ( aData[0] == CHtiMessagesServicePlugin::EAddAudioMsg &&
+            aData.Length() < KAddAudioCmdMinLength + 1 ) // +1 = cmd code
+        {
+        HTI_LOG_TEXT( "ValidateAddMmsOrAddEmailCommand: Error: missing data" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+        return EFalse;
+        }
+
+    TInt offset = 0;
+    TInt cmdCode = aData[offset];
+    offset++;
+    TInt fromToLength = aData[offset];
+    fromToLength++; // the length byte
+
+    offset = offset + fromToLength;
+    if ( offset > aData.Length() - 1 )
+        {
+        HTI_LOG_TEXT( "Error: wrong length of data" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+        return EFalse;
+        }
+    TInt descrLength = aData[offset];
+    descrLength++; // the length byte
+
+    offset = offset + descrLength;
+    TInt bodyLength = 0;
+    if ( cmdCode != CHtiMessagesServicePlugin::EAddAudioMsg )
+        {
+        if ( offset > aData.Length() - 2 ) // body length in two bytes
+            {
+            HTI_LOG_TEXT( "Error: wrong length of data" );
+            SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+            return EFalse;
+            }
+        bodyLength = aData[offset] + ( aData[offset+1] << 8 );
+        bodyLength += 2; // the body length bytes
+        }
+
+    offset = offset + bodyLength;
+    if ( offset > aData.Length() - 1 )
+        {
+        HTI_LOG_TEXT( ": wrong length of data" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+        return EFalse;
+        }
+    TInt attPathLength = aData[offset];
+    if ( attPathLength == 0 && cmdCode == CHtiMessagesServicePlugin::EAddAudioMsg )
+        {
+        // attachment (the audio) is mandatory for audio message
+        HTI_LOG_TEXT( "Error: missing attachment" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+        return EFalse;
+        }
+    attPathLength++; // the length byte
+
+    TInt wholeLength = 1 + // command code
+                       fromToLength + descrLength +  bodyLength + attPathLength +
+                       1 + // is new
+                       1 + // is unread
+                       1;  // folder
+
+    if ( wholeLength != aData.Length() )
+        {
+        HTI_LOG_TEXT( "Error: wrong length of data (wholeLength)" );
+        HTI_LOG_FORMAT( "Expected: %d", wholeLength );
+        HTI_LOG_FORMAT( "Was:      %d", aData.Length() );
+        SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+        return EFalse;
+        }
+
+    return ETrue;
+    }
+
+
+// ----------------------------------------------------------------------------
+TBool CMessageMgmntHandler::ValidateAddObexMsgCommand( const TDesC8& aData )
+    {
+    if ( aData.Length() < KAddObexMsgCmdMinLength )
+        {
+        HTI_LOG_TEXT( "ValidateAddObexMsgCommand: Error: missing data" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+        return EFalse;
+        }
+
+    TInt offset = 0;
+    TInt fromToLength = aData[offset];
+
+    offset = 1 + fromToLength;
+    if ( offset > aData.Length() - 1 )
+        {
+        HTI_LOG_TEXT( "ValidateAddObexMsgCommand: Error: wrong length of data" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+        return EFalse;
+        }
+    TInt descrLength = aData[offset];
+
+    offset = offset + 1 + descrLength;
+    if ( offset > aData.Length() - 1 )
+        {
+        HTI_LOG_TEXT( "ValidateAddObexMsgCommand: Error: wrong length of data" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+        return EFalse;
+        }
+    TInt attPathLength = aData[offset];
+
+    TInt wholeLength = 1 + fromToLength +
+                       1 + descrLength +
+                       1 + attPathLength +
+                       1 + // is new
+                       1 + // is unread
+                       1;  // folder
+
+    if ( wholeLength != aData.Length() )
+        {
+        HTI_LOG_TEXT( "ValidateAddObexMsgCommand: Error: wrong length of data" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+        return EFalse;
+        }
+
+    return ETrue;
+    }
+
+// ----------------------------------------------------------------------------
+TBool CMessageMgmntHandler::ValidateAddSmartMsgCommand( const TDesC8& aData )
+    {
+    if ( aData.Length() < KAddSmartMsgCmdMinLength )
+        {
+        HTI_LOG_TEXT( "ValidateAddSmartMsgCommand: Error: missing data" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+        return EFalse;
+        }
+
+    TInt offset = 0;
+    TInt fromToLength = aData[offset];
+
+    offset = 1 + fromToLength;
+    if ( offset > aData.Length() - 1 )
+        {
+        HTI_LOG_TEXT( "ValidateAddSmartMsgCommand: Error: wrong length of data" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+        return EFalse;
+        }
+    TInt descrLength = aData[offset];
+
+    offset = offset + 1 + descrLength;
+    if ( offset > aData.Length() - 2 ) // body length in two bytes
+        {
+        HTI_LOG_TEXT( "ValidateAddSmartMsgCommand: Error: wrong length of data" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+        return EFalse;
+        }
+    TInt bodyLength = aData[offset] + ( aData[offset+1] << 8 );
+
+    TInt wholeLength = 1 + fromToLength +
+                       1 + descrLength +
+                       2 + bodyLength +
+                       1 + // is new
+                       1 + // is unread
+                       1 + // folder
+                       4;  // biomessage uid
+
+    if ( wholeLength != aData.Length() )
+        {
+        HTI_LOG_TEXT( "ValidateAddSmartMsgCommand: Error: wrong length of data" );
+        SendErrorMessageL( KErrArgument, KErrorInvalidParameters );
+        return EFalse;
+        }
+
+    return ETrue;
+    }
+
+
+// ----------------------------------------------------------------------------
+// Extracts UTF-8 data, converts it to Unicode and returns as 16-bit descriptor.
+// Within aData, read descriptor from aPosition:
+//  - first bytes tell the size of data for UTF8 formatted data
+//  - next bytes are the data as indicated by the size
+//  - position is finally set to the end of UTF8 data area
+// ----------------------------------------------------------------------------
+HBufC16* CMessageMgmntHandler::ExtractDesLC( const TDesC8& aUtf8Data,
+                                             TInt& aPosition,
+                                             TInt aSizeBytes )
+    {
+    HTI_LOG_FUNC_IN( "CMessageMgmntHandler::ExtractDesLC" );
+    TInt length = 0;
+    for ( TInt i = 0; i < aSizeBytes; i++ )
+        {
+        length += ( aUtf8Data[aPosition+i] << ( i * 8 ) );
+        }
+
+    if ( length < 0 ||
+         length > aUtf8Data.Mid( aPosition ).Length() )
+        {
+        User::Leave( KErrBadDescriptor );
+        }
+
+    HBufC16* result = NULL;
+
+    if ( length > 0 )
+        {
+        result = CnvUtfConverter::ConvertToUnicodeFromUtf8L(
+            aUtf8Data.Mid( aPosition + aSizeBytes, length ) );
+        HTI_LOG_TEXT( "ExtractDesLC: Conversion to Unicode done" );
+        CleanupStack::PushL( result );
+        }
+
+    else
+        {
+        result = HBufC16::NewLC( 0 );
+        }
+
+    aPosition += ( aSizeBytes + length );
+
+    HTI_LOG_FUNC_OUT( "CMessageMgmntHandler::ExtractDesLC" );
+    return result;
+    }
+
+
+// ----------------------------------------------------------------------------
+// Extracts UTF-8 data to 8-bit descriptor without doing any conversions.
+// ----------------------------------------------------------------------------
+HBufC8* CMessageMgmntHandler::ExtractDes8LC( const TDesC8& aUtf8Data,
+                                             TInt& aPosition,
+                                             TInt aSizeBytes )
+    {
+    HTI_LOG_FUNC_IN( "CMessageMgmntHandler::ExtractDes8LC" );
+    TInt length = 0;
+    for ( TInt i = 0; i < aSizeBytes; i++ )
+        {
+        length += ( aUtf8Data[aPosition+i] << ( i * 8 ) );
+        }
+
+    if ( length < 0 ||
+         length > aUtf8Data.Mid( aPosition ).Length() )
+        {
+        User::Leave( KErrBadDescriptor );
+        }
+
+    HBufC8* result = HBufC8::NewLC( length );
+
+    if ( length > 0 )
+        {
+        result->Des().Copy( aUtf8Data.Mid( aPosition + aSizeBytes, length ) );
+        }
+
+    aPosition += ( aSizeBytes + length );
+
+    HTI_LOG_FUNC_OUT( "CMessageMgmntHandler::ExtractDes8LC" );
+    return result;
+    }
+
+
+// ----------------------------------------------------------------------------
+TMsvId CMessageMgmntHandler::MapFolderToIdL( TFolder aFolder )
+    {
+    TMsvId id = 0;
+
+    switch ( aFolder )
+        {
+        case EInbox:  { id = KMsvGlobalInBoxIndexEntryId;   break; }
+        case EDrafts: { id = KMsvDraftEntryId;              break; }
+        case ESent:   { id = KMsvSentEntryId;               break; }
+        case EOutbox: { id = KMsvGlobalOutBoxIndexEntryId;  break; }
+        default:      { User::Leave( KErrArgument );        break; }
+        }
+
+    return id;
+    }
+
+// ----------------------------------------------------------------------------
+TUid CMessageMgmntHandler::MapMessageTypeToUidL( TMessageType aType )
+    {
+    TUid uid = { 0 };
+
+    switch ( aType )
+        {
+        case ESMS:          { uid = KUidMsgTypeSMS;            break; }
+        case EAudioMessage: // fall through - audio msg is MMS sub type
+        case EMMS:          { uid = KUidMsgTypeMultimedia;     break; }
+        case ESmartMessage: { uid = KUidBIOMessageTypeMtm;     break; }
+        case EEmail:        { uid = KUidMsgTypeSMTP;           break; }
+        case EEmailPOP3:    { uid = KUidMsgTypePOP3;           break; }
+        case EEmailIMAP4:   { uid = KUidMsgTypeIMAP4;          break; }
+        case EIrMessage:    { uid = KUidMsgTypeIrUID;          break; }
+        case EBtMessage:    { uid = KUidMsgTypeBt;             break; }
+        default:            { User::Leave( KErrArgument );     break; }
+        }
+
+    return uid;
+    }
+
+// ----------------------------------------------------------------------------
+void CMessageMgmntHandler::HandleSessionEventL( TMsvSessionEvent /*aEvent*/,
+                                                TAny* /*aArg1*/,
+                                                TAny* /*aArg2*/,
+                                                TAny* /*aArg3*/ )
+    {
+    }
+
+
+
+// ----------------------------------------------------------------------------
+CWaiter* CWaiter::NewL( TInt aPriority )
+    {
+    CWaiter* self = new(ELeave) CWaiter( aPriority );
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+CWaiter* CWaiter::NewLC( TInt aPriority )
+    {
+    CWaiter* self = new(ELeave) CWaiter( aPriority );
+    CleanupStack::PushL( self );
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+CWaiter::CWaiter( TInt aPriority ) : CActive( aPriority )
+    {
+    CActiveScheduler::Add( this );
+    }
+
+// ----------------------------------------------------------------------------
+CWaiter::~CWaiter()
+    {
+    Cancel();
+    }
+
+// ----------------------------------------------------------------------------
+void CWaiter::StartAndWait()
+    {
+    iStatus = KRequestPending;
+    SetActive();
+    iWait.Start();
+    }
+
+// ----------------------------------------------------------------------------
+TInt CWaiter::Result() const
+    {
+    return iResult;
+    }
+
+// ----------------------------------------------------------------------------
+void CWaiter::RunL()
+    {
+    iResult = iStatus.Int();
+    iWait.AsyncStop();
+    }
+
+// ----------------------------------------------------------------------------
+void CWaiter::DoCancel()
+    {
+    iResult = KErrCancel;
+    if ( iStatus == KRequestPending )
+        {
+        TRequestStatus* status = &iStatus;
+        User::RequestComplete( status, KErrCancel );
+        }
+
+    iWait.AsyncStop();
+    }
+
+
+// End of file