commsprocess/commsrootserverconfig/configurator/src/c32cmi.cpp
changeset 0 dfb7c4ff071f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commsprocess/commsrootserverconfig/configurator/src/c32cmi.cpp	Thu Dec 17 09:22:25 2009 +0200
@@ -0,0 +1,873 @@
+/*
+* Copyright (c) 2003-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 <f32file.h>
+#include "c32cmi.h"
+#include <cfextras.h>
+#include <e32base.h>
+#include "c32cmiutils.h"
+
+/** Implements the parser for .CMI configuration files.
+@file
+@publishedPartner
+@released
+*/
+
+/** Name of application for logging
+*/
+__FLOG_STMT(_LIT8(KSubsys,"C32Start");)
+
+/** Logging second tag
+*/
+__FLOG_STMT(_LIT8(KComponent,"Events");)
+
+/** .CMI file section "[Loader]" contains the configuration of
+the CPM and its bindings
+*/
+_LIT8(KSectionLoader,		"Loader");
+
+/** .CMI optional file section "[IniData]" contains application specific
+data.
+*/
+_LIT8(KSectionIniData,		"IniData");
+
+/** Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrName,			"Name");
+
+/** Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrFileName,		"FileName");
+
+/** Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrIniDataFile,		"IniData");
+
+/** Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrIsServer,		"IsServer");
+
+/** Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrPriority,		"Priority");
+
+/** Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrStackSize,		"StackSize");
+
+/** Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrHeapOption,		"HeapOption");
+
+/** Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrStartSequence,	"StartSequence");
+
+/** Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrScaledStartupState,	"ScaledStartupState");
+
+/** Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrMinHeapSize,		"MinHeapSize");
+
+/** Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrMaxHeapSize,		"MaxHeapSize");
+
+/** Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrSharedHeapName,	"SharedHeapName");
+
+/** Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrThreadFuncOrdinal,"ThreadFunctionOrdinal");
+
+/** Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrIsSticky,		"IsSticky");
+
+/** Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrSystemCritical,	"SystemCritical");
+
+/** Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrSystemCriticalAfterInit,	"SystemCriticalAfterInit");
+
+/** Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrControlFlags,	"ControlFlags");
+
+/**Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrOnDemand, "OnDemand");
+
+/**Attribute which can be found in a .CMI file in the [loader] section.
+*/
+_LIT8(KAttrGroupName, "Group");
+
+/** PANICs which can occur during .CMI file parsing.
+*/
+enum TIniPanic
+	{
+	/** The name of a section is too long.
+	*/
+	ESectionNameTooBig,
+	/** The name of a variable is too big.
+	*/
+	EVarNameTooBig
+	};
+
+#ifdef _DEBUG
+/** Function whch will PANIC the module, but only in debug mode.
+*/
+static void Panic(TIniPanic aPanic)
+	{
+	_LIT(KC32CmiData,"C32CmiData");
+	User::Panic(KC32CmiData,aPanic);
+	}
+#endif
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+C32ParseIniFile* C32ParseIniFile::NewL(const TDesC& aFileName, TAutoClose<RFs>& aFileServer)
+	{
+	C32ParseIniFile* self = new(ELeave) C32ParseIniFile;
+	CleanupStack::PushL(self);
+	self->ConstructL(aFileName, aFileServer);
+	CleanupStack::Pop();
+	return self;
+	}
+
+void C32ParseIniFile::ConstructL(const TDesC& aFileName, TAutoClose<RFs>& aFileServer)
+	{
+	__FLOG_OPEN(KSubsys,KComponent);
+    iToken = HBufC8::NewL(KTokenSize+2);	// 2 extra chars for [tokenName]
+	ReadFileL(aFileName, aFileServer);
+	}
+
+C32ParseIniFile::~C32ParseIniFile()
+	{
+	delete iCmiData;
+	delete iToken;
+	__FLOG_CLOSE;
+	}
+
+TBool C32ParseIniFile::FindVar(const TDesC8 &aSection, const TDesC8 &aVarName, TPtrC8 &aResult, TInt aEnumerator)
+/** Find a variable's value given a section name and a var name.
+@param aSection The section to search.
+@param aVarName The name that will have aEnumerator appended to it to generate the key that will be searched for.
+@param aResult The result.
+@param aEnumerator Appended to the var name to generate a the key that will be searched for.
+@return Success or fail.
+*/
+	{
+	__ASSERT_DEBUG(aSection.Length()<=KTokenSize,Panic(ESectionNameTooBig));
+	__ASSERT_DEBUG(aVarName.Length()<=KTokenSize,Panic(EVarNameTooBig));
+
+	// append enumeration to the key name
+	TBuf8<256> aKey(aVarName);
+	aKey.AppendNum(aEnumerator);
+
+	return CommsFW::GetVarFromIniData(*iCmiData, aSection, aKey, aResult);
+	}
+
+TBool C32ParseIniFile::FindVar(const TDesC8 &aSection, const TDesC8 &aVarName, TPtrC8 &aResult)
+/** Find a variable's value given a section name and a var name.
+@param aSection The section to search.
+@param aVarName The name to find.
+@param aResult The result.
+@return Success or fail.
+*/
+	{
+	__ASSERT_DEBUG(aSection.Length()<=KTokenSize,Panic(ESectionNameTooBig));
+	__ASSERT_DEBUG(aVarName.Length()<=KTokenSize,Panic(EVarNameTooBig));
+	return CommsFW::GetVarFromIniData(*iCmiData, aSection, aVarName, aResult);
+	}
+
+
+TBool C32ParseIniFile::FindVar(const TDesC8 &aSection, const TDesC8 &aVarName, TInt &aResult)
+/**
+@param aSection The section to search.
+@param aVarName The name to find.
+@param aResult The result.
+@return Success or fail.
+*/
+	{
+	TPtrC8 ptr(NULL,0);
+	if (FindVar(aSection,aVarName,ptr))
+		{
+		TRadix radix;
+		_LIT8(KHexPrefix, "0x");
+		if(ptr.Left(2).CompareF(KHexPrefix) == 0)
+			{
+			ptr.Set(ptr.Mid(2));
+			radix = EHex;
+			}
+		else
+			{
+			radix = EDecimal;
+			}
+		TLex8 lex(ptr);
+		TUint32 result;
+		if (lex.Val(result, radix)==KErrNone)
+			{
+			aResult = result;
+			return(ETrue);
+			}
+		}
+	return(EFalse);
+	}
+
+void C32ParseIniFile::ReadFileL(const TDesC& aFileName, TAutoClose<RFs>& aFileServer)
+/** Reads the file content into a narrow-char buffer. By design the
+configurator only supports ASCII text, as its purpose is invisible
+system configuration.
+@param aFileName The name of the file to be read.
+*/
+	{
+	// Open session to the FileServer
+	//TAutoClose<RFs> fs;
+	TInt result;
+	//check if the session is already open
+	if(aFileServer.iObj.Handle() == 0)
+		{
+		if(KErrNone!=(result=aFileServer.iObj.Connect()))
+			{
+			__FLOG( _L( "Unable to connect to the File Server" ) );
+			User::Leave(result);
+			}
+		}
+	//fs.PushL();
+
+	// Open file
+	TAutoClose<RFile> rfile;
+	result = rfile.iObj.Open(aFileServer.iObj, aFileName, EFileShareReadersOnly);
+	if(KErrNone==result)
+		{
+		rfile.PushL();
+
+		// Get filesize for allocating the buffer for the data
+		TInt size;
+		result = rfile.iObj.Size(size);
+		if(KErrNone!=result)
+			{
+			__FLOG_1(_L("Couldn't get size of file %S"), &aFileName);
+			User::Leave(result);
+			}
+
+		if(size<=0)
+			{
+			__FLOG_1(_L("File %S has no contents"), &aFileName);
+			User::Leave(KErrCorrupt);
+			}
+
+		// Allocate a buffer that can contain the file data
+		iCmiData = HBufC8::NewL(size);
+		TPtr8 fileDataPtr = iCmiData->Des();
+
+		// Read the contents of the file into the buffer
+		result=rfile.iObj.Read(fileDataPtr);
+		if(KErrNone!=result)
+			{
+			__FLOG_1(_L("Couldn't read contents of file %S"), &aFileName);
+			User::Leave(result);
+			}
+		rfile.Pop();
+		}
+	//fs.Pop();
+	}
+
+TPtrC8 C32ParseIniFile::RetrieveSectionStart(const TDesC8& aSectionName)
+/** Returns a byte descriptor containing the data from the start of a section to the
+end of the file.
+*/
+	{
+	TPtrC8 section;
+	TPtr8 sectionToken = iToken->Des();
+	_LIT8(sectionTokenString,"[%S]");
+	sectionToken.Format(sectionTokenString, &aSectionName);
+	TInt sectionStart = iCmiData->Find(sectionToken);
+	if (KErrNotFound==sectionStart)
+		return section;
+
+	section.Set(iCmiData->Mid(sectionStart));
+	sectionStart += section.Find(TPtrC8(_S8("]")));
+	if (KErrNotFound==sectionStart)
+		{
+		section.Set(KNullDesC8);
+		}
+	else
+		{
+		sectionStart++;
+		section.Set(iCmiData->Mid(sectionStart, iCmiData->Length()-sectionStart));
+		}
+	return section;
+	}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+C32CmiData::C32CmiData()
+/** C'tor. Sets th default values for the attributes as well as
+the default required attributes.
+*/
+	{
+	__FLOG_OPEN(KSubsys,KComponent);
+	iAttrPriority = EPriorityNormal;
+//	iAttrThreadFuncOrdinal = 0; // Rootserver uses defaults ordinal when this is set to 0.
+	iAttrStackSize = KDefaultStackSize * sizeof(TText); // Bigger stack if unicode
+	iAttrRequired = (AttrName|AttrFileName);
+	iAttrScaledStartupState = 0x3000;
+//	iAttrIsSticky=EFalse;
+//	iAttrSystemCritical=EFalse;
+//	iAttrControlFlags=0;
+	}
+
+C32CmiData::~C32CmiData()
+/** D'tor.
+*/
+	{
+	delete iCmiFile;
+	__FLOG_CLOSE;
+	}
+
+/*static*/ C32CmiData* C32CmiData::NewL(const TDesC& aFileName, TAutoClose<RFs>& aFileServer)
+/**
+@param aFileName The filename of the file to be read.
+@return pointer to new C32CmiData object.
+*/
+	{
+	C32CmiData* p = new(ELeave) C32CmiData;
+	CleanupStack::PushL(p);
+	p->ConstructL(aFileName, aFileServer);
+	CleanupStack::Pop();
+	return p;
+	}
+
+void C32CmiData::RetrieveAttribute(TInt aAttr, const TDesC8 &aVarName, TInt &aResult)
+/**
+@param aAttr The attibute set and returned.
+@param aVarName The name to be found.
+@param aResult The result.
+*/
+	{
+	if(FindVar(KSectionLoader, aVarName, aResult))
+		{
+		SetAttr(aAttr);
+		}
+	}
+
+void C32CmiData::RetrieveAttribute(TInt aAttr, const TDesC8 &aVarName, TPtrC8 &aResult)
+/** Retrieves an option from the file data and
+if it was found set the requested TPtrC to point to it.
+@param aAttr The attibute set and returned.
+@param aVarName The name to be found.
+@param aResult The result.
+*/
+	{
+	if(FindVar(KSectionLoader, aVarName, aResult))
+		{
+		SetAttr(aAttr);
+		}
+	}
+
+void C32CmiData::RetrievePriorityL()
+/** Retrieves a priority option from the file data. If present, checks it is a valid
+TThreadPriority enumerator name, and sets the corresponding priority attribute.
+@leave KErrCorrupt If the priority name is invalid
+*/
+	{
+	TPtrC8 priorityName;
+	if(FindVar(KSectionLoader, KAttrPriority, priorityName))
+		{
+		TThreadPriority priority;
+		if(C32CmiUtils::ThreadPriorityNameToEnum(priorityName, priority) == KErrNone)
+			{
+			iAttrPriority = priority;
+			SetAttr(AttrPriority);
+			return;
+			}
+		__FLOG_1(_L8("Invalid Priority %S"), &priorityName);
+		User::Leave(KErrCorrupt);
+		}
+	}
+
+TBool C32CmiData::CompareHeapTypes(const TDesC8 &aType1, const TDesC8 &aType2, TRSHeapType aType3)
+/** Helper function: Compares two strings and if there
+is a match set the AttrHeapOption bit and save the requested value.
+@param aType1 The first descriptor.
+@param aType2 The second descriptor.
+@param aType3 Enum type to be set on a positive match.
+@return Success or fail.
+*/
+	{
+	if(0==aType1.CompareF(aType2))
+		{
+		iAttrHeapOption=aType3;
+		SetAttr(AttrHeapOption);
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+void C32CmiData::RetrieveHeapTypeL()
+/** Determines the heap type required.
+*/
+	{
+	TPtrC8 type;
+	if(FindVar(KSectionLoader, KAttrHeapOption, type))
+		{
+		// List of possible heap types
+		_LIT8(KEDefaultHeap, "EDefaultHeap");
+		_LIT8(KEShareHeap, "EShareHeap");
+		_LIT8(KENewHeap, "ENewHeap");
+		if(CompareHeapTypes(type, KEDefaultHeap, EDefaultHeap))
+			return;
+		if(CompareHeapTypes(type, KEShareHeap, EShareHeap))
+			{
+			iAttrRequired |= AttrSharedHeapName;
+			return;
+			}
+		if(CompareHeapTypes(type, KENewHeap, ENewHeap))
+			{
+			iAttrRequired |= (AttrMinHeapSize|AttrMaxHeapSize);
+			return;
+			}
+		__FLOG_1(_L8("Invalid Heap Type %S"), &type);
+		User::Leave(KErrCorrupt);
+		}
+	}
+
+void C32CmiData::RetrieveIniDataSection()
+/** Sets a narrow ptr to point from the start of
+the inidata to the end of the file.
+*/
+	{
+	TPtrC8 sectionStart = iCmiFile->RetrieveSectionStart(KSectionIniData);
+	iAttrIniData.Set(sectionStart.Ptr(), sectionStart.Length());
+	SetAttr(AttrIniData);
+	}
+
+void C32CmiData::RetrieveAttributesL()
+/** Controls extraction of data.
+*/
+	{
+	RetrieveAttribute(AttrName, KAttrName, iAttrName);
+
+	RetrieveAttribute(AttrFileName, KAttrFileName, iAttrFileName);
+	RetrieveAttribute(AttrIniDataFile, KAttrIniDataFile, iAttrIniDataFile);
+	RetrieveAttribute(AttrIsServer, KAttrIsServer, iAttrIsServer);
+
+	RetrievePriorityL();
+
+	RetrieveAttribute(AttrStackSize, KAttrStackSize, iAttrStackSize);
+	RetrieveHeapTypeL();
+	TInt scaledStartupState = (TInt) iAttrScaledStartupState;
+	RetrieveAttribute(AttrScaledStartupState, KAttrScaledStartupState, scaledStartupState);
+	iAttrScaledStartupState = (TUint32) scaledStartupState;
+	// The original start sequence scheme is remapped to the scaled startup states
+	TInt attrStartSequence = KC32LowStartSequenceCeiling;
+	RetrieveAttribute(AttrStartSequence, KAttrStartSequence, attrStartSequence);
+	if(AttrIsSet(AttrStartSequence))
+		{
+		if(AttrIsSet(AttrScaledStartupState))
+			{
+			__FLOG(_L("ERROR: Both StartSequence and ScaledStartupState given"));
+			User::Leave(KErrCorrupt);
+			}
+		if(attrStartSequence < KC32LowStartSequenceCeiling)
+			{
+			iAttrScaledStartupState = KC32LowStartSequenceScaleBase + attrStartSequence;
+			}
+		else if(attrStartSequence < KC32MidStartSequenceCeiling)
+			{
+			iAttrScaledStartupState = KC32MidStartSequenceScaleBase + attrStartSequence;
+			}
+		else
+			{
+			iAttrScaledStartupState = KC32HighStartSequenceScaleBase + attrStartSequence;
+			}
+		__FLOG_2(_L("...StartSequence %d converted to ScaledStartupState 0x%x"), attrStartSequence, iAttrScaledStartupState);
+		SetAttr(AttrScaledStartupState);
+		}
+	else
+		{
+		__FLOG_1(_L("...ScaledStartupState 0x%x"), iAttrScaledStartupState);
+		}
+	RetrieveAttribute(AttrMinHeapSize, KAttrMinHeapSize, iAttrMinHeapSize);
+	RetrieveAttribute(AttrMaxHeapSize, KAttrMaxHeapSize, iAttrMaxHeapSize);
+	RetrieveAttribute(AttrSharedHeapName, KAttrSharedHeapName, iAttrSharedHeapName);
+	RetrieveAttribute(AttrThreadFuncOrdinal, KAttrThreadFuncOrdinal, iAttrThreadFuncOrdinal);
+	RetrieveAttribute(AttrIsSticky, KAttrIsSticky, iAttrIsSticky);
+	RetrieveAttribute(AttrSystemCritical, KAttrSystemCritical, iAttrSystemCritical);
+	RetrieveAttribute(AttrSystemCriticalAfterInit, KAttrSystemCriticalAfterInit, iAttrSystemCriticalAfterInit);
+
+	//Added for on demand loading
+	RetrieveAttribute(AttrOnDemand, KAttrOnDemand, iAttrOnDemand);
+	RetrieveAttribute(AttrGroupName, KAttrGroupName, iAttrGroupName);
+
+	TInt controlFlags = 0;
+	RetrieveAttribute(AttrControlFlags, KAttrControlFlags, controlFlags);
+	iAttrControlFlags = (TUint32) controlFlags;
+
+ 	RetrieveIniDataSection();
+
+	// Check that the required attributes were set
+	if(!AttrIsSet(iAttrRequired))
+		{
+		__FLOG(_L("Required attributes not set!"));
+		User::Leave(KErrCorrupt);
+		}
+	}
+
+void C32CmiData::ConstructL(const TDesC& aFileName, TAutoClose<RFs>& aFileServer)
+/** Second stage Constructor. Will cause file to be read and content to be parsed.
+@param aFileName The filename.
+*/
+	{
+	iCmiFile = C32ParseIniFile::NewL(aFileName, aFileServer);
+	RetrieveAttributesL();
+	}
+
+
+TBool C32CmiData::FindVar(const TDesC8 &aSection,const TDesC8 &aVarName,TPtrC8 &aResult)
+/** Find a variable's value given a section name and a var name.
+@param aSection The section to search.
+@param aVarName The name to find.
+@param aResult The result.
+@return Success or fail.
+*/
+	{
+	return iCmiFile->FindVar(aSection, aVarName, aResult);
+	}
+
+TBool C32CmiData::FindVar(const TDesC8 &aSection,const TDesC8 &aVarName,TInt &aResult)
+/**
+@param aSection The section to search.
+@param aVarName The name to find.
+@param aResult The result.
+@return Success or fail.
+*/
+	{
+	return iCmiFile->FindVar(aSection, aVarName, aResult);
+	}
+
+HBufC8* C32CmiData::IniDataL()
+/**
+@return Pointer to the ini data.
+*/
+	{
+
+	if((!AttrIsSet(AttrIniDataFile)) && (!AttrIsSet(AttrIniData)))
+		{
+		return NULL;
+		}
+
+	// If there was a inidata file specified we read that one, ignoring any inidata section
+	if(AttrIsSet(AttrIniDataFile))
+		{
+
+		// Open fileserver sesion
+		TInt result=KErrNone;
+		TAutoClose<RFs> fs;
+		if(KErrNone!=(result=fs.iObj.Connect()))
+			{
+			__FLOG( _L( "Unable to connect to the File Server" ) );
+			User::Leave(result);
+			}
+		fs.PushL();
+
+		// Open File and read content
+		TInt size = 0;
+		TAutoClose<RFile> rfile;
+		TFileName fileName;
+		fileName.Copy(iAttrIniDataFile);
+		result = rfile.iObj.Open(fs.iObj, fileName, EFileShareReadersOnly);
+
+		if(KErrNone!=result)
+			{
+			__FLOG_1(_L("Couldn't open inidata file %S"), &iAttrIniDataFile);
+			User::Leave(result);
+			}
+		else
+			{
+			rfile.PushL();
+			// Get filesize for allocating the buffer
+			result=rfile.iObj.Size(size);
+
+			if(size<=0)
+				{
+				__FLOG_1(_L("Inidata file %S has no contents"), &iAttrIniDataFile);
+				User::Leave(KErrCorrupt);
+				}
+
+			// Allocate buffer and read data
+			HBufC8* iniData = HBufC8::NewL(size);
+			CleanupStack::PushL(iniData);
+			TPtr8 fileDataPtr = iniData->Des();
+			result = rfile.iObj.Read(fileDataPtr);
+
+			if(KErrNone!=result)
+				{
+				__FLOG_1(_L("Couldn't read Inidata file %S"), &iAttrIniDataFile);
+				User::Leave(result);
+				}
+
+			rfile.Pop();
+			CleanupStack::Pop(iniData);
+			return iniData;
+			}
+		}
+	// else the inidata is embedded in the file
+	// If inidata section is empty just return NULL, this is non-critical
+	if(iAttrIniData.Length()<=0)
+		{
+		return NULL;
+		}
+
+	// Allocate heap buffer with room for data and return it
+	// IniData is required to be Narrow...
+	HBufC8* iniData = iAttrIniData.AllocL();
+	return iniData;
+	}
+
+void C32CmiData::SplitBindingL(TPtrC8 aSource, TPtrC8& aAddr1, TPtrC8& aAddr2,
+     TPtrC8& aType, TInt& aForwardQLength, TInt& aReverseQLength)
+/** Identifies the various components of a line specifying a binding.
+@param aSource The line to parse.
+@param aAddr1 Pointer to name.
+@param aAddr2 Pointer to name.
+@param aType Pointer to binding type.
+@leave KErrCorrupt
+*/
+	{
+
+	TPtrC8 temp;
+	TPtrC8 tempNum;
+	TLex8 lex;
+	TInt pos = aSource.Locate(',');
+    //Set aAddr1
+	if((pos==KErrNotFound) || (pos==0))
+		{
+		__FLOG(_L("Binding string corrupt"));
+		User::Leave(KErrCorrupt);
+		}
+	aAddr1.Set(aSource.Ptr(), pos);
+
+	//Set aAddr2
+	if (pos < aSource.Length())
+		{
+		temp.Set(aSource.Ptr() + pos + 1, aSource.Length() - pos -1);
+	    pos = temp.Locate(',');
+		}
+	else
+		{
+		pos = KErrNotFound;
+		}
+	if((pos==KErrNotFound) || (pos==0))
+		{
+		__FLOG(_L("Binding string corrupt"));
+		User::Leave(KErrCorrupt);
+		}
+	aAddr2.Set(temp.Ptr(), pos);
+
+	//Set aType
+	if (pos < temp.Length())
+		{
+		temp.Set(temp.Ptr() + pos + 1,temp.Length() - pos - 1);
+		pos = temp.Locate(',');
+		}
+	else
+		{
+		pos = KErrNotFound;
+		}
+	if((pos==KErrNotFound) || (pos==0))
+		{
+		__FLOG(_L("Binding string corrupt"));
+		User::Leave(KErrCorrupt);
+		}
+	aType.Set(temp.Ptr(), pos);
+
+	//Set aForwardQLength
+	if (pos < temp.Length())
+		{
+		temp.Set(temp.Ptr() + pos + 1,temp.Length() - pos - 1);
+		pos = temp.Locate(',');
+		}
+	else
+		{
+		pos = KErrNotFound;
+		}
+	if((pos==KErrNotFound) || (pos==0))
+		{
+		__FLOG(_L("Binding - no Forward queue length specified set to default of 1"));
+		aForwardQLength = 1;
+		aReverseQLength = 1;
+		return;
+		}
+	tempNum.Set(temp.Ptr(),pos);
+	lex.Assign(tempNum);
+	if (lex.Val(aForwardQLength) != KErrNone)
+		{
+		__FLOG(_L("Binding string corrupt - ForwardQLength Invalid"));
+		User::Leave(KErrCorrupt);
+		}
+
+	//Set aReverseQLength
+	if (pos < temp.Length())
+		{
+		temp.Set(temp.Ptr() + pos + 1,temp.Length() - pos - 1);
+		pos = temp.Length();
+		}
+	else
+		{
+		pos = KErrNotFound;
+		__FLOG(_L("Binding - no Reverse queue length specified set to default of 1"));
+		aReverseQLength = 1;
+		return;
+		}
+	tempNum.Set(temp.Ptr(),pos);
+	lex.Assign(tempNum);
+	if (lex.Val(aReverseQLength) != KErrNone)
+		{
+		__FLOG(_L("Binding string corrupt - ForwardQLength Invalid"));
+		User::Leave(KErrCorrupt);
+		}
+
+	}
+
+void C32CmiData::MakeAddressL(const TPtrC8& aAddress, TCFSubModuleAddress& aSubModuleAddress)
+/** Generate an aAddress from a string.
+@param aAddress Pointer to string name.
+@param aSubModuleAddress The value to be filled and returned.
+@leave KErrCorrupt
+*/
+	{
+	TCFModuleNameF name;
+	TCFModuleNameF subName;
+	TInt pos = aAddress.Locate(':');
+	if((pos==KErrNotFound) || (pos==0))
+		{
+		__FLOG(_L("Binding string corrupt"));
+		User::Leave(KErrCorrupt);
+		}
+	TPtrC8 tempptr(aAddress.Ptr(), pos);
+	name.Copy(tempptr);
+	name.TrimLeft();
+	name.TrimRight();
+	if(name.Length()<=0)
+		{
+		__FLOG(_L("Binding string corrupt"));
+		User::Leave(KErrCorrupt);
+		}
+	pos++;
+	if(aAddress.Length()<=pos)
+		{
+		__FLOG(_L("Binding string corrupt"));
+		User::Leave(KErrCorrupt);
+		}
+	tempptr.Set(aAddress.Ptr()+pos, aAddress.Length()-pos);
+	subName.Copy(tempptr);
+	subName.TrimLeft();
+	subName.TrimRight();
+	aSubModuleAddress.SetModule(name);
+	aSubModuleAddress.SetSubModule(subName);
+	}
+
+TRSBindType C32CmiData::MakeBindingTypeL(const TDesC8& aTxtType)
+/** Generate a bindtype object from a string.
+@param aTxtType The type of binding required in text form.
+@return Type of binding.
+@leave KErrCorrupt
+*/
+	{
+	TBuf8<32> buf=aTxtType;
+	buf.TrimLeft();
+	buf.TrimRight();
+	buf.LowerCase();
+
+    _LIT8(KEHierarchical, "ehierarchical");
+    _LIT8(KECustom, "ecustom");
+
+	if(0==buf.CompareF(KEHierarchical))
+		{
+		return EHierarchical;
+		}
+
+	if(0==buf.CompareF(KECustom))
+		{
+		return ECustom;
+		}
+
+	__FLOG(_L("Binding type string corrupt"));
+	User::Leave(KErrCorrupt);
+	return ECustom;		//lint !e527 // LINT knows that we can't get here, but the compiler doesn't
+	}
+
+TBool C32CmiData::NextBindingL(TRSBindingInfo& aBinding, TBool aReset/*=EFalse*/)
+/** Find the next binding.
+@param aBinding The bindinfo struct to be filled with a found binding.
+@param TBool aReset Indicates sequence of call to this function - first
+has aReset=ETrue.
+@return Found or not.
+*/
+	{
+
+	if(aReset)
+		{
+		iNextBinding=0;
+		}
+
+	TBuf8<C32ParseIniFile::KTokenSize> buf;
+	_LIT8(bindingTgt,"Binding%d");
+	buf.Format(bindingTgt, iNextBinding);
+	TPtrC8 ptr(NULL, 0);
+	TBool found;
+
+	// Get next BindingX string
+	if((found = FindVar(KSectionLoader, buf, ptr)) != EFalse)
+		{
+		__FLOG_2(_L8("Found binding: %S=%S"), &buf, &ptr);
+		++iNextBinding;
+		TPtrC8 addr1;
+		TPtrC8 addr2;
+		TPtrC8 type;
+		TInt forwardQLength;
+		TInt reverseQLength;
+		SplitBindingL(ptr, addr1, addr2, type,
+		forwardQLength,reverseQLength); // Split into sections between ','
+
+		TCFSubModuleAddress address;
+		MakeAddressL(addr1, address);
+		aBinding.iParams.iAddress1=address;
+
+		MakeAddressL(addr2, address);
+		aBinding.iParams.iAddress2=address;
+
+		aBinding.iParams.iType=MakeBindingTypeL(type);
+
+		aBinding.iParams.iForwardQLength = forwardQLength;
+		aBinding.iParams.iReverseQLength = reverseQLength;
+		}
+	return found;
+	}
+
+