dbgagents/trkagent/engine/TrkDispatchLayer.cpp
author ravikurupati
Tue, 02 Mar 2010 10:33:16 +0530
changeset 0 c6b0df440bee
permissions -rw-r--r--
Initial contribution of EPL licensed sources

/*
* Copyright (c) 2004 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 "TrkEngine.h"
#include "TrkDispatchLayer.h"
#include "DateTimeConverter.h"

#ifndef __TEXT_SHELL__
#include "TrkSwInstall.h"
#endif

//
// Macros
//

//
// Version Information
//

#define MAJOR_VERSION_NUMBER	3
#define MINOR_VERSION_NUMBER	2
#define BUILD_NUMBER			4


//
// Support Information
//

#define DS_SUPPORT_MASK_00_07	0x7E	// kDSConnect, kDSDisconnect, kDSReset, kDSVersions, kDSSupportMask, kDSCPUType */
#define DS_SUPPORT_MASK_08_0F	0x00
#define DS_SUPPORT_MASK_10_17	0x4f	// R/W Memory, R/W Registers, FlushCache
#define DS_SUPPORT_MASK_18_1F	0x5f	// kDSContinue, kDSStep, kDSStop, kDSSetBreak, kDSClearBreak
#define DS_SUPPORT_MASK_20_27	0x01	// kDSNotifyFileInput
#define DS_SUPPORT_MASK_28_2F	0x00
#define DS_SUPPORT_MASK_30_37	0x00
#define DS_SUPPORT_MASK_38_3F	0x00
#define DS_SUPPORT_MASK_40_47	0x0f	// OS Create/Delete Item, OS Read/Write Info
#define DS_SUPPORT_MASK_48_4F	0x1f	// OS Read/Write/Open/Close/Position File
#define DS_SUPPORT_MASK_50_57	0x00
#define DS_SUPPORT_MASK_58_5F	0x00
#define DS_SUPPORT_MASK_60_67	0x00
#define DS_SUPPORT_MASK_68_6F	0x00
#define DS_SUPPORT_MASK_70_77	0x00
#define DS_SUPPORT_MASK_78_7F	0x00
#define DS_SUPPORT_MASK_80_87	0x01	// kDSReplyACK
#define DS_SUPPORT_MASK_88_8F	0x00
#define DS_SUPPORT_MASK_90_97	0x11	// kDSNotifyStopped, kDSNotifyStopped2
#define DS_SUPPORT_MASK_98_9F	0x00
#define DS_SUPPORT_MASK_A0_A7	0x03	// kDSOSNotifyCreated, kDSOSNotifyDeleted
#define DS_SUPPORT_MASK_A8_AF	0x00
#define DS_SUPPORT_MASK_B0_B7	0x00
#define DS_SUPPORT_MASK_B8_BF	0x00
#define DS_SUPPORT_MASK_C0_C7	0x00
#define DS_SUPPORT_MASK_C8_CF	0x00
#define DS_SUPPORT_MASK_D0_D7	0x03	// kDSWriteFile, kDSReadFile
#define DS_SUPPORT_MASK_D8_DF	0x00
#define DS_SUPPORT_MASK_E0_E7	0x00
#define DS_SUPPORT_MASK_E8_EF	0x00
#define DS_SUPPORT_MASK_F0_F7	0x00
#define DS_SUPPORT_MASK_F8_FF	0x80	// kDSReplyNAK

#define KProcessKilled 0x4B696C6C // "Kill"

#ifdef EKA2
#define EUSER_LIBPATH _L("Z:\\Sys\\Bin\\euser.dll")
#else
#define EUSER_LIBPATH _L("Z:\\System\\Libs\\euser.dll")
#endif

#ifdef __OEM_TRK__
#define TRK_TYPE_DESCRIPTION _L8("System TRK")
#else
#define TRK_TYPE_DESCRIPTION _L8("Application TRK")
#endif


//
// Swap2
//
// Byte-swaps a 2-byte value.  Used to convert to/from little/big endian.
//
static TUint16 Swap2(TUint16 aSource)
{
	TUint16 dest = 0;
	for (TInt i=0; i<2; i++)
	{
		dest <<= 8;
		dest |= aSource & 0xFF;
		aSource >>= 8;
	}
	
	return dest;
} 

//
// Swap4
//
// Byte-swaps a 4-byte value.  Used to convert to/from little/big endian.
//
static TUint32 Swap4(TUint32 aSource)
{
	TUint32 dest = 0;
	for (TInt i=0; i<4; i++)
	{
		dest <<= 8;
		dest |= aSource & 0xFF;
		aSource >>= 8;
	}
	
	return dest;
} 

//
// Swap4xN
//
//	Byte-swaps N 4-byte values *in place*.  Used to convert to/from little/big endian.
//
void Swap4xN(TUint32 *aSource, TInt aCount)
{
	while (aCount--)
	{
		TUint32 temp = Swap4(*aSource);
		*aSource++ = temp;
	}
} 


//
//
// CExitTrapper implementation
//
//

//
// CExitTrapper constructor
//
// Accepts CTrkDispatchLayer interface and the process ID of the
// process to watch
//
CExitTrapper::CExitTrapper(CTrkDispatchLayer *aDispatch, TUint32 aProcessId)
	: CActive(EPriorityStandard),
	  iProcessId(aProcessId),
	  iDispatch(aDispatch)
{
	CActiveScheduler::Add(this);

	TInt error = iProcess.Open(iProcessId);
	if (KErrNone != error)
		User::Panic(_L("Unable to open process"), __LINE__);
}

//
// CExitTrapper destructor
//
CExitTrapper::~CExitTrapper()
{
	Cancel();
	Deque();
	iProcess.Close();
}

//
// CExitTrapper::Watch
//
// Watch for the process to exit
//
void CExitTrapper::Watch()
{
	iProcess.Logon(iStatus);
	SetActive();
}

//
// CExitTrapper::RunL
//
// Called when the process exits
//
void CExitTrapper::RunL()
{
	// sometimes this is run when the process has yet to exit
	if (iProcess.ExitType() == EExitPending)
	{
		iProcess.LogonCancel(iStatus);
		Watch();
	}
	else
	{
		iDispatch->DoNotifyProcessDiedL(iProcessId, iProcess.ExitReason());
	}
}

//
// CExitTrapper::DoCancel
//
// Stop waiting for this process to exit
//
void CExitTrapper::DoCancel()
{
	iProcess.LogonCancel(iStatus);
}


//
//
// CEventTrapper implementation
//
//

//
// CEventTrapper constructor
//
// Accepts CTrkDispatchLayer interface
//
CEventTrapper::CEventTrapper(CTrkDispatchLayer *aDispatch)
	: CActive(CActive::EPriorityStandard),
	  iDispatch(aDispatch)
{
	CActiveScheduler::Add(this);
}

//
// CEventTrapper destructor
//
CEventTrapper::~CEventTrapper()
{
	Cancel();
	Deque();
}

//
// CEventTrapper::Watch
//
// Start listening for events
//
void CEventTrapper::Watch()
{
	iDispatch->iKernelDriver.GetEvent(iStatus, iEventInfo);
	SetActive();
}

//
// CEventTrapper::RunL
//
// Called when an event occurs
//
void CEventTrapper::RunL()
{
	// determine the type of event and handle accordingly
	switch (iEventInfo.iEventType)
	{
		case SEventInfo::EThreadBreakPoint:
		{
			iDispatch->DoNotifyStoppedL(iEventInfo.iProcessId, iEventInfo.iThreadId, iEventInfo.iCurrentPC, KNullDesC8);
			break;
		}
		case SEventInfo::EThreadException:
		{
			TBuf8<100> buf;
			
			switch(iEventInfo.iExceptionNumber)
			{
				case EExcIntegerDivideByZero:
				{
					buf.Format(_L8("An integer divide by zero exception has occurred."));
					break;
				}
				case EExcIntegerOverflow:
				{
					buf.Format(_L8("An integer overflow exception has occurred."));
					break;
				}
				case EExcBoundsCheck:
				{
					buf.Format(_L8("An bounds check exception has occurred."));
					break;
				}
				case EExcInvalidOpCode:
				{
					buf.Format(_L8("An invalid instruction exception has occurred."));
					break;
				}
				case EExcDoubleFault:
				{
					buf.Format(_L8("A double fault exception has occurred."));
					break;
				}
				case EExcStackFault:
				{
					buf.Format(_L8("A stack fault exception has occurred."));
					break;
				}
				case EExcAccessViolation:
				{
					buf.Format(_L8("An access violation exception has occurred."));
					break;
				}
				case EExcPrivInstruction:
				{
					buf.Format(_L8("A priveledged instruction exception has occurred."));
					break;
				}
				case EExcAlignment:
				{
					buf.Format(_L8("An alignment exception has occurred."));
					break;
				}
				case EExcPageFault:
				{
					buf.Format(_L8("A page fault exception has occurred."));
					break;
				}
				case EExcFloatDenormal:
				case EExcFloatDivideByZero:
				case EExcFloatInexactResult:
				case EExcFloatInvalidOperation:
				case EExcFloatOverflow:
				case EExcFloatStackCheck:
				case EExcFloatUnderflow:
				{
					buf.Format(_L8("A floating point exception has occurred."));
					break;
				}
				case EExcAbort:
				{
					buf.Format(_L8("An abort exception has occurred."));
					break;
				}
				case EExcUserInterrupt:
				{
					buf.Format(_L8("A user interrupt exception has occurred."));
					break;
				}
				case EExcDataAbort:
				{
					buf.Format(_L8("A data abort exception has occurred."));
					break;
				}
				case EExcCodeAbort:
				{
					buf.Format(_L8("A code abort exception has occurred."));
					break;
				}				
				case EExcGeneral:
				case EExcSingleStep:
				case EExcBreakPoint:
				case EExcKill:
				case EExcMaxNumber:
				case EExcInvalidVector:
				default:
				{
					buf.Format(_L8("An unknown exception (%d) has occurred."), iEventInfo.iExceptionNumber);
					break;				
				}
			}
			
			iDispatch->DoNotifyStoppedL(iEventInfo.iProcessId, iEventInfo.iThreadId, iEventInfo.iCurrentPC, buf);
			break;
		}
		case SEventInfo::EThreadPanic:
		{
			TBuf8<100> buf;
//			buf.Format(_L8("Thread 0x%x has panicked.\nCategory: %S\nReason: %d"), iEventInfo.iThreadId, &iEventInfo.iPanicCategory, iEventInfo.iExceptionNumber);
			buf.Format(_L8("Thread 0x%x has panicked. Category: %S; Reason: %d"), iEventInfo.iThreadId, &iEventInfo.iPanicCategory, iEventInfo.iPanicReason);
			
			iDispatch->DoNotifyStoppedL(iEventInfo.iProcessId, iEventInfo.iThreadId, iEventInfo.iCurrentPC, buf, true, iEventInfo.iExceptionNumber);
			break;
		}
		case SEventInfo::EProcessPanic:
		{
			TBuf8<100> buf;
			buf.Format(_L8("Process 0x%x has panicked.\nCategory: %S\nReason: %d"), iEventInfo.iProcessId, &iEventInfo.iPanicCategory, iEventInfo.iExceptionNumber);
			
			iDispatch->DoNotifyStoppedL(iEventInfo.iProcessId, iEventInfo.iThreadId, iEventInfo.iCurrentPC, buf);
			break;
		}
		case SEventInfo::ELibraryLoaded:
		{
			// a library has been loaded.  we get statically linked library loaded notifications
			// the very first time the process is created.  we want to ignore these because we
			// handle static libs in another way.  if the process the library was loaded for is
			// not being debugging, just resume the thread and ignore the event.  if the process
			// is being debugged but it hasn't yet been created, then this must be a static lib
			// and we ignore it.  note that we do not bother resuming the thread since it has not
			// been started yet!

			TBool created = EFalse;
			TBool found = EFalse;
					
			for (TInt i=0; i<iDispatch->iDebugProcessList.Count(); i++)
			{
				if (iDispatch->iDebugProcessList[i]->ProcessId() == iEventInfo.iProcessId)
				{
					created = iDispatch->iDebugProcessList[i]->iReadyForLibraryLoadNotification;
					found = ETrue;
					break;
				}
			}

		#ifndef EKA2
			if (!iEventInfo.iCodeAddress)
			{
				TBuf<KMaxPath> libName;
				libName.Copy(iEventInfo.iFileName);
				
				RLibrary lib;
				TInt err = lib.LoadRomLibrary(libName, KNullDesC);
				if (KErrNone == err)
				{
					iEventInfo.iCodeAddress = (TUint32)lib.EntryPoint();
					lib.Close();
				}
			}
		#endif

			if (!created || !iEventInfo.iCodeAddress || !found)
			{
				iDispatch->iKernelDriver.ResumeThread(iEventInfo.iThreadId);
			}
			else
			{
				iDispatch->DoNotifyLibraryLoadedL(iEventInfo.iFileName, iEventInfo.iProcessId, iEventInfo.iThreadId, iEventInfo.iCodeAddress, iEventInfo.iDataAddress);
			}
			break;
		}
		case SEventInfo::ELibraryUnloaded:
		{
			TBool found = EFalse;
			
			for (TInt i=0; i<iDispatch->iDebugProcessList.Count(); i++)
			{
				if (iDispatch->iDebugProcessList[i]->ProcessId() == iEventInfo.iProcessId)
				{
					found = ETrue;
					break;
				}
			}
			
			if (!found)
			{
				iDispatch->iKernelDriver.ResumeThread(iEventInfo.iThreadId);
			}
			else
			{
				iDispatch->DoNotifyLibraryUnloadedL(iEventInfo.iFileName, iEventInfo.iProcessId, iEventInfo.iThreadId);
			}
			
			break;
		}
		case SEventInfo::EUserTrace:
		{
			iDispatch->DoNotifyUserTraceL(iEventInfo.iTraceData);
			break;
		}
		case SEventInfo::EProcessAdded:
		{
			iDispatch->DoNotifyProcessAddedL(iEventInfo.iFileName, iEventInfo.iProcessId, 
											 iEventInfo.iThreadId, iEventInfo.iUid, 
											 iEventInfo.iCodeAddress, iEventInfo.iDataAddress);
			break;
		}
		case SEventInfo::EUnknown:
		default:
			User::Panic(_L("Unknown event type"), __LINE__);
			break;
	}

	// reset the values
	iEventInfo.Reset();

	// keep listening for more events
	Watch();
}

//
// CEventTrapper::DoCancel
//
// Stop listening for events
//
void CEventTrapper::DoCancel()
{
	iDispatch->iKernelDriver.CancelGetEvent();
}


//
//
// CDebugProcess implementation
//
//

//
// CDebugProcess::NewL
//
// Accepts CTrkDispatchLayer interface and the process ID and main
// thread ID of a process being debugged
//
CDebugProcess* CDebugProcess::NewL(CTrkDispatchLayer *aDispatch, TUint32 aProcessId, TUint32 aMainThreadId)
{
	CDebugProcess* self = new(ELeave) CDebugProcess();
	self->ConstructL(aDispatch, aProcessId, aMainThreadId);
	return self;
}

//
// CDebugProcess::ConstructL
//
// Accepts CTrkDispatchLayer interface and the process ID and main
// thread ID of a process being debugged
//
void CDebugProcess::ConstructL(CTrkDispatchLayer *aDispatch, TUint32 aProcessId, TUint32 aMainThreadId)
{
	iProcessId = aProcessId;
	iMainThreadId = aMainThreadId;
	iReadyForLibraryLoadNotification = EFalse;
	
	// start waiting for this process to exit
	iExitTrapper = new(ELeave) CExitTrapper(aDispatch, aProcessId);
	iExitTrapper->Watch();
}

//
// CDebugProcess destructor
//
CDebugProcess::~CDebugProcess()
{
	SafeDelete(iExitTrapper);
}

#ifndef __TEXT_SHELL__

//
// CPhoneInfo implementation
//
CPhoneInfo::CPhoneInfo():
           CActive(EPriorityStandard),
           iPhoneIdV1Pckg(iPhoneIdV1),
           iDispatchLayer(NULL)
{
    CActiveScheduler::Add(this);
}

CPhoneInfo* CPhoneInfo::NewL()
{
    CPhoneInfo* self = new(ELeave) CPhoneInfo();
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop();
    return self;
}

void CPhoneInfo::ConstructL()
{
    iTelephony = CTelephony::NewL();
}

CPhoneInfo::~CPhoneInfo() 
{ 
    Cancel();
    Deque();
    SafeDelete(iTelephony);
}

void CPhoneInfo::GetPhoneName(CTrkDispatchLayer* aDispatchLayer)
{
    iDispatchLayer = aDispatchLayer;
    iTelephony->GetPhoneId(iStatus, iPhoneIdV1Pckg);
    SetActive();
}

void CPhoneInfo::RunL()
{   
    if(iStatus == KErrNone)
	{          
        iDispatchLayer->UpdatePhoneNameInfo(iPhoneIdV1.iModel);              
    }
}

void CPhoneInfo::DoCancel()
{
	iTelephony->CancelAsync(CTelephony::EGetPhoneIdCancel);
}
#endif

//
//
// CTrkDispatchLayer implementation
//
//

//
// CTrkDispatchLayer constructor
//
CTrkDispatchLayer::CTrkDispatchLayer()
	: iEngine(NULL),
	  iFramingLayer(NULL),
#ifndef __TEXT_SHELL__
	  iPhoneInfo(NULL),
#endif
	  iFileState(EFileUnknown),
	  iDebugProcessList(1),
	  iProcessList(1),
	  iThreadList(1),
	  iSuspendedThreadList(1),
	  iEventTrapper(NULL),
	  iIsConnected(EFalse),
	  iPhoneNameInfoAvailable(EFalse)
	  
#ifdef __OEM_TRK__	  
	  ,iUseTcbServer(EFalse)
#endif	  
{
}

//
// CTrkDispatchLayer::NewL
//
CTrkDispatchLayer* CTrkDispatchLayer::NewL(CTrkCommPort *aPort, CTrkEngine* aEngine)
{
	CTrkDispatchLayer* self = new(ELeave) CTrkDispatchLayer();
	self->ConstructL(aPort, aEngine);
	return self;
}

//
// CTrkDispatchLayer destructor
//
CTrkDispatchLayer::~CTrkDispatchLayer()
{
	SafeDelete(iFramingLayer);

	SafeDelete(iInputBuffer);
	SafeDelete(iReplyBuffer);
#ifndef __TEXT_SHELL__
	SafeDelete(iPhoneInfo);
#endif
	// just in case a disconnect never happened
	SafeDelete(iEventTrapper);
	
#ifndef __WINS__
	iKernelDriver.Close();
#endif

    CloseTcbServer();
	iProcessList.Close();
	iThreadList.Close();
	iSuspendedThreadList.Close();
	
	iDebugProcessList.ResetAndDestroy();	
	iDebugProcessList.Close();
	//Notify the server that Debugging is ended
    if (iEngine)
        iEngine->DebuggingEnded();  
        
}
//
// CTrkDispathcLayer::CloseTcbServer()
//
void CTrkDispatchLayer::CloseTcbServer()
{
#ifdef __OEM_TRK__  
    //Shutdown the tcb server.
    if (iUseTcbServer)
    {
        iTrkTcbSession.ShutDownServer();
        iTrkTcbSession.Close();
        iUseTcbServer = EFalse;
    }
#endif  

}

//
// CTrkDispatchLayer::ConstructL
//
void CTrkDispatchLayer::ConstructL(CTrkCommPort *aPort, CTrkEngine* aEngine)
{
	iEngine = aEngine;
	
	// create the framing layer interface
	iFramingLayer = new CTrkFramingLayer(aPort);

	// At a minimum, we assume that the host debugger supports 3.3 version of the protocol
	// From 3.0 to 3.3, TRK is backwards compatible. Starting with version 3.4, TRK sends 
	// process created notifications as part of notify created event. Unless the host 
	// debugger sets the supported protocol version to 3.4, we are not going to send this 
	// new notification. Going forward, we should check for the protocol version before 
	// we send new notifications. 
	iHostVersion.iMajor = DS_PROTOCOL_MAJOR_VERSION_3;
	iHostVersion.iMinor = DS_PROTOCOL_MINOR_VERSION_3;
	
	//To find the sw version runnning in the phone
	FindPhoneSWVersion();
		
	// On techview, this functionality is not available for some reason.
	// This needs to be investigated further, but this functionality is not critical for techview platform right now.
#ifdef __S60__
	// To find the name of the phone.
	TRAPD(err1, FindPhoneNameL());
	if (err1 != KErrNone)
#endif	   
	{
	    iPhoneNameInfoAvailable = EFalse;
	}
}

//
// CTrkDispathLayer::FindPhoneSWVersion()
//
// Finds out the software version of the phone
//
void CTrkDispatchLayer::FindPhoneSWVersion()
{
#ifndef __TEXT_SHELL__
    TBuf<KSysUtilVersionTextLength> version;
    if (SysUtil::GetSWVersion( version ) == KErrNone ) 
	{
        iPhoneVersion.Copy(version);
	}                
#endif
}

//
// CTrkDispathLayer::FindPhoneName()
//
// Finds the name of the phone 
//
void CTrkDispatchLayer::FindPhoneNameL()
{
#ifndef __TEXT_SHELL__
    iPhoneInfo = CPhoneInfo::NewL();
    iPhoneInfo->GetPhoneName(this);
#endif             
}

//
// CTrkDispatchLayer::Listen
//
// Start listening to the communications port for messages from the host debugger
//
void CTrkDispatchLayer::Listen()
{
	iFramingLayer->Listen(this);
}

//
// CTrkDispatchLayer::StopListening
//
// Stop listening to the communications port for messages from the host debugger
//
void CTrkDispatchLayer::StopListening()
{
	// just in case the user quit MetroTrk while something was being debugged.
	RProcess process;
	for (TInt i=0; i<iDebugProcessList.Count(); i++)
	{
		if (KErrNone == process.Open(iDebugProcessList[i]->ProcessId()))
		{
		#ifdef EKA2
			process.Kill(KErrNone);
		#else	
			process.Kill(KProcessKilled);
		#endif
			process.Close();
		}
	}

	iFramingLayer->StopListening();
}

//
// CTrkDispatchLayer::GetVersionInfo
//
// Get the current version of MetroTrk
//
void CTrkDispatchLayer::GetVersionInfo(TInt &aMajorVersion, TInt &aMinorVersion, TInt &aMajorAPIVersion, TInt &aMinorAPIVersion, TInt &aBuildNumber)
{
	aMajorVersion = MAJOR_VERSION_NUMBER;
	aMinorVersion = MINOR_VERSION_NUMBER;
	aMajorAPIVersion = DS_PROTOCOL_MAJOR_VERSION;
	aMinorAPIVersion = DS_PROTOCOL_MINOR_VERSION;
	aBuildNumber = BUILD_NUMBER;
}

//
// CTrkDispatchLayer::HandleMsg
//
// Handle a command sent by the host debugger
//
void CTrkDispatchLayer::HandleMsg(const TDesC8& aMsg)
{
	TInt error = KErrNone;

	// reset the input buffer and set it to the new unframed message
	SafeDelete(iInputBuffer);
	iInputBuffer = aMsg.Alloc();

	if (!iInputBuffer)
		User::Panic(_L("Failed to allocate input buffer"), __LINE__);
	
	TRAP(error, DispatchMsgL());

	if (error < 0)
	{
		// its a symbian os error
		error = kDSReplyOsError;
	}
	
	// handle errors raised during command execution
	switch(error)
	{
		// no error and ack was sent by handler
 		case kDSReplyNoError:
 			break;

		// there was a problem with the packet received
		case kDSReplyPacketSizeError:
		case kDSReplyEscapeError:
		case kDSReplyBadFCS:
		case kDSReplyOverflow:
		case kDSReplySequenceMissing:
			iFramingLayer->RespondErr(kDSReplyNAK, error);
			break;
			
		// command and format were OK, but failed for some other reason
 		default:
			iFramingLayer->RespondErr(kDSReplyACK, error);
	}
}

//
// CTrkDispatchLayer::DispatchMsgL
//
// Handle the command sent by the host debugger
//
void CTrkDispatchLayer::DispatchMsgL()
{
	// make sure the input buffer is setup
	User::LeaveIfNull(iInputBuffer);

	// iInputBuffer holds the unframed message from the host
	switch (iInputBuffer->Ptr()[0])
	{
		case kDSPing:
		{
			// nothing to do
			iFramingLayer->RespondOkL(KNullDesC8);
			break;
		}
		case kDSConnect:
		{
			DoConnectL();
			break;
		}
		case kDSDisconnect:
		{
			DoDisconnectL();
			break;
		}
		case kDSVersions:
		{
			DoVersionsL();
			break;
		}
		case kDSVersions2:
		{
			DoVersions2L();
			break;
		}
		case kDSVersions3:
		{
			DoVersions3L();
			break;
		}
		case kDSHostVersions:
		{
			DoHostVersionsL();
			break;
		}
		case kDSSupportMask:
		{
			DoSupportMaskL();
			break;
		}
		case kDSCPUType:
		{
			DoCPUTypeL();
			break;
		}
		case kDSReadMemory:
		{
			DoReadMemoryL();
			break;
		}
		case kDSWriteMemory:
		{
			DoWriteMemoryL();
			break;
		}
		case kDSReadRegisters:
		{
			DoReadRegistersL();
			break;
		}
		case kDSWriteRegisters:
		{
			DoWriteRegistersL();
			break;
		}
		case kDSContinue:
		{
			DoContinueL();
			break;
		}
		case kDSStep:
		{
			DoStepL();
			break;
		}
		case kDSStop:
		{
			DoStopL();
			break;
		}
		case kDSSetBreak:
		{
			DoSetBreakL();
			break;
		}
		case kDSClearBreak:
		{
			DoClearBreakL();
			break;
		}
		case kDSModifyBreakThread:
		{
			DoModifyBreakThreadL();
			break;
		}
		case kDSOSCreateItem:
		{
			DoCreateItemL();
			break;
		}
		case kDSOSDeleteItem:
		{
			DoDeleteItemL();
			break;
		}
		case kDSOSReadInfo:
		{
			DoReadInfoL();
			break;
		}
		case kDSOSWriteInfo:
		{
			DoWriteInfoL();
			break;
		}
		case kDSOSWriteFile:
		{
			DoWriteFileL();
			break;
		}
		case kDSOSReadFile:
		{
			DoReadFileL();
			break;
		}
		case kDSOSOpenFile:
		{
			DoOpenFileL();
			break;
		}	
		case kDSOSCloseFile:
		{
			DoCloseFileL();
			break;
		}
		case kDSOSPositionFile:
		{
			DoPositionFileL();
			break;
		}
		case kDSOSInstallFile:
		{
			DoInstallFileL();
			break;
		}
		case kDSOSInstallFile2:
		{
			DoInstallFile2L();
			break;
		}
		case kDSOSPhoneSWVersion:
	    {		    
		    DoGetPhoneSWVersionL();
			break;
		}
		case kDSOSPhoneName:		    
		{
		    DoGetPhoneNameL();
		    break;
		}
		
		case kDSReplyACK:
		case kDSReplyNAK:
			break;

		case kDSReset:
		case kDSFillMemory:
		case kDSCopyMemory:
		case kDSFlushCache:
		case kDSDownload:
		case kDSNotifyFileInput:			
		default:
		{
			// unsupported command
			iFramingLayer->RespondErr(kDSReplyACK, kDSReplyUnsupportedCommandError);
			break;
		}
	}
}

//
// CTrkDispatchLayer::DoConnectL
//
// The host debugger is starting a new debug session
//
void CTrkDispatchLayer::DoConnectL()
{	
	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSConnect != command)
		User::Leave(kDSReplyError);

	// if we're already connected for some reason, we need to cleanup so we're ready
	// for a new debug session
	if (iIsConnected)
	{
		// reset the sequence ids for the next debug session
		iFramingLayer->ResetSequenceIDs();

		//stop listening for events
		SafeDelete(iEventTrapper);

		// let the kernel side driver cleanup
		iKernelDriver.Close();

		iIsConnected = EFalse;
	}

	// reset the lists so that they are ready for use
	iProcessList.Reset();
	iThreadList.Reset();
	iSuspendedThreadList.Reset();
	iDebugProcessList.ResetAndDestroy();

	TMetroTrkDriverInfo info;
#ifndef EKA2
	RLibrary euser;
	User::LeaveIfError(euser.Load(EUSER_LIBPATH));
	CleanupClosePushL(euser);
	
	info.iPanic1Address = (TUint32)euser.Lookup(812);			// RThread::Panic
	info.iPanic2Address = (TUint32)euser.Lookup(813);			// RProcess::Panic
	info.iException1Address = (TUint32)euser.Lookup(868);		// RThread::RaiseException
	info.iException2Address = (TUint32)euser.Lookup(520);		// User::HandleException
	info.iLibraryLoadedAddress = (TUint32)euser.Lookup(636);	// UserSvr::LibraryLoaded

	// calculate the end address of the user library.  breakpoints and stepping will not
	// be allowed from the start of ROM to the end of the user library since stopping a
	// kernel thread could end up freezing the target
	RFs fs;
	User::LeaveIfError(fs.Connect());
	CleanupClosePushL(fs);

	RFile file;
	User::LeaveIfError(file.Open(fs, EUSER_LIBPATH, EFileStream|EFileRead|EFileShareReadersOnly));
	CleanupClosePushL(file);

	TInt size;
	User::LeaveIfError(file.Size(size));
	
	info.iUserLibraryEnd = (TUint32)euser.EntryPoint() + size;

	CleanupStack::PopAndDestroy(); // file
	CleanupStack::PopAndDestroy(); // fs
	CleanupStack::PopAndDestroy(); // euser
#endif	
	
	// start the kernel side driver
	User::LeaveIfError(iKernelDriver.Open(info));
	
	// start listening for events
	iEventTrapper = new(ELeave) CEventTrapper(this);
	iEventTrapper->Watch();

	iIsConnected = ETrue;	
#ifdef __S60__	
	// now close close crash logger
	CloseCrashLogger();
#endif	
	
	if (iEngine)
		iEngine->DebuggingStarted();
	
	iFramingLayer->RespondOkL(KNullDesC8);
}

//
// CTrkDispatchLayer::DoDisconnectL
//
// The host debugger is stopping the current debug session
//
void CTrkDispatchLayer::DoDisconnectL()
{
	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSDisconnect != command)
		User::Leave(kDSReplyError);

	// make sure we're connected
	if (!iIsConnected)
	{
		User::Leave(KErrCouldNotDisconnect);
	}

	//stop listening for events
	SafeDelete(iEventTrapper);

	iIsConnected = EFalse;

	iFramingLayer->RespondOkL(KNullDesC8);

	// let the kernel side driver cleanup
	iKernelDriver.Close();

	//Shutdown the tcb server.
	CloseTcbServer();
	
	// send the callback to the trk server
	if (iEngine)
		iEngine->DebuggingEnded();	
        
}

//
// CTrkDispatchLayer::DoVersionsL
//
// The host debugger is requesting MetroTrk version information
//
void CTrkDispatchLayer::DoVersionsL()
{
	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSVersions != command)
		User::Leave(kDSReplyError);
	
	TUint8 kernelMajorVersion = MAJOR_VERSION_NUMBER;
	TUint8 kernelMinorVersion = MINOR_VERSION_NUMBER;
	TUint8 protocolMajorVersion = DS_PROTOCOL_MAJOR_VERSION;
	TUint8 protocolMinorVersion = DS_PROTOCOL_MINOR_VERSION;

	AddToReplyBufferL(kernelMajorVersion, true);
	AddToReplyBufferL(kernelMinorVersion);
	AddToReplyBufferL(protocolMajorVersion);
	AddToReplyBufferL(protocolMinorVersion);

	RespondOkL();
}

//
// CTrkDispatchLayer::DoVersionsL
//
// The host debugger is requesting MetroTrk version information
//
void CTrkDispatchLayer::DoVersions2L()
{
	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSVersions2 != command)
		User::Leave(kDSReplyError);
	
	TUint8 kernelMajorVersion = MAJOR_VERSION_NUMBER;
	TUint8 kernelMinorVersion = MINOR_VERSION_NUMBER;
	TUint8 protocolMajorVersion = DS_PROTOCOL_MAJOR_VERSION;
	TUint8 protocolMinorVersion = DS_PROTOCOL_MINOR_VERSION;
	TUint8 buildNumber = BUILD_NUMBER;

	AddToReplyBufferL(kernelMajorVersion, true);
	AddToReplyBufferL(kernelMinorVersion);
	AddToReplyBufferL(protocolMajorVersion);
	AddToReplyBufferL(protocolMinorVersion);
	AddToReplyBufferL(buildNumber);

	RespondOkL();
}

//
// CTrkDispatchLayer::DoVersions3L
//
// The host debugger is requesting MetroTrk version information
//
void CTrkDispatchLayer::DoVersions3L()
{
	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSVersions3 != command)
		User::Leave(kDSReplyError);
	
	TUint8 kernelMajorVersion = MAJOR_VERSION_NUMBER;
	TUint8 kernelMinorVersion = MINOR_VERSION_NUMBER;
	TUint8 protocolMajorVersion = DS_PROTOCOL_MAJOR_VERSION;
	TUint8 protocolMinorVersion = DS_PROTOCOL_MINOR_VERSION;
	TUint8 buildNumber = BUILD_NUMBER;

	AddToReplyBufferL(kernelMajorVersion, true);
	AddToReplyBufferL(kernelMinorVersion);
	AddToReplyBufferL(protocolMajorVersion);
	AddToReplyBufferL(protocolMinorVersion);
	AddToReplyBufferL(buildNumber);
	
	TUint16 len = TRK_TYPE_DESCRIPTION.Length();
	
	AddToReplyBufferL(len);
	AddToReplyBufferL(TRK_TYPE_DESCRIPTION);

	RespondOkL();
}

//
// CTrkDispatchLayer::DoHostVersionsL
//
// The host debugger is sending the supported protocol version
//
void CTrkDispatchLayer::DoHostVersionsL()
{
	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSHostVersions != command)
		User::Leave(kDSReplyError);
	
	GetDataFromBufferL(&iHostVersion.iMajor, 1);
	GetDataFromBufferL(&iHostVersion.iMinor, 1);
	
	iFramingLayer->RespondOkL(KNullDesC8);
}

//
// CTrkDispatchLayer::DoSupportMaskL
//
// The host debugger is requesting MetroTrk capabilities
//
void CTrkDispatchLayer::DoSupportMaskL()
{
	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSSupportMask != command)
		User::Leave(kDSReplyError);
	
	TBuf8<32> supportMask;
	TUint8 level = DS_PROTOCOL_RTOS;
	
	supportMask.Zero();
	supportMask.Append(DS_SUPPORT_MASK_00_07);
	supportMask.Append(DS_SUPPORT_MASK_08_0F);
	supportMask.Append(DS_SUPPORT_MASK_10_17);
	supportMask.Append(DS_SUPPORT_MASK_18_1F);
	supportMask.Append(DS_SUPPORT_MASK_20_27);
	supportMask.Append(DS_SUPPORT_MASK_28_2F);
	supportMask.Append(DS_SUPPORT_MASK_30_37);
	supportMask.Append(DS_SUPPORT_MASK_38_3F);
	supportMask.Append(DS_SUPPORT_MASK_40_47);
	supportMask.Append(DS_SUPPORT_MASK_48_4F);
	supportMask.Append(DS_SUPPORT_MASK_50_57);
	supportMask.Append(DS_SUPPORT_MASK_58_5F);
	supportMask.Append(DS_SUPPORT_MASK_60_67);
	supportMask.Append(DS_SUPPORT_MASK_68_6F);
	supportMask.Append(DS_SUPPORT_MASK_70_77);
	supportMask.Append(DS_SUPPORT_MASK_78_7F);
	supportMask.Append(DS_SUPPORT_MASK_80_87);
	supportMask.Append(DS_SUPPORT_MASK_88_8F);
	supportMask.Append(DS_SUPPORT_MASK_90_97);
	supportMask.Append(DS_SUPPORT_MASK_98_9F);
	supportMask.Append(DS_SUPPORT_MASK_A0_A7);
	supportMask.Append(DS_SUPPORT_MASK_A8_AF);
	supportMask.Append(DS_SUPPORT_MASK_B0_B7);
	supportMask.Append(DS_SUPPORT_MASK_B8_BF);
	supportMask.Append(DS_SUPPORT_MASK_C0_C7);
	supportMask.Append(DS_SUPPORT_MASK_C8_CF);
	supportMask.Append(DS_SUPPORT_MASK_D0_D7);
	supportMask.Append(DS_SUPPORT_MASK_D8_DF);
	supportMask.Append(DS_SUPPORT_MASK_E0_E7);
	supportMask.Append(DS_SUPPORT_MASK_E8_EF);
	supportMask.Append(DS_SUPPORT_MASK_F0_F7);
	supportMask.Append(DS_SUPPORT_MASK_F8_FF);
	
	AddToReplyBufferL(supportMask, true);
	AddToReplyBufferL(level);

	RespondOkL();
}

//
// CTrkDispatchLayer::DoCPUTypeL
//
// The host debugger is requesting cpu information
//
void CTrkDispatchLayer::DoCPUTypeL()
{
	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSCPUType != command)
		User::Leave(kDSReplyError);

	TUint8 cpuMajor = DS_CPU_MAJOR_ARM;
	TUint8 cpuMinor = 0;
	TUint8 bigEndian = iFramingLayer->IsBigEndian() ? 1 : 0;
	TUint8 defaultTypeSize = 4;
	TUint8 fpTypeSize = 0;
	TUint8 extended1TypeSize = 0;
	TUint8 extended2TypeSize = 0;

	AddToReplyBufferL(cpuMajor, true);
	AddToReplyBufferL(cpuMinor);
	AddToReplyBufferL(bigEndian);
	AddToReplyBufferL(defaultTypeSize);
	AddToReplyBufferL(fpTypeSize);
	AddToReplyBufferL(extended1TypeSize);
	AddToReplyBufferL(extended2TypeSize);

	RespondOkL();
}

//
// CTrkDispatchLayer::DoReadMemoryL
//
// Read memory from the target device and return to the host
//
void CTrkDispatchLayer::DoReadMemoryL()
{
	// make sure we're connected
	if (!iIsConnected)
	{
		User::Leave(KErrGeneral);
	}

	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSReadMemory != command)
		User::Leave(kDSReplyError);

 	// get the options
	TUint8 options = 0;
	GetDataFromBufferL(&options, 1);

	if ((options & DS_MSG_MEMORY_EXTENDED) != 0)
		User::Leave(kDSReplyUnsupportedOptionError);

	// get the length to read
	TUint16 length = 0;
	GetDataFromBufferL(&length, 2);

	if (length > DS_MAXREADWRITELENGTH)
		User::Leave(kDSReplyParameterError);
	
	// get the start address
	TUint32 address = 0;
	GetDataFromBufferL(&address, 4);

	// get the process id
	TUint32 processId = 0;
	GetDataFromBufferL(&processId, 4);

	// get the thread id
	TUint32 threadId = 0;
	GetDataFromBufferL(&threadId, 4);

	// allocate enough room for the data
	HBufC8 *data = HBufC8::NewLC(length);
	TPtr8 ptr(data->Des());

	TInt err = iKernelDriver.ReadMemory(threadId, address, length, ptr);
	if (KErrNone != err)
	{
		CleanupStack::PopAndDestroy(data);
		User::Leave(err);
	}
	
	AddToReplyBufferL(length, true);
	AddToReplyBufferL(ptr);

	RespondOkL();

	CleanupStack::PopAndDestroy(data);
}

//
// CTrkDispatchLayer::DoWriteMemoryL
//
// Write memory from the host to the target device
//
void CTrkDispatchLayer::DoWriteMemoryL()
{
	// make sure we're connected
	if (!iIsConnected)
	{
		User::Leave(KErrGeneral);
	}

	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSWriteMemory != command)
		User::Leave(kDSReplyError);

 	// get the options
	TUint8 options = 0;
	GetDataFromBufferL(&options, 1);

	if ((options & DS_MSG_MEMORY_EXTENDED) != 0)
		User::Leave(kDSReplyUnsupportedOptionError);

	// get the length to write
	TUint16 length = 0;
	GetDataFromBufferL(&length, 2);

	if (length > DS_MAXREADWRITELENGTH)
		User::Leave(kDSReplyParameterError);
	
	// get the start address
	TUint32 address = 0;
	GetDataFromBufferL(&address, 4);

	// get the process id
	TUint32 processId = 0;
	GetDataFromBufferL(&processId, 4);

	// get the thread id
	TUint32 threadId = 0;
	GetDataFromBufferL(&threadId, 4);

	User::LeaveIfError(iKernelDriver.WriteMemory(threadId, address, length, *iInputBuffer));
	
	AddToReplyBufferL(length, true);

	RespondOkL();
}

//
// CTrkDispatchLayer::DoReadRegistersL
//
// Read registers from the target device and return to the host
//
void CTrkDispatchLayer::DoReadRegistersL()
{
	// make sure we're connected
	if (!iIsConnected)
	{
		User::Leave(KErrGeneral);
	}

	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSReadRegisters != command)
		User::Leave(kDSReplyError);

	// get the options
	TUint8 options = 0;
	GetDataFromBufferL(&options, 1);

	if (DS_MSG_REGISTERS_TYPE(options) != kDSRegistersDefault)
		User::Leave(kDSReplyUnsupportedOptionError);
		
	// get the first register
	TInt16 firstRegister = 0;
	GetDataFromBufferL(&firstRegister, 2);

	// get the last register
	TInt16 lastRegister = 0;
	GetDataFromBufferL(&lastRegister, 2);

	if ((firstRegister < 0) || (lastRegister > 16))
		User::Leave(kDSReplyInvalidRegisterRange);
	
	// get the process id
	TUint32 processId = 0;
	GetDataFromBufferL(&processId, 4);

	// get the thread id
	TUint32 threadId = 0;
	GetDataFromBufferL(&threadId, 4);

	// allocate enough space to hold the values
	HBufC8 *values = HBufC8::NewLC((lastRegister - firstRegister + 1) * 4);
	TPtr8 ptr(values->Des());
	
	TInt err = iKernelDriver.ReadRegisters(threadId, firstRegister, lastRegister, ptr);
	if (KErrNone != err)
	{
		CleanupStack::PopAndDestroy(values);
		User::Leave(err);
	}
	
	for (int i=0; i<=lastRegister - firstRegister; i++)
		AddToReplyBufferL(*(TUint32 *)&ptr.Ptr()[i*4], i==0 ? true : false);
			
	RespondOkL();

	CleanupStack::PopAndDestroy(values);
}

//
// CTrkDispatchLayer::DoWriteRegistersL
//
// Write registers from the host to the target device
//
void CTrkDispatchLayer::DoWriteRegistersL()
{
	// make sure we're connected
	if (!iIsConnected)
	{
		User::Leave(KErrGeneral);
	}

	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSWriteRegisters != command)
		User::Leave(kDSReplyError);

	// get the options
	TUint8 options = 0;
	GetDataFromBufferL(&options, 1);

	if (DS_MSG_REGISTERS_TYPE(options) != kDSRegistersDefault)
		User::Leave(kDSReplyUnsupportedOptionError);

	// get the first register
	TInt16 firstRegister = 0;
	GetDataFromBufferL(&firstRegister, 2);

	// get the last register
	TInt16 lastRegister = 0;
	GetDataFromBufferL(&lastRegister, 2);

	if ((firstRegister < 0) || (lastRegister > 16))
		User::Leave(kDSReplyInvalidRegisterRange);

	// get the process id
	TUint32 processId = 0;
	GetDataFromBufferL(&processId, 4);

	// get the thread id
	TUint32 threadId = 0;
	GetDataFromBufferL(&threadId, 4);
	
	// MetroTrk register values come in as big endian so we may need to swap them
	if (!iFramingLayer->IsBigEndian())
	{
		Swap4xN((TUint32 *)iInputBuffer->Ptr(), lastRegister-firstRegister + 1);
	}
	
	User::LeaveIfError(iKernelDriver.WriteRegisters(threadId, firstRegister, lastRegister, *iInputBuffer));
	
	iFramingLayer->RespondOkL(KNullDesC8);
}

//
// CTrkDispatchLayer::DoContinueL
//
// Resume thread execution
//
void CTrkDispatchLayer::DoContinueL()
{
	// make sure we're connected
	if (!iIsConnected)
	{
		User::Leave(KErrGeneral);
	}

	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSContinue != command)
		User::Leave(kDSReplyError);

	// get the process id
	TUint32 processId = 0;
	GetDataFromBufferL(&processId, 4);

	// get the thread id
	TUint32 threadId = 0;
	GetDataFromBufferL(&threadId, 4);
	
	// see if this thread is in the the suspended threads list
	// if so, remove it and resume.  otherwise we need to handle
	// the special case of the first time a thread is resumed
	TInt index = iSuspendedThreadList.Find(threadId);
	if (index >= 0)
	{
		iSuspendedThreadList.Remove(index);
		User::LeaveIfError(iKernelDriver.ResumeThread(threadId));
		iFramingLayer->RespondOkL(KNullDesC8);
	}
	else
	{
		// if it's not in the suspended list then this is the first time it has been
		// resumed (the process has just been created).  see if there are statically
		// linked libraries that we need to report to the host debugger.  if so, we
		// don't really want to resume yet.  let the host debugger set any breakpoints
		// in the libraries first.  it will call resume again once it's done.

		// since we never mark it as suspended, we'll actually get here when the host
		// debugger calls resume the second time.  we really don't want to mark it as
		// suspended because then the host debugger will try to draw the thread window
		TBool found = EFalse;
		for (TInt i=0; i<iDebugProcessList.Count(); i++)
		{
			if (iDebugProcessList[i]->ProcessId() == processId)
			{
				found = ETrue;
				// if we're already marked it as ready, just resume and return
				if (iDebugProcessList[i]->iReadyForLibraryLoadNotification)
				{
					User::LeaveIfError(iKernelDriver.ResumeThread(threadId));
					iFramingLayer->RespondOkL(KNullDesC8);		
					return;
				}

				iDebugProcessList[i]->iReadyForLibraryLoadNotification = ETrue;
				break;
			}
		}
		// For RUN mode, we created the process but we didn't put it into the list
		// therefore we do not want to notify the host debugger about static libraries
		// so just resume and return  (see DoCreateExeL)
		// The host debugger will soon disconnect in this mode
		if (!found)
		{
			User::LeaveIfError(iKernelDriver.ResumeThread(threadId));
			iFramingLayer->RespondOkL(KNullDesC8);		
			return;
		}

		// the process has been created and the host debugger is listening for messages
		// see if there are any statically linked libraries for this process.  if so, let
		// the host debugger know about them now. note that the host debugger will send
		// another resume command once it's handled the static libraries.  if there are
		// not static libraries for this process, we really do need to resume the thread.
		
		TInt err = KErrNone;
		TInt i = 0;
		for (i=0; KErrNone==err; i++)
		{
			SEventInfo info;
			info.iProcessId = processId;
			info.iThreadId = threadId;
			err = iKernelDriver.GetStaticLibraryInfo(i, info);
			
			if (KErrNone == err)
			{
				DoNotifyLibraryLoadedL(info.iFileName, info.iProcessId, 0xFFFFFFFF, info.iCodeAddress, info.iDataAddress);
			}
			//else if (0 == i)
			//{
				// there are no static libraries for this process
				//User::LeaveIfError(iKernelDriver.ResumeThread(threadId));			
			//}
		}
		//Always resume the thread instead of asking the host debugger to resume when sending the last static library notification.
		User::LeaveIfError(iKernelDriver.ResumeThread(threadId));			
		iFramingLayer->RespondOkL(KNullDesC8);		
	}
}

//
// CTrkDispatchLayer::DoStepL
//
// Execute one instruction in a thread
//
void CTrkDispatchLayer::DoStepL()
{
	// make sure we're connected
	if (!iIsConnected)
	{
		User::Leave(KErrGeneral);
	}

	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSStep != command)
		User::Leave(kDSReplyError);

	// get the options
	TUint8 options = 0;
	GetDataFromBufferL(&options, 1);
	
	// we only support stepping out of a range of instructions
	if ((kDSStepIntoRange != options) && (kDSStepOverRange != options))
	{
		User::Leave(kDSReplyUnsupportedOptionError);
	}

	// get the range start address
	TUint32 startAddress = 0;
	GetDataFromBufferL(&startAddress, 4);

	// get the range stop address
	TUint32 stopAddress = 0;
	GetDataFromBufferL(&stopAddress, 4);
		
	// get the process id
	TUint32 processId = 0;
	GetDataFromBufferL(&processId, 4);

	// get the thread id
	TUint32 threadId = 0;
	GetDataFromBufferL(&threadId, 4);

	User::LeaveIfError(iKernelDriver.StepRange(threadId, startAddress, stopAddress, (kDSStepIntoRange == options)));

	iFramingLayer->RespondOkL(KNullDesC8);
}

//
// CTrkDispatchLayer::DoStopL
//
// Stop the execution of a thread
//
void CTrkDispatchLayer::DoStopL()
{
	// make sure we're connected
	if (!iIsConnected)
	{
		User::Leave(KErrGeneral);
	}

	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSStop != command)
		User::Leave(kDSReplyError);

	// get the options
	TUint8 options = 0;
	GetDataFromBufferL(&options, 1);
	
	TUint32 processId = 0;
	TUint32 threadId = 0;
	
	switch(options)
	{
		case kDSStopThread:
		{
			// get the process id
			GetDataFromBufferL(&processId, 4);

			// get the thread id
			GetDataFromBufferL(&threadId, 4);
			
			User::LeaveIfError(iKernelDriver.SuspendThread(threadId));
			
			break;
		}
		case kDSStopSystem:
		case kDSStopProcess:
		default:
		{
			User::Leave(kDSReplyUnsupportedOptionError);
			break;
		}
	}

	iFramingLayer->RespondOkL(KNullDesC8);
	
	TBuf8<4> currentPC;
	
	User::LeaveIfError(iKernelDriver.ReadRegisters(threadId, 15, 15, currentPC));
	
	DoNotifyStoppedL(processId, threadId, *(TUint32 *)currentPC.Ptr(), KNullDesC8);
}

//
// CTrkDispatchLayer::DoSetBreakL
//
// Set a breakpoint
//
void CTrkDispatchLayer::DoSetBreakL()
{
	// make sure we're connected
	if (!iIsConnected)
	{
		User::Leave(KErrGeneral);
	}

	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSSetBreak != command)
		User::Leave(kDSReplyError);

	// get the options - unused
	TUint8 options = 0;
	GetDataFromBufferL(&options, 1);

	// get the mode
	TUint8 thumbMode = 0;
	GetDataFromBufferL(&thumbMode, 1);

	// get the address
	TUint32 address = 0;
	GetDataFromBufferL(&address, 4);

	// get the length
	TUint32 length = 0;
	GetDataFromBufferL(&length, 4);

	// get the count
	TUint32 count = 0;
	GetDataFromBufferL(&count, 4);

	// get the process id
	TUint32 processId = 0;
	GetDataFromBufferL(&processId, 4);

	// get the thread id
	TUint32 threadId = 0;
	GetDataFromBufferL(&threadId, 4);
	
	TInt32 breakId = 0;
	User::LeaveIfError(iKernelDriver.SetBreak(processId, threadId, address, thumbMode, breakId));

	// return the id of this breakpoint to the host debugger
	AddToReplyBufferL((TUint32)breakId, true);
	
	RespondOkL();
}

//
// CTrkDispatchLayer::DoClearBreakL
//
// Clear a breakpoint
//
void CTrkDispatchLayer::DoClearBreakL()
{
	// make sure we're connected
	if (!iIsConnected)
	{
		User::Leave(KErrGeneral);
	}

	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);

	if (kDSClearBreak != command)
		User::Leave(kDSReplyError);

	// get the breakpoint id
	TUint32 breakId = 0;
	GetDataFromBufferL(&breakId, 4);

	User::LeaveIfError(iKernelDriver.ClearBreak(breakId));

	iFramingLayer->RespondOkL(KNullDesC8);
}

//
// CTrkDispatchLayer::DoModifyBreakThreadL
//
// Change the thread(s) that a breakpoint is associated with
//
void CTrkDispatchLayer::DoModifyBreakThreadL()
{
	// make sure we're connected
	if (!iIsConnected)
	{
		User::Leave(KErrGeneral);
	}

	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);

	if (kDSModifyBreakThread != command)
		User::Leave(kDSReplyError);

	// get the breakpoint id
	TUint32 breakId = 0;
	GetDataFromBufferL(&breakId, 4);

	// get the thread id
	TUint32 threadId = 0;
	GetDataFromBufferL(&threadId, 4);

	User::LeaveIfError(iKernelDriver.ChangeBreakThread(threadId, breakId));

	iFramingLayer->RespondOkL(KNullDesC8);
}

//
// CTrkDispatchLayer::DoCreateItemL
//
// Create a new OS item on the target device
//
void CTrkDispatchLayer::DoCreateItemL()
{
	// make sure we're connected
	if (!iIsConnected)
	{
		User::Leave(KErrGeneral);
	}

	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSOSCreateItem != command)
		User::Leave(kDSReplyError);

	// get the item type
	TUint16 type = 0;
	GetDataFromBufferL(&type, 2);

	switch(type)
	{
		case kDSOSProcessItem:
		{
			DoCreateProcessL();
			break;
		}
		case kDSOSProcRunItem:
		{
			DoCreateProcessL(ETrue);
			break;
		}
		case kDSOSProcAttachItem:
		{
			DoAttachProcessL(kDSOSProcAttachItem);
			break;
		}
		case kDSOSProcAttach2Item:
		{
			DoAttachProcessL(kDSOSProcAttach2Item);
			break;
		}
		case kDSOSProcAttach3Item:
		{
			DoAttachProcessL(kDSOSProcAttach3Item);
			break;
		}
		case kDSOSThreadItem:
		case kDSOSDLLItem:
		case kDSOSAppItem:
		case kDSOSMemBlockItem:
		case kDSOSThreadAttachItem:
		default:
		{
			User::Leave(kDSReplyUnsupportedOptionError);
			break;
		}
	}
}

//
// CTrkDispatchLayer::DoDeleteItemL
//
// Delete an OS item from the target device
//
void CTrkDispatchLayer::DoDeleteItemL()
{
	// make sure we're connected
	if (!iIsConnected)
	{
		User::Leave(KErrGeneral);
	}

	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSOSDeleteItem != command)
		User::Leave(kDSReplyError);

	// get the item type
	TUint16 type = 0;
	GetDataFromBufferL(&type, 2);

	switch(type)
	{
		case kDSOSProcessItem:
		{
			DoKillProcessL();
			break;
		}
		case kDSOSProcAttachItem:
		{
		    DoDetachProcessL();
			break;
		}
		case kDSOSThreadItem:
		case kDSOSDLLItem:
		case kDSOSAppItem:
		case kDSOSMemBlockItem:
		case kDSOSThreadAttachItem:
		default:
		{
			User::Leave(kDSReplyUnsupportedOptionError);
			break;
		}
	}
}

//
// CTrkDispatchLayer::DoReadInfoL
//
// Read OS information from the target device
//
void CTrkDispatchLayer::DoReadInfoL()
{	
	// make sure we're connected
	if (!iIsConnected)
	{
		User::Leave(KErrGeneral);
	}

	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);

	if (kDSOSReadInfo != command)
		User::Leave(kDSReplyError);

	// get the type of info requested
	TUint16 type = 0;
	GetDataFromBufferL(&type, 2);

	// get the start index
	TUint32 index = 0;
	GetDataFromBufferL(&index, 4);	
	
	switch(type)
	{
		case kDSOSProcessList:
		{
			DoReadProcessListL(index);
			break;
		}
		case kDSOSThreadList:
		{
			DoReadThreadListL(index);
			break;
		}
		case kDSOSDLLInfo:
		{
			TUint16 nameLength = 0;
			GetDataFromBufferL(&nameLength, 2);
			
			// make sure the length of the message is correct
			if (iInputBuffer->Length() != nameLength)
				User::Leave(kDSReplyPacketSizeError);
			
			TBuf8<KMaxFileName> fileName;
			fileName.Copy(*iInputBuffer);
			fileName.ZeroTerminate();

			DoReadLibraryInfoL(fileName);
			break;
		}
		case kDSOSProcessInfo:
		{
			TUint32 uid3 = 0;
			GetDataFromBufferL(&uid3, 4);
			TUint16 nameLength = 0;
			GetDataFromBufferL(&nameLength, 2);
			
			// make sure the length of the message is correct
			if (iInputBuffer->Length() != nameLength)
				User::Leave(kDSReplyPacketSizeError);
			
			TBuf8<KMaxFileName> fileName;
			fileName.Copy(*iInputBuffer);
			fileName.ZeroTerminate();
			
			DoReadProcessInfoL(uid3, fileName);
			break;
		}
		case kDSOSProcessState:
		case kDSOSThreadState:
		case kDSOSDLLList:
		case kDSOSDLLState:
		default:
		{
			User::Leave(kDSReplyUnsupportedOptionError);
			break;
		}
	}
}

//
// CTrkDispatchLayer::DoWriteInfoL
//
// Set options for the Trk
//
void CTrkDispatchLayer::DoWriteInfoL()
{
	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);

	if (kDSOSWriteInfo != command)
		User::Leave(kDSReplyError);

	// get the type of info requested
	TUint16 type = 0;
	GetDataFromBufferL(&type, 2);

	// get the start index
	TUint32 index = 0;
	GetDataFromBufferL(&index, 4);

	// no options supported yet.  might add something for auto-target libraries later
	User::Leave(kDSReplyUnsupportedOptionError);
}

//
// CTrkDispatchLayer::DoOpenFileL
//
// Open or create a file on the target
//
void CTrkDispatchLayer::DoOpenFileL()
{
	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSOSOpenFile != command)
		User::Leave(kDSReplyError);

	// get the file mode(s)
	TUint8 modes = 0;
	GetDataFromBufferL(&modes, 1);

	if ((modes & kDSFileOpenAppend) || (modes & kDSFileOpenCreate))
		modes |= kDSFileOpenWrite;

	TUint16 nameLength = 0;
	GetDataFromBufferL(&nameLength, 2);
	
	// make sure the length of the message is correct
	if (iInputBuffer->Length() != nameLength)
		User::Leave(kDSReplyPacketSizeError);
	
	TBuf<KMaxPath> fullpath;
	fullpath.Copy(*iInputBuffer);
	fullpath.ZeroTerminate();
		
	TUint mode = EFileShareExclusive;

	// get the file mode(s)
	if (modes & kDSFileOpenRead)
		mode |= EFileRead;

	if (modes & kDSFileOpenWrite)
		mode |= EFileWrite;

	if (modes & kDSFileOpenAppend)
		mode |= EFileWrite;

	if (modes & kDSFileOpenCreate)
		mode |= EFileWrite;
	

	//for getting the modification date
	TTime time;
	
	OpenFileL(fullpath, mode, time);
	
	TDateTime dateTime = time.DateTime();

	TDateTimeConverter winTime(dateTime);
	
	TUint32 timestamp = winTime.GetWinTimeDate();

	TUint32 handle = 1;
	TUint8 err = 0;

	AddToReplyBufferL(err, true);
	AddToReplyBufferL(handle);
	AddToReplyBufferL(timestamp);
	
	RespondOkL();
}

//
// CTrkDispatchLayer::OpenFileL
//
// Open a file on the target, if plat security is enabled, uses TrkTcbServer to open the file.
//
void CTrkDispatchLayer::OpenFileL(const TDesC& aFullPath, TUint aMode, TTime& aTime)
{

#ifdef __OEM_TRK__	
	//Check to see if TCB capability is enforced, if so, connect to the tcb server as well.
	if (!iUseTcbServer && PlatSec::IsCapabilityEnforced(ECapabilityTCB))
	{
		if (!iTrkTcbSession.Connect())
		{
			iUseTcbServer = ETrue;
		}	
	}

	if (iUseTcbServer)
	{
		User::LeaveIfError(iTrkTcbSession.OpenFile(aFullPath, aMode, aTime));
	}
	else
#endif	
	{
	#ifndef __OEM_TRK__
		if (IsRestrictedFolder(aFullPath))
			User::Leave(KErrAccessDenied);
	#endif
		// connect to the file server
		User::LeaveIfError(iFs.Connect());

		TInt error = iFs.MkDirAll(aFullPath);

		if ((KErrNone != error) && (KErrAlreadyExists != error))
		{
			iFs.Close();
			User::Leave(error);
		}
		
		error = iFile.Open(iFs, aFullPath, aMode);
		
		if (KErrNone != error)
			User::LeaveIfError(iFile.Replace(iFs, aFullPath, aMode));
		
		User::LeaveIfError(iFile.Modified(aTime));
		iFileState = EFileOpened;
	}
}

//
// CTrkDispatchLayer::DoReadFileL
//
// Read data from a file on the target
//
void CTrkDispatchLayer::DoReadFileL()
{
	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSOSReadFile != command)
		User::Leave(kDSReplyError);

	// make sure the length of the message is correct
	if (iInputBuffer->Length() != 6)
		User::Leave(kDSReplyPacketSizeError);
	
	// remove the handle
	iInputBuffer->Des().Delete(0, 4);

	// get the length
	TUint8 err = 0;
	TUint16 length = 0;
	GetDataFromBufferL(&length, 2);
	
	// allocate a buffer large enough for the data
	HBufC8 *buffer = HBufC8::NewLC(length);
	TPtr8 ptr(buffer->Des());
	
	//	CleanupStack::PushL(buffer);
	
	TInt error = ReadFileL(length, ptr);	
	if (KErrNone != error)
	{
		CleanupStack::PopAndDestroy(buffer);	
		User::Leave(error);
	}
	
	length = buffer->Length();
	
	AddToReplyBufferL(err, true);
	AddToReplyBufferL(length);
//	AddToReplyBufferL(buffer[0], length);
	AddToReplyBufferL(ptr);
	RespondOkL();
	
	CleanupStack::PopAndDestroy(buffer);
}

//
// CTrkDispatchLayer::ReadFileL
//
// Reads data from a file on the target
//
TInt CTrkDispatchLayer::ReadFileL(TUint16 aLength, TPtr8& aData)
{
	TInt error = KErrNone;

#ifdef __OEM_TRK__
	if (iUseTcbServer)
	{
		User::LeaveIfError(iTrkTcbSession.ReadFile(aLength, aData));
	}
	else
#endif	
	{
		iFileState = EFileReading;
		error = iFile.Read(aData);
	}
	return error;
}

//
// CTrkDispatchLayer::DoWriteFileL
//
// Write data to a file on the target
//
void CTrkDispatchLayer::DoWriteFileL()
{
	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSOSWriteFile != command)
		User::Leave(kDSReplyError);
	
	// get the length
	TUint32 handle = 0;
	GetDataFromBufferL(&handle, 4);
	
	if (handle != 1)
		User::Leave(kDSReplyParameterError);

	// get the length
	TUint8 err = 0;
	TUint16 length = 0;
	GetDataFromBufferL(&length, 2);

	// make sure the length of the message is correct
	if (iInputBuffer->Length() != length)
		User::Leave(kDSReplyPacketSizeError);
		
	WriteFileL(*iInputBuffer);
	
	length = iInputBuffer->Length();
	
	AddToReplyBufferL(err, true);
	AddToReplyBufferL(length);
	RespondOkL();
}

//
// CTrkDispatchLayer::WriteFileL
//
// Write data to a file on the target. If plat sec is enabled, uses Trk Tcb Server.
//
void CTrkDispatchLayer::WriteFileL(TDesC8& aData)
{
#ifdef __OEM_TRK__
	if (iUseTcbServer)
	{
		User::LeaveIfError(iTrkTcbSession.WriteFile(aData));
	}
	else
#endif	
	{	
		if (iFileState == EFileOpened)
		{
			iFile.SetSize(0);
			iFileState = EFileWriting;
		}
		User::LeaveIfError(iFile.Write(aData));
		User::LeaveIfError(iFile.Flush());
	}
}

//
// CTrkDispatchLayer::DoPositionFileL
//
// Change the current file position of a file on the target
//
void CTrkDispatchLayer::DoPositionFileL()
{
	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSOSPositionFile != command)
		User::Leave(kDSReplyError);

	// make sure the length of the message is correct
	if (iInputBuffer->Length() != 9)
		User::Leave(kDSReplyPacketSizeError);
	
	// get the positioning mode
	TUint8 mode = 0;
	GetDataFromBufferL(&mode, 1);

	// remove the handle
	iInputBuffer->Des().Delete(0, 4);

	TUint8 err = 0;
	TUint32 offset = 0;
	GetDataFromBufferL(&offset, 4);

	TSeek seek;
	
	// convert mode to native parameter and set the position accordingly
	switch(mode)
	{
		default:
		case kDSFileSeekSet:
		{
			seek = ESeekStart;
			break;
		}
		case kDSFileSeekCur:
		{
			seek = ESeekCurrent;
			break;
		}
		case kDSFileSeekEnd:
		{
			seek = ESeekEnd;
			break;
		}
	}

	PositionFileL(seek, (TInt &)offset);

	AddToReplyBufferL(err, true);
	
	RespondOkL();
}

//
// CTrkDispatchLayer::PositionFileL
//
// Change the current file position of a file on the target. If plat sec is enabled,
// uses Trk Tcb Server.
//
void CTrkDispatchLayer::PositionFileL(TSeek aSeek, TInt& aOffset)
{
#ifdef __OEM_TRK__
	if (iUseTcbServer)
	{
		User::LeaveIfError(iTrkTcbSession.PositionFile(aSeek, aOffset));
	}
	else
#endif	
	{
		User::LeaveIfError(iFile.Seek(aSeek, aOffset));
	}
}


//
// CTrkDispatchLayer::DoCloseFileL
//
// Close a file on the target
//
void CTrkDispatchLayer::DoCloseFileL()
{
	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSOSCloseFile != command)
		User::Leave(kDSReplyError);

	// make sure the length of the message is correct
	if (iInputBuffer->Length() != 8)
		User::Leave(kDSReplyPacketSizeError);

	// remove the handle
	iInputBuffer->Des().Delete(0, 4);
	
	TUint8 err = 0;
	TUint32 timestamp = 0;
	GetDataFromBufferL(&timestamp, 4);
	
	TDateTimeConverter epocTime(timestamp);
	
	CloseFileL(epocTime.GetEpocTimeDate());

	AddToReplyBufferL(err, true);

	RespondOkL();
}

//
// CTrkDispatchLayer::CloseFileL
//
// Close a file on the target. If plat sec is enabled, uses Trk Tcb Server.
//
void CTrkDispatchLayer::CloseFileL(const TTime& aModifiedTime)
{
#ifdef __OEM_TRK__
	if (iUseTcbServer)
	{
		User::LeaveIfError(iTrkTcbSession.CloseFile(aModifiedTime));
	}
	else
#endif	
	{
		User::LeaveIfError(iFile.SetModified(aModifiedTime));
		User::LeaveIfError(iFile.Flush());
		
		iFile.Close();
		iFs.Close();
		iFileState = EFileClosed;
	}
}

//
// CTrkDispatchLayer::DoInstallFileL
//
// Install the application, supplied as a SIS file.
//
void CTrkDispatchLayer::DoInstallFileL()
{
	// make sure we're connected
	if (!iIsConnected)
	{
		User::Leave(KErrGeneral);
	}

#ifndef __TEXT_SHELL__
	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSOSInstallFile != command)
		User::Leave(kDSReplyError);

	// get the installation drive
	TUint8 drive = 'C';
	GetDataFromBufferL(&drive, 1);
	
	TChar installDrive(drive);

	TUint16 nameLength = 0;
	GetDataFromBufferL(&nameLength, 2);
	
	// make sure the length of the message is correct
	if (iInputBuffer->Length() != nameLength)
		User::Leave(kDSReplyPacketSizeError);
	
	TBuf<KMaxPath> fullpath;
	fullpath.Copy(*iInputBuffer);
	fullpath.ZeroTerminate();
			
	TUint8 err = 0;
	// Temporarily disable the lib loaded event before launching the SW Installer.
	// This is necessary when launching the SIS installer since  launching the 
	// installer causes several libraries to be loaded. The driver suspends the 
	// thread thats loaded the library. This suspension might potentially cause 
	// a deadlock as the event handling active object will never get a chance to 
	// run as the Install function below blocks until the installation is completed.
	User::LeaveIfError(iKernelDriver.DisableLibLoadedEvent());
	
	// now launch the installer
	User::LeaveIfError(CTrkSwInstall::SilentInstallL(fullpath, installDrive));

	// now enable the lib loaded event
	iKernelDriver.EnableLibLoadedEvent();
	
	AddToReplyBufferL(err, true);
	RespondOkL();
#else 
	User::LeaveIfError(-1); 
#endif
}

//
// CTrkDispatchLayer::DoInstallFileL
//
// Install the application, supplied as a SIS file.
//
void CTrkDispatchLayer::DoInstallFile2L()
{
	// make sure we're connected
	if (!iIsConnected)
	{
		User::Leave(KErrGeneral);
	}

#ifndef __TEXT_SHELL__
	// make sure we got here from DispatchMsgL
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);
	
	if (kDSOSInstallFile2 != command)
		User::Leave(kDSReplyError);

	TUint16 nameLength = 0;
	GetDataFromBufferL(&nameLength, 2);
	
	// make sure the length of the message is correct
	if (iInputBuffer->Length() != nameLength)
		User::Leave(kDSReplyPacketSizeError);
	
	TBuf<KMaxPath> fullpath;
	fullpath.Copy(*iInputBuffer);
	fullpath.ZeroTerminate();
			
	TUint8 err = 0;
	// Temporarily disable the lib loaded event before launching the SW Installer.
	// This is necessary when launching the SIS installer since  launching the 
	// installer causes several libraries to be loaded. The driver suspends the 
	// thread thats loaded the library. This suspension might potentially cause 
	// a deadlock as the event handling active object will never get a chance to 
	// run as the Install function below blocks until the installation is completed.
	User::LeaveIfError(iKernelDriver.DisableLibLoadedEvent());

	// now launch the installer
	User::LeaveIfError(CTrkSwInstall::Install(fullpath));

	// now enable the lib loaded event
	iKernelDriver.EnableLibLoadedEvent();
	
	AddToReplyBufferL(err);
	RespondOkL();
#else
	User::LeaveIfError(-1);
#endif
}


//
// CTrkDispathLayer::DoGetPhoneSWVesionL()
//
// sends  the software version of the phone to reply buffer
//
void CTrkDispatchLayer::DoGetPhoneSWVersionL()
{
    // make sure we got here from DispatchMsgL
    
	TUint8 command = 0;
	GetDataFromBufferL(&command, 1);

	if (kDSOSPhoneSWVersion != command)
	{
		User::Leave(kDSReplyError);
	}
#ifndef __TEXT_SHELL__
	if (iPhoneVersion.Size()>0 )
	{
		TUint16 versionNameLength = iPhoneVersion.Length();
		AddToReplyBufferL(versionNameLength, ETrue); 
		AddToReplyBufferL(iPhoneVersion);       
		RespondOkL();
	}
	else
#endif	    
	{
		User::Leave(KErrGeneral);
	}    
                
}


//
//CTrkDispathLayer::DoGetPhoneNameL()
//
//sends the phone model name to the reply buffer
//
void CTrkDispatchLayer::DoGetPhoneNameL()
{    
    TUint8 command = 0;
    GetDataFromBufferL(&command, 1);
    
    if (kDSOSPhoneName != command)
    {
    	User::Leave(kDSReplyError);
	}

#ifndef __TEXT_SHELL__
    if (iPhoneNameInfoAvailable)
    {
     	TUint16 phoneModelLen = iPhoneModel.Length();
     	AddToReplyBufferL(phoneModelLen, true);
     	AddToReplyBufferL(iPhoneModel);
        RespondOkL();
    }    
    else
#endif
    {
        User::Leave(KErrGeneral);
    }
}
//
//To Update the phone model name 
//
//callback function from the CPhoneInfo
//
void CTrkDispatchLayer::UpdatePhoneNameInfo(TDesC16& aPhoneModel)
{
#ifndef __TEXT_SHELL__
    iPhoneModel.Copy(aPhoneModel);
    iPhoneNameInfoAvailable = ETrue;    
#endif
}

//
// CTrkDispatchLayer::DoCreateProcessL
//
// Create a new process on the target device
//
void CTrkDispatchLayer::DoCreateProcessL(TBool aRun)
{
	// remove the options - currently unused
	iInputBuffer->Des().Delete(0, 1);

	// get the length of the data
	TUint16 length = 0;
	GetDataFromBufferL(&length, 2);

	// make sure the length of the message is correct
	if (iInputBuffer->Length() != length)
		User::Leave(kDSReplyPacketSizeError);

	// extract the filename and path, command line args, and working directory
	TPtrC8 exec8(iInputBuffer->Ptr());
	TPtrC8 args8(exec8.Ptr() + exec8.Length() + 1);
		
	// convert the filename and args to unicode descriptors
	HBufC* exec = HBufC::NewLC(exec8.Length());
	exec->Des().Copy(exec8);

	HBufC* args = HBufC::NewLC(args8.Length());
	args->Des().Copy(args8);

	// open the file and get the type (app, exe, etc.)
	RFs fs;
	
	// connect to the file server
	User::LeaveIfError(fs.Connect());
	
	TEntry entry;
		
	User::LeaveIfError(fs.Entry(*exec, entry));
	
	fs.Close();

	TCreateProcessData data;
		
	switch(entry[0].iUid)
	{
		case 0x1000007a:
		{
			// EXE
			DoCreateExeL(*exec, *args, data, aRun);
			break;
		}
		default:
			User::Leave(KErrGeneral);
	}

	CleanupStack::PopAndDestroy(args);
	CleanupStack::PopAndDestroy(exec);

	AddToReplyBufferL(data.iProcessId, true);
	AddToReplyBufferL(data.iMainThreadId);
	if (!aRun)
	{
		AddToReplyBufferL(data.iCodeAddr);
		AddToReplyBufferL(data.iDataAddr);
	}
		
	RespondOkL();
}

//
// CTrkDispatchLayer::DoCreateExeL
//
// Create a new executable on the target device
//
void CTrkDispatchLayer::DoCreateExeL(const TDesC& aPath, const TDesC& aArgs, TCreateProcessData& aData, TBool aRun)
{
	RProcess process;
	User::LeaveIfError(process.Create(aPath, aArgs));
	CleanupClosePushL(process);

	aData.iProcessId = process.Id();
	
	HBufC* threadName = HBufC::NewLC(KMaxFullName);

	*threadName = process.Name();
	_LIT(KMainThreadSuffix, "::Main");
	threadName->Des().Append(KMainThreadSuffix);

	// this function should be (indirectly) called when the debuggee
	// has been created but not yet resumed.  So it should have a main
	// thread whose name ends with "::Main", and so the following call
	// should not fail.
	RThread thread;
	User::LeaveIfError(thread.Open(*threadName));
		
	aData.iMainThreadId = thread.Id();
	thread.Close();

	if (!aRun)
	{
		CDebugProcess *proc = CDebugProcess::NewL(this, aData.iProcessId, aData.iMainThreadId);
		iDebugProcessList.Append(proc);

		User::LeaveIfError(iKernelDriver.GetProcessAddresses(aData.iMainThreadId, aData.iCodeAddr, aData.iDataAddr));
	}
		
	CleanupStack::PopAndDestroy(threadName);
	CleanupStack::PopAndDestroy(); // process
}

//
// CTrkDispatchLayer::DoKillProcessL
//
// Kill an existing process
//
void CTrkDispatchLayer::DoKillProcessL()
{
	// get the process id
	TUint32 processId = 0;
	GetDataFromBufferL(&processId, 4);
	
	RProcess process;
	User::LeaveIfError(process.Open(processId));
#ifdef EKA2
	process.Kill(KErrNone);
#else	
	process.Kill(KProcessKilled);
#endif
	process.Close();

	iFramingLayer->RespondOkL(KNullDesC8);	
}

//
// CTrkDispatchLayer::DoAttachProcessL
//
// Create a new process on the target device
//
void CTrkDispatchLayer::DoAttachProcessL(DSOSItemTypes aAttachType)
{
	// remove the options - currently unused
	iInputBuffer->Des().Delete(0, 1);

	// get the length of the data
	TUint32 processId = 0;
	GetDataFromBufferL(&processId, 4);

	RProcess process;
	User::LeaveIfError(process.Open(processId));
	CleanupClosePushL(process);
	
	// do not allow attaching to a system, protected, or the MetroTrk process because
	// if the user were to stop the wrong thread, the whole system could stop
#ifdef EKA2
	if ((TUint)processId == RProcess().Id())
#else
	if (process.System() || process.Protected() || ((TUint)processId == RProcess().Id()))
#endif
	{
		User::Leave(kDSReplyUnsupportedOptionError);
	}

	TMetroTrkTaskInfo threadInfo(processId);
	User::LeaveIfError(iKernelDriver.GetThreadInfo(0, threadInfo));

	
	TUint32 codeAddr;
	TUint32 dataAddr;
	User::LeaveIfError(iKernelDriver.GetProcessAddresses(threadInfo.iId, codeAddr, dataAddr));	
	//this is necessary to get the process died notifications and also any other event for this process
	CDebugProcess *proc = CDebugProcess::NewL(this, processId, threadInfo.iId);
	// For processes that we are attaching, we need to set this flag to true.
	// otherwise library load notifications for this process will be ignored
	proc->iReadyForLibraryLoadNotification = ETrue;
	iDebugProcessList.Append(proc);	
			
	AddToReplyBufferL(threadInfo.iId, true);
	if (aAttachType == kDSOSProcAttach3Item)
	{
		// now get the UID3 for this process
		// and add it to the reply
		TMetroTrkProcUidInfo procUidInfo(processId);
		User::LeaveIfError(iKernelDriver.GetProcUidInfo(procUidInfo));
		AddToReplyBufferL(procUidInfo.iUid3);
	}
	if (aAttachType == kDSOSProcAttach3Item || aAttachType == kDSOSProcAttach2Item)
	{				
		AddToReplyBufferL(codeAddr);
		AddToReplyBufferL(dataAddr);
		
		TBuf8<KMaxFullName> procName;
		procName.Copy(process.Name());
		TUint16 nameLength = procName.Length();

		AddToReplyBufferL(nameLength);
		AddToReplyBufferL(procName);		
	}

	CleanupStack::PopAndDestroy(); // process
	RespondOkL();
}

//
// CTrkDispatchLayer::DoDetachProcessL
//
// To detach the process from the list of processes
//
void CTrkDispatchLayer::DoDetachProcessL()
{
    TUint32 processId = 0;
    GetDataFromBufferL(&processId, 4);
    
    RProcess process;
    User::LeaveIfError(process.Open(processId));
    
	for (TInt i=0 ; i<iDebugProcessList.Count(); i++)
	{
		if(iDebugProcessList[i]->ProcessId()== processId) 
		{
			SafeDelete(iDebugProcessList[i]);
			iDebugProcessList.Remove(i);
		}
	}
    User::LeaveIfError(iKernelDriver.DetachProcess(processId));    

    iFramingLayer->RespondOkL(KNullDesC8);
}


//
// CTrkDispatchLayer::DoReadProcessListL
//
// Return a list of the current processes to the host debugger
//
void CTrkDispatchLayer::DoReadProcessListL(TInt32 aIndex)
{
	// remove the options - unused
	iInputBuffer->Des().Delete(0, 1);

	// remove the filter - unused
	iInputBuffer->Des().Delete(0, 4);

	// an index of zero means we start fresh.  and index other than zero means
	// we were not able to return all of the processes in the last round due to
	// message size limitations, so we need to pick up where we left off
	if (aIndex == 0)
	{
		DoReBuildProcessList();
	}
	
	TInt32 totalCount = iProcessList.Count();
	TInt32 returnedCount = 0;
	TInt32 bytesRemaining = MAXMESSAGESIZE_V2 - 30; // minus the framing bytes
	TInt32 restOfMsgSize = sizeof(TUint32) // process id
						 + sizeof(TUint32) // priority
						 + sizeof(TUint8); // NULL character
	
	for (TInt32 i=aIndex; i<totalCount; i++)
	{
		// make sure there is enough room left in the message
		if (bytesRemaining >= (iProcessList[i].iName.Length() + restOfMsgSize))
		{
			returnedCount++;
			bytesRemaining -= (iProcessList[i].iName.Length() + restOfMsgSize);
		}
		else
			break;
	}

	// add values for returnedCount and totalCount
	AddToReplyBufferL((TUint32)returnedCount, true);
	AddToReplyBufferL((TUint32)totalCount);

	for (TInt32 i=aIndex; i<(aIndex + returnedCount); i++)
	{
		// add this process info to the buffer
		AddToReplyBufferL(iProcessList[i].iId);
		AddToReplyBufferL(iProcessList[i].iPriority);
		AddToReplyBufferL(iProcessList[i].iName);
		
		// host expects the name to be a null terminated string
		AddToReplyBufferL((TUint8)0);
	}
	
	RespondOkL();
}

//
// CTrkDispatchLayer::DoReadThreadListL
//
// Return a list of the current threads for a process to the host debugger
//
void CTrkDispatchLayer::DoReadThreadListL(TInt32 aIndex)
{
	// remove the options - unused
	iInputBuffer->Des().Delete(0, 1);

	// get the process id
	TUint32 processId = 0;
	GetDataFromBufferL(&processId, 4);

	// an index of zero means we start fresh.  and index other than zero means
	// we were not able to return all of the threads in the last round due to
	// message size limitations, so we need to pick up where we left off
	if (aIndex == 0)
	{
		DoReBuildThreadList(processId);
	}
	
	TInt32 totalCount = iThreadList.Count();
	TInt32 returnedCount = 0;
	TInt32 bytesRemaining = MAXMESSAGESIZE_V2 - 30; // minus the framing bytes
	TInt32 restOfMsgSize = sizeof(TUint32) // process id
						 + sizeof(TUint32) // priority
						 + sizeof(TUint8)  // state
						 + sizeof(TUint8); // NULL character
	
	
	for (TInt32 i=aIndex; i<totalCount; i++)
	{
		// make sure there is enough room left in the message
		if (bytesRemaining >= (iThreadList[i].iName.Length() + restOfMsgSize))
		{
			returnedCount++;
			bytesRemaining -= (iThreadList[i].iName.Length() + restOfMsgSize);
		}
		else
			break;
	}

	// add values for returnedCount and totalCount
	AddToReplyBufferL((TUint32)returnedCount, true);
	AddToReplyBufferL((TUint32)totalCount);

	for (TInt32 i=aIndex; i<(aIndex + returnedCount); i++)
	{
		// add this thread info to the buffer
		AddToReplyBufferL(iThreadList[i].iId);
		AddToReplyBufferL(iThreadList[i].iPriority);
		AddToReplyBufferL(IsThreadSuspended(iThreadList[i].iId));		
		AddToReplyBufferL(iThreadList[i].iName);

		// host expects the name to be a null terminated string
		AddToReplyBufferL((TUint8)0);
	}

	RespondOkL();
}

//
// CTrkDispatchLayer::DoReBuildProcessList
//
// Build a list of the current processes
//
void CTrkDispatchLayer::DoReBuildProcessList()
{
	TInt err = KErrNone;

	// reset the process list
	iProcessList.Reset();
	
	// fill up the process list
	for (TInt i=0; KErrNone==err; i++)
	{
		TMetroTrkTaskInfo processInfo(0);
		err = iKernelDriver.GetProcessInfo(i, processInfo);
		
		//Get a Handle to the process
		RProcess proc;
		if(KErrNone == err && KErrNone == proc.Open(TProcessId(processInfo.iId)))
		{			
			//Only display currently running processes
			if(EExitPending == proc.ExitType())
			{
				iProcessList.Append(processInfo);
			}
			proc.Close();
		}
	}
}

//
// CTrkDispatchLayer::DoReBuildThreadList
//
// Build a list of the current threads for a process
//
void CTrkDispatchLayer::DoReBuildThreadList(TUint32 aProcessId)
{
	TInt err = KErrNone;

	// reset the thread list
	iThreadList.Reset();
	
	// fill up the thread list
	for (TInt i=0; KErrNone==err; i++)
	{
		TMetroTrkTaskInfo threadInfo(aProcessId);
		err = iKernelDriver.GetThreadInfo(i, threadInfo);
		
		//Get a Handle to the thread
		RThread thread;
		if(KErrNone == err && KErrNone == thread.Open(TThreadId(threadInfo.iId)))
		{			
			//Only display currently running processes
			if(EExitPending == thread.ExitType())
			{
				iThreadList.Append(threadInfo);
			}
			thread.Close();
		}
	}
}

// CTrkDispatchLayer::DoNotifyStoppedL
//
// Notify the host debugger that a thread has stopped
//
// START_PANIC
//void CTrkDispatchLayer::DoNotifyStoppedL(TUint32 aProcessId, TUint32 aThreadId, TUint32 aCurrentPC, const TDesC8 &aDescription)
void CTrkDispatchLayer::DoNotifyStoppedL(TUint32 aProcessId, TUint32 aThreadId, TUint32 aCurrentPC, const TDesC8 &aDescription, TBool aAddException, const TUint16 aExceptionNumber)
// END_PANIC
{	
	// add this thread to the suspended threads list
	iSuspendedThreadList.Append(aThreadId);

//	TUint8 event = (aAddException==true) ? kDSNotifyStopped2 : kDSNotifyStopped;
	TUint8 event = kDSNotifyStopped;
	TUint16 descLength = aDescription.Length();
	
	AddToReplyBufferL(event, true);
	AddToReplyBufferL(aCurrentPC);
	AddToReplyBufferL(aProcessId);
	AddToReplyBufferL(aThreadId);
	AddToReplyBufferL(descLength);

	if (descLength)
	{
		AddToReplyBufferL(aDescription);

		// host expects the string to be a null terminated string
		AddToReplyBufferL((TUint8)0);
	}
	// START_PANIC
	if (aAddException)
		AddToReplyBufferL(aExceptionNumber);
	// END_PANIC
	
	InformEventL();
}

//
// CTrkDispatchLayer::DoNotifyProcessDiedL
//
// Notify the host debugger that a process has exited
//
void CTrkDispatchLayer::DoNotifyProcessDiedL(TUint32 aProcessId, TInt aExitCode)
{
	// remove this process from our list
	for (TInt i=0; i<iDebugProcessList.Count(); i++)
	{
		if (iDebugProcessList[i]->ProcessId() == aProcessId)
		{
			SafeDelete(iDebugProcessList[i]);
			iDebugProcessList.Remove(i);
		}
	}

	TUint8 event = kDSOSNotifyDeleted;
	TUint16 type = kDSOSProcessItem;

	AddToReplyBufferL(event, true);
	AddToReplyBufferL(type);
	AddToReplyBufferL((TUint32)aExitCode);
	AddToReplyBufferL(aProcessId);

	InformEventL();
}

//
// CTrkDispatchLayer::DoNotifyLibraryLoadedL
//
// Notify the host debugger that a library in now loaded
//
void CTrkDispatchLayer::DoNotifyLibraryLoadedL(TDesC8 &aName, TUint32 aProcessId, TUint32 aThreadId, TUint32 aCodeBaseAddress, TUint32 aDataBaseAddress)
{
	TUint8 event = kDSOSNotifyCreated;
	TUint16 type = kDSOSDLLItem;

	TUint16 nameLength = aName.Length();
	
	AddToReplyBufferL(event, true);
	AddToReplyBufferL(type);
	AddToReplyBufferL(aProcessId);
	AddToReplyBufferL(aThreadId);
	AddToReplyBufferL(aCodeBaseAddress);
	AddToReplyBufferL(aDataBaseAddress);
	AddToReplyBufferL(nameLength);
	AddToReplyBufferL(aName);

	InformEventL();
}

//
// CTrkDispatchLayer::DoNotifyLibraryUnloadedL
//
// Notify the host debugger that a library has been unloaded
//
void CTrkDispatchLayer::DoNotifyLibraryUnloadedL(TDesC8 &aName, TUint32 aProcessId, TUint32 aThreadId)
{
	TUint8 event = kDSOSNotifyDeleted;
	TUint16 type = kDSOSDLLItem;
	
	TUint16 nameLength = aName.Length();
	
	AddToReplyBufferL(event, true);
	AddToReplyBufferL(type);
	AddToReplyBufferL(aProcessId);
	AddToReplyBufferL(aThreadId);
	AddToReplyBufferL(nameLength);
	AddToReplyBufferL(aName);

	InformEventL();
}

//
// CTrkDispatchLayer::GetDataFromBufferL
//
// Notify the host debugger that trace data has been recieved
//
void CTrkDispatchLayer::DoNotifyUserTraceL(TDesC8 &aTrace)
{
	if (iIsConnected)
		iFramingLayer->SendRawMsgL(aTrace);
}

void CTrkDispatchLayer::DoNotifyProcessAddedL(TDesC8 &aName, TUint32 aProcessId, TUint32 aThreadId, TUint32 aUid, TUint32 aCodeBaseAddress, TUint32 aDataBaseAddress)
{
	// check to see if the host supported protocol handles this event, 
	// otherwise just resume the thread. If not, this thread would get suspended indefinitely.
	if (iHostVersion.iMajor < 3 || (iHostVersion.iMajor == 3  && iHostVersion.iMinor <= 3))
	{
		iKernelDriver.ResumeThread(aThreadId);				
	}
	else
	{
		TUint8 event = kDSOSNotifyCreated;
		TUint16 type = kDSOSProcessItem;

		TUint16 nameLength = aName.Length();
		
		AddToReplyBufferL(event, true);
		AddToReplyBufferL(type);
		AddToReplyBufferL(aProcessId);
		AddToReplyBufferL(aThreadId);
		AddToReplyBufferL(aUid);
		AddToReplyBufferL(aCodeBaseAddress);
		AddToReplyBufferL(aDataBaseAddress);
		AddToReplyBufferL(nameLength);
		AddToReplyBufferL(aName);

		InformEventL();
	}
}

//
// CTrkDispatchLayer::DoReadLibraryInfoL()
//
void CTrkDispatchLayer::DoReadLibraryInfoL(TDesC8& aFileName)
{
	TMetroTrkLibInfo libInfo(aFileName.Length(), &aFileName);
	
	TInt err = iKernelDriver.GetLibraryInfo(libInfo);
	
	if (err == KErrNone)
	{
		AddToReplyBufferL(libInfo.iCodeAddress, true);
		AddToReplyBufferL(libInfo.iDataAddress);
		AddToReplyBufferL(libInfo.iAttachProcessId);
		AddToReplyBufferL(libInfo.iAttachThreadId);
		
		RespondOkL();
	}
	else
	{
		User::Leave(err);
	}			
}

//
// CTrkDispatchLayer::DoReadProcessInfoL()
//
void CTrkDispatchLayer::DoReadProcessInfoL(TUint32 aUid, TDesC8& aFileName)
{
	TMetroTrkExeInfo exeInfo(aUid, aFileName.Length(), &aFileName);
	
	TInt err = iKernelDriver.GetExeInfo(exeInfo);
	
	if (err == KErrNone)
	{
		AddToReplyBufferL(exeInfo.iProcessID, true);
		AddToReplyBufferL(exeInfo.iThreadID);
		AddToReplyBufferL(exeInfo.iCodeAddress);
		AddToReplyBufferL(exeInfo.iDataAddress);
		
		RespondOkL();
	}
	else
	{
		User::Leave(err);
	}			
}

//
// CTrkDispatchLayer::GetDataFromBufferL
//
// Get data from the input buffer
//
void CTrkDispatchLayer::GetDataFromBufferL(TAny* aData, TInt aLength)
{
	if (aLength > iInputBuffer->Length())
		User::Leave(kDSReplyPacketSizeError);
		
	if (iFramingLayer->IsBigEndian())
	{
		Mem::Copy(aData, iInputBuffer->Ptr(), aLength);
	}
	else
	{
		TUint8 *p = (TUint8 *)aData;
		for (int i=aLength-1, j=0; i>=0; i--, j++)
			p[j] = iInputBuffer->Ptr()[i];
	}
	
	// now remove it from the buffer
	iInputBuffer->Des().Delete(0, aLength);
}

//
// CTrkDispatchLayer::AddToReplyBufferL
//
// Add data to the buffer which will be sent back to the host as a reply
//
void CTrkDispatchLayer::AddToReplyBufferL(TUint8 aData, TBool aReset)
{
	if (aReset)
	{
		// free the memory associated with the old reply buffer and allocate a new one
		SafeDelete(iReplyBuffer);
		iReplyBuffer = HBufC8::New(sizeof(TUint8));
	}
	else
	{
		// reallocate to make enough room for the new data
		iReplyBuffer = iReplyBuffer->ReAlloc(iReplyBuffer->Length() + sizeof(TUint8));
	}
	
	// make sure the above worked
	if (!iReplyBuffer)
		User::Leave(KErrNoMemory);
	
	iReplyBuffer->Des().Append(aData);
}

//
// CTrkDispatchLayer::AddToReplyBufferL
//
// Add data to the buffer which will be sent back to the host as a reply
//
void CTrkDispatchLayer::AddToReplyBufferL(TUint16 aData, TBool aReset)
{
	TUint16 temp = aData;
	
	if (aReset)
	{
		// free the memory associated with the old reply buffer and allocate a new one
		SafeDelete(iReplyBuffer);
		iReplyBuffer = HBufC8::New(sizeof(TUint16));
	}
	else
	{
		// reallocate to make enough room for the new data
		iReplyBuffer = iReplyBuffer->ReAlloc(iReplyBuffer->Length() + sizeof(TUint16));
	}
	
	// make sure the above worked
	if (!iReplyBuffer)
		User::Leave(KErrNoMemory);
	
	// the host expects all values except for raw data to be returned in big endian format
	if (!iFramingLayer->IsBigEndian())
	{
		temp = Swap2(aData);
	}

	iReplyBuffer->Des().Append((TUint8 *)&temp, sizeof(TUint16));
}

//
// CTrkDispatchLayer::AddToReplyBufferL
//
// Add data to the buffer which will be sent back to the host as a reply
//
void CTrkDispatchLayer::AddToReplyBufferL(TUint32 aData, TBool aReset)
{
	TUint32 temp = aData;
	
	if (aReset)
	{
		// free the memory associated with the old reply buffer and allocate a new one
		SafeDelete(iReplyBuffer);
		iReplyBuffer = HBufC8::New(sizeof(TUint32));
	}
	else
	{
		// reallocate to make enough room for the new data
		iReplyBuffer = iReplyBuffer->ReAlloc(iReplyBuffer->Length() + sizeof(TUint32));
	}
	
	// make sure the above worked
	if (!iReplyBuffer)
		User::Leave(KErrNoMemory);
	
	// the host expects all values except for raw data to be returned in big endian format
	if (!iFramingLayer->IsBigEndian())
	{
		temp = Swap4(aData);
	}

	iReplyBuffer->Des().Append((TUint8 *)&temp, sizeof(TUint32));
}

//
// CTrkDispatchLayer::AddToReplyBufferL
//
// Add data to the buffer which will be sent back to the host as a reply
//
void CTrkDispatchLayer::AddToReplyBufferL(const TDesC8 &aData, TBool aReset)
{
	if (aReset)
	{
		// free the memory associated with the old reply buffer and allocate a new one
		SafeDelete(iReplyBuffer);
		iReplyBuffer = HBufC8::New(aData.Length());
	}
	else
	{
		// reallocate to make enough room for the new data
		iReplyBuffer = iReplyBuffer->ReAlloc(iReplyBuffer->Length() + aData.Length());
	}
	
	// make sure the above worked
	if (!iReplyBuffer)
		User::Leave(KErrNoMemory);
	
	iReplyBuffer->Des().Append(aData);
}

//
// CTrkDispatchLayer::IsThreadSuspended
//
// Determines whether or not a thread is suspended
//
TUint8 CTrkDispatchLayer::IsThreadSuspended(TUint32 aThreadId)
{
	if (iSuspendedThreadList.Find(aThreadId) >= 0)
		return 1;
	
	return 0;
}

//
// CTrkDispatchLayer::IsRestrictedFolder
//
// Check to see if the path is any of the data caged paths like \sys\ or \private\ or \resource\
//
TBool CTrkDispatchLayer::IsRestrictedFolder(const TDesC& aPath)
{
	_LIT(KSYS, "\\sys\\");
	_LIT(KRESOURCE, "\\resource\\");
	_LIT(KPRIVATE, "\\private\\");
	
	if ( (aPath.FindC(KSYS)>=0) || (aPath.FindC(KRESOURCE)>=0) || (aPath.FindC(KPRIVATE)>=0) )
		return ETrue;
	
	return EFalse;
}


TInt CTrkDispatchLayer::CloseCrashLogger()
{
    TInt err = KErrNone;
    
    //The old mobile crash file name is "d_exc_mc.exe" and the new one is "mc_useragent.exe"    
    //This is the string that needs to be passed to the RProcess::Open call to get a handle.
    //The complete process name actually includes the UID info as well.
    //Instead of hard coding the process name, its better to just 
    //search for the process and find it that way.      
    //_LIT16(KCrashLoggerName, "mc_useragent.exe[1020e519]0001");
    _LIT16(KOldCrashLoggerName, "d_exc_mc*");
    _LIT16(KCrashLoggerName, "mc_useragent*");
    
    err = TerminateProcess(KOldCrashLoggerName);
    err = TerminateProcess(KCrashLoggerName);

    return err;
}

TInt CTrkDispatchLayer::TerminateProcess(const TDesC& aProcessName)
{
    TFindProcess find(aProcessName);
    TFullName name; 
        
    TInt err = find.Next(name);
    if (KErrNone == err)
    {   
        RProcess process;
        err = process.Open(find);
    
        if (KErrNone == err)
        {
            process.Kill(KErrNone);
        }
    }
    return err;
}