libraries/qr3/src/KernLbxModel.cpp
changeset 0 7f656887cf89
child 7 184a1eb85cf2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libraries/qr3/src/KernLbxModel.cpp	Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,1370 @@
+// KernLbxModel.cpp
+// 
+// Copyright (c) 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "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:
+// Accenture - Initial contribution
+//
+#include "KernLbxModel.h"
+#include "Utils.h"
+#include <fshell/memoryaccess.h>
+#include "QResources3.hrh"
+#include <HAL.h>
+#include <fshell/common.mmh>
+#include <fshell/clogger.h>
+
+#ifdef FSHELL_APPARC_SUPPORT
+#include <apgcli.h>
+#include <APGWGNAM.H>
+#include <APMREC.H>
+#endif
+#ifdef FSHELL_WSERV_SUPPPORT
+#include <W32STD.H>
+#endif
+
+#include <fshell/ltkutils.h>
+#include "sandbox.h"
+
+using namespace LtkUtils;
+
+CKernListBoxData::CKernListBoxData(CKernListBoxModel* aModel)
+	: /*CQikListBoxData(),*/ iModel(aModel)
+	{
+	}
+
+CKernListBoxData::~CKernListBoxData()
+	{
+	if (iDelegate)
+		{
+		iDelegate->DataObjectAboutToDestruct(this);
+		}
+	delete iInfo;
+	}
+
+
+CKernListBoxModel::CKernListBoxModel(RMemoryAccess& aMemoryAccess)
+	: iSort(NULL), iMemAccess(aMemoryAccess)
+	{
+	}
+
+void CKernListBoxModel::ConstructL()
+	{
+	iUnd = new(ELeave) CUndertaker(*this);
+	iUnd->Register();
+#ifdef FSHELL_WSERV_SUPPORT
+	iWsSession = new (ELeave) RWsSession;
+	TInt err = iWsSession->Connect();
+	if (err != KErrNone)
+		{
+		delete iWsSession;
+		iWsSession = NULL;
+		// Null pointer is used to indicate wserv not present
+		}
+#endif
+	iTempBuf1.CreateL(256);
+	iTempBuf2.CreateL(256);
+	}
+
+TInt CKernListBoxModel::Count() const
+	{
+	return iItemData.Count();
+	}
+
+TInt CKernListBoxModel::ItemIdIndex(TInt aItemId) const
+	{
+	const TInt count = iItemData.Count();
+	for (TInt i = 0; i < count; i++)
+		{
+		if (iItemData[i]->ItemId() == aItemId)
+			return i;
+		}
+	return KErrNotFound;
+	}
+
+CKernListBoxData* CKernListBoxModel::RetrieveDataL(TInt aItemIndex)
+	{
+	iItemData[aItemIndex]->Open();
+	return iItemData[aItemIndex];
+	}
+
+CKernListBoxData* CKernListBoxModel::RetrieveDataLC(TInt aItemIndex)
+	{
+	CKernListBoxData* data = iItemData[aItemIndex];
+	data->Open();
+	CleanupClosePushL(*data);
+	return data;
+	}
+
+void CKernListBoxModel::RemoveAllDataL()
+	{
+	const TInt count = iItemData.Count();
+	for (TInt i = 0; i < count; i++)
+		{
+		iItemData[i]->Close();
+		}
+	iItemData.Reset();
+	}
+
+void CKernListBoxModel::ModelBeginUpdateLC()
+	{
+	}
+
+void CKernListBoxModel::ModelEndUpdateL()
+	{
+	}
+
+void CKernListBoxModel::DataUpdatedL(TInt /*aIndex*/)
+	{
+	}
+
+TInt CKernListBoxModel::Compare(TInt aLeft, TInt aRight) const
+	{
+	const CKernListBoxData* left = iItemData[aLeft];
+	const CKernListBoxData* right = iItemData[aRight];
+	return (*iSort)(left, right);
+	}
+
+void CKernListBoxModel::Swap(TInt aLeft,TInt aRight) const
+	{
+	const_cast<CKernListBoxModel*>(this)->WtfSwap(aLeft, aRight);
+	}
+
+void CKernListBoxModel::WtfSwap(TInt aLeft,TInt aRight)
+	{
+	CKernListBoxData* temp = iItemData[aLeft];
+	iItemData[aLeft] = iItemData[aRight];
+	iItemData[aRight] = temp;
+	}
+
+void CKernListBoxModel::RemoveDataL(TInt aItemIndex)
+	{
+	iItemData[aItemIndex]->Close();
+	iItemData.Remove(aItemIndex);
+	}
+
+void CKernListBoxModel::SetCurrentListL(TInt aCurrentList)
+	{
+	if (iCurrentList != aCurrentList)
+		{
+		RemoveAllDataL();
+		}
+	iCurrentList = aCurrentList;
+	}
+
+TInt CKernListBoxModel::GetCurrentList() const
+	{
+	return iCurrentList;
+	}
+
+void CKernListBoxModel::NewKernDataL(TInt aType, TObjectKernelInfo* aInfo)
+	{
+	DoNewKernDataL(aType, aInfo, NULL);
+	}
+
+void CKernListBoxModel::DoNewKernDataL(TInt aType, TObjectKernelInfo* aInfo, MKernListBoxDataDelegate* aDelegate)
+	{
+	CKernListBoxData* data;
+	switch (aType)
+		{
+	case EListOpenFiles:
+		data = new(ELeave) COpenFilesListBoxData(this);
+		break;
+	case EListThread:
+		data = new(ELeave) CThreadsListBoxData(this);
+		break;
+	case EListFeatureReg:
+		data = new(ELeave) CFeatRegListBoxData(this);
+		break;
+	case EListServer:
+		data = new(ELeave) CServerListBoxData(this);
+		break;
+	case EListHal:
+		data = new(ELeave) CHalListBoxData(this);
+		break;
+	case EListWindowGroups:
+#ifdef FSHELL_WSERV_SUPPORT
+		data = new(ELeave) CWindowGroupListBoxData(this);
+#else
+		data = NULL; // Compiler shutter upper
+		User::Leave(KErrNotSupported);
+#endif
+		break;
+	case EListMessageQueue:
+		data = new(ELeave) CMsgQueListBoxData(this);
+		break;
+	case EListMutex:
+		data = new(ELeave) CMutexListBoxData(this);
+		break;
+	case EListSemaphore:
+		data = new(ELeave) CSemaphoreListBoxData(this);
+		break;
+	case EListTimer:
+		data = new(ELeave) CTimerListBoxData(this);
+		break;
+	default:
+		data = new(ELeave) CKernListBoxData(this);
+		break;
+		}
+	
+	data->SetDelegate(aDelegate);
+	CleanupStack::PushL(data);
+	data->iType = aType;
+	data->ConstructL();
+
+	data->FormatL(aInfo, iTempBuf1, iTempBuf2);
+
+	iItemData.AppendL(data);
+	CleanupStack::Pop(data);
+	data->Open(); // open for model
+
+	//data->Open(); // open for return
+	data->iInfo = aInfo;
+	//return data;
+	}
+
+
+// This function is used for the list box items
+void CKernListBoxData::FormatL(TObjectKernelInfo* aInfo, RBuf& aTempBuf1, RBuf& aTempBuf2)
+	{
+	RBuf& name = aTempBuf1;
+	RBuf& more = aTempBuf2;
+	name.Zero();
+	more.Zero();
+
+	TInt itemId = (TInt)aInfo; // By default use the ptr unless the type can suggest anything better
+	DoFormatL(aInfo, aTempBuf1, aTempBuf2, itemId);
+	SetItemId(itemId);
+
+	if (iDelegate)
+		{
+		iDelegate->FormatChangedL(this, name, more);
+		}
+	}
+
+
+void CKernListBoxData::DoFormatL(TObjectKernelInfo* aInfo, RBuf& name, RBuf& more, TInt& itemId)
+	{
+	switch (iType)
+		{
+	case EListChunk:
+		{
+		TChunkKernelInfo& info = *(TChunkKernelInfo*)aInfo;
+		name.Copy(info.iFullName);
+		PrettyName(iType, name);
+		TBuf<16> size, maxSize;
+		HR(size, info.iSize);
+		HR(maxSize, info.iMaxSize);
+		more.Format(_L("Size %S / %S"), &size, &maxSize);
+		break;
+		}
+	case EListProcess:
+		{
+		TProcessKernelInfo& info = *(TProcessKernelInfo*)aInfo;
+		name.Copy(info.iFullName);
+		PrettyName(iType, name);
+		TUint pid = info.iProcessId;
+		TUint sid = info.iProcessSecurityInfo.iSecureId;
+		TExitType exitType = EExitPending;
+		RProcess proc;
+		if (proc.Open(pid) == KErrNone)
+			{
+			exitType = proc.ExitType();
+			}
+		if (exitType == EExitPending)
+			{
+			more.Format(_L("Pid %i Sid 0x%x"), pid, sid);
+			}
+		else
+			{
+			TExitCategoryName cat = proc.ExitCategory();
+			more.Format(_L("Pid %i %S %i Sid 0x%x"), pid, &cat, proc.ExitReason(), sid);
+			}
+		proc.Close();
+		itemId = pid;
+		break;
+		}
+	case EListCodeSeg:
+		{
+		TTomsciCodeSegKernelInfo& info = *reinterpret_cast<TTomsciCodeSegKernelInfo*>(aInfo);
+		name.Copy(info.iName);
+
+		TBuf<16> size;
+		HR(size, info.iSize);
+		more.Format(_L("Size %S Ref count %i"), &size, info.iAccessCount);
+		break;
+		}
+	case EListMimeTypes:
+		{
+		SDataType& info = *reinterpret_cast<SDataType*>(aInfo);
+		name.Copy(info.iMime);
+		more.Format(_L("From: %S"), &info.iRecog);
+		break;
+		}
+	default:
+		break;
+		}
+	
+	}
+
+void CKernListBoxModel::DumpToCloggerL(RClogger& clogger)
+	{
+	TInt count = Count();
+
+#ifdef __WINS__
+	clogger.Log("NOTE: This data is from a WINS[CW] build so is not representative of a real device!");
+#endif
+
+	for (TInt i = 0; i < count; i++)
+		{
+		CKernListBoxData* data = static_cast<CKernListBoxData*>(RetrieveDataLC(i));
+		data->DumpToCloggerL(clogger, i, count);
+		CleanupStack::PopAndDestroy(data);
+		}
+	}
+
+void CKernListBoxData::DumpToCloggerL(RClogger& clogger, TInt i, TInt count)
+	{
+	_LIT8(KChunkDesc,"Chunk;FullName;Size;(SizeHumanReadable);MaxSize;(MaxSizeHumanReadable);CreatorPid;BaseAddr");
+	_LIT8(KChunkFmt,"Chunk;%S;%i;(%S);%i;(%S);%i;%08x");
+
+	_LIT8(KProcessDesc,"Process;FullName;Pid;Priority;(PriorityHumanReadable);Sid;Vid;CreatorSid;CreatorName;Capabilities;(CapsHumanReadable);ExitStatus;ExitCategory;ExitReason;FixedProcess;DProcessAddr");
+	_LIT8(KProcessFmt,"Process;%S;%i;%i;(%S);%x;%x;%x;%S;%x;(%S);%S;%S;%i;%S;%08x");
+
+	_LIT8(KCodesegDesc,"CodeSeg;FileName;Size;(SizeHumanReadable);RefCount;DepCount");
+	_LIT8(KCodesegFmt,"CodeSeg;%S;%i;%S;%i;%i");
+
+	_LIT(KMimeDesc,"MimeType;Name;Recogniser;AppUid;AppName");
+	_LIT(KMimeFmt, "MimeType;%S;%S;%x;%S");
+
+	CKernListBoxData* data = this;
+	TObjectKernelInfo* aInfo = data->iInfo;
+
+	switch (iType)
+		{
+	case EListChunk:
+		{
+		if (i == 0) clogger.Log(KChunkDesc);
+		if (i == 0)
+			{
+			// Also log free at the start, so we can tally up mem losses
+			TInt freeRam = -1, totalRam = -1;
+			TBuf8<16> free, total;
+			HAL::Get(HAL::EMemoryRAMFree, freeRam);
+			HAL::Get(HAL::EMemoryRAM, totalRam);
+			HR(free, freeRam);
+			HR(total, totalRam);
+			_LIT8(KFree, "FREE");
+			clogger.Log(KChunkFmt, &KFree, freeRam, &free, totalRam, &total, 0);
+			}
+
+		TChunkKernelInfo& info = *(TChunkKernelInfo*)aInfo;
+		TBuf8<16> size, maxSize;
+		HR(size, info.iSize);
+		HR(maxSize, info.iMaxSize);
+		clogger.Log(KChunkFmt, &info.iFullName, info.iSize, &size, info.iMaxSize, &maxSize, info.iControllingOwnerProcessId, info.iBase);
+
+		if (i == count-1)
+			{
+			// Also print out free RAM at end, so we can see if mem usage changed much during
+			TInt freeRam = -1, totalRam = -1;
+			TBuf8<16> free, total;
+			HAL::Get(HAL::EMemoryRAMFree, freeRam);
+			HAL::Get(HAL::EMemoryRAM, totalRam);
+			HR(free, freeRam);
+			HR(total, totalRam);
+			_LIT8(KFree, "FREE");
+			clogger.Log(KChunkFmt, &KFree, freeRam, &free, totalRam, &total, 0);
+			}
+		break;
+		}
+	case EListProcess:
+		{
+		if (i == 0) clogger.Log(KProcessDesc);
+		TProcessKernelInfo& info = *(TProcessKernelInfo*)aInfo;
+
+		TBuf<16> priority16 = ToString((TProcessPriority)info.iPriority);
+		TPtr8 priority = priority16.Collapse();
+		HBufC* caps16 = ToStringL(info.iProcessSecurityInfo.iCaps);
+		TPtr8 caps(caps16->Des().Collapse());
+		TPtrC exitStatus;
+		TInt exitReason = 0;
+		TExitCategoryName exitCategory;
+		RProcess handle;
+		if (handle.Open(info.iProcessId) == KErrNone)
+			{
+			exitStatus.Set(ToString(handle.ExitType()));
+			exitCategory = handle.ExitCategory();
+			exitReason = handle.ExitReason();
+			handle.Close();
+			}
+		TBuf8<16> exitStatus8;
+		exitStatus8.Copy(exitStatus);
+		TPtrC8 exitCategory8 = exitCategory.Collapse();
+		RBuf creatorName;
+		data->ExeNameForSid(info.iProcessCreatorSecurityInfo.iSecureId, creatorName);
+		TPtrC8 creatorName8 = creatorName.Collapse();
+		TBool fixed = info.iAttributes & 1; // TMemModelProcessAttributes::EFixedAddress
+		_LIT8(KFixed, "FIXED");
+		TPtrC8 fixedPtr = fixed ? KFixed() : KNullDesC8();
+		clogger.Log(KProcessFmt, &info.iFullName, info.iProcessId, info.iPriority, &priority, info.iProcessSecurityInfo.iSecureId, info.iProcessSecurityInfo.iVendorId, info.iProcessCreatorSecurityInfo.iSecureId, &creatorName8, info.iProcessSecurityInfo.iCaps[0], &caps, &exitStatus8, &exitCategory8, exitReason, &fixedPtr, info.iAddressOfKernelObject);
+		creatorName.Close();
+		delete caps16;
+		break;
+		}
+	case EListCodeSeg:
+		{
+		if (i == 0) clogger.Log(KCodesegDesc);
+		TTomsciCodeSegKernelInfo& info = *reinterpret_cast<TTomsciCodeSegKernelInfo*>(aInfo);
+		TBuf8<16> size;
+		HR(size, info.iSize);
+		clogger.Log(KCodesegFmt, &info.iName, info.iSize, &size, info.iAccessCount, info.iDepCount);
+		break;
+		}
+	case EListMimeTypes:
+		{
+		if (i == 0) clogger.Log(KMimeDesc);
+		SDataType& info = *reinterpret_cast<SDataType*>(aInfo);
+		clogger.Log(KMimeFmt, &info.iMime, &info.iRecog, info.iAppUid, &info.iApp);
+		break;
+		}
+	default:
+		break;
+		}
+	}
+
+void CKernListBoxData::InfoForDialogL(RBuf& aTitle, RBuf& aText, TBool aRefresh)
+	{
+	if (aRefresh)
+		{
+		// Figure out our index in the model
+		TInt index = iModel->ItemIdIndex(ItemId());
+		iModel->RefreshDataL(index);
+		}
+
+	aTitle.Zero();
+	aText.Zero();
+
+	if (aTitle.MaxLength() < 256)
+		{
+		aTitle.ReAllocL(256);
+		}
+	if (aText.MaxLength() < 1024)
+		{
+		aText.ReAllocL(1024);
+		}
+
+	RBuf& inf = aText;
+	TBuf<256>* name = new(ELeave) TBuf<256>;
+	CleanupStack::PushL(name);
+	DoInfoForDialogL(aTitle, inf, name);
+	CleanupStack::PopAndDestroy(name);
+	}
+
+void AppendProcessFlags(TDes& aBuf, TUint32 aFlags)
+	{
+	TInt len = aBuf.Length();
+
+	// 9.1/9.2 doesn't have these, it's easier to redefine them to the correct value than make all the code conditional
+	const TUint KThreadFlagRealtime = 0x00000040;
+	const TUint KThreadFlagRealtimeTest = 0x00000080;
+
+#define IF_MATCH(aBuf, aFlags, aFlag) if (aFlags&aFlag) { aBuf.Append(_L( #aFlag )); aBuf.Append('|'); }
+	IF_MATCH(aBuf, aFlags, KThreadFlagProcessCritical)
+	IF_MATCH(aBuf, aFlags, KThreadFlagProcessPermanent)
+	IF_MATCH(aBuf, aFlags, KThreadFlagSystemCritical)
+	IF_MATCH(aBuf, aFlags, KThreadFlagSystemPermanent)
+	IF_MATCH(aBuf, aFlags, KThreadFlagOriginal)
+	IF_MATCH(aBuf, aFlags, KThreadFlagLastChance)
+	IF_MATCH(aBuf, aFlags, KThreadFlagRealtime)
+	IF_MATCH(aBuf, aFlags, KThreadFlagRealtimeTest)
+	IF_MATCH(aBuf, aFlags, KProcessFlagPriorityControl)
+	IF_MATCH(aBuf, aFlags, KProcessFlagJustInTime)
+	if (aBuf.Length() > len)
+		{
+		// Remove trailing |
+		aBuf.SetLength(aBuf.Length() - 1);
+		}
+	}
+
+void CKernListBoxData::DoInfoForDialogL(RBuf& aTitle, RBuf& inf, TDes* aTemp)
+	{
+	TDes* name = aTemp;
+	switch (iType)
+		{
+		case EListProcess:
+			{
+			TProcessKernelInfo& info = *(TProcessKernelInfo*)iInfo;
+			RProcess process;
+			TInt err = process.Open(info.iProcessId);
+			CleanupClosePushL(process);
+
+			_LIT(KInfo, "Process info");
+			aTitle.Copy(KInfo);
+			inf.Copy(iInfo->iFullName);
+			if (!err)
+				{
+				inf.Append(Klf);
+				inf.Append(process.FileName());
+				}
+			if (info.iCommandLine.Length())
+				{
+				inf.Append(' ');
+				//aTemp->Copy(info.iCommandLine);
+				// Command line args are generally 16-bit descriptors even though they're represented in 8-bit kernel-side
+				TPtrC widePtr((const TUint16*)info.iCommandLine.Ptr(), info.iCommandLine.Size()/2);
+				inf.Append(widePtr);
+				}
+
+			//_LIT8(KProcessDesc, "Process\tFullName\tPid\tPriority\t(PriorityHumanReadable)\tSid\tVid\tCapabilities\t(CapsHumanReadable)\tExitStatus\tExitCategory\tExitReason");
+
+			_LIT(KProcess, "\n\nPid: %i %S\nSid: 0x%x Vid: 0x%x");
+			_LIT(KPriority, "\nPriority: %i (%S)");
+			_LIT(KOtherStuff, "\nCreator Sid: 0x%x (%S)\n\nCapabilities: %S");
+			_LIT(KKern, "\nKernel object address: 0x%08x");
+			_LIT(KFlags, "\nFlags: 0x%x (");
+			_LIT(KDied, "\n\nDied with: %S %S %i");
+
+			HBufC* caps = ToStringL(info.iProcessSecurityInfo.iCaps);
+			TUint creatorSid = info.iProcessCreatorSecurityInfo.iSecureId;
+			TBool fixed = info.iAttributes & 1; // TMemModelProcessAttributes::EFixedAddress
+			_LIT(KFixed, "(fixed process)");
+			TPtrC fixedPtr = fixed ? KFixed() : KNullDesC();
+			inf.AppendFormat(KProcess, info.iProcessId, &fixedPtr, info.iProcessSecurityInfo.iSecureId, info.iProcessSecurityInfo.iVendorId);
+			if (!err)
+				{
+				TPtrC priority = ToString(process.Priority());
+				inf.AppendFormat(KPriority, process.Priority(), &priority);
+				}
+			inf.AppendFormat(KKern, info.iAddressOfKernelObject);
+			if (info.iFlags)
+				{
+				inf.AppendFormat(KFlags, info.iFlags);
+				AppendProcessFlags(inf, info.iFlags);
+				inf.Append(')');
+				}
+
+			RBuf parentName;
+			ExeNameForSid(creatorSid, parentName);
+
+			inf.AppendFormat(KOtherStuff, creatorSid, &parentName, caps);
+			delete caps;
+			parentName.Close();
+
+			if (!err && process.ExitType() != EExitPending)
+				{
+				TPtrC exitStatus;
+				TInt exitReason = 0;
+				TExitCategoryName exitCategory;
+				exitStatus.Set(ToString(process.ExitType()));
+				if (process.ExitType() == EExitPanic)
+					{
+					exitCategory = process.ExitCategory();
+					}
+				exitReason = process.ExitReason();
+				inf.AppendFormat(KDied, &exitStatus, &exitCategory, exitReason);
+				}
+			CleanupStack::PopAndDestroy(&process);
+			break;
+			}
+		case EListChunk:
+			{
+			TChunkKernelInfo& info = *(TChunkKernelInfo*)iInfo;
+			_LIT(KInfo, "Chunk info");
+			aTitle.Copy(KInfo);
+			inf.Copy(iInfo->iFullName);
+			inf.Append(Klflf);
+
+			TBuf<16> size, maxSize;
+			HR(size, info.iSize);
+			HR(maxSize, info.iMaxSize);
+
+			RProcess creator;
+			TInt err = creator.Open(info.iControllingOwnerProcessId);
+			if (!err) 
+				{
+				*name = creator.FullName();
+				PrettyName(EListProcess, *name);
+				creator.Close();
+				}
+			_LIT(KKern, "Kernel object address: 0x%08x\n");
+			_LIT(KChunk, "Base: 0x%08x\nSize: %S\nMax Size: %S\nCreator pid: %i (%S)");
+			inf.AppendFormat(KKern, info.iAddressOfKernelObject);
+			inf.AppendFormat(KChunk, info.iBase, &size, &maxSize, info.iControllingOwnerProcessId, name);
+			break;
+			}
+		case EListCodeSeg:
+			{
+			TTomsciCodeSegKernelInfo& info = *reinterpret_cast<TTomsciCodeSegKernelInfo*>(iInfo);
+			_LIT(KInfo, "Code segment info");
+			aTitle.Copy(KInfo);
+			inf.Copy(info.iName);
+			inf.Append(Klflf);
+
+			TBuf<16> size;
+			HR(size, info.iSize);
+			_LIT(KCodesegFmt, "File name: %S\nSize %S\nRef count %i\nDependancy count %i\nRun address 0x%08x");
+			aTemp->Copy(info.iFileName);
+			inf.AppendFormat(KCodesegFmt, aTemp, &size, info.iAccessCount, info.iDepCount, info.iRunAddress);
+			break;
+			}
+		case EListMimeTypes:
+			{
+			SDataType& info = *reinterpret_cast<SDataType*>(iInfo);
+			_LIT(KInfo, "Mime type info");
+			aTitle.Copy(KInfo);
+
+			inf.AppendFormat(_L("%S\n\n%S\nApp UID: 0x%x\n%S"), &info.iMime, &info.iRecog, info.iAppUid, &info.iApp);
+			break;
+			}
+		default:
+			break;
+		}
+	}
+
+void CKernListBoxModel::SummaryInfoL(TDes& aBuf)
+	{
+	switch (iCurrentList)
+		{
+		case EListProcess:
+			{
+			_LIT(KFmt, "%i processes");
+			aBuf.Format(KFmt, Count());
+			break;
+			}
+		case EListThread:
+			{
+			_LIT(KFmt, "%i threads");
+			aBuf.Format(KFmt, Count());
+			break;
+			}
+		case EListChunk:
+			{
+			_LIT(KFmt, "%i chunks, free %S/%S");
+			TInt freeRam = -1, totalRam = -1;
+			TBuf<16> free, total;
+			HAL::Get(HAL::EMemoryRAMFree, freeRam);
+			HAL::Get(HAL::EMemoryRAM, totalRam);
+			HR(free, freeRam);
+			HR(total, totalRam);
+			aBuf.Format(KFmt, Count(), &free, &total);
+			break;
+			}
+		case EListCodeSeg:
+			{
+			_LIT(KFmt, "%i code segments");
+			aBuf.Format(KFmt, Count());
+			break;
+			}
+		case EListHal:
+			{
+			_LIT(KFmt, "%i HAL attributes");
+			aBuf.Format(KFmt, Count());
+			break;
+			}
+		case EListWindowGroups:
+			{
+			_LIT(KFmt, "%i window groups");
+			aBuf.Format(KFmt, Count());
+			break;
+			}
+		case EListMimeTypes:
+			{
+			_LIT(KFmt, "%i mime types");
+			aBuf.Format(KFmt, Count());
+			break;
+			}
+		case EListOpenFiles:
+			{
+			_LIT(KFmt, "%i open files");
+			aBuf.Format(KFmt, Count());
+			break;
+			}
+		case EListFeatureReg:
+			{
+			_LIT(KFmt, "%i features in registry");
+			aBuf.Format(KFmt, Count());
+			break;
+			}
+		case EListServer:
+			{
+			_LIT(KFmt, "%i servers");
+			aBuf.Format(KFmt, Count());
+			break;
+			}
+		case EListMessageQueue:
+			{
+			_LIT(KFmt, "%i message queues");
+			aBuf.Format(KFmt, Count());
+			break;
+			}
+		case EListMutex:
+			{
+			_LIT(KFmt, "%i mutexes");
+			aBuf.Format(KFmt, Count());
+			break;
+			}
+		case EListSemaphore:
+			{
+			_LIT(KFmt, "%i semaphores");
+			aBuf.Format(KFmt, Count());
+			break;
+			}
+		case EListTimer:
+			{
+			_LIT(KFmt, "%i timers");
+			aBuf.Format(KFmt, Count());
+			break;
+			}
+		default:
+			break;
+		}
+	}
+
+TBool CKernListBoxData::SupportsCommand(TInt aCommand)
+	{
+	switch (aCommand)
+		{
+		case ECmdPoll:
+		case ECmdHandleInfo:
+			{
+			if (iType == EListProcess || iType == EListChunk) return ETrue;
+			break;
+			}
+		case ECmdKill:
+			{
+			if (iType == EListProcess) return ETrue;
+			break;
+			}
+		default:
+			break;
+		}
+	return EFalse;
+	}
+
+void CKernListBoxData::KillL()
+	{
+	TUint8* addr = iInfo->iAddressOfKernelObject;
+	RMemoryAccess& mem = iModel->MemAccess();
+	User::LeaveIfError(mem.ObjectDie(iType == EListThread ? EThread : EProcess, 0, addr, EExitKill, 666999, KNullDesC));
+	// The undertaker should cause an update via ThreadDiedL
+	}
+
+TAny* CKernListBoxData::GetHandleL()
+	{
+	return iInfo->iAddressOfKernelObject;
+	}
+
+TInt CKernListBoxData::ExeNameForSid(TUint aSid, RBuf& aName)
+	{
+	// First try our list
+	TInt lserr = KErrNotFound;
+	if (aName.Create(256) != KErrNone) lserr = KErrNoMemory;
+	if (iModel && aName.MaxLength())
+		{
+		for (TInt i = 0; i < iModel->iItemData.Count(); i++)
+			{
+			CKernListBoxData* data = static_cast<CKernListBoxData*>(iModel->iItemData[i]);
+			TProcessKernelInfo* pinfo = static_cast<TProcessKernelInfo*>(data->iInfo);
+			if (data->iType == EListProcess && pinfo->iProcessSecurityInfo.iSecureId == aSid)
+				{
+				lserr = KErrNone;
+				aName.Copy(pinfo->iName);
+				PrettyName(EListProcess, aName);
+				break;
+				}
+			}
+		}
+#ifdef FSHELL_APPARC_SUPPORT
+	if (lserr == KErrNotFound)
+		{
+		// Didn't find the process in our process list. Must have already closed. Try
+		// apparc as a fallback - will only work for fully-fledged applications
+		RApaLsSession ls;
+		TInt lserr = ls.Connect();
+		TApaAppInfo* appinfo = new TApaAppInfo;
+		if (!appinfo ) lserr = KErrNoMemory;
+		if (!lserr)
+			{
+			lserr = ls.GetAppInfo(*appinfo , TUid::Uid(aSid));
+			}
+		if (!lserr)
+			{
+			TInt slash = appinfo->iFullName.LocateReverse('\\');
+			aName.Copy(appinfo->iFullName.Mid(slash+1));
+			}
+		delete appinfo;
+		ls.Close();
+		}
+#endif
+
+	if (aName.Length() == 0 && aSid == 0x10205c44)
+		{
+		// Special case this because sysstart isn't running & isn't an app, and appears
+		// enough as parent to be worth special-casing
+		aName.Copy(_L("SysStart"));
+		lserr = KErrNone;
+		}
+	return lserr;
+	}
+
+void CKernListBoxModel::ThreadDiedL(TInt aHandle)
+	{
+	RThread thread;
+	thread.SetHandle(aHandle);
+	TThreadId id = thread.Id();
+	iThreadHandleArray.Append(aHandle);
+
+	if (iCurrentList == EListThread)
+		{
+		TInt idx = ItemIdIndex(id);
+		if (idx != KErrNotFound)
+			{
+			ModelBeginUpdateLC();
+			CKernListBoxData* data = static_cast<CKernListBoxData*>(iItemData[idx]);
+			data->FormatL(data->iInfo, iTempBuf1, iTempBuf2); // Thread death info isn't stored in iInfo, so no need to update it
+			DataUpdatedL(idx);
+			ModelEndUpdateL();
+
+			if (iInfoChangedCallback.iFunction != NULL && data == iCallbackData)
+				{
+				iInfoChangedCallback.CallBack();
+				}
+
+			}
+		else
+			{
+			// We don't have an entry for this thread id. Oh well, just storing it in the tid list will guarantee it will still be there when the user hits refresh
+			}
+		}
+	else if (iCurrentList == EListProcess)
+		{
+		RProcess p;
+		if (thread.Process(p) == KErrNone)
+			{
+			TProcessId id = p.Id();
+			TInt idx = ItemIdIndex(id);
+			p.Close();
+			if (idx != KErrNotFound)
+				{
+				ModelBeginUpdateLC();
+				CKernListBoxData* data = static_cast<CKernListBoxData*>(iItemData[idx]);
+				data->FormatL(data->iInfo, iTempBuf1, iTempBuf2); // Process death info isn't stored in iInfo, so no need to update it
+				DataUpdatedL(idx);
+				ModelEndUpdateL();
+				if (iInfoChangedCallback.iFunction != NULL && data == iCallbackData)
+					{
+					iInfoChangedCallback.CallBack();
+					}
+
+				}
+			}
+		}
+	}
+
+void CKernListBoxModel::CloseAllThreadHandles()
+	{
+	for (TInt i = 0; i < iThreadHandleArray.Count(); i++)
+		{
+		RThread t;
+		t.SetHandle(iThreadHandleArray[i]);
+		t.Close();
+		}
+	iThreadHandleArray.Reset();
+	}
+
+CKernListBoxModel::~CKernListBoxModel()
+	{
+	CloseAllThreadHandles();
+	delete iUnd;
+#ifdef FSHELL_WSERV_SUPPORT
+	if (iWsSession)
+		{
+		iWsSession->Close();
+		delete iWsSession;
+		}
+#endif
+	iTempBuf1.Close();
+	iTempBuf2.Close();
+
+	for (TInt i = iItemData.Count()-1; i >= 0; i--)
+		{
+		iItemData[i]->Close();
+		}
+	iItemData.Close();
+	}
+
+CUndertaker::CUndertaker(CKernListBoxModel& aModel)
+	: CActive(EPriorityStandard), iModel(aModel)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+CUndertaker::~CUndertaker()
+	{
+	Cancel();
+	iUnd.Close();
+	}
+
+void CUndertaker::Register()
+	{
+	TInt err = KErrNone;
+	if (!iUnd.Handle())
+		{
+		err = iUnd.Create();
+		}
+	if (!err)
+		{
+		iUnd.Logon(iStatus, iHandle);
+		SetActive();
+		}
+	}
+
+void CUndertaker::RunL()
+	{
+	if (iStatus == KErrDied)
+		{
+		iModel.ThreadDiedL(iHandle);
+		Register();
+		}
+	}
+
+void CUndertaker::DoCancel()
+	{
+	iUnd.LogonCancel();
+	}
+
+void CKernListBoxModel::RefreshDataL(TInt aIndex)
+	{
+	if (iCurrentList == EListWindowGroups && !iWsSession)
+		{
+		User::Leave(KErrNotSupported);
+		}
+
+	// Change some names so the code is the same
+	RMemoryAccess& mem(iMemAccess);
+	CKernListBoxModel& model(*this);
+
+	if (iCurrentList == EListCodeSeg)
+		{
+		// Code segs don't support random access
+		aIndex = -1;
+		}
+
+	if (aIndex == -1)
+		{
+		model.RemoveAllDataL();
+		}
+	model.ModelBeginUpdateLC();
+	
+	TObjectType type = EProcess; // Just set it to something to shut up compiler
+	switch (iCurrentList) {
+	case EListProcess: type = EProcess; break;
+	case EListThread: type = EThread; break;
+	case EListChunk: type = EChunk; break;
+	case EListServer: type = EServer; break;
+	case EListMessageQueue: type = EMsgQueue; break;
+	case EListMutex: type = EMutex; break;
+	case EListSemaphore: type = ESemaphore; break;
+	case EListTimer: type = ETimer; break;
+	default: break;
+		}
+
+	TPtr8 buf(0,0);
+	TObjectKernelInfo* info = NULL;
+	CKernListBoxData* data = NULL;
+	if (aIndex != -1)
+		{
+		data = static_cast<CKernListBoxData*>(model.RetrieveDataL(aIndex));
+		CleanupClosePushL(*data);
+		}
+
+	if (iCurrentList == EListCodeSeg)
+		{
+		mem.AcquireCodeSegMutex();
+		TTomsciCodeSegKernelInfo* inf = new(ELeave) TTomsciCodeSegKernelInfo;
+		info = reinterpret_cast<TObjectKernelInfo*>(inf); // These aren't actually related classes, just convenient
+		buf.Set(TPckg<TTomsciCodeSegKernelInfo>(*inf));
+		while (mem.GetNextCodeSegInfo(buf) == KErrNone)
+			{
+			TRAPD(err, model.NewKernDataL(iCurrentList, info));
+			if (err)
+				{
+				break;
+				}
+			inf = NULL;
+			inf = new(ELeave) TTomsciCodeSegKernelInfo;
+			buf.Set(TPckg<TTomsciCodeSegKernelInfo>(*inf));
+			info = reinterpret_cast<TObjectKernelInfo*>(inf); // These aren't actually related classes, just convenient
+			}
+		delete inf;
+		mem.ReleaseCodeSegMutex();
+		}
+	else if (iCurrentList == EListHal)
+		{
+		// HAL isn't actually a kernel container type but from the PoV of this app it is treated similarly
+		//HAL::SEntry* entry = new(ELeave) HAL::SEntry;
+		if (aIndex == -1)
+			{
+			HAL::SEntry* ents = NULL;
+			TInt numEntries = 0;
+			User::LeaveIfError(HAL::GetAll(numEntries, ents));
+			CleanupDeletePushL(ents);
+			for (TInt i = 0; i < numEntries; i++)
+				{
+				SHalInfo* entry = new(ELeave) SHalInfo;
+				entry->iProperties = ents[i].iProperties;
+				entry->iValue = ents[i].iValue;
+				entry->iAttribute = i;
+				CleanupDeletePushL(entry);
+				model.NewKernDataL(iCurrentList, reinterpret_cast<TObjectKernelInfo*>(entry));
+				CleanupStack::Pop(entry);
+				}
+			CleanupStack::PopAndDestroy(ents);
+			}
+		else
+			{
+			SHalInfo* entry = reinterpret_cast<SHalInfo*>(data->iInfo);
+			/*TInt err =*/ HAL::Get((HAL::TAttribute)entry->iAttribute, entry->iValue); // Nothing needs to be done if this fails
+			}
+		}
+	else if (iCurrentList == EListWindowGroups)
+		{
+#if defined(FSHELL_WSERV_SUPPORT) && defined(FSHELL_APPARC_SUPPORT)
+		if (aIndex == -1)
+			{
+			CArrayFixFlat<TInt>* wgIds = new(ELeave) CArrayFixFlat<TInt>(16);
+			CleanupStack::PushL(wgIds);
+			User::LeaveIfError(iWsSession->WindowGroupList(0, wgIds));
+			TInt numEntries = wgIds->Count();
+			for (TInt i = 0; i < numEntries; i++)
+				{
+				TInt handle = (*wgIds)[i];
+				CApaWindowGroupName* name = CApaWindowGroupName::NewLC(*iWsSession, handle);
+				SWgInfo* info = new(ELeave) SWgInfo;
+				CleanupStack::PushL(info);
+				info->iHandle = handle;
+				info->iName = name;
+				info->iSession = iWsSession;
+				model.NewKernDataL(iCurrentList, reinterpret_cast<TObjectKernelInfo*>(info));
+				CleanupStack::Pop(2, name); // info, name
+				}
+			CleanupStack::PopAndDestroy(wgIds);
+			}
+		else
+			{
+			SWgInfo* info = reinterpret_cast<SWgInfo*>(data->iInfo);
+			info->iName->ConstructFromWgIdL(info->iHandle);
+			}
+#endif
+		}
+	else if (iCurrentList == EListMimeTypes)
+		{
+		if (aIndex == -1)
+			{
+#ifdef FSHELL_APPARC_SUPPORT
+			RApaLsSession apparc;
+			User::LeaveIfError(apparc.Connect());
+			CleanupClosePushL(apparc);
+			RImplInfoPtrArray array;
+			CleanupResetAndDestroyPushL(array);
+			REComSession::ListImplementationsL(TUid::Uid(0x101F7D87), array); // Recognisers ECOM interface UID
+			TFileName* dllNamePtr = new(ELeave)TFileName;
+			CleanupStack::PushL(dllNamePtr);
+			TFileName& dllName = *dllNamePtr;
+			RArray<TDataType> mimeTypes;
+			CleanupClosePushL(mimeTypes);
+			gPlugin->DisablePanicCheckPushL();
+			for (TInt i = 0; i < array.Count(); i++)
+				{
+				dllName = _L("UnknownDll");
+				
+				TRAP_IGNORE(Sandbox::GetDllNameFromEcomUidL(mem, array[i]->ImplementationUid(), dllName));
+				mimeTypes.Reset();
+				Sandbox::GetRecogniserInfoL(array[i]->ImplementationUid(), mimeTypes);
+
+				TInt count = mimeTypes.Count();
+				for (TInt j = 0; j < count; j++)
+					{
+					SDataType* info = new(ELeave) SDataType;
+					CleanupStack::PushL(info);
+					info->iMime.Copy(mimeTypes[j].Des8());
+					info->iRecog = dllName;
+					
+					TInt err = apparc.AppForDataType(mimeTypes[j], info->iAppUid);
+					if (!err)
+						{
+						TApaAppInfo appInfo;
+						err = apparc.GetAppInfo(appInfo, info->iAppUid);
+						if (!err)
+							{
+							info->iApp = appInfo.iFullName;
+							}
+						}
+					model.NewKernDataL(iCurrentList, reinterpret_cast<TObjectKernelInfo*>(info));
+					CleanupStack::Pop(info);
+					}
+				}
+			CleanupStack::PopAndDestroy(); // reenables panic checks
+			CleanupStack::PopAndDestroy(4, &apparc); // mimeTypes, dllNamePtr, array, apparc
+#else
+			User::Leave(KErrNotSupported);
+#endif
+			}
+		else
+			{
+			// No refreshing necessary for mime types
+			}
+		}
+	else if (iCurrentList == EListOpenFiles)
+		{
+		if (aIndex == -1)
+			{
+			RPtrHashMap<TDesC, SOpenFile> fileMap;
+			CleanupClosePushL(fileMap);
+			RFs fs;
+			User::LeaveIfError(fs.Connect());
+			CleanupClosePushL(fs);
+			TOpenFileScan scan(fs);
+			CFileList* fileList = NULL;
+			FOREVER
+				{
+				scan.NextL(fileList);
+				if (fileList == NULL)
+					{
+					break;
+					}
+				CleanupStack::PushL(fileList);
+				const TInt numOpenFiles = fileList->Count();
+				for (TInt i = 0; i < numOpenFiles; i++)
+					{
+					const TEntry& entry = (*fileList)[i];
+					// See if we already have an SOpenFile for this filename
+					SOpenFile* info = fileMap.Find(entry.iName);
+					if (info)
+						{
+						if (info->iNumThreads < info->iThreadIds.Count())
+							{
+							info->iThreadIds[info->iNumThreads] = scan.ThreadId();
+							}
+						info->iNumThreads++; // Increment iNumThreads regardless - so we can see how many threads there actually are, rather than how many we can store
+						CKernListBoxData* data = static_cast<CKernListBoxData*>(model.RetrieveDataLC(model.ItemIdIndex((TInt)info)));
+						data->FormatL(reinterpret_cast<TObjectKernelInfo*>(info), iTempBuf1, iTempBuf2); // now we've updated the number of threads, that will have changed the Format view
+						CleanupStack::PopAndDestroy(data);
+						}
+					else
+						{
+						SOpenFile* info = new(ELeave) SOpenFile;
+						CleanupStack::PushL(info);
+						info->iName = entry.iName;
+						info->iNumThreads = 1;
+						info->iThreadIds[0] = scan.ThreadId();
+						model.NewKernDataL(iCurrentList, reinterpret_cast<TObjectKernelInfo*>(info));
+						CleanupStack::Pop(info);
+						fileMap.InsertL(&info->iName, info);
+						}
+					}
+				CleanupStack::PopAndDestroy(fileList);
+				fileList = NULL;
+				}
+			CleanupStack::PopAndDestroy(2, &fileMap); // fileMap, fs
+			}
+		else
+			{
+			// No refreshing possible for open files
+			}
+		}
+	else if (iCurrentList == EListFeatureReg)
+		{
+		// Can't link directly against featreg.dll because it doesn't exist on generic 9.1
+		RLibrary featLib;
+		TInt err = featLib.Load(_L("featreg.dll"));
+		if (err) return; // No feature registry, no features!
+
+		#ifdef __WINS__
+			#define KQueryOrdinal 9
+		#else
+			#define KQueryOrdinal 4
+		#endif
+
+		typedef TInt (*QueryFn)(TUid, TUint32&);
+		QueryFn Query = (QueryFn)featLib.Lookup(KQueryOrdinal);
+
+		if (aIndex == -1)
+			{
+			RArray<TUid> features;
+			CleanupClosePushL(features);
+			gPlugin->GetFeatureUidsL(features);
+
+			for (TInt i = 0; i < features.Count(); i++)
+				{
+				SFeature* info = new(ELeave) SFeature;
+				CleanupStack::PushL(info);
+				info->iFeature = features[i].iUid;
+				info->iErr = Query(features[i], info->iInfo);
+				model.NewKernDataL(iCurrentList, reinterpret_cast<TObjectKernelInfo*>(info));
+				CleanupStack::Pop(info);
+				}
+			CleanupStack::PopAndDestroy(&features);
+			}
+		else
+			{
+			SFeature* info = reinterpret_cast<SFeature*>(data->iInfo);
+			info->iErr = Query(TUid::Uid(info->iFeature), info->iInfo);
+			}
+		featLib.Close();
+		}
+	else
+		{
+		// Generic code that works for all first-class Kernel objects (ie processes, threads, chunks. Despite appearances, code segs are not first-class kernel objects).
+
+		TInt sizeofObjectBuf = 0;
+		switch(iCurrentList)
+			{
+			case EListProcess:
+				sizeofObjectBuf = sizeof(TProcessKernelInfo); break;
+			case EListThread:
+				sizeofObjectBuf = sizeof(TThreadKernelInfo); break;
+			case EListChunk:
+				sizeofObjectBuf = sizeof(TChunkKernelInfo); break;
+			case EListServer:
+				sizeofObjectBuf = sizeof(TServerKernelInfo); break;
+			case EListMessageQueue:
+				sizeofObjectBuf = sizeof(TMsgQueueKernelInfo); break;
+			case EListMutex:
+				sizeofObjectBuf = sizeof(TMutexKernelInfo); break;
+			case EListSemaphore:
+				sizeofObjectBuf = sizeof(TSemaphoreKernelInfo); break;
+			case EListTimer:
+				sizeofObjectBuf = sizeof(TTimerKernelInfo); break;
+			default:
+				User::Panic(_L("QR3 Missing type"), iCurrentList);
+			}
+
+		if (aIndex == -1)
+			{
+			// Be paranoid about releasing the mutexes, to avoid the risk of deadlocking. Only likely if we were looking through the chunk container AND needed to grow our chunk in NewKernDataL, but err on the side of caution
+			//mem.AcquireContainerMutex(type);
+			TUint count;
+			mem.GetContainerCount(type, count);
+			//mem.ReleaseContainerMutex(type);
+			for (TUint i = 0; i < count; i++)
+				{
+				info = (TObjectKernelInfo*)User::AllocZL(sizeofObjectBuf);
+				buf.Set((TUint8*)info, sizeofObjectBuf, sizeofObjectBuf);
+
+				CleanupStack::PushL(info);
+				// Don't need to grab the lock any more
+				//mem.AcquireContainerMutex(type);
+				TInt err = mem.GetObjectInfo(type, i, buf);
+				//mem.ReleaseContainerMutex(type);
+				if (err == KErrNone)
+					{
+					model.NewKernDataL(iCurrentList, info);
+					CleanupStack::Pop(info);
+					}
+				else
+					{
+					CleanupStack::PopAndDestroy(info);
+					}
+				}
+			}
+		else
+			{
+			buf.Set((TUint8*)data->iInfo, sizeofObjectBuf, sizeofObjectBuf);
+			mem.GetObjectInfo(type, data->iInfo->iAddressOfKernelObject, buf); // Nothing required on error
+			}
+		}
+	
+	if (aIndex != -1)
+		{
+		data->FormatL(data->iInfo, iTempBuf1, iTempBuf2);
+		model.DataUpdatedL(aIndex);
+		CleanupStack::PopAndDestroy(data);
+		}
+	model.Sort(); // We can't do this in NewKernDataL because the things we sort on aren't setup until FormatL
+	model.ModelEndUpdateL();
+
+	if (iInfoChangedCallback.iFunction != NULL && (aIndex == -1 || data == iCallbackData))
+		{
+		iInfoChangedCallback.CallBack();
+		}
+	}
+
+void CKernListBoxModel::Sort(TLinearOrder<CKernListBoxData> aOrder)
+	{
+	iSort = aOrder;
+	Sort();
+	}
+
+void CKernListBoxModel::Sort()
+	{
+	if (iSort)
+		{
+		User::QuickSort(Count(), *this, *this);
+		}
+	}
+
+void CKernListBoxModel::SetInfoChangedCallback(TInt aIndex, const TCallBack& aCallback)
+	{
+	iInfoChangedCallback = aCallback;
+	if (aCallback.iFunction)
+		{
+		iCallbackData = iItemData[aIndex];
+		iCallbackData->Open();
+		}
+	else
+		{
+		iCallbackData->Close();
+		iCallbackData = NULL;
+		}
+	}
+
+void CKernListBoxData::Open()
+	{
+	iRefCount++;
+	}
+
+void CKernListBoxData::Close()
+	{
+	iRefCount--;
+	if (iRefCount == 0)
+		delete this;
+	}
+
+void CKernListBoxData::SetDelegate(MKernListBoxDataDelegate* aDelegate)
+	{
+	iDelegate = aDelegate;
+	}
+
+MKernListBoxDataDelegate* CKernListBoxData::Delegate()
+	{
+	return iDelegate;
+	}
+
+const MKernListBoxDataDelegate* CKernListBoxData::Delegate() const
+	{
+	return iDelegate;
+	}
+
+TInt CKernListBoxData::ItemId() const
+	{
+	return iItemId;
+	}
+
+void CKernListBoxData::SetItemId(TInt aItemId)
+	{
+	iItemId = aItemId;
+	}
+
+void CKernListBoxData::ConstructL()
+	{
+	}
+
+CKernListBoxModel& CKernListBoxData::Model()
+	{
+	return *iModel;
+	}