smsprotocols/smsstack/gsmu/src/gsmuieoperations.cpp
changeset 0 3553901f7fa8
child 24 6638e7f4bd8f
child 42 3adadc800673
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/smsprotocols/smsstack/gsmu/src/gsmuieoperations.cpp	Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,1852 @@
+// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "Gsmumain.h"
+#include "gsmuieoperations.h"
+#include "Gsmumsg.h"
+#include "gsmumsgadditionalattributes.h"
+#include "Gsmuelem.h"
+#include "smsstacklog.h"
+
+
+/**
+ *  This is used by the CSmsMessage to create a CSmsIEOperation.
+ *  Each instance is owned by the CSmsMessage which created it.
+ *  Therefore only the CSmsMessage (GSMU component) is allowed to
+ *  create and delete CSmsIEOperations.
+ *  
+ *  @param aId
+ *  The ID for the CSmsInformationElement for whom an operation class needs to be created.
+ *  @param aMessage
+ *  The CSmsMessage that this operations class belongs to.
+ *  @param aCharacterSetConverter
+ *  A reference to a character set converter, needed by some derived operation classes.
+ *  @param aFs
+ *  A reference to the file server, needed by some derived operations classes.
+ *  
+ *  @internalComponent
+ */
+CSmsIEOperation*  CSmsIEOperation::NewL(CSmsInformationElement::TSmsInformationElementIdentifier aId, CSmsMessage& aMessage, CCnvCharacterSetConverter& aCharacterSetConverter, RFs& aFs)
+	{
+	LOGGSMU1("CSmsIEOperation::NewL()");
+
+	CSmsIEOperation* iEOperation = NULL;
+
+	switch (aId)
+	    {
+	    case CSmsInformationElement::ESmsHyperLinkFormat:
+	        iEOperation = new (ELeave)  CSmsHyperLinkOperations(aId,aMessage);
+	        break;
+	    case CSmsInformationElement::ESmsReplyAddressFormat:
+	        iEOperation = new (ELeave) CSmsReplyAddressOperations(aId, aMessage, aCharacterSetConverter, aFs);
+	        break;
+	    case CSmsInformationElement::ESmsEnhanceVoiceMailInformation:
+	        iEOperation = new (ELeave) CSmsEnhancedVoiceMailOperations(aId, aMessage, aCharacterSetConverter, aFs);
+	        break;
+	    case CSmsInformationElement::ESmsIEISpecialSMSMessageIndication:
+	        iEOperation = new (ELeave)  CSmsSpecialSMSMessageOperations(aId,aMessage);
+	        break;
+	    case CSmsInformationElement::ESmsIEISMSCControlParameters:
+	        iEOperation = new (ELeave)  CSmsSMSCCtrlParameterOperations(aId,aMessage); 
+	        break;
+	    default:
+	        User::Leave(KErrArgument);
+	        break;
+	    }
+
+	iEOperation->ConstructL();
+
+	return iEOperation;
+	} // CSmsIEOperation::NewL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Identifies the information element which is supported by this operations class.
+ *  
+ *  @return The information element ID supported by this operations class.
+ *  @capability None
+ */
+EXPORT_C CSmsInformationElement::TSmsInformationElementIdentifier CSmsIEOperation::Id() const
+	{
+	LOGGSMU1("CSmsIEOperation::Id()");
+
+	return iId;
+	} // CSmsInformationElement::TSmsInformationElementIdentifier
+
+
+/**
+ *  @internalComponent
+ *  
+ *  Identifies whether the message type supports is supported
+ *  
+ *  @return True if the message type is supported. False otherwise.
+ */
+TBool CSmsIEOperation::MessageTypeSupported() const
+	{
+	LOGGSMU1("CSmsIEOperation::MessageTypeSupported()");
+
+	CSmsPDU::TSmsPDUType type = iMessage.Type();
+
+    return ((type == CSmsPDU::ESmsDeliver) ||
+            (type == CSmsPDU::ESmsSubmit));
+	} // CSmsIEOperation::MessageTypeSupported
+
+
+CSmsIEOperation::CSmsIEOperation(CSmsInformationElement::TSmsInformationElementIdentifier aId, CSmsMessage& aMessage) : iId(aId), iMessage(aMessage)
+	{
+	//NOP
+	} // CSmsIEOperation::CSmsIEOperation
+
+
+/**
+ *  @internalComponent
+ *  
+ *  Prevent clients from using the assignment operator by including it in the class definition
+ *  but making it protected and not exporting it.
+ *  
+ *  @capability None
+ */
+void CSmsIEOperation::operator=(const CSmsIEOperation&)
+    {
+    // Ignore in code coverage - not intended to be used
+    BULLSEYE_OFF    
+    LOGGSMU1("CSmsIEOperation::operator=");
+    Panic(KGsmuPanicMethodBodyNotImplemented1);
+    BULLSEYE_RESTORE
+    }
+
+/**
+ *  @internalComponent
+ *  
+ *  Prevent clients from using the equality operator by including it in the class definition
+ *  but making it protected and not exporting it.
+ *  
+ *  @capability None
+ */
+TBool CSmsIEOperation::operator==(const CSmsIEOperation&)
+    {
+    // Ignore in code coverage - not intended to be used
+    BULLSEYE_OFF    
+    LOGGSMU1("CSmsIEOperation::operator==");
+    Panic(KGsmuPanicMethodBodyNotImplemented1);
+    return EFalse;
+    BULLSEYE_RESTORE
+    }
+
+/**
+ *  @internalComponent
+ *  
+ *  Prevent clients from using the assignment operator by including it in the class definition
+ *  but making it protected and not exporting it.
+ *  
+ *  @capability None
+ */
+void CSmsCtrlOperation::operator=(const CSmsCtrlOperation&)
+    {
+    // Ignore in code coverage - not intended to be used
+    BULLSEYE_OFF    
+    LOGGSMU1("CSmsCtrlOperation::operator=");
+    Panic(KGsmuPanicMethodBodyNotImplemented1);
+    BULLSEYE_RESTORE
+    }
+
+/**
+ *  @internalComponent
+ *  
+ *  Prevent clients from using the equality operator by including it in the class definition
+ *  but making it protected and not exporting it.
+ *  
+ *  @capability None
+ */
+TBool CSmsCtrlOperation::operator==(const CSmsCtrlOperation&)
+    {
+    // Ignore in code coverage - not intended to be used
+    BULLSEYE_OFF    
+    LOGGSMU1("CSmsCtrlOperation::operator==");
+    Panic(KGsmuPanicMethodBodyNotImplemented1);
+    return EFalse;
+    BULLSEYE_RESTORE
+    }
+
+CSmsCtrlOperation::CSmsCtrlOperation(CSmsInformationElement::TSmsInformationElementIdentifier aId, CSmsMessage& aMessage) : CSmsIEOperation(aId, aMessage)
+	{
+	//NOP
+	} // CSmsCtrlOperation::CSmsCtrlOperation
+
+
+CSmsHyperLinkOperations::CSmsHyperLinkOperations(CSmsInformationElement::TSmsInformationElementIdentifier aId, CSmsMessage& aMessage) : CSmsCtrlOperation(aId, aMessage)
+	{
+	//NOP
+	} // CSmsHyperLinkOperations::CSmsHyperLinkOperations
+
+
+void CSmsIEOperation::ConstructL()
+	{
+	LOGGSMU1("CSmsIEOperation::ConstructL()");
+	} // CSmsIEOperation::ConstructL
+
+
+/**
+ *  @internalComponent
+ *  
+ *  Prevent clients from using the assignment operator by including it in the class definition
+ *  but making it protected and not exporting it.
+ *  
+ *  @capability None
+ */
+void CSmsHyperLinkOperations::operator=(const CSmsHyperLinkOperations&)
+    {
+    // Ignore in code coverage - not intended to be used
+    BULLSEYE_OFF    
+    LOGGSMU1("CSmsHyperLinkOperations::operator=");
+    Panic(KGsmuPanicMethodBodyNotImplemented1);
+    BULLSEYE_RESTORE
+    }
+
+/**
+ *  @internalComponent
+ *  
+ *  Prevent clients from using the equality operator by including it in the class definition
+ *  but making it protected and not exporting it.
+ *  
+ *  @capability None
+ */
+TBool CSmsHyperLinkOperations::operator==(const CSmsHyperLinkOperations&)
+    {
+    // Ignore in code coverage - not intended to be used
+    BULLSEYE_OFF    
+    LOGGSMU1("CSmsHyperLinkOperations::operator==");
+    Panic(KGsmuPanicMethodBodyNotImplemented1);
+    return EFalse;
+    BULLSEYE_RESTORE
+    }
+
+/**
+ *  @internalComponent
+ *  
+ *  Identifies whether the message type or version supports this operation
+ *  
+ *  @leave
+ *  If the message type or version does not support this operation.
+ */
+void CSmsHyperLinkOperations::ValidateOperationL() const
+	{
+	LOGGSMU1("CSmsHyperLinkOperations::ValidateOperationL()");
+
+	if (iMessage.Version() < CSmsMessage::ESmsMessageV1)
+	    {
+	    LOGGSMU2("CSmsHyperLinkOperations::AddHyperLinkL, Operation not supported, Msg Version %d", iMessage.Version());
+	    User::Leave(KErrNotSupported);
+	    }
+
+	if (!MessageTypeSupported())
+	    {
+	    LOGGSMU2("CSmsHyperLinkOperations::AddHyperLinkL, Operation not supported by this PDU type, type = %d", iMessage.Type());
+	    User::Leave(KErrNotSupported);
+	    }
+	} // CSmsHyperLinkOperations::ValidateOperationL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  This method adds a HyperLink to the CSmsMessage.
+ *  
+ *  @param aPosition
+ *  The absolute character position within the message text.
+ *  @param aTitle
+ *  An integer representation of the number of characters in the hyperlink title.
+ *  @param URL Length
+ *  An integer representation of the number of characters in the URL.
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support hyperlinks.
+ *  @capability None
+ */
+EXPORT_C void CSmsHyperLinkOperations::AddHyperLinkL(TUint aPosition, TUint8 aTitleLength,  TUint8  aURLLength) const
+	{
+	LOGGSMU1("CSmsHyperLinkOperations::AddHyperLinkL()");
+
+	ValidateOperationL();
+
+	CSmsMessageAdditionalAttributes& additionalAttributes = *((CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo());
+
+	TBuf8 <4> buffer;
+	buffer.SetLength(4);
+	buffer[0] = (TUint8) (aPosition >> 8); // lowest octet contains the
+	buffer[1] = (TUint8)  aPosition;       // most significant bits
+	buffer[2] = aTitleLength;
+	buffer[3] = aURLLength;
+
+	CSmsInformationElement* iE = CSmsInformationElement::NewL(CSmsInformationElement::ESmsHyperLinkFormat, buffer);
+	CleanupStack::PushL(iE);
+	additionalAttributes.AddControlInformationElementL(iE);
+	CleanupStack::Pop(iE);
+	} // CSmsHyperLinkOperations::AddHyperLinkL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Returns the number of Hyper Link IEs contained in this message.
+ *  @leave KErrNotSupported
+ *  If this functionality is not supported by this version or type of message.
+ *  @return
+ *  The number of hyper links contained in this message.
+ *  @capability None
+ */
+EXPORT_C TUint CSmsHyperLinkOperations::NumberOfHyperLinksL() const
+	{
+	LOGGSMU1("CSmsHyperLinkOperations::NumberOfHyperLinks");
+
+	ValidateOperationL();
+
+	TUint numberOfHyperLinks = 0;
+
+	TSmsInformationElementCategories::TInformationElementCategory category;
+
+	if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsHyperLinkFormat, category) == EFalse)
+			{
+		User::Leave(KErrArgument);
+		}
+
+	CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo();
+	TUint numberOfElements = additionalAttributes->NumberOfControlInformationElements(category);
+
+	for (TUint i = 0; i < numberOfElements; i++)
+	    {
+	    CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum;
+	    
+	    // If function leaves, allow the error to propagate upwards
+	    id = additionalAttributes->GetControlInformationElementL(category, i).Identifier();
+
+	    if (id == CSmsInformationElement::ESmsHyperLinkFormat)
+	        {
+	        numberOfHyperLinks++;
+	        }
+	    }
+
+	return numberOfHyperLinks;
+	} // CSmsHyperLinkOperations::NumberOfHyperLinksL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Copies the attributes of the specified hyperlink.
+ *  aIndex has the range [0..[n-1]] where n is the
+ *  value returned by NumberOfHyperLinks()
+ *  
+ *  @param aIndex
+ *  Identifies the hyperlink to extract. Has the range [0..[n-1]]
+ *  where n is the value returned by NumberOfHyperLinks().
+ *  @param &aPosition
+ *  The absolute character position within the message text.
+ *  @param &aTitleLength
+ *  An integer representation of the number of characters in the hyperlink title.
+ *  @param &aURLLength
+ *  An integer representation of the number of characters in the URL.
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support hyperlinks.
+ *  @leave KErrArgument
+ *  If aIndex is out of range.
+ *  @capability None
+ */
+EXPORT_C void  CSmsHyperLinkOperations::CopyHyperLinkAtIndexL(TUint aIndex, TUint& aPosition, TUint8& aTitleLength,  TUint8&  aURLLength) const
+	{
+	LOGGSMU2("CSmsHyperLinkOperations::CopyHyperLinkAtIndexL(): aIndex=%d", aIndex);
+
+	ValidateOperationL();
+
+	TUint numberOfHyperLinks = 0;
+
+	TSmsInformationElementCategories::TInformationElementCategory category;
+	if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsHyperLinkFormat, category) == EFalse)
+		{
+		User::Leave(KErrArgument);
+		}
+
+	CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo();
+	TUint numberOfElements = additionalAttributes->NumberOfControlInformationElements(category);
+
+	if (aIndex >= numberOfElements)
+	    {
+	    User::Leave(KErrArgument);
+	    }
+
+	for (TUint i = 0; i < numberOfElements; i++)
+	    {
+	    CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum;
+	    
+	    // If function leaves, allow the error to propagate upwards
+	    id = additionalAttributes->GetControlInformationElementL(category, i).Identifier();
+
+	    if ((id == CSmsInformationElement::ESmsHyperLinkFormat) &&
+	        (numberOfHyperLinks++ == aIndex))
+	        {
+	        aPosition     = (additionalAttributes->GetControlInformationElementL(category, i).Data()[0] << 8);
+	        aPosition    +=  additionalAttributes->GetControlInformationElementL(category, i).Data()[1];
+
+	        aTitleLength = additionalAttributes->GetControlInformationElementL(category, i).Data()[2];
+	        aURLLength   = additionalAttributes->GetControlInformationElementL(category, i).Data()[3];
+	        break;
+	        }
+	    }
+	} // CSmsHyperLinkOperations::CopyHyperLinkAtIndexL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Removes all hyper Link IEs contained in this message.
+ *  
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support hyperlinks.
+ *  @capability None
+ */
+EXPORT_C void  CSmsHyperLinkOperations::RemoveAllHyperLinksL() const
+	{
+	LOGGSMU1("CSmsHyperLinkOperations::RemoveAllHyperLinks");
+
+	ValidateOperationL();
+
+	TSmsInformationElementCategories::TInformationElementCategory category;
+
+	if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsHyperLinkFormat, category) == EFalse)
+		{
+		User::Leave(KErrArgument);
+		}
+
+	CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo();
+	TUint i = additionalAttributes->NumberOfControlInformationElements(category);
+
+	while (i-- != 0)
+	    {
+	    CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum;
+	    
+	    // If function leaves, allow the error to propagate upwards
+	    id = additionalAttributes->GetControlInformationElementL(category, i).Identifier();
+
+	    if (id == CSmsInformationElement::ESmsHyperLinkFormat)
+	        {
+	        additionalAttributes->DeleteControlInformationElement(category, i);
+	        }
+	    }
+	} // CSmsHyperLinkOperations::RemoveAllHyperLinksL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Removes the indexed hyperlink from this message.
+ *  
+ *  @param aIndex
+ *  aIndex has the range [0..[n-1]] where n is the
+ *  value returned by NumberOfHyperLinks()
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support hyperlinks.
+ *  @leave KErrArgument
+ *  If the index is out of range.
+ *  @capability None
+ */
+EXPORT_C void  CSmsHyperLinkOperations::RemoveHyperLinkL(TUint aIndex) const
+	{
+	LOGGSMU1("CSmsHyperLinkOperations::RemoveHyperLink");
+
+	ValidateOperationL();
+
+	TUint numberOfHyperLinks = 0;
+
+	TSmsInformationElementCategories::TInformationElementCategory category;
+
+	if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsHyperLinkFormat, category) == EFalse)
+		{
+		User::Leave(KErrArgument);
+		}
+
+	CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo();
+	TUint numberOfElements = additionalAttributes->NumberOfControlInformationElements(category);
+
+	if (aIndex >= numberOfElements)
+	    {
+	    User::Leave(KErrArgument);
+	    }
+
+	for (TUint i = 0; i < numberOfElements; i++)
+	    {
+	    CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum;
+
+	    // If function leaves, allow the error to propagate upwards
+	    id = additionalAttributes->GetControlInformationElementL(category, i).Identifier();
+
+	    if ((id == CSmsInformationElement::ESmsHyperLinkFormat) &&
+	        (numberOfHyperLinks++ == aIndex))
+	        {
+	        additionalAttributes->DeleteControlInformationElement(category, i);
+	        break;
+	        }
+	    }
+	} // CSmsHyperLinkOperations::RemoveHyperLinkL
+
+
+/**
+ *  @internalComponent
+ *  
+ *  Prevent clients from using the assignment operator by including it in the class definition
+ *  but making it protected and not exporting it.
+ *  
+ *  @capability None
+ */
+void CSmsReplyAddressOperations::operator=(const CSmsReplyAddressOperations&)
+    {
+    // Ignore in code coverage - not intended to be used
+    BULLSEYE_OFF    
+    LOGGSMU1("CSmsReplyAddressOperations::operator=");
+    Panic(KGsmuPanicMethodBodyNotImplemented1);
+    BULLSEYE_RESTORE
+    }
+
+/**
+ *  @internalComponent
+ *  
+ *  Prevent clients from using the equality operator by including it in the class definition
+ *  but making it protected and not exporting it.
+ *  
+ *  @capability None
+ */
+TBool CSmsReplyAddressOperations::operator==(const CSmsReplyAddressOperations&)
+    {
+    // Ignore in code coverage - not intended to be used
+    BULLSEYE_OFF    
+    LOGGSMU1("CSmsReplyAddressOperations::operator==");
+    Panic(KGsmuPanicMethodBodyNotImplemented1);
+    return EFalse;
+    BULLSEYE_RESTORE
+    }
+
+/**
+ *  @internalComponent
+ *  
+ *  Identifies whether the message type or version supports this operation
+ *  
+ *  @leave
+ *  If the message type or version does not support this operation.
+ */
+void CSmsReplyAddressOperations::ValidateOperationL() const
+	{
+	LOGGSMU1("CSmsReplyAddressOperations::ValidateOperationL()");
+
+	if (iMessage.Version() < CSmsMessage::ESmsMessageV1)
+	    {
+	    LOGGSMU2("CSmsReplyAddressOperations::AddReplyAddressL, Operation not supported, Msg Version %d", iMessage.Version());
+	    User::Leave(KErrNotSupported);
+	    }
+
+	if (!MessageTypeSupported())
+	    {
+	    LOGGSMU2("CSmsReplyAddressOperations::AddReplyAddressL, Operation not supported by this PDU type, type = %d", iMessage.Type());
+	    User::Leave(KErrNotSupported);
+	    }
+	} // CSmsReplyAddressOperations::ValidateOperationL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Adds a reply address information element.
+ *  
+ *  @param aAddress
+ *  The international number to be used in the reply address.
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support a reply addresses.
+ *  @leave KErrAlreadyExists
+ *  If the message already contains a reply address.
+ *  @capability None
+ */
+EXPORT_C void  CSmsReplyAddressOperations::AddReplyAddressL(const TDesC& aAddress) const
+	{
+	LOGGSMU1("CSmsReplyAddressOperations::AddReplyAddressL()");
+
+	ValidateOperationL();
+
+	if (ContainsReplyAddressIEL())
+	    {
+	    LOGGSMU1("CSmsReplyAddressOperations::AddReplyAddressL, Already Exists");
+	    User::Leave(KErrAlreadyExists);
+	    }
+
+	CSmsMessageAdditionalAttributes& additionalAttributes = *((CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo());
+
+	CSmsAddress* address = CSmsAddress::NewL(iCharacterSetConverter,iFs); // needed for encoding the address into the IE.
+	CleanupStack::PushL(address);
+	address->SetAddressL(aAddress);
+	TBuf8<CSmsAddress::KSmsAddressMaxAddressLength> addressBuffer;
+	addressBuffer.SetLength(CSmsAddress::KSmsAddressMaxAddressLength);
+	TUint8* startPtr = &addressBuffer[0];
+	TUint8* endPtr = address->EncodeL(startPtr);
+	TInt length = 0;
+	(endPtr > startPtr) ? (length = endPtr - startPtr) : (length = startPtr - endPtr);
+	addressBuffer.SetLength(length);
+	CleanupStack::PopAndDestroy(address);
+
+	CSmsInformationElement* iE = CSmsInformationElement::NewL(CSmsInformationElement::ESmsReplyAddressFormat, addressBuffer);
+	CleanupStack::PushL(iE);
+	additionalAttributes.AddControlInformationElementL(iE);
+	CleanupStack::Pop(iE);
+	} // CSmsReplyAddressOperations::AddReplyAddressL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Adds a reply address information element.
+ *  
+ *  @param aAddress
+ *  Sets To and From addresses in ETSI format.
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support a reply addresses.
+ *  @leave KErrAlreadyExists
+ *  If the message already contains a reply address.
+ *  @capability None
+ */
+EXPORT_C void  CSmsReplyAddressOperations::AddParsedReplyAddressL(const TGsmSmsTelNumber& aParsedAddress) const
+	{
+	LOGGSMU1("CSmsReplyAddressOperations::AddParsedReplyAddressL");
+
+	ValidateOperationL();
+
+	if (ContainsReplyAddressIEL())
+	    {
+	    LOGGSMU1("CSmsReplyAddressOperations::AddParsedReplyAddressL, Already Exists");
+	    User::Leave(KErrAlreadyExists);
+	    }
+
+	CSmsMessageAdditionalAttributes& additionalAttributes = *((CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo());
+
+	CSmsAddress* address = CSmsAddress::NewL(iCharacterSetConverter,iFs);
+	CleanupStack::PushL(address);
+	address->SetParsedAddressL(aParsedAddress);
+	TBuf8<CSmsAddress::KSmsAddressMaxAddressLength> addressBuffer;
+	addressBuffer.SetLength(CSmsAddress::KSmsAddressMaxAddressLength);
+	TUint8* startPtr = &addressBuffer[0];
+	TUint8* endPtr = address->EncodeL(startPtr);
+	TInt length = 0;
+	(endPtr > startPtr) ? (length = endPtr - startPtr) : (length = startPtr - endPtr);
+	addressBuffer.SetLength(length);
+	CleanupStack::PopAndDestroy(address);
+
+	CSmsInformationElement* iE = CSmsInformationElement::NewL(CSmsInformationElement::ESmsReplyAddressFormat, addressBuffer);
+	CleanupStack::PushL(iE);
+	additionalAttributes.AddControlInformationElementL(iE);
+	CleanupStack::Pop(iE);
+	} // CSmsReplyAddressOperations::AddParsedReplyAddressL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Identifies whether a reply address has already been added to this
+ *  CSmsMessage using the CSmsReplyAddressOperations interface.
+ *  
+ *  @return
+ *  True if the reply address has already been added using this interface.
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support this query.
+ *  @capability None
+ */
+EXPORT_C TBool CSmsReplyAddressOperations::ContainsReplyAddressIEL() const
+	{
+	LOGGSMU1("CSmsReplyAddressOperations::ContainsReplyAddressIEL()");
+
+	TBool rc = EFalse;
+
+	ValidateOperationL();
+
+	TSmsInformationElementCategories::TInformationElementCategory category;
+
+	if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsReplyAddressFormat, category) == EFalse)
+		{
+		User::Leave(KErrArgument);
+		}
+
+	CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo();
+	TUint numberOfElements = additionalAttributes->NumberOfControlInformationElements(category);
+
+	for (TUint i = 0; i < numberOfElements; i++)
+	    {
+	    CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum;
+	    
+	    // If function leaves, allow the error to propagate upwards
+	    id = additionalAttributes->GetControlInformationElementL(category, i).Identifier();
+
+	    if (id == CSmsInformationElement::ESmsReplyAddressFormat)
+	        {
+	        rc = ETrue;
+	        break;
+	        }
+	    }
+
+	return rc;
+	} // CSmsReplyAddressOperations::ContainsReplyAddressIEL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Returns the reply address as an international number
+ *  
+ *  @return
+ *  The reply address as an international number.
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support this query.
+ *  @leave KErrNotFound
+ *  If the message does not contain a reply address information element.
+ *  @leave KErrCorrupt
+ *  If the reply address is corrupt
+ *  @capability None
+ */
+EXPORT_C HBufC* CSmsReplyAddressOperations::GetReplyAddressL() const
+	{
+	LOGGSMU1("CSmsReplyAddressOperations::GetReplyAddressL");
+
+	ValidateOperationL();
+
+	TBool found = EFalse;
+
+	CSmsAddress* address = CSmsAddress::NewL(iCharacterSetConverter,iFs);
+	CleanupStack::PushL(address);
+
+	TSmsInformationElementCategories::TInformationElementCategory category;
+
+	if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsReplyAddressFormat, category) == EFalse)
+		{
+		User::Leave(KErrArgument);
+		}
+
+	CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo();
+	TUint numberOfElements = additionalAttributes->NumberOfControlInformationElements(category);
+
+	for (TUint i = 0; i < numberOfElements; i++)
+	    {
+	    CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum;
+	    
+	    // If function leaves, allow the error to propagate upwards
+	    id = additionalAttributes->GetControlInformationElementL(category, i).Identifier();
+
+	    if (id == CSmsInformationElement::ESmsReplyAddressFormat)
+	        {
+	        TGsmuLex8 encodedAddress(additionalAttributes->GetControlInformationElementL(category, i).Data());
+	        TRAPD(err,address->DecodeL(encodedAddress));
+
+	        if (err == KErrNone)
+	            {
+	            found = ETrue;
+	            break;
+	            }
+	        else
+	            {
+	            User::Leave(KErrCorrupt);
+	            }
+	        }
+	    }
+
+	HBufC* buf = NULL;
+	if (found)
+	    {
+	    buf = HBufC::NewL(TGsmSmsTelNumberMaxLen); // 20 characters preceeded by '+'
+	    *buf = address->Address();
+	    }
+	else
+	    {
+	    User::Leave(KErrNotFound);
+	    }
+
+	CleanupStack::PopAndDestroy(address);
+
+	return buf;
+	} // CSmsReplyAddressOperations::GetReplyAddressL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Returns the reply address in ETSI format.
+ *  
+ *  @return
+ *  True, if the CSmsMessage contains a reply address.
+ *  False, otherwise
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support this query.
+ *  @leave KErrCorrupt
+ *  If the reply address is corrupt
+ *  @capability None
+ */
+EXPORT_C TInt  CSmsReplyAddressOperations::GetParsedReplyAddressL(TGsmSmsTelNumber& aParsedAddress) const
+	{
+	LOGGSMU1("CSmsReplyAddressOperations::GetParsedReplyAddressL");
+
+	ValidateOperationL();
+
+	TBool rc = EFalse;
+
+	CSmsAddress* address = CSmsAddress::NewL(iCharacterSetConverter,iFs);
+	CleanupStack::PushL(address);
+
+	TSmsInformationElementCategories::TInformationElementCategory category;
+
+	if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsReplyAddressFormat, category) == EFalse)
+		{
+		User::Leave(KErrArgument);
+		}
+
+	CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo();
+	TUint numberOfElements = additionalAttributes->NumberOfControlInformationElements(category);
+
+	for (TUint i = 0; i < numberOfElements; i++)
+	    {
+	    CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum;
+	    
+	    // If function leaves, allow the error to propagate upwards
+	    id = additionalAttributes->GetControlInformationElementL(category, i).Identifier();
+
+	    // CSmsAddress is used here for encoding the reply address into an IE.
+	    // It also used to encode the source / destination address in the CSmsMessage.
+	    // CSmsAddress::DecodeL expects internally that alphanumeric addresses will be size
+	    // CSmsAddress::KSmsAddressMaxAddressValueLength=10.
+	    // Need to add padding bytes to bring the address field up to the maximum size.
+	    if (id == CSmsInformationElement::ESmsReplyAddressFormat)
+	        {
+	        TBuf8<CSmsAddress::KSmsAddressMaxAddressLength> data;
+	        data = additionalAttributes->GetControlInformationElementL(category, i).Data();
+	        TUint8 actualDataLength = data.Length();
+	        data.SetLength(CSmsAddress::KSmsAddressMaxAddressLength);
+	        for (TUint8 j = actualDataLength; j < CSmsAddress::KSmsAddressMaxAddressLength; j++)
+	            {
+	            data[j] = 0;
+	            }
+
+	        TGsmuLex8 encodedAddress(data);
+	        TRAPD(err,address->DecodeL(encodedAddress));
+	        if (err==KErrNone)
+	            {
+	            address->ParsedAddress(aParsedAddress);
+	            rc = ETrue;
+	            break;
+	            }
+	        else
+	            {
+	            User::Leave(KErrCorrupt);
+	            }
+	        }
+	    }
+
+	CleanupStack::PopAndDestroy(address);
+
+	return rc;
+	} // CSmsReplyAddressOperations::GetParsedReplyAddressL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Removes the reply address information element.
+ *  
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support this query.
+ *  @capability None
+ */
+EXPORT_C void  CSmsReplyAddressOperations::RemoveReplyAddressL() const
+	{
+	LOGGSMU1("CSmsReplyAddressOperations::RemoveReplyAddress");
+
+	ValidateOperationL();
+
+	TSmsInformationElementCategories::TInformationElementCategory category;
+
+	if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsReplyAddressFormat, category) == EFalse)
+		{
+		User::Leave(KErrArgument);
+		}
+
+	CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo();
+	TUint numberOfElements = additionalAttributes->NumberOfControlInformationElements(category);
+
+	for (TInt i = 0; i < numberOfElements; i++)
+	    {
+	    CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum;
+	    
+	    // If function leaves, allow the error to propagate upwards
+	    id = additionalAttributes->GetControlInformationElementL(category, i).Identifier();
+
+	    if (id == CSmsInformationElement::ESmsReplyAddressFormat)
+	        {
+	        additionalAttributes->DeleteControlInformationElement(category, i);
+	        break;
+	        }
+	    }
+	} // CSmsReplyAddressOperations::RemoveReplyAddressL
+
+
+CSmsReplyAddressOperations::CSmsReplyAddressOperations(CSmsInformationElement::TSmsInformationElementIdentifier aId,  CSmsMessage& aMessage,
+                                                       CCnvCharacterSetConverter& aCharacterSetConverter, RFs& aFs) : CSmsCtrlOperation(aId, aMessage),
+                                                       iCharacterSetConverter(aCharacterSetConverter), iFs(aFs)
+	{
+	//NOP
+	} // CSmsReplyAddressOperations::CSmsReplyAddressOperations
+
+
+/**
+ *  @internalComponent
+ *  
+ *  Identifies whether the message type or version supports this operation
+ *  
+ *  @leave
+ *  If the message type or version does not support this operation.
+ */
+void CSmsSpecialSMSMessageOperations::ValidateOperationL() const
+	{
+	LOGGSMU1("CSmsSpecialSMSMessageOperations::ValidateOperationL()");
+
+	if (iMessage.Version() < CSmsMessage::ESmsMessageV1)
+	    {
+	    LOGGSMU2("CSmsSpecialSMSMessageOperations::AddSpecialMessageIndicationL, Operation not supported, version %d", iMessage.Version());
+	    User::Leave(KErrNotSupported);
+	    }
+
+	if (!MessageTypeSupported())
+	    {
+	    LOGGSMU2("CSmsSpecialSMSMessageOperations::AddSpecialMessageIndicationL, Operation not supported by this PDU type, type = %d", iMessage.Type());
+	    User::Leave(KErrNotSupported);
+	    }
+	} // CSmsSpecialSMSMessageOperations::ValidateOperationL
+
+
+/**
+ *  @internalComponent
+ *  
+ *  Prevent clients from using the assignment operator by including it in the class definition
+ *  but making it protected and not exporting it.
+ *  
+ *  @capability None
+ */
+void CSmsSpecialSMSMessageOperations::operator=(const CSmsSpecialSMSMessageOperations&)
+    {
+    // Ignore in code coverage - not intended to be used
+    BULLSEYE_OFF    
+    LOGGSMU1("CSmsSpecialSMSMessageOperations::operator=");
+    Panic(KGsmuPanicMethodBodyNotImplemented1);
+    BULLSEYE_RESTORE
+    }
+
+/**
+ *  @internalComponent
+ *  
+ *  Prevent clients from using the equality operator by including it in the class definition
+ *  but making it protected and not exporting it.
+ *  
+ *  @capability None
+ */
+TBool CSmsSpecialSMSMessageOperations::operator==(const CSmsSpecialSMSMessageOperations&)
+	{
+	LOGGSMU1("CSmsSpecialSMSMessageOperations::operator==");
+	Panic(KGsmuPanicMethodBodyNotImplemented1);
+	return EFalse;
+	} // CSmsSpecialSMSMessageOperations::operator
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Either adds a new or updates an existing special message indication information element.
+ *  
+ *  @param aStore
+ *  Indicates whether or not the message shall be stored.
+ *  @param aMessageIndicationType
+ *  Indicates the basic message type
+ *  @param aExtendedType
+ *  Indicates the extended message type
+ *  @param aProfile
+ *  Indicates the profile ID of the Multiple Subscriber Profile
+ *  @param aMessageCount
+ *  Indicates the number of messages of the type specified in Octet 1 that are waiting
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support this query.
+ *  @capability None
+ */
+EXPORT_C void CSmsSpecialSMSMessageOperations::AddSpecialMessageIndicationL(TBool aStore,
+                                                                            TSmsMessageIndicationType aMessageIndicationType,
+                                                                            TExtendedSmsIndicationType aExtendedType,
+                                                                            TSmsMessageProfileType aProfile,
+                                                                            TUint8 aMessageCount) const
+	{
+	LOGGSMU1("CSmsSpecialSMSMessageOperations::AddSpecialMessageIndicationL");
+
+	ValidateOperationL();
+
+	CSmsUserData& userData = iMessage.SmsPDU().UserData();
+
+	TBuf8<2> data;
+	data.SetLength(2);
+
+	data[0] = ( ((TUint8) aMessageIndicationType) +
+	            ((TUint8) (aExtendedType << 2))   +
+	            ((TUint8) (aProfile      << 5))   +
+	            ((TUint8) (aStore        << 7)) );
+
+	data[1] = aMessageCount;
+
+	CArrayFixFlat<TInt>* indices = new(ELeave) CArrayFixFlat<TInt>(4);
+	CleanupStack::PushL(indices);
+	userData.InformationElementIndicesL(CSmsInformationElement::ESmsIEISpecialSMSMessageIndication, *indices);
+
+	TBool found = EFalse;
+	TInt count = indices->Count();
+	for (TInt i=0; ((i<count) && (found==EFalse)); i++)
+	    {
+		TUint index = indices->operator[](i);
+		CSmsInformationElement& ieAlreadyInWorkingPDU = userData.InformationElement(index);
+
+	    if (ieAlreadyInWorkingPDU.Data()[0] == data[0])
+	        {
+	        ieAlreadyInWorkingPDU.Data()[1] = data[1];
+	        found = ETrue;
+	        break;
+	        }
+	    }
+	CleanupStack::PopAndDestroy(indices);
+
+	if (found == EFalse)
+	    {
+	    userData.AddInformationElementL(CSmsInformationElement::ESmsIEISpecialSMSMessageIndication,data);
+	    }
+	} // CSmsSpecialSMSMessageOperations::AddSpecialMessageIndicationL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Gets a count of the number of special message indication information elements which
+ *  are stored inside the user data.
+ *  
+ *  @return The number of special message indication information elements which
+ *  are stored inside the user data.
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support this query.
+ *  @capability None
+ */
+EXPORT_C TUint CSmsSpecialSMSMessageOperations::GetCountOfSpecialMessageIndicationsL() const
+	{
+	LOGGSMU1("CSmsSpecialSMSMessageOperations::GetCountOfSpecialMessageIndicationsL()");
+
+	ValidateOperationL();
+
+	CSmsUserData& userData = iMessage.SmsPDU().UserData();
+
+	CArrayFixFlat<TInt>* indices = new (ELeave) CArrayFixFlat<TInt>(8);
+	CleanupStack::PushL(indices);
+	userData.InformationElementIndicesL(CSmsInformationElement::ESmsIEISpecialSMSMessageIndication,*indices);
+	TUint  count = indices->Count();
+	CleanupStack::PopAndDestroy(indices);
+
+	return count;
+	} // CSmsSpecialSMSMessageOperations::GetCountOfSpecialMessageIndicationsL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Gets the attributes of the Special Message Indication specified by aIndex.
+ *  
+ *  @param aIndex
+ *  aIndex is a value less than GetCountOfSpecialMessageIndications().
+ *  @param aStore
+ *  Indicates whether or not the message shall be stored.
+ *  @param aMessageIndicationType
+ *  Indicates the basic message type
+ *  @param aExtendedType
+ *  Indicates the extended message type
+ *  @param aProfile
+ *  Indicates the profile ID of the Multiple Subscriber Profile
+ *  @param aMessageCount
+ *  Indicates the number of messages of the type specified in Octet 1 that are waiting
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support this query.
+ *  @leave KErrArgument
+ *  If aIndex is >= GetCountOfSpecialMessageIndications()
+ *  @capability None
+ */
+EXPORT_C void CSmsSpecialSMSMessageOperations::GetMessageIndicationIEL(TUint aIndex,
+                                                                       TBool& aStore,
+                                                                       TSmsMessageIndicationType& aMessageIndicationType,
+                                                                       TExtendedSmsIndicationType& aExtendedType,
+                                                                       TSmsMessageProfileType&  aProfile,
+                                                                       TUint8& aMessageCount) const
+	{
+	LOGGSMU1("CSmsSpecialSMSMessageOperations::GetMessageIndicationIEL()");
+
+	ValidateOperationL();
+
+	CSmsUserData& userData = iMessage.SmsPDU().UserData();
+
+	CArrayFixFlat<TInt>* indices = new (ELeave) CArrayFixFlat<TInt>(8);
+	CleanupStack::PushL(indices);
+	userData.InformationElementIndicesL(CSmsInformationElement::ESmsIEISpecialSMSMessageIndication,*indices);
+
+	if (aIndex < indices->Count())
+	    {
+	    CSmsInformationElement& informationElement = userData.InformationElement((*indices)[aIndex]);
+
+	    aMessageIndicationType =  (TSmsMessageIndicationType)   (informationElement.Data()[0]       & 0x03);
+	    aExtendedType          =  (TExtendedSmsIndicationType) ((informationElement.Data()[0] >> 2) & 0x07);
+	    aProfile               =  (TSmsMessageProfileType)     ((informationElement.Data()[0] >> 5) & 0x03);
+	    aStore                 =  (TBool)                      ((informationElement.Data()[0] >> 7) & 0x01);
+	    aMessageCount          =  (TUint8)                      (informationElement.Data()[1]);
+	    }
+	else
+	    {
+	    User::Leave(KErrArgument);
+	    }
+
+	CleanupStack::PopAndDestroy(indices);
+	} // CSmsSpecialSMSMessageOperations::GetMessageIndicationIEL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Removes the Special Message Indication specified by the input attributes, provided it exists.
+ *  
+ *  @param aMessageIndicationType
+ *  Indicates the basic message type
+ *  @param aExtendedType
+ *  Indicates the extended message type
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support this query.
+ *  @capability None
+ */
+EXPORT_C void CSmsSpecialSMSMessageOperations::RemoveSpecialMessageIndicationL(TSmsMessageIndicationType aMessageIndicationType, TExtendedSmsIndicationType aExtendedType) const
+	{
+	LOGGSMU1("CSmsSpecialSMSMessageOperations::RemoveAllSpecialMessageIndications");
+
+	ValidateOperationL();
+
+	CSmsUserData& userData = iMessage.SmsPDU().UserData();
+
+	CArrayFixFlat<TInt>* indices = new (ELeave) CArrayFixFlat<TInt>(8);
+	CleanupStack::PushL(indices);
+	userData.InformationElementIndicesL(CSmsInformationElement::ESmsIEISpecialSMSMessageIndication,*indices);
+
+	TUint i = indices->Count();
+
+	while (i-- != 0)
+	    {
+	    CSmsInformationElement& informationElement = userData.InformationElement((*indices)[i]);
+
+	    TSmsMessageIndicationType          type = ((TSmsMessageIndicationType)   (informationElement.Data()[0]       & 0x03));
+	    TExtendedSmsIndicationType extendedType =  (TExtendedSmsIndicationType) ((informationElement.Data()[0] >> 2) & 0x07);
+
+	    if ( (aMessageIndicationType == type) &&
+	         (aExtendedType == extendedType) )
+	        {
+	        userData.RemoveInformationElement((*indices)[i]);
+	        break;
+	        }
+	    }
+
+	CleanupStack::PopAndDestroy(indices);
+	} // CSmsSpecialSMSMessageOperations::RemoveSpecialMessageIndicationL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Removes all Special Message Indications Information Elements contained in the message.
+ *  
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support this query.
+ *  @capability None
+ */
+EXPORT_C void CSmsSpecialSMSMessageOperations::RemoveAllSpecialMessageIndicationsL() const
+	{
+	LOGGSMU1("CSmsSpecialSMSMessageOperations::RemoveAllSpecialMessageIndicationsL");
+
+	ValidateOperationL();
+
+	CSmsUserData& userData = iMessage.SmsPDU().UserData();
+
+	CArrayFixFlat<TInt>* indices = new (ELeave) CArrayFixFlat<TInt>(8);
+	CleanupStack::PushL(indices);
+	userData.InformationElementIndicesL(CSmsInformationElement::ESmsIEISpecialSMSMessageIndication,*indices);
+
+	TUint i = indices->Count();
+
+	while (i-- != 0)
+	   {
+	   userData.RemoveInformationElement((*indices)[i]);
+	   }
+
+	CleanupStack::PopAndDestroy(indices);
+	} // CSmsSpecialSMSMessageOperations::RemoveAllSpecialMessageIndicationsL
+
+
+CSmsSpecialSMSMessageOperations::CSmsSpecialSMSMessageOperations(CSmsInformationElement::TSmsInformationElementIdentifier aId, CSmsMessage& aMessage) : CSmsCtrlOperation(aId, aMessage)
+	{
+	//NOP
+	} // CSmsSpecialSMSMessageOperations::CSmsSpecialSMSMessageOperations
+
+
+/**
+ *  @internalComponent
+ *  
+ *  Prevent clients from using the assignment operator by including it in the class definition
+ *  but making it protected and not exporting it.
+ *  
+ *  @capability None
+ */
+void CSmsEnhancedVoiceMailOperations::operator=(const CSmsEnhancedVoiceMailOperations&)
+    {
+    // Ignore in code coverage - not intended to be used
+    BULLSEYE_OFF    
+    LOGGSMU1("CSmsEnhancedVoiceMailOperations::operator=");
+    Panic(KGsmuPanicMethodBodyNotImplemented1);
+    BULLSEYE_RESTORE
+    }
+
+/**
+ *  @internalComponent
+ *  
+ *  Prevent clients from using the equality operator by including it in the class definition
+ *  but making it protected and not exporting it.
+ *  
+ *  @capability None
+ */
+TBool CSmsEnhancedVoiceMailOperations::operator==(const CSmsEnhancedVoiceMailOperations&)
+    {
+    // Ignore in code coverage - not intended to be used
+    BULLSEYE_OFF    
+    LOGGSMU1("CSmsEnhancedVoiceMailOperations::operator==");
+    Panic(KGsmuPanicMethodBodyNotImplemented1);
+    return EFalse;
+    BULLSEYE_RESTORE
+    }
+
+/**
+ *  @internalComponent
+ *  
+ *  Identifies whether the message type or version supports this operation
+ *  
+ *  @leave
+ *  If the message type or version does not support this operation.
+ */
+void CSmsEnhancedVoiceMailOperations::ValidateOperationL() const
+	{
+	LOGGSMU1("CSmsEnhancedVoiceMailOperations::ValidateOperationL()");
+
+	if (iMessage.Version() < CSmsMessage::ESmsMessageV1)
+	    {
+	    LOGGSMU2("CSmsEnhancedVoiceMailInformation::AddEnhancedVoiceMailIEL, Operation not supported, Msg Version %d", iMessage.Version());
+	    User::Leave(KErrNotSupported);
+	    }
+
+	if (!MessageTypeSupported())
+	    {
+	    LOGGSMU2("CSmsSpecialSMSMessageOperations::AddEnhancedVoiceMailIEL, Operation not supported by this PDU type, type = %d", iMessage.Type());
+	    User::Leave(KErrNotSupported);
+	    }
+	} // CSmsEnhancedVoiceMailOperations::ValidateOperationL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Adds an Enhanced Voice Mail Information Element to the CSmsMessage.
+ *  The information element can be either an Enhanced Voice Mail Notification or
+ *  an Enhanced Voice Mail Delete Confirmation. Enhanced Voice Mail Notifications
+ *  and Enhanced Voice Mail Delete Confirmations are abstracted in classes derived
+ *  from CEnhancedVoiceMailBoxInformation.
+ *  @param aEVMI
+ *  A pointer to the Enhanced Voice Mail Information Element.
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support this query.
+ *  @leave KErrAlreadyExists
+ *  If an Enhanced Voice Mail Information Element has already been installed.
+ *  @leave KErrArgument
+ *  If the input parameter contains invalid parameters.
+ *  @capability None
+ */
+EXPORT_C void CSmsEnhancedVoiceMailOperations::AddEnhancedVoiceMailIEL(const CEnhancedVoiceMailBoxInformation& aEVMI) const
+	{
+	LOGGSMU1("CSmsEnhancedVoiceMailInformation::AddEnhancedVoiceMailIEL");
+
+	ValidateOperationL();
+
+	if (ContainsEnhancedVoiceMailIEL())
+	    {
+	    LOGGSMU1("CSmsEnhancedVoiceMailInformation::AddEnhancedVoiceMailIEL, Already Exists");
+	    User::Leave(KErrAlreadyExists);
+	    }
+
+	CSmsMessageAdditionalAttributes& additionalAttributes = *((CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo());
+
+	// The Enhanced Voice Mail Information Element must fit into a single PDU.
+	// The maximum size for its data field is therefore
+	// the maximum size of the user data minus user data header length, the ie identifier byte and
+	// ie length byte.
+	TBuf8<CEnhancedVoiceMailBoxInformation::KSmsMaxEnhancedVoiceMailSize> voiceMailInfo;
+	voiceMailInfo.SetLength(CEnhancedVoiceMailNotification::KSmsMaxEnhancedVoiceMailSize);
+	TUint8* startPtr = &voiceMailInfo[0];
+	TUint8* endPtr = aEVMI.EncodeL(startPtr, iCharacterSetConverter, iFs);
+	TInt length = (TInt) (endPtr - startPtr);
+	voiceMailInfo.SetLength(length);
+
+	CSmsInformationElement* iE = CSmsInformationElement::NewL(CSmsInformationElement::CSmsInformationElement::ESmsEnhanceVoiceMailInformation, voiceMailInfo);
+	CleanupStack::PushL(iE);
+
+	additionalAttributes.AddControlInformationElementL(iE);
+	CleanupStack::Pop();
+	} // CSmsEnhancedVoiceMailOperations::AddEnhancedVoiceMailIEL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Removes the Enhanced Voice Mail Information Element from the CSmsMessage,
+ *  provided it exists.
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support this query.
+ *  @leave KErrNotFound
+ *  If the CSmsMessage does not contain an Enhanced Voice Mail Information Element
+ *  @capability None
+ */
+EXPORT_C CEnhancedVoiceMailBoxInformation* CSmsEnhancedVoiceMailOperations::RemoveEnhancedVoiceMailIEL() const
+	{
+	LOGGSMU1("CSmsEnhancedVoiceMailInformation::RemoveEnhancedVoiceMailIE");
+
+	ValidateOperationL();
+
+	CEnhancedVoiceMailBoxInformation* voiceMailBoxInfo = NULL;
+	TBool deleteInformationElement = ETrue;
+	
+	// If function leaves, allow the error to propagate upwards
+	voiceMailBoxInfo = GetEnhancedVoiceMailIEL(deleteInformationElement);
+
+	return voiceMailBoxInfo;
+	} // CSmsEnhancedVoiceMailOperations::RemoveEnhancedVoiceMailIEL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Copies the Enhanced Voice Mail Information Element contained in the CSmsMessage,
+ *  provided one exists.
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support this query.
+ *  @leave KErrNotFound
+ *  If the CSmsMessage does not contain an Enhanced Voice Mail Information Element to copy.
+ *  @capability None
+ */
+EXPORT_C CEnhancedVoiceMailBoxInformation* CSmsEnhancedVoiceMailOperations::CopyEnhancedVoiceMailIEL() const
+	{
+	LOGGSMU1("CSmsEnhancedVoiceMailInformation::CopyEnhancedVoiceMailIEL");
+
+	ValidateOperationL();
+
+	CEnhancedVoiceMailBoxInformation* voiceMailBoxInfo = NULL;
+	TBool deleteInformationElement = EFalse;
+	
+	// If function leaves, allow the error to propagate upwards
+	voiceMailBoxInfo = GetEnhancedVoiceMailIEL(deleteInformationElement);
+
+	return voiceMailBoxInfo;
+	} // CSmsEnhancedVoiceMailOperations::CopyEnhancedVoiceMailIEL
+
+
+/**
+ *  @internalComponent
+ *  
+ *  Returns a copy of the Enhanced Voice Mail Information Element contained in the CSmsMessage,
+ *  provided one exists. Optionally deletes the information element.
+ *  @param aRemove
+ *  Indicates that the information element should be deleted once its contents have been copied.
+ *  @leave KErrNotFound
+ *  If the CSmsMessage does not contain an Enhanced Voice Mail Information Element to copy.
+ */
+CEnhancedVoiceMailBoxInformation* CSmsEnhancedVoiceMailOperations::GetEnhancedVoiceMailIEL(TBool aRemove) const
+	{
+	LOGGSMU1("CSmsEnhancedVoiceMailOperations::GetEnhancedVoiceMailIEL()");
+
+	TBool found = EFalse;
+
+	CEnhancedVoiceMailBoxInformation* voiceMailBoxInfo = NULL;
+
+	TSmsInformationElementCategories::TInformationElementCategory category;
+
+	if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsEnhanceVoiceMailInformation, category) == EFalse)
+		{
+		User::Leave(KErrArgument);
+		}
+
+	CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo();
+	TUint numberOfElements = additionalAttributes->NumberOfControlInformationElements(category);
+
+	for (TUint i = 0; i < numberOfElements; i++)
+	    {
+	    CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum;
+	    id = additionalAttributes->GetControlInformationElementL(category, i).Identifier();
+
+	    if (id == CSmsInformationElement::CSmsInformationElement::ESmsEnhanceVoiceMailInformation)
+	        {
+	        if (additionalAttributes->GetControlInformationElementL(category, i).Data()[0] & 0x01)
+	            {
+	            voiceMailBoxInfo = CEnhancedVoiceMailDeleteConfirmations::NewL();
+	            }
+	        else
+	            {
+	            voiceMailBoxInfo = CEnhancedVoiceMailNotification::NewL();
+	            }
+
+	        CleanupStack::PushL(voiceMailBoxInfo);
+	        TGsmuLex8 encodedVoiceMailBox(additionalAttributes->GetControlInformationElementL(category, i).Data());
+	        voiceMailBoxInfo->DecodeL(encodedVoiceMailBox, iCharacterSetConverter, iFs);
+	        CleanupStack::Pop(voiceMailBoxInfo);
+
+	        if (aRemove)
+	            {
+	            additionalAttributes->DeleteControlInformationElement(category, i);
+	            }
+
+	        found = ETrue;
+
+	        break;
+	        }
+	    }
+
+	if (found == EFalse)
+	    {
+	    User::Leave(KErrNotFound);
+	    }
+
+	return voiceMailBoxInfo;
+	} // CSmsEnhancedVoiceMailOperations::GetEnhancedVoiceMailIEL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Determines whether the CSmsMessage contains an Enhanced Voice Mail Information Element.
+ *  @leave KErrNotSupported
+ *  If the message version or type does not support this query.
+ *  @return
+ *  True if the CSmsMessage contains an Enhanced Voice Mail Information Element.
+ *  @capability None
+ */
+EXPORT_C TBool CSmsEnhancedVoiceMailOperations::ContainsEnhancedVoiceMailIEL() const
+	{
+	LOGGSMU1("CSmsEnhancedVoiceMailInformation::ContainsEnhancedVoiceMailIEL");
+
+	ValidateOperationL();
+
+	TBool rc = EFalse;
+
+	TSmsInformationElementCategories::TInformationElementCategory category;
+
+	if (TSmsInformationElementCategories::GetCategoryDefinition(CSmsInformationElement::ESmsEnhanceVoiceMailInformation, category) == EFalse)
+		{
+		User::Leave(KErrArgument);
+		}
+
+	CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo();
+	TUint numberOfElements = additionalAttributes->NumberOfControlInformationElements(category);
+
+	for (TUint i = 0; i < numberOfElements; i++)
+	    {
+	    CSmsInformationElement::TSmsInformationElementIdentifier id = CSmsInformationElement::ESmsIEMaximum;
+	    
+	    // If function leaves, allow the error to propagate upwards
+	    id = additionalAttributes->GetControlInformationElementL(category, i).Identifier();
+
+	    if (id == CSmsInformationElement::ESmsEnhanceVoiceMailInformation)
+	        {
+	        rc = ETrue;
+	        break;
+	        }
+	    }
+
+	return rc;
+	} // CSmsEnhancedVoiceMailOperations::ContainsEnhancedVoiceMailIEL
+
+
+/**
+ *  Status Reporting.
+ *  
+ *  @note This should be the last thing that should be configured in CSmsMessage.
+ *  If anything is changed after this then the number of PDUs might change which
+ *  will affect status reporting.
+ */
+CSmsEnhancedVoiceMailOperations::CSmsEnhancedVoiceMailOperations(CSmsInformationElement::TSmsInformationElementIdentifier aId,  CSmsMessage& aMessage,
+                                                                 CCnvCharacterSetConverter& aCharacterSetConverter, RFs& aFs) : CSmsCtrlOperation(aId, aMessage),
+                                                                 iCharacterSetConverter(aCharacterSetConverter), iFs(aFs)
+	{
+	// NOP
+	} // CSmsEnhancedVoiceMailOperations::CSmsEnhancedVoiceMailOperations
+
+
+CSmsSMSCCtrlParameterOperations::CSmsSMSCCtrlParameterOperations(CSmsInformationElement::TSmsInformationElementIdentifier aId, CSmsMessage& aMessage)
+: CSmsCtrlOperation(aId, aMessage)
+	{
+	
+	} // CSmsSMSCCtrlParameterOperations::CSmsSMSCCtrlParameterOperations
+	
+
+/**
+ *  @internalComponent  
+ *  
+ *  Prevent clients from using the assignment operator by including it in the class definition
+ *  but making it protected and not exporting it.
+ *  
+ *  @capability None
+ */
+void CSmsSMSCCtrlParameterOperations::operator=(const CSmsSMSCCtrlParameterOperations&)
+    {
+    // Ignore in code coverage - not intended to be used
+    BULLSEYE_OFF    
+    LOGGSMU1("CSmsSMSCCtrlParameterOperations::operator=");
+    Panic(KGsmuPanicMethodBodyNotImplemented1);
+    BULLSEYE_RESTORE
+    }
+
+/**
+ *  @internalComponent  
+ *  
+ *  Prevent clients from using the equality operator by including it in the class definition
+ *  but making it protected and not exporting it.
+ *  
+ *  @capability None
+ */
+TBool CSmsSMSCCtrlParameterOperations::operator==(const CSmsSMSCCtrlParameterOperations&)
+    {
+    // Ignore in code coverage - not intended to be used
+    BULLSEYE_OFF    
+    LOGGSMU1("CSmsSMSCCtrlParameterOperations::operator==");
+    Panic(KGsmuPanicMethodBodyNotImplemented1);
+    return EFalse;
+    BULLSEYE_RESTORE
+    }
+
+/**
+ *  @internalComponent
+ *  
+ *  Identifies whether the message type or version supports this operation
+ *  
+ *  @leave
+ *  If the message type or version does not support this operation.
+ */
+void CSmsSMSCCtrlParameterOperations::ValidateOperationL() const
+	{
+	if (iMessage.Version() < CSmsMessage::ESmsMessageV2)
+	    {
+	    LOGGSMU2("CSmsSMSCCtrlParameterOperations Operation not supported, Msg Version %d", iMessage.Version());
+	    User::Leave(KErrNotSupported); 
+	    }
+
+	if (!MessageTypeSupported())
+	    {
+	    LOGGSMU2("CSmsSMSCCtrlParameterOperations Operation not supported by this PDU type, type = %d", iMessage.Type());
+	    User::Leave(KErrNotSupported);
+	    }
+	} // CSmsSMSCCtrlParameterOperations::ValidateOperationL()
+
+
+/**
+ *  @internalComponent
+ *  
+ *  Checks that the octet passed to it has the valid bits set in it. If the bits which 
+ *  are not supported yet are set then reset it. 
+ *  This method is called by SetStatusReportL.
+ *  
+ *  @param aSelectiveStatus
+ *  The octet which needs to be set as the Selective Status for the report.
+ *  @return
+ *  ETrue if the selective status is valid.
+ *  @leave KErrNotSupported
+ *  If the last 4 bits are set as they are not supported.
+ */
+TBool CSmsSMSCCtrlParameterOperations::ValidateControlParametersL(TUint8& aSelectiveStatus) const
+	{
+	if (aSelectiveStatus & ESmsStatusReportForFutureUse1)
+		{
+		User::Leave(KErrNotSupported);
+		}
+		
+	if (aSelectiveStatus & ESmsStatusReportForFutureUse2)
+		{
+		User::Leave(KErrNotSupported);	
+		}
+		
+	if (aSelectiveStatus & ESmsStatusReportCancelRestSRR)
+		{
+		User::Leave(KErrNotSupported);	
+		}
+		
+	if (aSelectiveStatus & ESmsStatusReportIncludeOriginalUDH)
+		{
+		User::Leave(KErrNotSupported);
+		}
+	
+	return ETrue;	
+	} // CSmsSMSCCtrlParameterOperations::ValidateControlParametersL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Sets the status report for a PDU. First the scheme is obtained by calling the 
+ *  GetStatusReportScheme and checked if it is the valid scheme. Then aSelectiveStatus is 
+ *  checked to see if it is the default value. If it is then nothing is done. But if 
+ *  aSelectiveStatus is non-default then it is appended to the array 
+ *  iControlParametersStatusReport along with the aSegmentSequenceNum 
+ *  
+ *  @param aSegmentSequenceNum
+ *  The segment sequence number of the PDU which needs to be updated.
+ *  @param aSelectiveStatus
+ *  The octet which needs to be set as the Selective Status for the report.
+ *  @return KErrNone if the operation is successful.
+ *  KErrNotFound if the Segment Sequence Number is out of range or the scheme is inavlid.
+ *  KErrNotSupported if aSelectiveStatus is not valid.
+ *  @leave
+ *  If ValidateOperationL or AppendL leaves.
+ *  @capability None
+ */
+EXPORT_C TInt CSmsSMSCCtrlParameterOperations::SetStatusReportL(TUint aSegmentSequenceNum, TUint8 aSelectiveStatus)
+	{
+	ValidateOperationL();
+	TBool validateStatus = ValidateControlParametersL(aSelectiveStatus);
+	
+	if(validateStatus)
+		{
+		CSmsMessageAdditionalAttributes& additionalAttributes = *((CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo());
+		CSmsMessageAdditionalAttributes::CSmsStatusReportScheme& scheme = additionalAttributes.GetStatusReportScheme();
+		if (scheme.Id() == EControlParametersScheme)
+			{
+			CSmsMessageAdditionalAttributes::CControlParametersScheme& ctrlParamsScheme = (CSmsMessageAdditionalAttributes::CControlParametersScheme&)scheme;
+			if(aSegmentSequenceNum>=ctrlParamsScheme.iNumOfPDUs)
+				{
+				return KErrNotFound;	//	aSegmentSequenceNum out of range.
+				}
+			if (aSelectiveStatus == ctrlParamsScheme.iDefaultStatusReport)
+				{
+				return KErrNone;	// It's the same as default so need for any updation.
+				}
+			else
+				{
+				TInt count = (ctrlParamsScheme.iControlParametersStatusReport).Count();
+				TBool found(EFalse);
+				for (TInt ii=0; !found && ii<count; ii++)
+					{
+					if ((ctrlParamsScheme.iControlParametersStatusReport[ii]).iSegmentSequenceNum == aSegmentSequenceNum)
+						{
+						(ctrlParamsScheme.iControlParametersStatusReport[ii]).iSelectiveStatus = aSelectiveStatus;
+						found = ETrue;
+						break;
+						}
+					}
+					
+				if (!found)
+					{
+					CSmsMessageAdditionalAttributes::CControlParametersScheme::TSmsSMSCCtrlParameterStatus smscCtrlParameterStatus;
+					smscCtrlParameterStatus.iSegmentSequenceNum = aSegmentSequenceNum;
+					smscCtrlParameterStatus.iSelectiveStatus = aSelectiveStatus;
+					(ctrlParamsScheme.iControlParametersStatusReport).AppendL(smscCtrlParameterStatus);
+					}
+			
+				return KErrNone;	
+				}
+			}
+		else
+			{
+			return KErrNotFound;	//	Scheme not valid.
+			}
+		}
+	else
+		{
+		return KErrNotSupported;	//	Invalid aSlectiveStatus.
+		}
+	} // CSmsSMSCCtrlParameterOperations::SetStatusReportL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Gets the selective status for a PDU if the scheme is set to the Control
+ *  Parameters Scheme.
+ *  
+ *  @param aSegmentSequenceNum
+ *  The segment sequence number of the PDU whose status report is required.
+ *  @param aSelectiveStatus
+ *  Returns the selective status octet for that PDU.
+ *  
+ *  @return KErrNotFound if the segment sequence number or the scheme is invalid.
+ *  
+ *  @capability None
+ */
+EXPORT_C TInt CSmsSMSCCtrlParameterOperations::GetStatusReport(TUint aSegmentSequenceNum,
+															   TUint8& aSelectiveStatus) const
+	{
+	CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo();
+	CSmsMessageAdditionalAttributes::CSmsStatusReportScheme& scheme = additionalAttributes->GetStatusReportScheme();
+	if (scheme.Id() == EControlParametersScheme)
+		{
+		CSmsMessageAdditionalAttributes::CControlParametersScheme& ctrlParamsScheme = (CSmsMessageAdditionalAttributes::CControlParametersScheme&)scheme;
+		
+		if(aSegmentSequenceNum>=ctrlParamsScheme.iNumOfPDUs)
+			{
+			return KErrNotFound;	//	aSegmentSequenceNum out of range.
+			}
+
+		TInt count = (ctrlParamsScheme.iControlParametersStatusReport).Count();
+		
+		for (TInt ii=0; ii<count; ii++)
+			{
+			if (ctrlParamsScheme.iControlParametersStatusReport[ii].iSegmentSequenceNum == aSegmentSequenceNum)
+				{
+				aSelectiveStatus = ctrlParamsScheme.iControlParametersStatusReport[ii].iSelectiveStatus;
+				return KErrNone;
+				}
+			}
+			
+		aSelectiveStatus = ctrlParamsScheme.iDefaultStatusReport;
+		return KErrNone;
+		}
+
+	return KErrNotFound;
+	} // CSmsSMSCCtrlParameterOperations::GetStatusReport
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Sets the default value of the status report to aDefaultSelectiveStatus.
+ *  
+ *  @param aDefaultSelectiveStatus
+ *  The selective status to be used as default.
+ *  @leave KErrNotFound
+ *  If the scheme is invalid.
+ *  @capability None
+ */
+EXPORT_C void CSmsSMSCCtrlParameterOperations::SetDefaultL(TUint8 aDefaultSelectiveStatus)
+	{
+	CSmsMessageAdditionalAttributes& additionalAttributes = *((CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo());
+	CSmsMessageAdditionalAttributes::CSmsStatusReportScheme& scheme = additionalAttributes.GetStatusReportScheme();
+	if (scheme.Id() == EControlParametersScheme)
+		{
+		CSmsMessageAdditionalAttributes::CControlParametersScheme& ctrlParamsScheme = (CSmsMessageAdditionalAttributes::CControlParametersScheme&)scheme;
+		if(aDefaultSelectiveStatus & ESmsSMSCControlParametersMask)
+			{
+			ctrlParamsScheme.iDefaultStatusReport = aDefaultSelectiveStatus;
+			}
+		else
+			{
+			ctrlParamsScheme.iDefaultStatusReport = 0x00;	
+			}
+		}
+	else
+		{
+		User::Leave(KErrNotFound);
+		}
+	} // CSmsSMSCCtrlParameterOperations::SetDefaultL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  This method is called to set the scheme to Control Parameters Scheme.
+ *  First iStatusReportScheme, which is obtained by calling GetStatusReportScheme,
+ *  is deleted and set to NULL. Then a new scheme is created and a default value is set.
+ *  This should be the last method to be called in a message sending process as all the 
+ *  operations in this interface depend on the number of PDUs being set.
+ *  
+ *  @leave
+ *  If ValidateOperationL or NumMessagePDUsL leaves.
+ *  @capability None
+ */
+EXPORT_C void CSmsSMSCCtrlParameterOperations::SetSchemeL()
+	{
+	ValidateOperationL();
+	
+	CSmsMessageAdditionalAttributes& additionalAttributes = *((CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo());
+	additionalAttributes.SetStatusReportSchemeL(EControlParametersScheme);
+	
+	TBuf8 <1> buffer;
+	buffer.SetLength(1);
+	buffer[0] = 0;
+	
+	CSmsUserData& userData = iMessage.SmsPDU().UserData();
+
+	userData.AddInformationElementL(CSmsInformationElement::ESmsIEISMSCControlParameters,buffer);
+	
+	CSmsMessageAdditionalAttributes::CSmsStatusReportScheme& scheme = additionalAttributes.GetStatusReportScheme();
+	CSmsMessageAdditionalAttributes::CControlParametersScheme& ctrlParamsScheme = (CSmsMessageAdditionalAttributes::CControlParametersScheme&)scheme;
+	ctrlParamsScheme.iNumOfPDUs = iMessage.NumMessagePDUsL();
+
+	SetDefaultL(0);
+	} // CSmsSMSCCtrlParameterOperations::SetSchemeL
+
+
+/**
+ *  @publishedAll
+ *  
+ *  Gets the current scheme being used.
+ *  
+ *  @return
+ *  EControlParametrsScheme is returned when Control Parameters Scheme is being used.
+ *  @capability None
+ */
+EXPORT_C TSmsStatusReportScheme CSmsSMSCCtrlParameterOperations::GetScheme() const
+	{
+	CSmsMessageAdditionalAttributes* additionalAttributes = (CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo();
+		
+	return (additionalAttributes->GetStatusReportScheme()).Id();
+	} // CSmsSMSCCtrlParameterOperations::GetScheme
+
+
+/**
+ *  @publishedAll
+ *  
+ *  This method re-sets the scheme to the Default Scheme.
+ *  
+ *  @capability None
+ */
+EXPORT_C void CSmsSMSCCtrlParameterOperations::ResetSchemeL()
+	{
+	CSmsMessageAdditionalAttributes& additionalAttributes = *((CSmsMessageAdditionalAttributes*) iMessage.AdditionalInfo());
+	
+	CSmsUserData& userData = iMessage.SmsPDU().UserData();
+
+	CArrayFixFlat<TInt>* indices = new (ELeave) CArrayFixFlat<TInt>(8);
+	CleanupStack::PushL(indices);
+	userData.InformationElementIndicesL(CSmsInformationElement::ESmsIEISMSCControlParameters,*indices);
+
+	TUint i = indices->Count();
+
+	while (i-- != 0)
+	    {
+	    userData.RemoveInformationElement((*indices)[i]);
+	    }
+    
+    CleanupStack::PopAndDestroy(indices);
+    additionalAttributes.SetStatusReportSchemeL(EDefaultScheme);
+	} // CSmsSMSCCtrlParameterOperations::ResetSchemeL
+