Revision: 201010 RCL_3
authorDremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 15 Mar 2010 12:45:50 +0200
branchRCL_3
changeset 21 e7d2d738d3c2
parent 20 597aaf25e343
child 22 2f92ad2dc5db
Revision: 201010 Kit: 201010
kernel/eka/debug/securityServer/inc/c_security_svr_async.h
kernel/eka/debug/securityServer/inc/c_security_svr_session.h
kernel/eka/debug/securityServer/src/c_process_pair.cpp
kernel/eka/debug/securityServer/src/c_security_svr_async.cpp
kernel/eka/debug/securityServer/src/c_security_svr_session.cpp
kernel/eka/drivers/debug/rmdebug/d_debug_agent.cpp
kernel/eka/drivers/debug/rmdebug/d_debug_agent.h
kernel/eka/drivers/debug/rmdebug/d_debug_agent.inl
kernel/eka/drivers/debug/rmdebug/d_list_manager.cpp
kernel/eka/drivers/debug/rmdebug/d_process_tracker.cpp
kernel/eka/drivers/debug/rmdebug/d_rmd_stepping.cpp
kernel/eka/drivers/debug/rmdebug/d_target_process.cpp
kernel/eka/drivers/debug/rmdebug/rm_debug_eventhandler.cpp
kernel/eka/drivers/debug/rmdebug/rm_debug_kerneldriver.cpp
kernel/eka/drivers/dma/dmapil.cpp
kernel/eka/drivers/media/base_e32_drivers_media.mrp
kernel/eka/drivers/pbus/spbus.cpp
kernel/eka/drivers/usbc/d_usbc.cpp
kernel/eka/drivers/usbcc/ps_usbc.cpp
kernel/eka/include/drivers/rm_debug_eventhandler.h
kernel/eka/include/e32ver.h
kernel/eka/include/nkern/nk_priv.h
kernel/eka/include/nkernsmp/nk_priv.h
kernel/eka/kernel/server.cpp
kernel/eka/kernel/sutils.cpp
kernel/eka/memmodel/emul/win32/mprocess.cpp
kernel/eka/memmodel/epoc/flexible/mmu/mm.cpp
kernel/eka/nkern/win32/ncsched.cpp
kernel/eka/release.txt
kerneltest/e32test/bmarm/t_wsd_dl1.def
kerneltest/e32test/bmarm/t_wsd_dl2.def
kerneltest/e32test/bmarm/t_wsd_dl3.def
kerneltest/e32test/bwins/t_wsd_dl1.def
kerneltest/e32test/bwins/t_wsd_dl2.def
kerneltest/e32test/bwins/t_wsd_dl3.def
kerneltest/e32test/bx86/t_wsd_dl1.def
kerneltest/e32test/bx86/t_wsd_dl2.def
kerneltest/e32test/bx86/t_wsd_dl3.def
kerneltest/e32test/debug/context.cia
kerneltest/e32test/dma/d_dma.cpp
kerneltest/e32test/dma/t_dma.cpp
kerneltest/e32test/eabi/t_wsd_dl1.def
kerneltest/e32test/eabi/t_wsd_dl2.def
kerneltest/e32test/eabi/t_wsd_dl3.def
kerneltest/e32test/group/bld.inf
kerneltest/e32test/group/t_wsd_dl1.mmh
kerneltest/e32test/group/t_wsd_dl1_cp.mmp
kerneltest/e32test/group/t_wsd_dl1_cu.mmp
kerneltest/e32test/group/t_wsd_dl1_xp.mmp
kerneltest/e32test/group/t_wsd_dl1_xu.mmp
kerneltest/e32test/group/t_wsd_dl2.mmh
kerneltest/e32test/group/t_wsd_dl2_cp.mmp
kerneltest/e32test/group/t_wsd_dl2_cu.mmp
kerneltest/e32test/group/t_wsd_dl2_xp.mmp
kerneltest/e32test/group/t_wsd_dl2_xu.mmp
kerneltest/e32test/group/t_wsd_dl3.mmh
kerneltest/e32test/group/t_wsd_dl3_cp.mmp
kerneltest/e32test/group/t_wsd_dl3_cu.mmp
kerneltest/e32test/group/t_wsd_dl3_xp.mmp
kerneltest/e32test/group/t_wsd_dl3_xu.mmp
kerneltest/e32test/group/t_wsd_tst.mmh
kerneltest/e32test/group/t_wsd_tst_cp.mmp
kerneltest/e32test/group/t_wsd_tst_cu.mmp
kerneltest/e32test/group/t_wsd_tst_xp.mmp
kerneltest/e32test/group/t_wsd_tst_xu.mmp
kerneltest/e32test/mmu/t_shbuf.cpp
kerneltest/e32test/mmu/t_wsd_dl1.cpp
kerneltest/e32test/mmu/t_wsd_dl2.cpp
kerneltest/e32test/mmu/t_wsd_dl3.cpp
kerneltest/e32test/mmu/t_wsd_tst.cpp
kerneltest/e32test/mmu/t_wsd_tst.h
kerneltest/e32test/rm_debug/basic_tests/r_kernel_low_memory_security_svr_session.cpp
kerneltest/e32test/rm_debug/basic_tests/r_kernel_low_memory_security_svr_session.h
kerneltest/e32test/rm_debug/basic_tests/r_low_memory_security_svr_session.cpp
kerneltest/e32test/rm_debug/basic_tests/r_low_memory_security_svr_session.h
kerneltest/e32test/rm_debug/basic_tests/r_user_low_memory_security_svr_session.cpp
kerneltest/e32test/rm_debug/basic_tests/r_user_low_memory_security_svr_session.h
kerneltest/e32test/rm_debug/basic_tests/t_rmdebug2.cpp
kerneltest/e32test/rm_debug/basic_tests/t_rmdebug2.h
kerneltest/e32test/rm_debug/basic_tests/t_rmdebug2_oemtoken.cpp
kerneltest/e32test/rm_debug/common/t_target_launcher.cpp
kerneltest/e32test/rm_debug/common/t_target_launcher.h
kerneltest/e32test/rm_debug/debug_targets/d_demand_paging.cia
kerneltest/e32test/rm_debug/debug_targets/d_demand_paging.h
kerneltest/e32test/rm_debug/debug_targets/d_rmdebug_step_test.h
kerneltest/e32test/rm_debug/debug_targets/d_rmdebug_step_test.s
kerneltest/e32test/rm_debug/debug_targets/d_rmdebug_step_test_armv4.h
kerneltest/e32test/rm_debug/debug_targets/d_rmdebug_step_test_armv4.s
kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthread.cpp
kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthread.h
kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthread2.cpp
kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthread2.h
kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthreadasm.cia
kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthreadasm2.cia
kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_app.cpp
kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_app.h
kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_dll.cpp
kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_dll.h
kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_security.cpp
kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_security.h
kerneltest/e32test/rm_debug/group/t_crashmonitor_lib.mmp
kerneltest/e32test/rm_debug/group/t_multi_agent_launcher.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug2.mmh
kerneltest/e32test/rm_debug/group/t_rmdebug2.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug2_oem.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug2_oem2.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug2_oemtoken.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug2_oemtoken2.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_app.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_app1.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_app10.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_app2.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_app3.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_app4.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_app5.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_app6.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_app7.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_app8.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_app9.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_dll.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_multi_agent.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_multi_target.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_security0.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_security1.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_security2.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_security3.mmp
kerneltest/e32test/rm_debug/group/t_rmdebug_target_launcher.mmp
kerneltest/e32test/rm_debug/group/t_trkdummyapp.mmp
kerneltest/e32test/rm_debug/metro_trk/d_rmdebugclient.h
kerneltest/e32test/rm_debug/metro_trk/d_rmdebugserver.cpp
kerneltest/e32test/rm_debug/metro_trk/d_rmdebugserver.h
kerneltest/e32test/rm_debug/metro_trk/t_rmdebug.cpp
kerneltest/e32test/rm_debug/metro_trk/t_rmdebug.h
kerneltest/e32test/rm_debug/multi_agent_tests/t_agent_eventhandler.cpp
kerneltest/e32test/rm_debug/multi_agent_tests/t_agent_eventhandler.h
kerneltest/e32test/rm_debug/multi_agent_tests/t_debug_logging.h
kerneltest/e32test/rm_debug/multi_agent_tests/t_multi_agent.cpp
kerneltest/e32test/rm_debug/multi_agent_tests/t_multi_agent.h
kerneltest/e32test/rm_debug/multi_agent_tests/t_multi_agent_launcher.cpp
kerneltest/e32test/rm_debug/multi_agent_tests/t_multi_agent_launcher.h
kerneltest/e32test/rm_debug/multi_target_tests/t_multi_target.cpp
kerneltest/e32test/rm_debug/multi_target_tests/t_multi_target.h
kerneltest/e32test/rm_debug/trk_blocking/t_trkdummyapp.cpp
kerneltest/e32test/rm_debug/trk_blocking/t_trkdummyapp.h
kerneltest/f32test/filesystem/fat/b_fat32.cpp
kerneltest/f32test/filesystem/fat/t_compat32.cpp
kerneltest/f32test/filesystem/fat/t_scn32dr1.cpp
kerneltest/f32test/filesystem/fat/t_tscan32.cpp
kerneltest/f32test/fileutils/inc/fat_utils.h
kerneltest/f32test/fileutils/src/fat_utils.cpp
kerneltest/f32test/server/t_main.cpp
kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/cmassstoragemountcb.cpp
kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/inc/cmassstoragefilesystem.h
kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/inc/cmassstoragemountcb.h
kerneltest/f32test/smassstorage/src/t_ms_fsunit.cpp
userlibandfileserver/fileserver/group/release.txt
userlibandfileserver/fileserver/inc/f32dbg.h
userlibandfileserver/fileserver/inc/f32ver.h
userlibandfileserver/fileserver/sfile/sf_debug.cpp
userlibandfileserver/fileserver/sfile/sf_lepoc.cpp
userlibandfileserver/fileserver/sfile/sf_main.cpp
userlibandfileserver/fileserver/sfile/sf_request.cpp
userlibandfileserver/fileserver/sfile/sf_std.h
userlibandfileserver/fileserver/sfile/sf_std.inl
userlibandfileserver/fileserver/sfsrv/cl_parse.cpp
userlibandfileserver/fileserver/smassstorage/cmassstoragefilesystem.cpp
userlibandfileserver/fileserver/smassstorage/cmassstoragemountcb.cpp
userlibandfileserver/fileserver/smassstorage/inc/cmassstoragefilesystem.h
userlibandfileserver/fileserver/smassstorage/inc/cmassstoragemountcb.h
--- a/kernel/eka/debug/securityServer/inc/c_security_svr_async.h	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/debug/securityServer/inc/c_security_svr_async.h	Mon Mar 15 12:45:50 2010 +0200
@@ -53,15 +53,39 @@
 	virtual TInt RunError(TInt aError);
 
 private:
-	RMessagePtr2 iMessage;			// The last GetEvent message details. Needed for completion by RunL()
+
+    /*
+     * The last GetEvent message details. Needed for completion by RunL()
+     */
+    RMessagePtr2 iMessage;			
 
-	Debug::TEventInfo iInfo;				// Temporary storage area for rm_debug.ldd to return data asynchronously.
+    /*
+     * Temporary storage area for rm_debug.ldd to return data asynchronously
+     */
+	Debug::TEventInfo iInfo;
+
+	/*
+	 * Identity of this server session. Used for completing iMessage
+	 */
+	CSecuritySvrSession* iSession;
 
-	CSecuritySvrSession* iSession;	// Identity of this server session. Used for completing iMessage
+	/*
+	 * Name of the process being debugged associated with this AO
+	 */
+	RBuf8 iProcessName;
 
-	RBuf8 iProcessName;				// Name of the process being debugged associated with this AO
-
-	TProcessId iAgentId;				// Debug Agent Id
+	/*
+	 * Debug Agent Id
+	 */
+	TProcessId iAgentId;
+	
+	/*
+	 * Balance between event requests and event deliveries.
+	 * @see GetEvent()
+	 * @see NotifyEvent()
+	 * @see DoCancel()
+	 */
+	TInt iEventBalance;
 };
  
 #endif	// C_SECURITY_SVR_ASYNC_H
--- a/kernel/eka/debug/securityServer/inc/c_security_svr_session.h	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/debug/securityServer/inc/c_security_svr_session.h	Mon Mar 15 12:45:50 2010 +0200
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
 // All rights reserved.
 // This component and the accompanying materials are made available
 // under the terms of the License "Eclipse Public License v1.0"
--- a/kernel/eka/debug/securityServer/src/c_process_pair.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/debug/securityServer/src/c_process_pair.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -61,7 +61,7 @@
 
 @param aProcessPair a CProcessPair object to match with this one
 
-@return ETrue is process id and name match, EFalse otherwise
+@return 0 if process ids and names do not match, non-zero if they do
 */
 TBool CProcessPair::operator==(const CProcessPair &aProcessPair) const
 	{
@@ -74,7 +74,7 @@
 @param aProcessName process name to check
 @param aProcessId process id to check
 
-@return ETrue is process id and name match, EFalse otherwise
+@return 0 if process ids and names do not match, non-zero if they do
 */
 TBool CProcessPair::Equals(const TDesC& aProcessName, const TProcessId aProcessId) const
 	{
@@ -86,7 +86,7 @@
 
 @param aProcessPair a CProcessPair object to compare with this one
 
-@return ETrue is process id matches, EFalse otherwise
+@return 0 if process ids do not match, non-zero if they do
 */
 TBool CProcessPair::ProcessIdMatches(const CProcessPair &aProcessPair) const
 	{
@@ -98,7 +98,7 @@
 
 @param aProcessId a process ID to compare with this pair's process ID
 
-@return ETrue is process id matches, EFalse otherwise
+@return 0 if process ids do not match, non-zero if they do
 */
 TBool CProcessPair::ProcessIdMatches(const TProcessId &aProcessId) const
 	{
@@ -110,7 +110,7 @@
 
 @param aProcessPair a CProcessPair object to compare with this one
 
-@return ETrue is process names match, EFalse otherwise
+@return 0 if process names do not match, non-zero if they do
 */
 TBool CProcessPair::ProcessNameMatches(const CProcessPair &aProcessPair) const
 	{
@@ -122,11 +122,10 @@
 
 @param aProcessName a process name to compare with this pair's process name
 
-@return ETrue is process names match, EFalse otherwise
+@return 0 if process names do not match, non-zero if they do
 */
 TBool CProcessPair::ProcessNameMatches(const TDesC& aProcessName) const
 	{
-	TInt equal = iProcessName->CompareF(aProcessName);
-	return (equal == 0) ? ETrue : EFalse;
+	return iProcessName->CompareF(aProcessName) == 0;
 	}
 
--- a/kernel/eka/debug/securityServer/src/c_security_svr_async.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/debug/securityServer/src/c_security_svr_async.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -25,10 +25,11 @@
 
 // ctor
 CSecuritySvrAsync::CSecuritySvrAsync(CSecuritySvrSession* aSession, TProcessId aAgentId)
-: CActive(CActive::EPriorityStandard),
-  iSession(aSession),
-  iProcessName(NULL),
-  iAgentId(aAgentId)
+	: CActive(CActive::EPriorityStandard),
+	iSession(aSession),
+	iProcessName(NULL),
+	iAgentId(aAgentId),
+	iEventBalance(0)
 	{
 	LOG_MSG("CSecuritySvrAsync::CSecuritySvrAsync()");
 	CActiveScheduler::Add(this);
@@ -72,7 +73,9 @@
 // RunL() completes a previously issued call (currently only GetEvent() completion)
 void CSecuritySvrAsync::RunL()
 	{
-	LOG_MSG("CSecuritySvrAsync::RunL()");
+
+	LOG_MSG3("CSecuritySvrAsync::RunL() &iInfo=0x%08x, iEventBalance=%d", (TUint8*)&iInfo, iEventBalance);
+
 	// Something bad happened in the driver
 	User::LeaveIfError(iStatus.Int());
 
@@ -96,44 +99,54 @@
 	iMessage.WriteL(1,data,0);
 
 	iMessage.Complete(KErrNone);
+	--iEventBalance;
 	}
 
 // Cancels the oustanding GetEvent call. May cope with other async calls in future.
 void CSecuritySvrAsync::DoCancel()
 	{
-	LOG_MSG("CSecuritySvrAsync::DoCancel()");
+	LOG_MSG2("CSecuritySvrAsync::DoCancel() iEventBalance=%d", iEventBalance);
 	iSession->Server().iKernelDriver.CancelGetEvent(iProcessName,iAgentId.Id());
 
 	iMessage.Complete(KErrCancel);
+	iEventBalance=0;
 	}
 
 // Report any leave to the client if possible.
 TInt CSecuritySvrAsync::RunError(TInt aError)
 	{
-	LOG_MSG("CSecuritySvrAsync::RunError()");
+	LOG_MSG2("CSecuritySvrAsync::RunError()=%d", aError);
 	iMessage.Complete(aError);
 
 	return KErrNone;
 	}
 
-// Start an Asynchronous GetEvent call to the rm_debug.ldd driver
-// and activate this Active Object.
+/*
+ * Start an asynchronous GetEvent call to the debug driver
+ * and activates this active object. 
+ */
 void CSecuritySvrAsync::GetEvent(const RMessage2& aMessage)
 	{
-	LOG_MSG("CSecuritySvrAsync::GetEvent()");
 	iMessage = aMessage;
 
-	iSession->Server().iKernelDriver.GetEvent(iProcessName,iAgentId.Id(),iStatus,iInfo);
+	iEventBalance++;
+	LOG_MSG5("CSecuritySvrAsync::GetEvent() this = 0x%08x, iInfo=0x%08x, iStatus=0x%08x \
+		iEventBalance=%d : >SetActive() > GetEvent() ",
+		this, &iInfo, &iStatus, iEventBalance );
 
+	/* 
+	SetActive is called before sending the message to the driver so 
+	that we do not get stray signal panics, since the driver may complete immediately
+ 	*/
 	SetActive();
+	iSession->Server().iKernelDriver.GetEvent(iProcessName,iAgentId.Id(),iStatus,iInfo);
 	}
 
 // Used for identifying which AO is associated with a debugged process
 const TDesC8& CSecuritySvrAsync::ProcessName(void)
-{
-	LOG_MSG("CSecuritySvrAsync::ProcessName()");
+	{
 	return iProcessName;
-}
+	}
 
 // End of file - c_security_svr_async.cpp
 
--- a/kernel/eka/debug/securityServer/src/c_security_svr_session.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/debug/securityServer/src/c_security_svr_session.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
 // All rights reserved.
 // This component and the accompanying materials are made available
 // under the terms of the License "Eclipse Public License v1.0"
@@ -1040,7 +1040,7 @@
 	{
 	LOG_MSG( "CSecuritySvrSession::AttachProcessL()\n" );
 
-	TBool aPassive = aMessage.Int0() ? ETrue : EFalse;
+	const TBool passive = aMessage.Int0();
 
 	TInt deslen = aMessage.GetDesLengthL(1);
 
@@ -1142,7 +1142,7 @@
 		IsDebuggableL(processName);
 		}
 
-	User::LeaveIfError(Server().AttachProcessL(processName, processId, aPassive));
+	User::LeaveIfError(Server().AttachProcessL(processName, processId, passive));
 
 	// Inform the kernel driver about the attachment, so that it
 	// can track per-agent data about the process.
@@ -1361,10 +1361,16 @@
 		}
 	if ( i == KMaxLocalDrives)
 		{
-			LOG_MSG("No crash log partition found with valid crash log signature found.  Exiting...");
-			User::Leave (KErrNotFound);
+		LOG_MSG("No crash log partition found with valid crash log signature found.  Exiting...");
+		User::Leave (KErrNotFound);
 		}
-	
+
+	// Nand Flash not currently supported.
+	if (iCaps.iType == EMediaNANDFlash)
+		{
+		LOG_MSG( "CSecuritySvrSession::ConnectCrashPartitionL()  Nand Flash not currently supported\n" );
+		User::Leave (KErrNotSupported);
+		}
 	}
 /** Checks that aHeaderData contains enough data to cast it to the
   appropriate header type.
--- a/kernel/eka/drivers/debug/rmdebug/d_debug_agent.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/debug/rmdebug/d_debug_agent.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -31,23 +31,24 @@
 #include "d_debug_agent.h"
 #include "debug_utils.h"
 
-using namespace Debug;
+#include "d_debug_agent.inl"
 
-#define NUMBER_OF_EVENTS_TO_QUEUE 100
-#define CRITICAL_BUFFER_SIZE (NUMBER_OF_EVENTS_TO_QUEUE - 50)
+using namespace Debug;
 
 // ctor
-DDebugAgent::DDebugAgent(TUint64 aId)
-: iId(aId),
-  iEventInfo(NULL),
-  iEventQueue(NUMBER_OF_EVENTS_TO_QUEUE, 0),
-  iRequestGetEventStatus(NULL),
-  iClientThread(0),
-  iHead(0),
-  iTail(0),
-  iIgnoringTrace(EFalse)
+DDebugAgent::DDebugAgent(TUint64 aId) :
+	iId(aId),
+	iRequestGetEventStatus(NULL),
+	iClientThread(0),
+	iEventQueue(KNumberOfEventsToQueue, 0),
+	iHead(0),
+	iTail(0),
+	iEventQueueLock(NULL),
+	iFreeSlots(KNumberOfEventsToQueue),
+	iIgnoringTrace(EFalse),
+	iEventBalance(0)
 	{
-	LOG_MSG("DDebugAgent::DDebugAgent() ");
+	LOG_MSG2("DDebugAgent::DDebugAgent(), this=0x%x ", this);
 
 	// Initialize all the Event Actions to Ignore
 	for(TInt i=0; i<EEventsLast; i++)
@@ -69,32 +70,59 @@
 		delete agent;
 		return (NULL);
 		}
+
+	// Use a semaphore to serialise access
+	TInt err = Kern::SemaphoreCreate(agent->iEventQueueLock, _L("RM_DebugAgentQueueLock"), 1 /* Initial count */);
+	if (err != KErrNone)
+		return NULL;
+
 	return agent;
 	}
 
+/** Standard contructor.
+ * Fills event queue with empty events
+ * @return : standard system error code
+ */
 TInt DDebugAgent::Construct()
 	{
 	// Empty the event queue
 	LOG_MSG("DDebugAgent::Construct()");
 	TDriverEventInfo emptyEvent;
+	TInt err = KErrNone;
 
-	for (TInt i=0; i<NUMBER_OF_EVENTS_TO_QUEUE; i++)
+	for (TInt i=0; i<KNumberOfEventsToQueue; i++)
 		{
-		TInt err = iEventQueue.Append(emptyEvent);
-		if (KErrNone != err)
+		err = iEventQueue.Append(emptyEvent);
+		if (err != KErrNone)
 			{
 			LOG_MSG("Error appending blank event entry");
 			return err;
 			}
 		}
-	return KErrNone;
+
+	err = Kern::CreateClientDataRequest(iRequestGetEventStatus);
+	if(err != KErrNone)
+		{
+		LOG_MSG("Error creating TClientDataRequest");
+		return err;
+		}
+
+	LOG_MSG2("DDebugAgent::Construct() iRequestGetEventStatus=0x%08x", iRequestGetEventStatus);
+
+	return err;
 	}
 
-
 // dtor
 DDebugAgent::~DDebugAgent()
 	{
 	iEventQueue.Reset();
+
+	if (iEventQueueLock)
+		iEventQueueLock->Close(NULL);
+	
+	if(iRequestGetEventStatus)
+		Kern::DestroyClientRequest(iRequestGetEventStatus);
+	
 	}
 
 // Associate an action with a particular kernel event
@@ -112,9 +140,9 @@
 	return KErrNone;
 	}
 
-/* Get the aEventAction associated with aEvent
+/** Get the aEventAction associated with aEvent
  *
- * Returns : aEventAction (always +ve), or KErrArgument.
+ * @return : aEventAction (always +ve), or KErrArgument.
  */
 TInt DDebugAgent::EventAction(TEventType aEvent)
 	{
@@ -129,90 +157,110 @@
 	return iEventActions[aEvent];
 	}
 
-// Obtain the details of the latest kernel event (if it exists) and place the details in aEventInfo
-// If there is no event in the queue for this process+agent combination, store the details
-// so that it can be notified later when an event actually occurs.
-//
-// @param aAsyncGetValueRequest - TClientDataRequest object used for pinning user memory
-// @param aEventInfo - Address of TEventInfo structure to place event data when available
-// @param aClientThread - The ThreadId of the requesting user-side process. In this case the DSS.
-void DDebugAgent::GetEvent(TClientDataRequest<TEventInfo>* aAsyncGetValueRequest, TEventInfo* aEventInfo, DThread* aClientThread)
+/** Obtain the details of the latest kernel event (if it exists) and place the details in aEventInfo
+ * If there is no event in the queue for this process+agent combination, store the details
+ * so that it can be notified later when an event actually occurs.
+ * 
+ * @param aAsyncGetValueRequest - TClientDataRequest object used for pinning user memory
+ * @param aClientThread - The ThreadId of the requesting user-side process. In this case the DSS.
+ */
+void DDebugAgent::GetEvent(TClientDataRequest<TEventInfo>* aAsyncGetValueRequest, DThread* aClientThread)
 	{
+	LockEventQueue();
+
+	iRequestGetEventStatus->Reset();
+	TInt err = iRequestGetEventStatus->SetStatus( aAsyncGetValueRequest->StatusPtr() );
+	if (err != KErrNone)
+		{
+		LOG_MSG2("Error :iRequestGetEventStatus->SetStatus ret %d", err);
+		return;
+		}
+	
+	iRequestGetEventStatus->SetDestPtr( aAsyncGetValueRequest->DestPtr() );
+
+	iEventBalance++;
+	
+	LOG_MSG4("DDebugAgent::GetEvent: this=0x%08x, iRequestGetEventStatus=0x%08x, iEventBalance=%d", 
+		this, iRequestGetEventStatus, iEventBalance );
+	
 	iClientThread = aClientThread;
-
+	
 	if (BufferEmpty())
 		{
-		LOG_MSG("no events available");
-
-		// store the pointer so we can modify it later
-		iEventInfo = (TEventInfo *)aEventInfo;
-		iRequestGetEventStatus = aAsyncGetValueRequest;
+		LOG_MSG2("Event buffer empty, iEventBalance=%d", iEventBalance);		
+		UnlockEventQueue();
 		return;
 		}
 
-	LOG_MSG("Event available");
+	LOG_MSG2("Event already available at queue pos=%d", iTail);
 
 	// returning the event to the client
-	TInt err = iEventQueue[iTail].WriteEventToClientThread(aAsyncGetValueRequest,iClientThread);
-	if (KErrNone != err)
+	err = iEventQueue[iTail].WriteEventToClientThread(iRequestGetEventStatus,iClientThread);
+	if (err != KErrNone)
 		{
 		LOG_MSG2("Error writing event info: %d", err);
+		UnlockEventQueue();
 		return;
 		}
 
 	// signal the DSS thread
-	Kern::QueueRequestComplete(iClientThread, aAsyncGetValueRequest, KErrNone);
+	Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrNone);
+	iEventBalance--;
 
 	iEventQueue[iTail].Reset();
 
 	// move to the next slot
-	IncrementPosition(iTail);
+	IncrementTailPosition();
+
+	UnlockEventQueue();
 	}
 
-// Stop waiting for an event to occur. This means events will be placed in the iEventQueue
-// until GetEvent is called.
+/**
+ * Stop waiting for an event to occur. This means events will be placed 
+ * in the iEventQueue (by setting iEventBalance to 0) until GetEvent is called. 
+ */ 
 TInt DDebugAgent::CancelGetEvent(void)
 	{
+	LOG_MSG2("DDebugAgent::CancelGetEvent. iEventBalance=%d. > QueueRequestComplete", iEventBalance);
 	Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrCancel);
-	iEventInfo = NULL;
-    iRequestGetEventStatus = 0;
+	iEventBalance=0;
 	iClientThread = 0;
-
 	return KErrNone;
 	}
 
-// Signal a kernel event to the user-side DSS when it occurs, or queue it for later
-// if the user-side has not called GetEvent (see above).
-//
-// @param aEventInfo - the details of the event to queue.
+/** Signal a kernel event to the user-side DSS when it occurs, or queue it for later
+ * if the user-side has not called GetEvent (see above).
+ * 
+ * @param aEventInfo - the details of the event to queue.
+ */
 void DDebugAgent::NotifyEvent(const TDriverEventInfo& aEventInfo)
 	{
-	LOG_MSG("DDebugAgent::NotifyEvent()");
-	// Action depends on the TKernelEvent type in aEventInfo.iType
-	
-	// Added to fix the pass by value issue seen in Coverity.  
-	// Function is changed to pass by reference but temp object is explicitly created.
-	TDriverEventInfo eventInfo = aEventInfo;
 
 	if(aEventInfo.iEventType >= EEventsLast)
 		{
-		// unknown event type so return
+		LOG_MSG3("DDebugAgent::NotifyEvent(),iEventType %d, this=0x%x. Ignoring since > EEventsLast", aEventInfo.iEventType, this);
 		return;
 		}
 
-	TKernelEventAction action = iEventActions[eventInfo.iEventType];
+	LockEventQueue();
+
+	DThread* currentThread = &Kern::CurrentThread();
+	
+	LOG_MSG5("DDebugAgent::NotifyEvent(), iEventType %d, this=0x%x currThrd=0x%08x, iEventBalance=%d",
+		aEventInfo.iEventType, this, currentThread, iEventBalance );
+	TKernelEventAction action = iEventActions[aEventInfo.iEventType];
 
 	switch (action)
 		{
 		case EActionSuspend:
 			{
 			LOG_MSG("DDebugAgent::NotifyEvent() Suspend thread");
-			DThread* currentThread = &Kern::CurrentThread();
-			switch(eventInfo.iEventType)
+
+			switch(aEventInfo.iEventType)
 				{
 				case EEventsAddLibrary:
 				case EEventsRemoveLibrary:
-					currentThread = DebugUtils::OpenThreadHandle(eventInfo.iThreadId);
+					currentThread = DebugUtils::OpenThreadHandle(aEventInfo.iThreadId);
 					if(currentThread)
 						{
 						currentThread->Close(NULL);
@@ -221,8 +269,8 @@
 				default:
 					break;
 				}
-			TInt err = TheDProcessTracker.SuspendThread(currentThread, eventInfo.FreezeOnSuspend());
-			if(!( (err == KErrNone) || (err == KErrAlreadyExists) ))
+			TInt err = TheDProcessTracker.SuspendThread(currentThread, aEventInfo.FreezeOnSuspend());
+			if((err != KErrNone) && (err != KErrAlreadyExists))
 				{
 				// Is there anything we can do in the future to deal with this error having happened?
 				LOG_MSG2("DDebugAgent::NotifyEvent() Problem while suspending thread: %d", err);
@@ -232,42 +280,62 @@
 			// the debug agent of the event
 			}
 		case EActionContinue:
-			LOG_MSG("DDebugAgent::NotifyEvent() Continue");
-
-			// Tell the user about this event
-			if (iEventInfo && iClientThread)
 			{
-				LOG_MSG("Completing event\r\n");
+			// Queue this event
+			QueueEvent(aEventInfo);
 
-				// returning the event to the client
-				TInt err = eventInfo.WriteEventToClientThread(iRequestGetEventStatus,iClientThread);
-				if (KErrNone != err)
+			// Tell the user about the oldest event in the queue
+			if ( iClientThread )
 				{
-					LOG_MSG2("Error writing event info: %d", err);
-				}
+				if( iRequestGetEventStatus && (iEventBalance > 0) )
+					{
+					// Fill the event data
+					TInt err = iEventQueue[iTail].WriteEventToClientThread(iRequestGetEventStatus,iClientThread);
+					if (err != KErrNone)
+						{
+						LOG_MSG2("Error writing event info: %d", err);
+						}
+
+					// signal the debugger thread 
+					LOG_MSG4("> QueueRequestComplete iRequestGetEventStatus=0x%08x, iEventBalance=%d, iTail=%d",
+						iRequestGetEventStatus->iStatus, iEventBalance, iTail );
+					Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrNone);
+
+					iEventBalance--;
 
-				// clear this since we've completed the request
-				iEventInfo = NULL;
+					iEventQueue[iTail].Reset();
 
-				// signal the debugger thread
-				Kern::QueueRequestComplete(iClientThread, iRequestGetEventStatus, KErrNone);
-			}
+					// move to the next slot
+					IncrementTailPosition();
+					}
+				else
+					{
+					if( !iRequestGetEventStatus )
+						{
+						LOG_MSG("iRequestGetEventStatus is NULL so not signalling client" );
+						}
+					else
+						{
+						LOG_MSG2("Queued event. iEventBalance=%d (unbalanced event requests vs notifications)", 
+							iEventBalance );
+						}
+					}
+				}
 			else
-			{
-				LOG_MSG("Queuing event\r\n");
-
-				QueueEvent(eventInfo);
-
+				{
+				 LOG_MSG("DDebugAgent::NotifyEvent() : Not informing client since its thread is NULL");
+				}
+			break;
 			}
-			break;
-
 		case EActionIgnore:
 		default:
-			LOG_MSG("DDebugAgent::NotifyEvent() fallen through to default case");
+			LOG_EVENT_MSG("DDebugAgent::NotifyEvent() fallen through to default case");
 			// Ignore everything we don't understand.
-			return;
+
 		}
 
+	UnlockEventQueue();
+
 	}
 
 // Used to identify which Debug Agent this DDebugAgent is associated with.
@@ -276,93 +344,77 @@
 	return iId;
 	}
 
-// Used to add an event to the event queue for this debug agent
-void DDebugAgent::QueueEvent(TDriverEventInfo& aEventInfo)
+/**
+ * Used to add an event to the event queue for this debug agent if event 
+ * queue is not at critical level. If it is at critical and it is trace event, 
+ * we start ignoring trace events and insert a lost trace event.
+ * If the buffer cannot store an event, only insert a buffer full event.
+ * @see EEventsBufferFull
+ * @see EEventsUserTracesLost
+ * @see TDriverEventInfo
+ * @see iEventQueue
+ */
+void DDebugAgent::QueueEvent(const TDriverEventInfo& aEventInfo)
 	{
 	// Have we caught the tail?
 	if(BufferFull())
 		{
+		LOG_MSG("DDebugAgent::QueueEvent : BufferFull. Not queueing");
 		return;
 		}
-	
-	//check to see if we wish to ignore this event - we dump trace events as they are lower priority than the other events
-	if(BufferAtCriticalLevel())
+
+	// Assert if we think there is space but the slot is not marked empty
+	__NK_ASSERT_DEBUG(iEventQueue[iHead].iEventType == EEventsUnknown);
+
+	const TBool bufferAtCritical = BufferAtCriticalLevel();
+
+	if(!bufferAtCritical)
 		{
+		//reset the iIgnoringTrace flag as we are not at 
+		//critical level and can store event
+		iIgnoringTrace = EFalse; 
+		
+		// Insert the event into the ring buffer at iHead
+		iEventQueue[iHead] = aEventInfo;
+		IncrementHeadPosition();
+		}
+	else if(bufferAtCritical && BufferCanStoreEvent())
+		{
+		LOG_MSG("DDebugAgent::QueueEvent : BufferCritical");
 		if(aEventInfo.iEventType == EEventsUserTrace)
 			{
 			if(!iIgnoringTrace)
 				{
-				//if this is the first time we are ignoring trace events, we need to issue a EEventsUserTracesLost event
-				aEventInfo.Reset();
-				aEventInfo.iEventType = EEventsUserTracesLost;
-				
+				//if this is the first time we are ignoring trace events, 
+				//we need to issue a EEventsUserTracesLost event
+				iEventQueue[iHead].Reset();
+				iEventQueue[iHead].iEventType = EEventsUserTracesLost;
+				IncrementHeadPosition();
+
 				iIgnoringTrace = ETrue;
 				}
 			else
 				{
 				//otherwise, ignore this event
-				return;
+				LOG_MSG("DDebugAgent::QueueEvent : Ignore EEventsUserTrace event");
 				}
 			}
+		else
+			{
+			// Store the event since its not a trace event
+			iEventQueue[iHead] = aEventInfo;
+			IncrementHeadPosition();
+			}
 		}
 	else
 		{
-		//reset the iIgnoringTrace flag as we are not at critical level
-		iIgnoringTrace = EFalse; 
-		}	
-
-	// only one space left so store a EEventsBufferFull event
-	if(!BufferCanStoreEvent())
-		{
-		aEventInfo.Reset();
-		aEventInfo.iEventType = EEventsBufferFull;
+		//At critical level and cannot store new events, so 
+		//only one space left. Store a EEventsBufferFull event
+		LOG_MSG("DDebugAgent::QueueEvent : Event Buffer Full, ignoring event");
+		iEventQueue[iHead].Reset();
+		iEventQueue[iHead].iEventType = EEventsBufferFull;
+		IncrementHeadPosition();
 		}
-
-	__NK_ASSERT_DEBUG(iEventQueue[iHead].iEventType == EEventsUnknown); // we think there is space but the slot is not marked empty
-
-	// Insert the event into the ring buffer at iHead
-	iEventQueue[iHead] = aEventInfo;
-	IncrementPosition(iHead);
-	}
-
-// Checks whether the event queue is empty
-TBool DDebugAgent::BufferEmpty() const
-	{
-	return (NumberOfEmptySlots() == NUMBER_OF_EVENTS_TO_QUEUE);
-	}
-
-// Checks whether the event queue is full
-TBool DDebugAgent::BufferFull() const
-	{
-	return (NumberOfEmptySlots() == 0);
 	}
 
-// Checks whether there is room in the event queue to store an event (i.e. at least two free slots)
-TBool DDebugAgent::BufferCanStoreEvent() const
-	{
-	return (NumberOfEmptySlots() > 1);
-	}
-
-//This looks to see if the buffer is close to being full and should only accept higher priority debug events (user trace is the only low priority event) 
-TBool DDebugAgent::BufferAtCriticalLevel() const
-	{
-	return (NumberOfEmptySlots() < NUMBER_OF_EVENTS_TO_QUEUE - CRITICAL_BUFFER_SIZE);
-	}
-
-// increments aPosition, wrapping at NUMBER_OF_EVENTS_TO_QUEUE if necessary
-void DDebugAgent::IncrementPosition(TInt& aPosition)
-	{
-	aPosition = (aPosition + 1) % NUMBER_OF_EVENTS_TO_QUEUE;
-	}
-
-// finds the number of empty slots in the event queue
-TInt DDebugAgent::NumberOfEmptySlots() const
-	{
-	if(iHead < iTail)
-		{
-		return (iTail - iHead) - 1;
-		}
-	// iHead >= iTail
-	return NUMBER_OF_EVENTS_TO_QUEUE - (iHead - iTail);
-	}
-
+// End of file - d_debug_agent.cpp
--- a/kernel/eka/drivers/debug/rmdebug/d_debug_agent.h	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/debug/rmdebug/d_debug_agent.h	Mon Mar 15 12:45:50 2010 +0200
@@ -22,6 +22,12 @@
 #include <rm_debug_api.h>
 #include "d_driver_event_info.h"
 
+/**
+* Handles events from the kernel, filters them according to the debug agent's requests, 
+* and signals these events to the user side in FIFO-style. 
+* @see TKernelEventAction
+* @see TEventInfo
+*/
 class DDebugAgent : public DBase
 {
 public:
@@ -29,7 +35,7 @@
 	~DDebugAgent();
 
 	TInt SetEventAction(Debug::TEventType aEvent, Debug::TKernelEventAction aEventAction);
-	void GetEvent(TClientDataRequest<Debug::TEventInfo>* aAsyncGetValueRequest, Debug::TEventInfo* aEventInfo, DThread* aClientThread);
+	void GetEvent(TClientDataRequest<Debug::TEventInfo>* aAsyncGetValueRequest, DThread* aClientThread);
 	TInt EventAction(Debug::TEventType aEvent);
 
 	TInt CancelGetEvent(void);
@@ -41,31 +47,99 @@
 	TInt Construct();
 
 private:
-	void QueueEvent(TDriverEventInfo& aEventInfo);
+	void QueueEvent(const TDriverEventInfo& aEventInfo);
 	TBool BufferEmpty() const;
 	TBool BufferFull() const;
 	TBool BufferCanStoreEvent() const;
 	TBool BufferAtCriticalLevel() const;
-	void IncrementPosition(TInt& aPosition);
+	void IncrementHeadPosition(void);
+	void IncrementTailPosition(void);
 	TInt NumberOfEmptySlots() const;
+	void LockEventQueue(void);
+	void UnlockEventQueue(void);
 
 private:
+
 	TUint64	iId;
 	Debug::TKernelEventAction iEventActions[Debug::EEventsLast];
 
-	//iEventInfo is a pointer to an object owned by the security server, so
-	//no clean up needs be performed on it
-	Debug::TEventInfo* iEventInfo;
-	RArray<TDriverEventInfo> iEventQueue;	// ring buffer.
+	/**
+	* Object used to write events back to DSS thread
+	* @see TEventInfo
+	*/
 	TClientDataRequest<Debug::TEventInfo>* iRequestGetEventStatus;
+
 	DThread* iClientThread;
 
-	// Ring buffer data
-	TInt iHead;	// points to the next empty slot in iEventQueue (exc. when iFull == ETrue)
-	TInt iTail; // points to the oldest full slot in iEventQueue (exc. when iEmpty == ETrue)
+	/** 
+	* Ring buffer of pending events. Access to it is controlled by 
+	* @see iEventQueueLock
+	*/
+	RArray<TDriverEventInfo> iEventQueue;
+
+	/**
+	* Ring buffer head. Points to the next empty slot in iEventQueue
+	* @see iEventQueue
+	*/
+	TInt iHead;	
+
+	/**
+	* Ring buffer tail. Points to the oldest full slot in iEventQueue
+	* @see iEventQueue 
+	*/
+	TInt iTail;
+
+	/** 
+	* Control access to event queue.
+	* @see iEventQueue
+	*/
+	DSemaphore* iEventQueueLock;
+
+	/**
+	* Keeps track of how many free slots are available in the event queue.
+	* @see iEventQueue
+	*/
+	TInt iFreeSlots;
+
+	/**
+	* Boolean to indicate if we have told the agent that we are ignoring trace events
+	* @see QueueEvent
+	*/
+	TBool iIgnoringTrace;
 	
-	//if we have told the agent that we are ignoring trace events
-	TBool iIgnoringTrace;
+	/**
+	* Used to control the delivery of events to the client so that only 
+	* when more requests than deliveries have taken place can we deliver the 
+	* next event
+	* 
+	* Incremented when a request for event takes place
+	* @see GetEvent
+	* 
+	* Decremented when an event is delivered. 
+	* @see NotifyEvent
+	* 
+	* Cleared when event requests are cancelled
+	* @see CancelGetEvent
+	* 
+	*/
+	TInt   iEventBalance;
+
+	/**
+	* Length of kernel-event queue.
+	* This is a power of two for efficiency when using the 
+	* remainder operator
+	* @see DDebugAgent::iEventQueue
+	*/
+	static const TUint KNumberOfEventsToQueue = 128;
+
+	/**
+	* This determines the number of events at which we stop accepting 
+	* low priority events into the event queue.
+	* @see DDebugAgent::BufferAtCriticalLevel
+	* @see DDebugAgent::iEventQueue
+	*/
+	static const TUint KCriticalBufferSize = 64;
+
 };
 
 #endif // D_DEBUG_AGENT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/drivers/debug/rmdebug/d_debug_agent.inl	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,106 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Inline methods for debug agent class
+//
+
+
+/**
+ @file
+ @internalComponent
+ @released
+*/
+
+#ifndef D_DEBUG_AGENT_INL
+#define D_DEBUG_AGENT_INL
+
+
+/**
+ Checks whether the event queue is empty
+*/
+inline TBool DDebugAgent::BufferEmpty() const
+	{
+	return (NumberOfEmptySlots() == KNumberOfEventsToQueue);
+	}
+
+/**
+ Checks whether the event queue is full
+*/
+inline TBool DDebugAgent::BufferFull() const
+	{
+	return (NumberOfEmptySlots() == 0);
+	}
+
+/**
+ Checks whether there is room in the event queue to store an event
+*/
+inline TBool DDebugAgent::BufferCanStoreEvent() const
+	{
+	return (NumberOfEmptySlots() > 0);
+	}
+
+/**
+ This looks to see if the buffer is close to being full and should only
+ accept higher priority debug events (user trace is the only low priority event) 
+*/
+inline TBool DDebugAgent::BufferAtCriticalLevel() const
+	{
+	return (NumberOfEmptySlots() < KNumberOfEventsToQueue - KCriticalBufferSize);
+	}
+
+/**
+ Increments Head position, wrapping at KNumberOfEventsToQueue if necessary
+*/
+inline void DDebugAgent::IncrementHeadPosition(void)
+	{
+	iHead = (iHead + 1) % KNumberOfEventsToQueue;
+
+	iFreeSlots--;
+	}
+
+/**
+ Increments Tail position, wrapping at KNumberOfEventsToQueue if necessary
+*/
+inline void DDebugAgent::IncrementTailPosition(void)
+	{
+	iTail = (iTail + 1) % KNumberOfEventsToQueue;
+
+	iFreeSlots++;
+}
+
+/**
+ Returns the number of free slots in the event queue
+*/
+inline TInt DDebugAgent::NumberOfEmptySlots() const
+	{
+	return iFreeSlots;
+	}
+
+/**
+ Lock access to this agent's event queue
+*/
+inline void DDebugAgent::LockEventQueue(void)
+	{
+	Kern::SemaphoreWait(*iEventQueueLock);
+	}
+
+/**
+ Release the lock on this agent's event queue
+*/
+inline void DDebugAgent::UnlockEventQueue(void)
+	{
+	Kern::SemaphoreSignal(*iEventQueueLock);
+	}
+
+
+#endif	// D_DEBUG_AGENT_INL
--- a/kernel/eka/drivers/debug/rmdebug/d_list_manager.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/debug/rmdebug/d_list_manager.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -422,7 +422,7 @@
 				}
 			//calculate data values
 			TFileName fileName(codeSeg->iFileName->Ptr());
-			TBool isXip = (codeSeg->iXIP) ? ETrue : EFalse;
+			TBool isXip = (TBool)(codeSeg->iXIP);
 
 			//get the code seg type, can ignore error as have already checked codeSeg is not NULL
 			TCodeSegType type = EUnknownCodeSegType;
@@ -535,7 +535,7 @@
 				}
 
 			TFileName fileName(codeSeg->iFileName->Ptr());
-			TBool isXip = (codeSeg->iXIP) ? ETrue : EFalse;
+			TBool isXip = (TBool)(codeSeg->iXIP);
 
 			//get the code seg type, can ignore error as have already checked codeSeg is not NULL
 			TCodeSegType type = EUnknownCodeSegType;
--- a/kernel/eka/drivers/debug/rmdebug/d_process_tracker.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/debug/rmdebug/d_process_tracker.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -76,24 +76,30 @@
 		{
 		return KErrNoMemory;
 		}
-
+	LOG_MSG2(" AttachProcess: < new DTargetProcess=0x%08x", tmpProcess );
+	
 	// Set the name
 	TInt err = KErrNone;
 	err = tmpProcess->SetProcessName(aProcessName);
 	if (err != KErrNone)
 		{
+		LOG_MSG2(" AttachProcess: < SetProcessName returned %d", err );
 		return err;
 		}
 
 	// Is this process being debugged (ie already attached?)
 	TInt index;
 	TBool found = EFalse;
-	for(index=0;index<iProcesses.Count();index++)
+	
+	TInt numberOfProcesses = iProcesses.Count();
+	for(index=0; index<numberOfProcesses; index++)
 		{
 		const TPtr8& tmpPtr8(iProcesses[index]->ProcessName() );
 
 		if ( tmpPtr8.CompareF(aProcessName) == 0)
 			{
+			LOG_MSG3(" Proc count=%d, found proc in iProcesses at %d. Count=%d",
+				index, iProcesses.Count() );
 			found = ETrue;
 			break;
 			}
@@ -104,6 +110,8 @@
 		// Yes, it is being debugged
 
 		// Add the agent to the list of agents for this process
+		LOG_MSG3(" > AddAgent(agent id %d) to existing iProcesses[%d]", I64LOW(aAgentId), index ); 
+
 		iProcesses[index]->AddAgent(aAgentId);
 
 		return KErrNone;
@@ -113,6 +121,8 @@
 		// No, it is not being debugged
 			
 		// Add the agent to the list of agents for this process
+		LOG_MSG2(" > AddAgent(agent %d) to new proc at index 0", I64LOW(aAgentId) ); 
+
 		tmpProcess->AddAgent(aAgentId);
 
 		// Add the process to the list of processes being debugged
@@ -143,7 +153,9 @@
 	TInt i;
 	TBool found = EFalse;
 	DTargetProcess* foundProcess = 0;
-	for(i=0;i<iProcesses.Count();i++)
+
+	TInt numberOfProcesses = iProcesses.Count();
+	for(i=0; i<numberOfProcesses; i++)
 		{
 		foundProcess = iProcesses[i];
 
@@ -186,7 +198,8 @@
 TInt DProcessTracker::DetachAgent(const TUint64 aAgentId)
 	{
 	// Remove this agent from all the processes being tracked.
-	for(TInt i=0;i<iProcesses.Count();i++)
+	TInt numberOfProcesses = iProcesses.Count();
+	for(TInt i=0; i<numberOfProcesses; i++)
 		{
 		// remove the agent from the process (we don't care about the return code)
 		iProcesses[i]->RemoveAgent(aAgentId);
@@ -226,13 +239,15 @@
 	if (aProcessName.Length() < 1 || aProcessName.Length() >= KMaxPath)
 		{
 		return 0;	// not found
-		};
+		}
 
 	// Can we find this in the array?
 	TInt i;
 	TBool found = EFalse;
 	DTargetProcess* foundProcess = 0;
-	for(i=0;i<iProcesses.Count();i++)
+
+	TInt numberOfProcesses = iProcesses.Count();
+	for(i=0; i<numberOfProcesses; i++)
 		{
 		foundProcess = iProcesses[i];
 
@@ -247,6 +262,7 @@
 
 	if (found == EFalse)
 		{
+		LOG_EVENT_MSG("DProcessTracker::FindProcess, not found" );
 		return 0;	// not found
 		}
 
@@ -272,73 +288,58 @@
  */
 DTargetProcess*	DProcessTracker::FuzzyFindProcess(const TDesC8& aProcessName)
 	{
-
 	// Valid ProcessName?
 	if (aProcessName.Length() < 1 || aProcessName.Length() >= KMaxPath)
 		{
 		return 0;	// not found
-		};
+		}
 
 	// Can we find this in the array?
-	TInt i;
 	TBool found = EFalse;
 	DTargetProcess* foundProcess = 0;
-	for(i=0;i<iProcesses.Count();i++)
+	const TChar KBackSlash('\\');
+
+	TInt numberOfProcesses = iProcesses.Count();
+	for(TInt i=0; i < numberOfProcesses; i++)
 		{
 		foundProcess = iProcesses[i];
 
-		const TPtr8& tmpPtr8( foundProcess->ProcessName() );
-
-		if ( tmpPtr8.CompareF(aProcessName) == 0)
+		TInt procListBackSlash = foundProcess->ProcessName().LocateReverse( KBackSlash );
+		if( procListBackSlash == KErrNotFound )
 			{
-			found = ETrue;
-			break;
+			procListBackSlash = 0;
 			}
 		else
 			{
-			// need to compare centre of this string
-			//
-			// e.g. 
-			//		z:\sys\bin\foobar.exe
-			// might be seen as:
-			//		foobar.exe
-			//
-			// Algorithm is start at the right side of foundProcess->ProcessName
-			// move left until we have some backslash, then finish.
-			TInt right= tmpPtr8.Size() - 1;
-			TInt left = right;
+			//Now move to the char after the backlash
+			procListBackSlash++;
+			}
+
+		TInt eventBackSlash = aProcessName.LocateReverse( KBackSlash );
+		if( eventBackSlash == KErrNotFound )
+			{
+			eventBackSlash = 0;
+			}
+		else
+			{
+			//Now move to the char after the backlash
+			eventBackSlash++;
+			}
 
-			// search for the rightmost backslash
-			while(left > 0)
-				{
-				if(tmpPtr8[left] == (TUint8)'\\')
-					break;
-				
-				--left;	// move left one character
-				}
-			// now we have
-			// left = index of rightmost backslash in foundProcess->ProcessName()
-			// right = index of rightmost character in foundProcess->ProcessName()
-
-			// We must expect that the size of names matches
-			TInt foundSize = right - left;	// == sizeof("foobar.exe")
-			TInt suppliedSize = aProcessName.Size();		
+		if( ( procListBackSlash == 0 ) && ( eventBackSlash == 0 ) )
+			{
+			//There were no backslashes on either name, so no point in continuing
+			break;
+			}
 
-			if (foundSize != suppliedSize)
-				{
-				// must be something else
-				break;
-				}
+		TPtrC8 eventCleanName( aProcessName.Mid( eventBackSlash ) );		
+		TPtrC8 procListCleanName( foundProcess->ProcessName().Mid( procListBackSlash ) );
 
-			for(TInt i=0;i< foundSize;i++)
-				{
-				if (tmpPtr8[left+i] != aProcessName[1+i])
-					{
-					break;
-					}
-				}
-			// All the characters match if we get here
+		if ( eventCleanName.CompareF( procListCleanName ) == 0 )
+			{
+			LOG_MSG2("DProcessTracker::FuzzyFindProcess() found a match : process list[%d]", i );
 			found = ETrue;
+			break;
 			}
 		}
 
@@ -360,7 +361,8 @@
 		}
 
 	//iterate through the processes trying to match the name, and check suspended if found
-	for(TInt i=0; i<iProcesses.Count(); i++)
+	TInt numberOfProcesses = iProcesses.Count();
+	for(TInt i=0; i < numberOfProcesses; i++)
 		{
 		if(iProcesses[i]->ProcessName().CompareF(*name) == 0)
 			{
@@ -407,7 +409,8 @@
 		}
 
 	//iterate through the processes trying to match the name, try to suspend the thread if found
-	for(TInt i=0; i<iProcesses.Count(); i++)
+	TInt numberOfProcesses = iProcesses.Count();
+	for(TInt i=0; i < numberOfProcesses; i++)
 		{
 		if(iProcesses[i]->ProcessName().CompareF(*name) == 0)
 			{
@@ -421,7 +424,8 @@
 
 void DProcessTracker::FSWait()
 	{
-	for(TInt i=0; i<iProcesses.Count(); i++)
+	TInt numberOfProcesses = iProcesses.Count();
+	for(TInt i=0; i < numberOfProcesses; i++)
 		{
 		iProcesses[i]->FSWait();
 		}
@@ -447,7 +451,8 @@
 		}
 
 	//iterate through the processes trying to match the name, try to resume the thread if found
-	for(TInt i=0; i<iProcesses.Count(); i++)
+	TInt numberOfProcesses = iProcesses.Count();
+	for(TInt i=0; i < numberOfProcesses; i++)
 		{
 		if(iProcesses[i]->ProcessName().CompareF(*name) == 0)
 			{
--- a/kernel/eka/drivers/debug/rmdebug/d_rmd_stepping.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/debug/rmdebug/d_rmd_stepping.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -46,15 +46,15 @@
 // DRMDStepping::~DRM_DebugChannel
 //
 DRMDStepping::~DRMDStepping()
-{
+	{
 	// to do
-}
+	}
 
 //
 // DRMDStepping::IsExecuted
 //
 TBool DRMDStepping::IsExecuted(TUint8 aCondition ,TUint32 aStatusRegister)
-{
+	{
 	LOG_MSG("DRMDStepping::IsExecuted()");
 
 	TBool N = ((aStatusRegister >> 28) & 0x0000000F) & 0x00000008;
@@ -63,7 +63,7 @@
 	TBool V = ((aStatusRegister >> 28) & 0x0000000F) & 0x00000001;
 
 	switch(aCondition)
-	{
+		{
 		case 0:
 			return Z;
 		case 1:
@@ -95,16 +95,16 @@
 		case 14:
 		case 15:
 			return ETrue;
-	}
+		}
 	
 	return EFalse;
-}
+	}
 
 //
 // DRMDStepping::IsPreviousInstructionMovePCToLR
 //
 TBool DRMDStepping::IsPreviousInstructionMovePCToLR(DThread *aThread)
-{
+	{
 	LOG_MSG("DRMDStepping::IsPreviousInstructionMovePCToLR()");
 
 	TInt err = KErrNone;
@@ -122,114 +122,114 @@
 	TUint32 address = 0;
 	err = iChannel->ReadKernelRegisterValue(aThread, PC_REGISTER, address);
 	if(err != KErrNone)
-	{
+		{
 		LOG_MSG2("Non-zero error code discarded: %d", err);
-	}
+		}
 	address -= 4;
 
 	TBuf8<4> previousInstruction;
 	err = iChannel->DoReadMemory(aThread, address, 4, previousInstruction);
 	if (KErrNone != err)
-	{
+		{
 		LOG_MSG2("Error %d reading memory at address %x", address);
 		return EFalse;
-	}
+		}
 
 	const TUint32 movePCToLRIgnoringCondition = 0x01A0E00F;
 
 	TUint32 inst = *(TUint32 *)previousInstruction.Ptr();
 	
 	if ((inst & 0x0FFFFFFF) == movePCToLRIgnoringCondition)
-	{
+		{
 		return ETrue;
-	}
+		}
 		
 	return EFalse;
-}
+	}
 
 //
 // DRMDStepping::DecodeDataProcessingInstruction
 //
 void DRMDStepping::DecodeDataProcessingInstruction(TUint8 aOpcode, TUint32 aOp1, TUint32 aOp2, TUint32 aStatusRegister, TUint32 &aBreakAddress)
-{
+	{
 	LOG_MSG("DRMDStepping::DecodeDataProcessingInstruction()");
 
 	switch(aOpcode)
-	{
+		{
 		case 0:
-		{
+			{
 			// AND
 			aBreakAddress = aOp1 & aOp2;
 			break;
-		}
+			}
 		case 1:
-		{
+			{
 			// EOR
 			aBreakAddress = aOp1 ^ aOp2;
 			break;
-		}
+			}
 		case 2:
-		{
+			{
 			// SUB
 			aBreakAddress = aOp1 - aOp2;
 			break;
-		}
+			}
 		case 3:
-		{
+			{
 			// RSB
 			aBreakAddress = aOp2 - aOp1;
 			break;
-		}
+			}
 		case 4:
-		{
+			{
 			// ADD
 			aBreakAddress = aOp1 + aOp2;
 			break;
-		}
+			}
 		case 5:
-		{
+			{
 			// ADC
 			aBreakAddress = aOp1 + aOp2 + (aStatusRegister & arm_carry_bit()) ? 1 : 0;
 			break;
-		}
+			}
 		case 6:
-		{
+			{
 			// SBC
 			aBreakAddress = aOp1 - aOp2 - (aStatusRegister & arm_carry_bit()) ? 0 : 1;
 			break;
-		}
+			}
 		case 7:
-		{
+			{
 			// RSC
 			aBreakAddress = aOp2 - aOp1 - (aStatusRegister & arm_carry_bit()) ? 0 : 1;
 			break;
-		}
+			}
 		case 12:
-		{
+			{
 			// ORR
 			aBreakAddress = aOp1 | aOp2;
 			break;
-		}
+			}
 		case 13:
-		{
+			{
 			// MOV
 			aBreakAddress = aOp2;
 			break;
-		}
+			}
 		case 14:
-		{
+			{
 			// BIC
 			aBreakAddress = aOp1 & ~aOp2;
 			break;
-		}
+			}
 		case 15:
-		{
+			{
 			// MVN
 			aBreakAddress = ~aOp2;
 			break;
+			}
 		}
 	}
-}
 
 //
 // DRMDStepping::CurrentInstruction
@@ -315,7 +315,7 @@
 // to remove obsolete parameters.
 //
 TUint32 DRMDStepping::PCAfterInstructionExecutes(DThread *aThread, TUint32 aCurrentPC, TUint32 aStatusRegister, TInt aInstSize, /*TBool aStepInto,*/ TUint32 &aNewRangeEnd, TBool &aChangingModes)
-{
+	{
 	LOG_MSG("DRMDStepping::PCAfterInstructionExecutes()");
 
 	// by default we will set the breakpoint at the next instruction
@@ -324,12 +324,12 @@
 	TInt err = KErrNone;
 
 	// determine the architecture
-    TUint32 cpuid;
-   	asm("mrc p15, 0, cpuid, c0, c0, 0 ");
+	TUint32 cpuid;
+	asm("mrc p15, 0, cpuid, c0, c0, 0 ");
 	LOG_MSG2("DRMDStepping::PCAfterInstructionExecutes() - cpuid = 0x%08x\n",cpuid);
 
-    cpuid >>= 8;
-    cpuid &= 0xFF;
+	cpuid >>= 8;
+	cpuid &= 0xFF;
 
 	// determine the architecture mode for the current instruction
 	TArchitectureMode mode = EArmMode;	// Default assumption is ARM 
@@ -345,9 +345,9 @@
 
 	// Decode instruction based on current CPU mode
 	switch(mode)
-	{
+		{
 		case Debug::EArmMode:
-		{
+			{
 			// Obtain the current instruction bit pattern
 			TUint32 inst;
 			ReturnIfError(CurrentInstruction(aThread,inst));
@@ -356,64 +356,64 @@
 
 			// check the conditions to see if this will actually get executed
 			if (IsExecuted(((inst>>28) & 0x0000000F), aStatusRegister)) 
-			{
+				{
 				switch(arm_opcode(inst)) // bits 27-25
-				{
+					{
 					case 0:
-					{
-						switch((inst & 0x00000010) >> 4) // bit 4
 						{
+						switch((inst & 0x00000010) >> 4) // bit 4
+							{
 							case 0:
-							{
+								{
 								switch((inst & 0x01800000) >> 23) // bits 24-23
-								{
+									{
 									case 2:
-									{
+										{
 										// move to/from status register.  pc updates not allowed
 										// or TST, TEQ, CMP, CMN which don't modify the PC
 										break;
-									}
+										}
 									default:
-									{
+										{
 										// Data processing immediate shift
 										if (arm_rd(inst) == PC_REGISTER)
-										{
+											{
 											TUint32 rn = aCurrentPC + 8;
 											if (arm_rn(inst) != PC_REGISTER) // bits 19-16
-											{
+												{
 												err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), rn);
 												if(err != KErrNone)
-												{
+													{
 													LOG_MSG2("Non-zero error code discarded: %d", err);
+													}
 												}
-											}
 
 											TUint32 shifter = ShiftedRegValue(aThread, inst, aCurrentPC, aStatusRegister);
 
 											DecodeDataProcessingInstruction(((inst & 0x01E00000) >> 21), rn, shifter, aStatusRegister, breakAddress);
+											}
+										break;
 										}
-										break;
 									}
+								break;
 								}
-								break;
-							}					
 							case 1:
-							{
+								{
 								switch((inst & 0x00000080) >> 7) // bit 7
-								{
-									case 0:
 									{
-										switch((inst & 0x01900000) >> 20) // bits 24-23 and bit 20
+									case 0:
 										{
+										switch((inst & 0x01900000) >> 20) // bits 24-23 and bit 20
+											{
 											case 0x10:
-											{
+												{
 												// from figure 3-3
 												switch((inst & 0x000000F0) >> 4) // bits 7-4
-												{
+													{
 													case 1:
-													{
+														{
 														if (((inst & 0x00400000) >> 22) == 0) // bit 22
-														{
+															{
 															// BX
 															// this is a strange case.  normally this is used in the epilogue to branch the the link
 															// register.  sometimes it is used to call a function, and the LR is stored in the previous
@@ -421,324 +421,319 @@
 															// we need to read the previous instruction to see what we should do
 															err = iChannel->ReadKernelRegisterValue(aThread, (inst & 0x0000000F), breakAddress);
 															if(err != KErrNone)
-															{
+																{
 																LOG_MSG2("Non-zero error code discarded: %d", err);
-															}
+																}
 
 															if ((breakAddress & 0x00000001) == 1)
-															{
+																{
 																aChangingModes = ETrue;
-															}
+																}
 
 															breakAddress &= 0xFFFFFFFE;
-														}
+															}
 														break;
-													}
+														}
 													case 3:
-													{
+														{
 														// BLX
-														{
+															{
 															err = iChannel->ReadKernelRegisterValue(aThread, (inst & 0x0000000F), breakAddress);
 															if(err != KErrNone)
-															{
+																{
 																LOG_MSG2("Non-zero error code discarded: %d", err);
-															}
+																}
 
 															if ((breakAddress & 0x00000001) == 1)
-															{
+																{
 																aChangingModes = ETrue;
-															}
+																}
 															
 															breakAddress &= 0xFFFFFFFE;
-														}
+															}
 														break;
-													}
+														}
 													default:
-													{
+														{
 														// either doesn't modify the PC or it is illegal to
 														break;
+														}
 													}
-												}
 												break;
-											}
+												}
 											default:
-											{
+												{
 												// Data processing register shift
 												if (((inst & 0x01800000) >> 23) == 2) // bits 24-23
-												{
+													{
 													// TST, TEQ, CMP, CMN don't modify the PC
-												}
+													}
 												else if (arm_rd(inst) == PC_REGISTER)
-												{
+													{
 													// destination register is the PC
 													TUint32 rn = aCurrentPC + 8;
 													if (arm_rn(inst) != PC_REGISTER) // bits 19-16
-													{
+														{
 														err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), rn);
 														if(err != KErrNone)
-														{
+															{
 															LOG_MSG2("Non-zero error code discarded: %d", err);
+															}
 														}
-													}
 													
 													TUint32 shifter = ShiftedRegValue(aThread, inst, aCurrentPC, aStatusRegister);
 													
 													DecodeDataProcessingInstruction(((inst & 0x01E00000) >> 21), rn, shifter, aStatusRegister, breakAddress);
-												}
+													}
 												break;
+												}
 											}
+										break;
 										}
-										break;
-									}
 									default:
-									{
+										{
 										// from figure 3-2, updates to the PC illegal
 										break;
+										}
 									}
-								}
 								break;
+								}
 							}
-						}
 						break;
-					}
+						}
 					case 1:
-					{
+						{
 						if (((inst & 0x01800000) >> 23) == 2) // bits 24-23
-						{
+							{
 							// cannot modify the PC
 							break;
-						}
+							}
 						else if (arm_rd(inst) == PC_REGISTER)
-						{
+							{
 							// destination register is the PC
 							TUint32 rn;
 							err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), rn); // bits 19-16
 							if(err != KErrNone)
-							{
+								{
 								LOG_MSG2("Non-zero error code discarded: %d", err);
-							}
+								}
 							TUint32 shifter = ((arm_data_imm(inst) >> arm_data_rot(inst)) | (arm_data_imm(inst) << (32 - arm_data_rot(inst)))) & 0xffffffff;
 
 							DecodeDataProcessingInstruction(((inst & 0x01E00000) >> 21), rn, shifter, aStatusRegister, breakAddress);
-						}
+							}
 						break;
-					}
+						}
 					case 2:
-					{
+						{
 						// load/store immediate offset
 						if (arm_load(inst)) // bit 20
-						{
+							{
 							// loading a register from memory
 							if (arm_rd(inst) == PC_REGISTER)
-							{
+								{
 								// loading the PC register
 								TUint32 base;
 								err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), base);
 								if(err != KErrNone)
-								{
+									{
 									LOG_MSG2("Non-zero error code discarded: %d", err);
-								}
+									}
 
 								/* Note: At runtime the PC would be 8 further on
 								 */
 								if (arm_rn(inst) == PC_REGISTER)
-								{
+									{
 									base = aCurrentPC + 8;
-								}
+									}
 
 								TUint32 offset = 0;
-					    		
-					    		if (arm_single_pre(inst))
-					    		{
-					    			// Pre-indexing
-					    			offset = arm_single_imm(inst);
-									
-									if (arm_single_u(inst))
+
+								if (arm_single_pre(inst))
 									{
-							    		base += offset;
-									}
+									// Pre-indexing
+									offset = arm_single_imm(inst);
+
+									if (arm_single_u(inst))
+										{
+										base += offset;
+										}
 									else
-									{
-							    		base -= offset;
+										{
+										base -= offset;
+										}
 									}
-								}
 
 								TBuf8<4> destination;
 								err = iChannel->DoReadMemory(aThread, base, 4, destination);
 								
 								if (KErrNone == err)
-								{
+									{
 									breakAddress = *(TUint32 *)destination.Ptr();
-								
+
 									if ((breakAddress & 0x00000001) == 1)
-									{
+										{
 										aChangingModes = ETrue;
-									}								
+										}
 									breakAddress &= 0xFFFFFFFE;
-								}
+									}
 								else
-								{
+									{
 									LOG_MSG("Error reading memory in decoding step instruction");
+									}
 								}
 							}
-						}	
 						break;
-					}
+						}
 					case 3:
-					{
+						{
 						if (((inst & 0xF0000000) != 0xF0000000) && ((inst & 0x00000010) == 0))
-						{
+							{
 							// load/store register offset
 							if (arm_load(inst)) // bit 20
-							{
+								{
 								// loading a register from memory
 								if (arm_rd(inst) == PC_REGISTER)
-								{
+									{
 									// loading the PC register
 									TUint32 base = 0;
 									if(arm_rn(inst) == PC_REGISTER)
-									{
+										{
 										base = aCurrentPC + 8;
-									}
+										}
 									else
-									{
+										{
 										err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), base);
 										if(err != KErrNone)
-										{
+											{
 											LOG_MSG2("Non-zero error code discarded: %d", err);
+											}
 										}
-									}
 
 									TUint32 offset = 0;
 
 									if (arm_single_pre(inst))
-									{
+										{
 										offset = ShiftedRegValue(aThread, inst, aCurrentPC, aStatusRegister);
 
 										if (arm_single_u(inst))
-										{
+											{
 											base += offset;
-										}
+											}
 										else
-										{
+											{
 											base -= offset;
+											}
 										}
-									}
 
 									TBuf8<4> destination;
 									err = iChannel->DoReadMemory(aThread, base, 4, destination);
 
 									if (KErrNone == err)
-									{
+										{
 										breakAddress = *(TUint32 *)destination.Ptr();
 
 										if ((breakAddress & 0x00000001) == 1)
-										{
+											{
 											aChangingModes = ETrue;
-										}								
+											}
 										breakAddress &= 0xFFFFFFFE;
-									}
+										}
 									else
-									{
+										{
 										LOG_MSG("Error reading memory in decoding step instruction");
+										}
 									}
 								}
-							}	
-						}
+							}
 						break;
-					}
+						}
 					case 4:
-					{
+						{
 						if ((inst & 0xF0000000) != 0xF0000000)
-						{
+							{
 							// load/store multiple
 							if (arm_load(inst)) // bit 20
-							{
+								{
 								// loading a register from memory
 								if (((inst & 0x00008000) >> 15))
-								{
+									{
 									// loading the PC register
 									TInt offset = 0;	
 									if (arm_block_u(inst))
-									{
+										{
 										TUint32 reglist = arm_block_reglist(inst);
 										offset = iChannel->Bitcount(reglist) * 4 - 4;
 										if (arm_block_pre(inst))
 											offset += 4;
-									}
+										}
 									else if (arm_block_pre(inst))
-									{
+										{
 										offset = -4;
-									}
-										
+										}
+
 									TUint32 temp = 0;
 									err = iChannel->ReadKernelRegisterValue(aThread, arm_rn(inst), temp);
 									if(err != KErrNone)
-									{
+										{
 										LOG_MSG2("Non-zero error code discarded: %d", err);
-									}
-									
+										}
+
 									temp += offset;
 
 									TBuf8<4> destination;
 									err = iChannel->DoReadMemory(aThread, temp, 4, destination);
-									
+
 									if (KErrNone == err)
-									{
+										{
 										breakAddress = *(TUint32 *)destination.Ptr();
 										if ((breakAddress & 0x00000001) == 1)
-										{
+											{
 											aChangingModes = ETrue;
-										}
+											}
 										breakAddress &= 0xFFFFFFFE;
-									}
+										}
 									else
-									{
+										{
 										LOG_MSG("Error reading memory in decoding step instruction");
+										}
 									}
 								}
-							}					
+							}
+						break;
 						}
-						break;
-					}
 					case 5:
-					{
+						{
 						if ((inst & 0xF0000000) == 0xF0000000)
-						{
+							{
 							// BLX
-							{
-								breakAddress = (TUint32)arm_instr_b_dest(inst, aCurrentPC);
+							breakAddress = (TUint32)arm_instr_b_dest(inst, aCurrentPC);
 
-								// Unconditionally change into Thumb mode
-								aChangingModes = ETrue;
-								
-								breakAddress &= 0xFFFFFFFE;
+							// Unconditionally change into Thumb mode
+							aChangingModes = ETrue;
+							breakAddress &= 0xFFFFFFFE;
 							}
-						}
 						else
-						{
+							{
 							if ((inst & 0x01000000)) // bit 24
-							{
+								{
 								// BL
-								{
 									breakAddress = (TUint32)arm_instr_b_dest(inst, aCurrentPC);
 								}
-							}
 							else
-							{
+								{
 								// B
 								breakAddress = (TUint32)arm_instr_b_dest(inst, aCurrentPC);
+								}
 							}
-						}
 						break;
-					}
-				}	
-			}
-		}
+						} // case 5
+					} //switch(arm_opcode(inst)) // bits 27-25
+				} // if (IsExecuted(((inst>>28) & 0x0000000F), aStatusRegister)) 
+			} // case Debug::EArmMode:
 		break;
 
 		case Debug::EThumbMode:
-		{
+			{
 			// Thumb Mode
 			//
 			// Notes: This now includes the extra code
@@ -758,22 +753,21 @@
 
 			// v6T2 instructions
 
-// Note: v6T2 decoding is only enabled for DEBUG builds or if using an
-// an ARM_V6T2 supporting build system. At the time of writing, no
-// ARM_V6T2 supporting build system exists, so the stepping code cannot
-// be said to be known to work. Hence it is not run for release builds
+			// Note: v6T2 decoding is only enabled for DEBUG builds or if using an
+			// an ARM_V6T2 supporting build system. At the time of writing, no
+			// ARM_V6T2 supporting build system exists, so the stepping code cannot
+			// be said to be known to work. Hence it is not run for release builds
 
 			TBool use_v6t2_decodings = EFalse;
 
 #if defined(DEBUG) || defined(__ARMV6T2__)
 			use_v6t2_decodings = ETrue;
-
 #endif
 			// coverity[dead_error_line]
 			if (use_v6t2_decodings)
-			{
+				{
 				// 16-bit encodings
-	 
+
 				// A6.2.5 Misc 16-bit instructions
 				// DONE Compare and branch on zero (page A8-66)
 				// If then hints
@@ -782,7 +776,7 @@
 				//
 				// Compare and branch on Nonzero and Compare and Branch on Zero.
 				if ((inst & 0xF500) == 0xB100)
-				{
+					{
 					LOG_MSG("ARM ARM DDI0406A - section A8.6.27 CBNZ, CBZ");
 
 					// Decoding as per ARM ARM description
@@ -821,7 +815,7 @@
 				//
 				// If Then instruction
 				if ((inst & 0xFF00) == 0xBF00)
-				{
+					{
 					LOG_MSG("ARM ARM DDI0406A - section A8.6.50 IT");
 
 					// Decoding as per ARM ARM description
@@ -829,18 +823,18 @@
 					TUint32 mask = inst & 0x000F;
 
 					if (firstcond == 0xF)
-					{
+						{
 						// unpredictable
 						LOG_MSG("ARM ARM DDI0406A - section A8.6.50 IT - Unpredictable");
 						break;
-					}
+						}
 
 					if ((firstcond == 0xE) && (BitCount(mask) != 1))
-					{
+						{
 						// unpredictable
 						LOG_MSG("ARM ARM DDI0406A - section A8.6.50 IT - Unpredictable");
 						break;
-					}
+						}
 
 					// should check if 'in-it-block'
 					LOG_MSG("Cannot step IT instructions.");
@@ -861,7 +855,7 @@
 					// perhaps we can just totally ignore this state, and always do the two-instruction
 					// breakpoint thing? Not if there is any possibility that the address target
 					// would be invalid for the non-taken branch address...
-				}
+					}
 
 
 				// 32-bit encodings.
@@ -873,12 +867,12 @@
 
 				// ARM ARM DDI0406A - section A8.6.26
 				if (inst32 & 0xFFF0FFFF == 0xE3C08F00)
-				{
+					{
 					LOG_MSG("ARM ARM DDI0406A - section A8.6.26 - BXJ is not supported");
 
 					// Decoding as per ARM ARM description
 					// TUint32 Rm = inst32 & 0x000F0000;	// not needed yet
-				}
+					}
 
 				// return from exception... SUBS PC,LR. page b6-25
 				//
@@ -886,7 +880,7 @@
 				//
 				// Encoding T1
 				if (inst32 & 0xFFFFFF00 == 0xF3DE8F00)
-				{
+					{
 					LOG_MSG("ARM ARM DDI0406A - section B6.1.13 - SUBS PC,LR Encoding T1");
 
 					// Decoding as per ARM ARM description
@@ -906,13 +900,13 @@
 					TUint32 result = lrVal - operand2;
 					
 					breakAddress = result;
-				}
-				
+					}
+
 				// ARM ARM DDI0406A - section A8.6.16 - B
 				//
 				// Branch Encoding T3
 				if (inst32 & 0xF800D000 == 0xF0008000)
-				{
+					{
 					LOG_MSG("ARM ARM DDI0406A - section A8.6.16 - B Encoding T3");
 
 					// Decoding as per ARM ARM description
@@ -931,13 +925,13 @@
 					imm32 = (imm32 << 1) | 0;
 
 					breakAddress = aCurrentPC + imm32;
-				}
+					}
 
 				// ARM ARM DDI0406A - section A8.6.16 - B
 				//
 				// Branch Encoding T4
 				if (inst32 & 0xF800D000 == 0xF0009000)
-				{
+					{
 					LOG_MSG("ARM ARM DDI0406A - section A8.6.16 - B");
 
 					// Decoding as per ARM ARM description
@@ -959,14 +953,14 @@
 					imm32 = (imm32 << 1) | 0;
 
 					breakAddress = aCurrentPC + imm32;
-				}
+					}
 
 
 				// ARM ARM DDI0406A - section A8.6.225 - TBB, TBH
 				//
 				// Table Branch Byte, Table Branch Halfword
 				if (inst32 & 0xFFF0FFE0 == 0xE8D0F000)
-				{
+						{
 					LOG_MSG("ARM ARM DDI0406A - section A8.6.225 TBB,TBH Encoding T1");
 
 					// Decoding as per ARM ARM description
@@ -976,10 +970,10 @@
 
 					// Unpredictable?
 					if (Rm == 13 || Rm == 15)
-					{
+						{
 						LOG_MSG("ARM ARM DDI0406A - section A8.6.225 TBB,TBH Encoding T1 - Unpredictable");
 						break;
-					}
+						}
 
 					TUint32 halfwords;
 					TUint32 address;
@@ -989,26 +983,25 @@
 					ReturnIfError(RegisterValue(aThread,Rm,offset));
 
 					if (H)
-					{
-
+						{
 						address += offset << 1;
-					}
+						}
 					else
-					{
+						{
 						address += offset;
-					}
+						}
 
 					ReturnIfError(ReadMem32(aThread,address,halfwords));
 
 					breakAddress = aCurrentPC + 2*halfwords;
 					break;
-				}
+					}
 
 				// ARM ARM DDI0406A - section A8.6.55 - LDMDB, LDMEA
 				//
 				// LDMDB Encoding T1
 				if (inst32 & 0xFFD02000 == 0xE9100000)
-				{
+					{
 					LOG_MSG("ARM ARM DDI0406 - section A8.6.55 LDMDB Encoding T1");
 
 					// Decoding as per ARM ARM description
@@ -1022,10 +1015,10 @@
 
 					// Unpredictable?
 					if (Rn == 15 || BitCount(registers) < 2 || ((P == 1) && (M==1)))
-					{
+						{
 						LOG_MSG("ARM ARM DDI0406 - section A8.6.55 LDMDB Encoding T1 - Unpredictable");
 						break;
-					}
+						}
 
 					TUint32 address;
 					ReturnIfError(RegisterValue(aThread,Rn,address));
@@ -1033,28 +1026,28 @@
 					address -= 4*BitCount(registers);
 
 					for(TInt i=0; i<15; i++)
-					{
+						{
 						if (IsBitSet(registers,i))
-						{
+							{
 							address +=4;
+							}
 						}
-					}
 
 					if (IsBitSet(registers,15))
-					{
+						{
 						TUint32 RnVal = 0;
 						ReturnIfError(ReadMem32(aThread,address,RnVal));
 
 						breakAddress = RnVal;
-					}
+						}
 					break;
-				}
+					}
 
 				// ARM ARM DDI0406A - section A8.6.121 POP
 				//
 				// POP.W Encoding T2
 				if (inst32 & 0xFFFF2000 == 0xE8BD0000)
-				{
+					{
 					LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T2");
 
 					// Decoding as per ARM ARM description
@@ -1064,33 +1057,33 @@
 
 					// Unpredictable?
 					if ( (BitCount(registers)<2) || ((P == 1)&&(M == 1)) )
-					{
+						{
 						LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T2 - Unpredictable");
 						break;
-					}
+						}
 
 					TUint32 address;
 					ReturnIfError(RegisterValue(aThread,13,address));
 					
 					for(TInt i=0; i< 15; i++)
-					{
+						{
 						if (IsBitSet(registers,i))
-						{
+							{
 							address += 4;
+							}
 						}
-					}
 
 					// Is the PC written?
 					if (IsBitSet(registers,15))
-					{
+						{
 						// Yes
 						ReturnIfError(ReadMem32(aThread,address,breakAddress));
+						}
 					}
-				}
 
 				// POP Encoding T3
 				if (inst32 & 0xFFFF0FFFF == 0xF85D0B04)
-				{
+					{
 					LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T3");
 
 					// Decoding as per ARM ARM description
@@ -1099,37 +1092,37 @@
 
 					// Unpredictable?
 					if (Rt == 13 || Rt == 15)
-					{
+						{
 						LOG_MSG("ARM ARM DDI0406A - section A8.6.121 POP Encoding T3 - Unpredictable");
 						break;
-					}
+						}
 					
 					TUint32 address;
 					ReturnIfError(RegisterValue(aThread,13,address));
 					
 					for(TInt i=0; i< 15; i++)
-					{
+						{
 						if (IsBitSet(registers,i))
-						{
+							{
 							address += 4;
+							}
 						}
-					}
 
 					// Is the PC written?
 					if (IsBitSet(registers,15))
-					{
+						{
 						// Yes
 						ReturnIfError(ReadMem32(aThread,address,breakAddress));
-					}
+						}
 
 					break;
-				}
+					}
 
 				// ARM ARM DDI0406A - section A8.6.53 LDM
 				//
 				// Load Multiple Encoding T2 
 				if ((inst32 & 0xFFD02000) == 0xE8900000)
-				{
+					{
 					LOG_MSG("ARM ARM DDI0406A - section A8.6.53 LDM Encoding T2");
 
 					// Decoding as per ARM ARM description
@@ -1142,17 +1135,17 @@
 				
 					// POP?
 					if ( (W == 1) && (Rn == 13) )
-					{
+						{
 						// POP instruction
 						LOG_MSG("ARM ARM DDI0406A - section A8.6.53 LDM Encoding T2 - POP");
-					}
+						}
 
 					// Unpredictable?
 					if (Rn == 15 || BitCount(register_list) < 2 || ((P == 1) && (M == 1)) )
-					{
+						{
 						LOG_MSG("ARM ARM DDI0406A - section A8.6.53 LDM Encoding T2 - Unpredictable");
 						break;
-					}
+						}
 					
 					TUint32 RnVal;
 					ReturnIfError(RegisterValue(aThread,Rn,RnVal));
@@ -1161,28 +1154,28 @@
 
 					// Calculate offset of address
 					for(TInt i = 0; i < 15; i++)
-					{
+						{
 						if (IsBitSet(registers,i))
 						{
 							address += 4;
 						}
-					}
+						}
 
 					// Does it load the PC?
 					if (IsBitSet(registers,15))
-					{
+						{
 						// Obtain the value loaded into the PC
 						ReturnIfError(ReadMem32(aThread,address,breakAddress));
-					}
+						}
 					break;
 
-				}
+					}
 
 				// ARM ARM DDI0406A - section B6.1.8 RFE
 				//
 				// Return From Exception Encoding T1 RFEDB
 				if ((inst32 & 0xFFD0FFFF) == 0xE810C000)
-				{
+					{
 					LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding T1");
 
 					// Decoding as per ARM ARM description
@@ -1195,11 +1188,11 @@
 
 					// Do calculation
 					if (Rn == 15)
-					{
+						{
 						// Unpredictable 
 						LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding T1 - Unpredictable");
 						break;
-					}
+						}
 
 					TUint32 RnVal = 0;
 					ReturnIfError(RegisterValue(aThread,Rn,RnVal));
@@ -1208,22 +1201,22 @@
 					ReturnIfError(ReadMem32(aThread,RnVal,address));
 
 					if (increment)
-					{
+						{
 						address -= 8;
-					}
+						}
 
 					if (wordhigher)
-					{
+						{
 						address += 4;
-					}				
+						}
 
 					breakAddress = address;
 					break;
-				}
+					}
 
 				// Return From Exception Encoding T2 RFEIA
 				if ((inst32 & 0xFFD0FFFF) == 0xE990C000)
-				{
+					{
 					LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding T2");
 
 					// Decoding as per ARM ARM description
@@ -1236,11 +1229,11 @@
 
 					// Do calculation
 					if (Rn == 15)
-					{
+						{
 						// Unpredictable 
 						LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding T2 - Unpredictable");
 						break;
-					}
+						}
 
 					TUint32 RnVal = 0;
 					ReturnIfError(RegisterValue(aThread,Rn,RnVal));
@@ -1249,22 +1242,22 @@
 					ReturnIfError(ReadMem32(aThread,RnVal,address));
 
 					if (increment)
-					{
+						{
 						address -= 8;
-					}
+						}
 
 					if (wordhigher)
-					{
+						{
 						address += 4;
-					}				
+						}
 
 					breakAddress = RnVal;
 					break;
-				}
+					}
 
 				// Return From Exception Encoding A1 RFE<amode>
 				if ((inst32 & 0xFE50FFFF) == 0xF8100A00)
-				{
+					{
 					LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding A1");
 
 					// Decoding as per ARM ARM description
@@ -1279,11 +1272,11 @@
 
 					// Do calculation
 					if (Rn == 15)
-					{
+						{
 						// Unpredictable 
 						LOG_MSG("ARM ARM DDI0406A - section B6.1.8 RFE Encoding A1 - Unpredictable");
 						break;
-					}
+						}
 
 					TUint32 RnVal = 0;
 					ReturnIfError(RegisterValue(aThread,Rn,RnVal));
@@ -1292,94 +1285,94 @@
 					ReturnIfError(ReadMem32(aThread,RnVal,address));
 
 					if (increment)
-					{
+						{
 						address -= 8;
-					}
+						}
 
 					if (wordhigher)
-					{
+						{
 						address += 4;
-					}				
+						}
 
 					breakAddress = address;
 					break;
+					}
 				}
-			}
 
 			// v4T/v5T/v6T instructions
 			switch(thumb_opcode(inst))
-			{		
+				{
 				case 0x08:
-				{
+					{
 					// Data-processing. See ARM ARM DDI0406A, section A6-8, A6.2.2.
 
 					if ((thumb_inst_7_15(inst) == 0x08F))
-					{
+						{
 						// BLX(2)
 						err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress);
 						if(err != KErrNone)
-						{
+							{
 							LOG_MSG2("Non-zero error code discarded: %d", err);
-						}
+							}
 
 						if ((breakAddress & 0x00000001) == 0)
-						{
+							{
 							aChangingModes = ETrue;
-						}
-						
+							}
+
 						breakAddress &= 0xFFFFFFFE;
 
 						// Report how we decoded this instruction
 						LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BLX (2)");
-					}
+						}
 					else if (thumb_inst_7_15(inst) == 0x08E)
-					{
+						{
 						// BX
 						err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress);
 						if(err != KErrNone)
-						{
+							{
 							LOG_MSG2("Non-zero error code discarded: %d", err);
-						}
+							}
 
 						if ((breakAddress & 0x00000001) == 0)
-						{
+							{
 							aChangingModes = ETrue;
-						}
+							}
 						
 						breakAddress &= 0xFFFFFFFE;
 
 						// Report how we decoded this instruction
 						LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BX");
-					}
+						}
 					else if ((thumb_inst_8_15(inst) == 0x46) && ((inst & 0x87) == 0x87))
-					{
+						{
 						// MOV with PC as the destination
 						err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress);
 						if(err != KErrNone)
-						{
+							{
 							LOG_MSG2("Non-zero error code discarded: %d", err);
-						}
+							}
 
 						// Report how we decoded this instruction
 						LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as MOV with PC as the destination");
-					}
+						}
 					else if ((thumb_inst_8_15(inst) == 0x44) && ((inst & 0x87) == 0x87))
-					{
+						{
 						// ADD with PC as the destination
 						err = iChannel->ReadKernelRegisterValue(aThread, ((inst & 0x0078) >> 3), breakAddress);
 						if(err != KErrNone)
-						{
+							{
 							LOG_MSG2("Non-zero error code discarded: %d", err);
-						}
+							}
 						breakAddress += aCurrentPC + 4; // +4 because we need to use the PC+4 according to ARM ARM DDI0406A, section A6.1.2.
 
 						// Report how we decoded this instruction
 						LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as ADD with PC as the destination");
-					}
+						}
 					break;
-				}
+					}
 				case 0x13:
-				{
+					{
 					// Load/Store single data item. See ARM ARM DDI0406A, section A6-10
 
 					//This instruction doesn't modify the PC.
@@ -1393,81 +1386,81 @@
 					// Report how we decoded this instruction
 					LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as This instruction doesn't modify the PC.");
 					break;
-				}
+					}
 				case 0x17:
-				{	
+					{
 					// Misc 16-bit instruction. See ARM ARM DDI0406A, section A6-11
 
 					if (thumb_inst_8_15(inst) == 0xBD)
-					{
+						{
 						// POP with the PC in the list
 						TUint32 regList = (inst & 0x00FF);
 						TInt offset = 0;
 						err = iChannel->ReadKernelRegisterValue(aThread,  SP_REGISTER, (T4ByteRegisterValue&)offset);
 						if(err != KErrNone)
-						{
+							{
 							LOG_MSG2("Non-zero error code discarded: %d", err);
-						}
+							}
 						offset += (iChannel->Bitcount(regList) * 4);
 
 						TBuf8<4> destination;
 						err = iChannel->DoReadMemory(aThread, offset, 4, destination);
 						
 						if (KErrNone == err)
-						{
+							{
 							breakAddress = *(TUint32 *)destination.Ptr();
 
 							if ((breakAddress & 0x00000001) == 0)
-							{
+								{
 								aChangingModes = ETrue;
-							}
+								}
 
 							breakAddress &= 0xFFFFFFFE;
-						}
+							}
 						else
-						{
+							{
 							LOG_MSG("Error reading memory in decoding step instruction");
-						}
+							}
 
 						// Report how we decoded this instruction
 						LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as POP with the PC in the list");
-					}
+						}
 					break;
-				}
+					}
 				case 0x1A:
 				case 0x1B:
-				{	
+					{
 					// Conditional branch, and supervisor call. See ARM ARM DDI0406A, section A6-13
 
 					if (thumb_inst_8_15(inst) < 0xDE)
-					{
+						{
 						// B(1) conditional branch
 						if (IsExecuted(((inst & 0x0F00) >> 8), aStatusRegister))
-						{
+							{
 							TUint32 offset = ((inst & 0x000000FF) << 1);
 							if (offset & 0x00000100)
-							{
+								{
 								offset |= 0xFFFFFF00;
-							}
+								}
 							
 							breakAddress = aCurrentPC + 4 + offset;
 
 							// Report how we decoded this instruction
 							LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as B(1) conditional branch");
+							}
 						}
-					}
 					break;
-				}
+					}
 				case 0x1C:
-				{
+					{
 					// Unconditional branch, See ARM ARM DDI0406A, section A8-44.
 
 					// B(2) unconditional branch
 					TUint32 offset = (inst & 0x000007FF) << 1;
 					if (offset & 0x00000800)
-					{
+						{
 						offset |= 0xFFFFF800;
-					}
+						}
 					
 					breakAddress = aCurrentPC + 4 + offset;
 
@@ -1475,114 +1468,111 @@
 					LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as B(2) unconditional branch");
 
 					break;
-				}
+					}
 				case 0x1D:
-				{
+					{
 					if (!(inst & 0x0001))
-					{
+						{
 						// BLX(1)
 						err = iChannel->ReadKernelRegisterValue(aThread, LINK_REGISTER, breakAddress);
 						if(err != KErrNone)
-						{
+							{
 							LOG_MSG2("Non-zero error code discarded: %d", err);
-						}
+							}
 						breakAddress +=  ((inst & 0x07FF) << 1);
 						if ((breakAddress & 0x00000001) == 0)
-						{
+							{
 							aChangingModes = ETrue;
-						}
+							}
 
 						breakAddress &= 0xFFFFFFFC;
 
 						// Report how we decoded this instruction
 						LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BLX(1)");
 
-					}
+						}
 					break;
-				}
+					}
 				case 0x1E:
-				{
-                    // Check for ARMv7 CPU
-                    if(cpuid == 0xC0)
-                    {
-    					// BL/BLX 32-bit instruction
-	    				aNewRangeEnd += 4;
+					{
+					// Check for ARMv7 CPU
+					if(cpuid == 0xC0)
+						{
+						// BL/BLX 32-bit instruction
+						aNewRangeEnd += 4;
 
 						breakAddress = (TUint32)thumb_instr_b_dest(inst32, aCurrentPC);
 
-            			if((inst32 >> 27) == 0x1D)
-            			{
-            			    // BLX(1)
-    						if ((breakAddress & 0x00000001) == 0)
-	    					{
-		    					aChangingModes = ETrue;
-			    			}
-    
-	    					breakAddress &= 0xFFFFFFFC;
+						if((inst32 >> 27) == 0x1D)
+							{
+							// BLX(1)
+							if ((breakAddress & 0x00000001) == 0)
+								{
+								aChangingModes = ETrue;
+								}
+
+							breakAddress &= 0xFFFFFFFC;
 
-    						// Report how we decoded this instruction
-	    					LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as 32-bit BLX(1)");
-                        }
-                        else
-                        {                            
-    					    // Report how we decoded this instruction
-	        				LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: 32-bit BL instruction");
-                        }
-        				LOG_MSG2(" 32-bit BL/BLX instruction: breakAddress = 0x%X", breakAddress);
-                    }            
-                    else
-                    {
-					    // BL/BLX prefix - destination is encoded in this and the next instruction
-					    aNewRangeEnd += 2;
+							// Report how we decoded this instruction
+							LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as 32-bit BLX(1)");
+							}
+						else
+							{
+							// Report how we decoded this instruction
+							LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: 32-bit BL instruction");
+							}
+						LOG_MSG2(" 32-bit BL/BLX instruction: breakAddress = 0x%X", breakAddress);
+						} // if(cpuid == 0xC0)
+					else
+						{
+						// BL/BLX prefix - destination is encoded in this and the next instruction
+						aNewRangeEnd += 2;
 
-					    // Report how we decoded this instruction
-					    LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: BL/BLX prefix - destination is encoded in this and the next instruction");
-                    }
-
+						// Report how we decoded this instruction
+						LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: BL/BLX prefix - destination is encoded in this and the next instruction");
+						}
 
 					break;
-				}
+					}
 				case 0x1F:
-				{
 					{
-						// BL
-						err = iChannel->ReadKernelRegisterValue(aThread, LINK_REGISTER, breakAddress);
-						if(err != KErrNone)
+					// BL
+					err = iChannel->ReadKernelRegisterValue(aThread, LINK_REGISTER, breakAddress);
+					if(err != KErrNone)
 						{
-							LOG_MSG2("Non-zero error code discarded: %d", err);
+						LOG_MSG2("Non-zero error code discarded: %d", err);
 						}
-						breakAddress += ((inst & 0x07FF) << 1);
+					breakAddress += ((inst & 0x07FF) << 1);
 
-						// Report how we decoded this instruction
-						LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BL");
+					// Report how we decoded this instruction
+					LOG_MSG("DRMDStepping::PCAfterInstructionExecutes: Decoded as BL");
+					break;
+					}
+				default:
+					{
+					// Don't know any better at this point!
+					LOG_MSG("DRMDStepping::PCAfterInstructionExecutes:- default to next instruction");
 					}
 					break;
-				}
-				default:
-					{
-						// Don't know any better at this point!
-						LOG_MSG("DRMDStepping::PCAfterInstructionExecutes:- default to next instruction");
-					}
-					break;
-			}
-		}
+				} // switch(thumb_opcode(inst))
+			} // case Debug::EThumbMode:
 		break;
-		
+
 		case Debug::EThumb2EEMode:
-		{
+			{
 			// Not yet supported
 			LOG_MSG("DRMDStepping::PCAfterInstructionExecutes - Debug::EThumb2Mode is not supported");
 
-		}
-		break;
+			}
+			break;
 
 		default:
 			LOG_MSG("DRMDStepping::PCAfterInstructionExecutes - Cannot determine CPU mode architecture");
-	}	
+		} // switch(mode)
 
 	LOG_MSG2("DRMDStepping::PCAfterInstructionExecutes : return 0x%08x",breakAddress);
 	return breakAddress;
-}
+	}
 
 // Obtain a 32-bit memory value with minimum fuss
 TInt DRMDStepping::ReadMem32(DThread* aThread, const TUint32 aAddress, TUint32& aValue)
@@ -1646,7 +1636,7 @@
 
 // Encodings from ARM ARM DDI0406A, section 9.2.1
 enum TThumb2EEOpcode
-{
+	{
 	EThumb2HDP,		// Handler Branch with Parameter
 	EThumb2UNDEF,	// UNDEFINED
 	EThumb2HB,		// Handler Branch, Handler Branch with Link
@@ -1656,76 +1646,76 @@
 	EThumb2LDRL,	// Load Register from a literal pool
 	EThumb2LDRA,	// Load Register (array operations)
 	EThumb2STR		// Store Register to a frame
-};
+	};
 
 //
 // DRMDStepping::ShiftedRegValue
 //
 TUint32 DRMDStepping::ShiftedRegValue(DThread *aThread, TUint32 aInstruction, TUint32 aCurrentPC, TUint32 aStatusRegister)
-{
-	LOG_MSG("DRM_DebugChannel::ShiftedRegValue()");
+	{
+	LOG_MSG("DRMDStepping::ShiftedRegValue()");
 
 	TUint32 shift = 0;
 	if (aInstruction & 0x10)	// bit 4
-	{
+		{
 		shift = (arm_rs(aInstruction) == PC_REGISTER ? aCurrentPC + 8 : aStatusRegister) & 0xFF;
-	}
+		}
 	else
-	{
+		{
 		shift = arm_data_c(aInstruction);
-	}
+		}
 	
 	TInt rm = arm_rm(aInstruction);
 	
 	TUint32 res = 0;
 	if(rm == PC_REGISTER)
-	{
+		{
 		res = aCurrentPC + ((aInstruction & 0x10) ? 12 : 8);
-	}
+		}
 	else
-	{
+		{
 		TInt err = iChannel->ReadKernelRegisterValue(aThread, rm, res);
 		if(err != KErrNone)
-		{
+			{
 			LOG_MSG2("DRMDStepping::ShiftedRegValue - Non-zero error code discarded: %d", err);
+			}
 		}
-	}
 
 	switch(arm_data_shift(aInstruction))
-	{
+		{
 		case 0:			// LSL
-		{
+			{
 			res = shift >= 32 ? 0 : res << shift;
 			break;
-		}
+			}
 		case 1:			// LSR
-		{
+			{
 			res = shift >= 32 ? 0 : res >> shift;
 			break;
-		}
+			}
 		case 2:			// ASR
-		{
+			{
 			if (shift >= 32)
 			shift = 31;
 			res = ((res & 0x80000000L) ? ~((~res) >> shift) : res >> shift);
 			break;
-		}
+			}
 		case 3:			// ROR/RRX
-		{
+			{
 			shift &= 31;
 			if (shift == 0)
-			{
+				{
 				res = (res >> 1) | ((aStatusRegister & arm_carry_bit()) ? 0x80000000L : 0);
-			}
+				}
 			else
-			{
+				{
 				res = (res >> shift) | (res << (32 - shift));
-			}
+				}
 			break;
-    	}
-    }
+			}
+		}
 
-  	return res & 0xFFFFFFFF;
+	return res & 0xFFFFFFFF;
 }
 
 //
--- a/kernel/eka/drivers/debug/rmdebug/d_target_process.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/debug/rmdebug/d_target_process.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -16,7 +16,7 @@
 // each process being debugged.
 // Note: Although TheDProcessTracker object is a global, it should be unique
 // as only the Debug Security Server should load and use this driver.
-// 
+//
 //
 
 #include <e32def.h>
@@ -101,12 +101,12 @@
 DDebugAgent* DTargetProcess::Agent(TUint64 aAgentId)
 	{
 	for(TInt i = 0; i < iAgentList.Count(); i++)
-	{
+		{
 		if (iAgentList[i]->Id() == aAgentId)
-		{
+			{
 			return iAgentList[i];
+			}
 		}
-	}
 
 	// what do we return if we don't have any agents?
 	return NULL;
@@ -115,8 +115,11 @@
 // Adds aAgentId as a tracking agent for this process.
 TInt DTargetProcess::AddAgent(TUint64 aAgentId)
 	{
-	LOG_MSG("DTargetProcess::AddAgent()");
+	
 	DDebugAgent* agent = DDebugAgent::New(aAgentId);
+	LOG_MSG4("DTargetProcess::AddAgent(), agentId=%d, curr iAgentList.Count=%d, new agent=0x%08x",
+		I64LOW(aAgentId), iAgentList.Count(), agent );
+
 	if(agent == NULL)
 		{
 		LOG_MSG("DTargetProcess::AddAgent() couldn't allocate memory for DDebugAgent");
@@ -172,19 +175,19 @@
 	//if resuming the suspended thread failed for an obscure reason return it
 	if((err1 != KErrNotFound) && (err1 != KErrNone))
 		{
-		LOG_MSG2("DTargetProcess::ResumeThread() unexpected exit, err1: %d", err1);
+		LOG_MSG2("DTargetProcess::ResumeThread() BUG : unexpected exit, err1: %d", err1);
 		return err1;
 		}
 	//if resuming the frozen thread failed for an obscure reason return it
 	if((err2 != KErrNotFound) && (err2 != KErrNone))
 		{
-		LOG_MSG2("DTargetProcess::ResumeThread() unexpected exit, err2: %d", err2);
+		LOG_MSG2("DTargetProcess::ResumeThread() BUG : unexpected exit, err2: %d", err2);
 		return err2;
 		}
 	// if resuming the suspended thread succeeded in both cases, we have a consistency problem
 	if ((err1 == KErrNone) && (err2 == KErrNone))
 		{
-		LOG_MSG("DTargetProcess::ResumeThread() unexpected exit, err1 == err2 == KErrNone");
+		LOG_MSG("DTargetProcess::ResumeThread() BUG : unexpected exit, err1 == err2 == KErrNone");
 		}
 
 	//if the thread was in neither list return KErrNotFound, otherwise KErrNone
@@ -232,7 +235,7 @@
 		if(iSuspendedThreads[i] == threadId)
 			{
 			iSuspendedThreads.Remove(i);
-			LOG_MSG2("DTargetProcess::ResumeSuspendedThread()> Kern::ThreadResume() 0x%x", aThread);
+			LOG_MSG2("DTargetProcess::ResumeSuspendedThread()> Kern::ThreadResume() 0x%08x", aThread);
 			Kern::ThreadResume(*aThread);
 			return KErrNone;
 			}
@@ -292,7 +295,8 @@
 	NFastSemaphore* sem = new NFastSemaphore();
 	NKern::ThreadLeaveCS();
 	sem->iOwningThread = &(Kern::CurrentThread().iNThread);
-	LOG_EVENT_MSG2("DTargetProcess::FreezeThread(): new NFastSemaphore() curr thread=0x%x", sem->iOwningThread);
+	LOG_MSG3("DTargetProcess::FreezeThread(): new NFastSemaphore() owning thread==curr NThread=0x%08x, DThread=0x%08x", 
+		sem->iOwningThread, &(Kern::CurrentThread()) );
 	return iFrozenThreadSemaphores.Append(sem);
 	}
 
@@ -322,6 +326,7 @@
 	TInt err = iSuspendedThreads.Append(threadId);
 	if(err == KErrNone)
 		{
+		LOG_MSG2("DTargetProcess::DoSuspendThread >Kern::ThreadSuspend() 0x%08x", aThread ); 
 		Kern::ThreadSuspend(*aThread, 1);
 		}
 	return err;
@@ -341,13 +346,13 @@
  */
 void DTargetProcess::FSWait()
 	{
-	LOG_MSG2("DTargetProcess::NotifyEvent(): number of attached agents: %d", AgentCount());
-	NThread* currentThread = &(Kern::CurrentThread().iNThread);
+	NThread* currentNThread = &(Kern::CurrentThread().iNThread);	
 	for(TInt i=0; i<iFrozenThreadSemaphores.Count(); i++)
 		{
-		if(iFrozenThreadSemaphores[i]->iOwningThread == currentThread)
+		if(iFrozenThreadSemaphores[i]->iOwningThread == currentNThread)
 			{
-			LOG_MSG3("DTargetProcess::FSWait(): > FSWait frozen sem %d, curr thread=0x%x", i, currentThread);
+			LOG_MSG4("DTargetProcess::FSWait(): > FSWait frozen sem %d, currentNThread=0x%08x, id=0x%x", 
+				i, currentNThread, Kern::CurrentThread().iId );
 			NKern::FSWait(iFrozenThreadSemaphores[i]);
 			return;
 			}
@@ -399,7 +404,8 @@
 void DTargetProcess::NotifyEvent(const TDriverEventInfo& aEventInfo)
 	{
 	// Stuff the event info into all the tracking agents event queues
-	LOG_MSG2("DTargetProcess::NotifyEvent(): number of attached agents: %d", AgentCount());
+	LOG_MSG4("DTargetProcess::NotifyEvent(): num attached agents: %d, iEventType=%d, this=0x%08x", 
+		AgentCount(), aEventInfo.iEventType, this);
 
 	for(TInt i = 0; i < AgentCount(); i++)
 		{
--- a/kernel/eka/drivers/debug/rmdebug/rm_debug_eventhandler.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/debug/rmdebug/rm_debug_eventhandler.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -44,7 +44,6 @@
 	iEventHandlers[EEventUserTrace] = &DRM_DebugChannel::HandleUserTrace;
 	iEventHandlers[EEventRemoveLibrary] = &DRM_DebugChannel::RemoveLibrary;
 	iEventHandlers[EEventAddLibrary] = &DRM_DebugChannel::AddLibrary;
-	iEventHandlers[EEventRemoveProcess] = &DRM_DebugChannel::RemoveProcess;
 	iEventHandlers[EEventStartThread] = &DRM_DebugChannel::StartThread;
 	iEventHandlers[EEventSwExc] = &DRM_DebugChannel::HandleSwException;
 	iEventHandlers[EEventHwExc] = &DRM_DebugChannel::HandleHwException;
@@ -55,7 +54,7 @@
 
 TInt DRM_DebugEventHandler::Create(DLogicalDevice* aDevice, DLogicalChannel* aChannel, DThread* aClient)
 {
-	LOG_MSG("DRM_DebugEventHandler::Create()");
+	LOG_MSG3("DRM_DebugEventHandler::Create(), aClientthread=0x%08x id=%d", aClient, aClient->iId);
 
 	TInt err;
 	err = aDevice->Open();
@@ -71,7 +70,7 @@
 	iClientThread = aClient;
 
 	// Use a semaphore to protect our data structures from concurrent access.
-	err = Kern::SemaphoreCreate(iLock, _L("RM_DebugEventHandlerLock"), 1 /* Initial count */);
+	err = Kern::SemaphoreCreate(iProtectionLock, _L("RM_DebugEventHandlerLock"), 1 /* Initial count */);
 	if (err != KErrNone)
 		return err;
 
@@ -84,8 +83,8 @@
 {
 	LOG_MSG("DRM_DebugEventHandler::~DRM_DebugEventHandler()");
 
-	if (iLock)
-		iLock->Close(NULL);
+	if (iProtectionLock)
+		iProtectionLock->Close(NULL);
 	
 	if (iDevice)
 		iDevice->Close(NULL);	
@@ -125,11 +124,23 @@
 
 TUint DRM_DebugEventHandler::HandleEvent(TKernelEvent aType, TAny* a1, TAny* a2)
 	{
-	if((!iTracking) || (aType > (TUint32)EEventLimit))
+	
+	/*
+	 * Check if we are tracking things at all OR 
+	 * this event is beyond the limit of known events OR 
+	 * this event is from the debug thread itself (don't want to debug ourselves) OR
+	 * this event has a handler (there is no point in proceeding without a handler)
+	 */
+	if( (!iTracking) || 
+			(aType > (TUint32)EEventLimit) ||
+			(iClientThread == &Kern::CurrentThread()) ||
+	    (iEventHandlers[aType] == &DRM_DebugChannel::HandleUnsupportedEvent) )
 		{
 		return ERunNext;
 		}
+	
 	return HandleSpecificEvent(aType,a1,a2) ? EExcHandled : ERunNext;
+
 	}
 
 TBool DRM_DebugEventHandler::HandleSpecificEvent(TKernelEvent aType, TAny* a1, TAny* a2)
@@ -137,14 +148,14 @@
 	TBool ret = EFalse;
 
 	NKern::ThreadEnterCS();
-	Kern::SemaphoreWait(*iLock);
-	
+	LockDataAccess();
+
+
 	if (iChannel)
 		{
 		ret = (iChannel->*(iEventHandlers[aType]))(a1, a2);
 		}
-
-	Kern::SemaphoreSignal(*iLock);
+	ReleaseDataAccess();
 	NKern::ThreadLeaveCS();
 
 	switch(aType)
--- a/kernel/eka/drivers/debug/rmdebug/rm_debug_kerneldriver.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/debug/rmdebug/rm_debug_kerneldriver.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -59,41 +59,41 @@
 // DRM_DebugDriverFactory constructor
 //
 DRM_DebugDriverFactory::DRM_DebugDriverFactory()
-{
+	{
 	iVersion = TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
-}
+	}
 
 //
 // DRM_DebugDriverFactory::Create
 //
 TInt DRM_DebugDriverFactory::Create(DLogicalChannelBase*& aChannel)
-{
+	{
 	if (iOpenChannels != 0)
 		return KErrInUse; // a channel is already open
 
 	aChannel = new DRM_DebugChannel(this);
 
 	return aChannel ? KErrNone : KErrNoMemory;
-}
+	}
 
 //
 // DRM_DebugDriverFactory::Install
 //
 TInt DRM_DebugDriverFactory::Install()
-{
-    return(SetName(&KRM_DebugDriverName));
-}
+	{
+	return(SetName(&KRM_DebugDriverName));
+	}
 
 //
 // DRM_DebugDriverFactory::Install
 //
 void DRM_DebugDriverFactory::GetCaps(TDes8& aDes) const
-{
-    TCapsRM_DebugDriver b;
-    b.iVersion = TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber);
+	{
+	TCapsRM_DebugDriver b;
+	b.iVersion = TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber);
 
 	Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
-}
+	}
 
 /////////////////////////////////////////////////////////////////////////
 //
@@ -106,37 +106,41 @@
 //
 DRM_DebugChannel::DRM_DebugChannel(DLogicalDevice* aLogicalDevice)
 	: iExcludedROMAddressStart(ROM_LINEAR_BASE),
-      iExcludedROMAddressEnd(0),
-   	  iPageSize(0x1000),
-	  iBreakManager(0),
-	  iStepper(0),
-	  iStepLock(0),
-  	  iDfcQ(NULL),
-	  iInitialisedCodeModifier(0),
-	  iAsyncGetValueRequest(NULL)
-{
+	iExcludedROMAddressEnd(0),
+	iPageSize(0x1000),
+	iBreakManager(0),
+	iStepper(0),
+	iStepLock(0),
+	iDfcQ(NULL),
+	iInitialisedCodeModifier(0),
+	iAsyncGetValueRequest(NULL)
+	{
 	LOG_MSG("DRM_DebugChannel::DRM_DebugChannel()");
 
 	iDevice = aLogicalDevice;
 
-	iClientThread = &Kern::CurrentThread();
+	iClientThread = &Kern::CurrentThread();	
 	iClientThread->Open();
 
+	LOG_MSG3("DRM_DebugChannel::DRM_DebugChannel() clientThread = 0x%08x, id=%d", 
+	            iClientThread, iClientThread->iId );
+
+
 	iPageSize = Kern::RoundToPageSize(1);
-}
+	}
 
 //
 // DRM_DebugChannel destructor
 //
 DRM_DebugChannel::~DRM_DebugChannel()
-{
+	{
 	LOG_MSG("DRM_DebugChannel::~DRM_DebugChannel()");
 
 	if (iAsyncGetValueRequest)
-	{
+		{
 		Kern::QueueRequestComplete(iClientThread, iAsyncGetValueRequest, KErrCancel); // does nothing if request not pending
 		Kern::DestroyClientRequest(iAsyncGetValueRequest);
-	}
+		}
 
 	NKern::ThreadEnterCS();
 	Kern::SafeClose((DObject*&)iClientThread, NULL);
@@ -144,19 +148,19 @@
 
 	// Close breakpoint manager
 	if (iBreakManager)
-	{
+		{
 		NKern::ThreadEnterCS();
 		delete iBreakManager;
 		NKern::ThreadLeaveCS();
-	}
+		}
 
 	// Close stepping manager
 	if (iStepper)
-	{
+		{
 		NKern::ThreadEnterCS();
 		delete iStepper;
 		NKern::ThreadLeaveCS();
-	}
+		}
 
 	//close the debug process list
 	iDebugProcessList.Close();
@@ -165,10 +169,10 @@
 
 	//close the code modifier
 	if (iInitialisedCodeModifier)
-	{
+		{
 		DebugSupport::CloseCodeModifier();
+		}
 	}
-}
 
 void DRM_DebugChannel::DestroyDfcQ()
 	{
@@ -185,47 +189,45 @@
 // DRM_DebugChannel::DoCreate
 //
 TInt DRM_DebugChannel::DoCreate(TInt /*aUnit*/, const TDesC* anInfo, const TVersion& aVer)
-{
+	{
 	LOG_MSG("DRM_DebugChannel::DoCreate()");
 	TInt err = Kern::CreateClientDataRequest(iAsyncGetValueRequest);
 	if(err != KErrNone)
 		return err;
 
-  	if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber), aVer))
+	if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber, KMinorVersionNumber, KBuildVersionNumber), aVer))
 		return KErrNotSupported;
 
-  	// Do the security check here so that any arbitrary application doesn't make
-  	// use of Trk kernel driver.
-  	if (!DoSecurityCheck())
-  	{
+	// Do the security check here so that any arbitrary application doesn't make
+	// use of Trk kernel driver.
+	if (!DoSecurityCheck())
+		{
 		LOG_MSG("DRM_DebugChannel::DoCreate() - permission denied!");
-  		return KErrPermissionDenied;
-  	}
-
-  	if (anInfo)
-  	{
-  		// this is the end address of the user library.
-  		// this doesn't seem to be valid for EKA2.
-  		// right now we dont need this for EKA2 since we are not worried
-  		// about kernel being stopped as kernel is multithreaded.
-  		// just retaining this for future use.
+			return KErrPermissionDenied;
+		}
+
+	if (anInfo)
+		{
+		// this is the end address of the user library.
+		// this doesn't seem to be valid for EKA2.
+		// right now we dont need this for EKA2 since we are not worried
+		// about kernel being stopped as kernel is multithreaded.
+		// just retaining this for future use.
 		TBuf8<32> buf;
 		TInt err = Kern::ThreadRawRead(iClientThread, anInfo, &buf, 32);
 		if(err != KErrNone)
 			return err;
-
-		//iExcludedROMAddressEnd = *(TUint32 *)(&(buf.Ptr()[20]));
-	}
+		}
 
 	// Allocate a D_RMD_Breakpoints class as a breakpoint manager
 	NKern::ThreadEnterCS();
 	iBreakManager = new D_RMD_Breakpoints(this);
 	NKern::ThreadLeaveCS();
 	if (iBreakManager == NULL)
-	{
+		{
 		LOG_MSG("DRM_DebugChannel::DRM_DebugChannel - could not construct breakpoint manager");
 		return KErrNoMemory;
-	}
+		}
 
 	// Initialise the new breakpoint manager object
 	iBreakManager->Init();
@@ -235,10 +237,10 @@
 	iStepper = new DRMDStepping(this);
 	NKern::ThreadLeaveCS();
 	if (iStepper == NULL)
-	{
+		{
 		LOG_MSG("DRM_DebugChannel::DRM_DebugChannel - could not construct stepper manager");
 		return KErrNoMemory;
-	}
+		}
 
 	// Initialize the code modifier for managing breakpoints.
 	TUint caps; //ignored for now
@@ -246,13 +248,13 @@
 	//if code modifier initializer failed,
 	//return here, since we can't set an breakpoints
 	if(err != KErrNone)
-	{
+		{
 		return err;
-	}
+		}
 	else
-	{
+		{
 		iInitialisedCodeModifier = ETrue;
-	}
+		}
 
 	//create and set the driver's Dfc queue
 	err = CreateDfcQ();
@@ -273,15 +275,29 @@
 
 	//return KErrNone;
 	return iEventHandler->Start();
-}
-
-//
-// DRM_DebugChannel::SendMsg
-//
+	}
+
+/**
+Forward call to either synch or asynch methods while serialising all calls via lock.
+ 
+Protect access via a the event handler lock to 
+serialise all calls and protect concurrent access to data structures
+
+@param aMsg pointer to a TMessageBase object 
+
+@return error returned by called methods
+
+@see DRM_DebugEventHandler::HandleSpecificEvent where lock is also used
+@see DRM_DebugEventHandler::iProtectionLock
+
+*/
 TInt DRM_DebugChannel::SendMsg(TMessageBase* aMsg)
 	{
-	LOG_MSG("DRM_DebugChannel::SendMsg()");
-
+	DThread * currThread = &Kern::CurrentThread();
+	LOG_MSG3("DRM_DebugChannel::SendMsg() currThread = 0x%08x, iClientThread=0x%08x", currThread, iClientThread );
+
+	iEventHandler->LockDataAccess();
+	
 	TThreadMessage& m = *(TThreadMessage*)aMsg;
 	TInt id = m.iValue;
 	TInt err = KErrNone;
@@ -298,6 +314,8 @@
 		{
 		err = DLogicalChannel::SendMsg(aMsg);
 		}
+	
+	iEventHandler->ReleaseDataAccess();
 	return err;
 	}
 
@@ -330,7 +348,8 @@
 //
 TInt DRM_DebugChannel::PreAsyncGetValue(TEventInfo* aValue, TRequestStatus* aStatus)
 	{
-	LOG_MSG("DRM_DebugChannel::PreAsyncGetValue()");
+	LOG_MSG3("DRM_DebugChannel::PreAsyncGetValue() TEventInfo=0x%08x, TRequestStatus=0x%08x",
+		aValue, aStatus );
 	
 	iAsyncGetValueRequest->Reset();
 	
@@ -364,89 +383,93 @@
 // to a user-side struct defining the cancellation
 //
 void DRM_DebugChannel::DoCancel(TInt aReqNo)
-{
+	{
 	LOG_MSG("DRM_DebugChannel::DoCancel()");
 
 	TRMD_DebugCancelInfo info;
 
 	TInt err = Kern::ThreadRawRead(iClientThread,(TAny*)aReqNo,(TAny*)&info,sizeof(info));
 	if (err != KErrNone)
-	{
+		{
 		// How do we cancel something we know nothing about???
 		LOG_MSG("DRM_DebugChannel::DoCancel - bad arguments");
 		return;
-	}
+		}
 
 	// Find the process
 	DTargetProcess* pProcess = TheDProcessTracker.FindProcess(info.iProcessName);
 	if (pProcess == NULL)
-	{
+		{
 		// We are doomed. We don't know which event to cancel..
 		LOG_MSG2("Cannot determine which process is being debugged: %S", &(info.iProcessName));
 
 		return;
-	}
+		}
 
 	// Find the agent
 	DDebugAgent* debugAgent = pProcess->Agent(info.iAgentId);
 	if (debugAgent == NULL)
-	{
+		{
 		// Bad agent means there is no tracking agent
 		LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",info.iAgentId);
 		return;
-	}
+		}
 
 	// Agent completes/pends the request as appropriate.
 	debugAgent->CancelGetEvent();
 
-}
+	}
 
 //
 // DRM_DebugChannel::DoRequest
 //
 void DRM_DebugChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
-{
-	LOG_MSG("DRM_DebugChannel::DoRequest()");
+	{
+	LOG_MSG4("DRM_DebugChannel::DoRequest(), iClientThread=0x%08x, tid=0x%08x, TRequestStatus=0x%08x", 
+		iClientThread, I64LOW(iClientThread->iId), aStatus);
 
 	switch(aReqNo)
-	{
+		{
 		case RRM_DebugDriver::ERequestGetEvent:
-		{
+			{
 			TEventMetaData eventMetaData;
 			TInt err = Kern::ThreadRawRead(iClientThread, a2, (TUint8 *)&eventMetaData, sizeof(TEventMetaData) );
 			if (err != KErrNone)
-			{
+				{
 				LOG_MSG("Error: could not read argument data from the DSS (TEventMetaData)");
 
 				// We could not read information from the user, so the a2 argument is probably wrong
 				Kern::RequestComplete(iClientThread, aStatus, KErrArgument);
 				return;
-			}
+				}
 
 			// Find the process
 			DTargetProcess* pProcess = TheDProcessTracker.FindProcess(eventMetaData.iTargetProcessName);
 			if (pProcess == NULL)
-			{
+				{
 				LOG_MSG("Cannot identify process being debugged");
 
 				// We could not locate the process, so the user asked for the wrong one.
 				Kern::RequestComplete(iClientThread, aStatus, KErrArgument);
 				return;
-			}
+				}
 
 			// Find the agent
 			DDebugAgent* debugAgent = pProcess->Agent(eventMetaData.iDebugAgentProcessId);
+			LOG_MSG5(" For agent pid=%d, DTargetProcess=0x%08x, Agent=0x%08x, iAsyncGetValueRequest0x%08x", 
+				I64LOW(eventMetaData.iDebugAgentProcessId), pProcess, debugAgent, iAsyncGetValueRequest );
+
 			if (debugAgent == NULL)
-			{
+				{
 				// Bad agent means there is no tracking agent
 				LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",eventMetaData.iDebugAgentProcessId);
 				return;
-			}
+				}
 			// Agent completes/pends the request as appropriate.
-			debugAgent->GetEvent(iAsyncGetValueRequest, (TEventInfo*)a1, iClientThread);
+			debugAgent->GetEvent(iAsyncGetValueRequest, iClientThread);
 
 			break;
-		}
+			}
 		default:
 			{
 			// Don't know what to do, should not get here!
@@ -454,14 +477,14 @@
 
 			Kern::RequestComplete(iClientThread, aStatus, KErrNotSupported);
 			}
+		}
 	}
-}
 
 //
 // DRM_DebugChannel::DoControl
 //
 TInt DRM_DebugChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
-{
+	{
 	LOG_MSG("DRM_DebugChannel::DoControl()");
 
 	LOG_MSG2("DoControl Function %d", aFunction);
@@ -470,121 +493,121 @@
 	DThread* threadObj = NULL;
 
 	switch(aFunction)
-	{
+		{
 		/* Security first */
 		case RRM_DebugDriver::EControlIsDebuggable:
-		{
+			{
 			err = IsDebuggable((TUint32)a1);
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlSetBreak:
-		{
+			{
 			err = SetBreak((TSetBreakInfo*)a1);
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlClearBreak:
-		{
+			{
 			err = iBreakManager->DoClearBreak((TInt32)a1);
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlModifyBreak:
-		{
+			{
 			err = iBreakManager->DoModifyBreak((TModifyBreakInfo*)a1);
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlModifyProcessBreak:
-		{
+			{
 			err = iBreakManager->DoModifyProcessBreak((TModifyProcessBreakInfo*)a1);
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlBreakInfo:
-		{
+			{
 			err = iBreakManager->DoBreakInfo((TGetBreakInfo*)a1);
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlSuspendThread:
-		{
+			{
 			threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
 			if (threadObj)
 			{
 				err = DoSuspendThread(threadObj);
 			}
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlResumeThread:
-		{
+			{
+			threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
+			if (threadObj)
+				{
+				err = DoResumeThread(threadObj);
+				}
+			break;
+			}
+		case RRM_DebugDriver::EControlStepRange:
+			{
+			threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
+			if (threadObj)
+				{
+				err = StepRange(threadObj, (TRM_DebugStepInfo*)a2);
+				}
+			break;
+			}
+		case RRM_DebugDriver::EControlReadMemory:
+			{
+			threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
+			if (threadObj)
+				{
+				err = ReadMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
+				}
+			break;
+			}
+		case RRM_DebugDriver::EControlWriteMemory:
+			{
 			threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
 			if (threadObj)
-			{
-				err = DoResumeThread(threadObj);
-			}
-			break;
-		}
-		case RRM_DebugDriver::EControlStepRange:
-		{
-           threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
-           if (threadObj)
-           {
-   			err = StepRange(threadObj, (TRM_DebugStepInfo*)a2);
-           }
+				{
+				err = WriteMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
+				}
 			break;
-		}
-		case RRM_DebugDriver::EControlReadMemory:
-		{
-           threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
-           if (threadObj)
-           {
-   			err = ReadMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
-           }
-			break;
-		}
-		case RRM_DebugDriver::EControlWriteMemory:
-		{
-           threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
-           if (threadObj)
-           {
-   			err = WriteMemory(threadObj, (TRM_DebugMemoryInfo*)a2);
-           }
-			break;
-		}
+			}
 		case RRM_DebugDriver::EControlReadRegistersLegacy:
-		{
-           threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
-           if (threadObj)
-           {
-   			err = ReadRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
-           }
+			{
+			threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
+			if (threadObj)
+				{
+				err = ReadRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
+				}
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlWriteRegistersLegacy:
-		{
-           threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
-           if (threadObj)
-           {
-   			err = WriteRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
-           }
+			{
+			threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
+			if (threadObj)
+				{
+				err = WriteRegistersLegacy(threadObj, (TRM_DebugRegisterInfo*)a2);
+				}
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlReadRegisters:
-		{
-           threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
-           if (threadObj)
-           {
-   			err = ReadRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
-           }
+			{
+			threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
+			if (threadObj)
+				{
+				err = ReadRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
+				}
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlWriteRegisters:
-		{
-           threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
-           if (threadObj)
-           {
-   			err = WriteRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
-           }
+			{
+			threadObj = DebugUtils::OpenThreadHandle((TUint32)a1);
+			if (threadObj)
+				{
+				err = WriteRegisters(threadObj, (TRM_DebugRegisterInformation*)a2);
+				}
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlGetDebugFunctionalityBufSize:
-		{
+			{
 			LOG_MSG("RRM_DebugDriver::EControlGetDebugFunctionalityBufSize\n");
 
 			TDebugFunctionality df;
@@ -594,9 +617,9 @@
 			// Return size to user-side in a safe manner
 			err = Kern::ThreadRawWrite(iClientThread, a1, (TUint8*)&size, sizeof(TUint), iClientThread);
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlGetDebugFunctionality:
-		{
+			{
 			LOG_MSG("RRM_DebugDriver::EControlGetDebugFunctionality\n");
 
 			TDebugFunctionality df;
@@ -608,64 +631,64 @@
 			TUint8* dfbuffer = (TUint8*)Kern::AllocZ(dfsize);
 			NKern::ThreadLeaveCS();
 			if (dfbuffer==NULL)
-			{
+				{
 				LOG_MSG2("Could not allocate memory for %d bytes\n",dfsize);
 
 				// could not allocate memory
 				return KErrNoMemory;
-			}
+				}
 
 			// Temporary descriptor to hold DF data
 			TPtr8 tmpPtr(dfbuffer,0,dfsize);
 
 			// Obtain the DF data
 			if (df.GetDebugFunctionality(tmpPtr) )
-			{
+				{
 				// Return the DF data to the user-side
 				err = Kern::ThreadDesWrite(iClientThread, a1, tmpPtr, 0, KChunkShiftBy0, iClientThread);
-			}
+				}
 			else
-			{
+				{
 				// Failed.
 				err = KErrGeneral;
-			}
+				}
 
 			// Free tmp buffer
 			NKern::ThreadEnterCS();
 			Kern::Free(dfbuffer);
 			NKern::ThreadLeaveCS();
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlAttachProcess:
-		{
+			{
 			LOG_MSG("RRM_DebugDriver::EControlAttachProcess");
 
 			err = AttachProcess(a1,a2);
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlDetachProcess:
-		{
+			{
 			LOG_MSG("RRM_DebugDriver::EControlDetachProcess");
 
 			err = DetachProcess(a1,a2);
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlDetachAgent:
-		{
+			{
 			LOG_MSG("RRM_DebugDriver::EControlDetachAgent");
 
 			err = DetachAgent(a1,a2);
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlSetEventAction:
-		{
+			{
 			LOG_MSG("RRM_DebugDriver::EControlSetEventAction");
 
 			err = SetEventAction(a1,a2);
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlGetMemoryOperationMaxBlockSize:
-		{
+			{
 			LOG_MSG("RRM_DebugDriver::EControlGetMemoryOperationMaxBlockSize\n");
 
 			TUint32 maxSize = TDebugFunctionality::GetMemoryOperationMaxBlockSize();
@@ -673,95 +696,95 @@
 			// Return size to user-side in a safe manner
 			err = Kern::ThreadRawWrite(iClientThread, a1, (TUint8*)&maxSize, sizeof(TUint32), iClientThread);
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlGetList:
-		{
+			{
 			LOG_MSG("RRM_DebugDriver::EControlGetList\n");
 			err = GetList((TListInformation*)a1);
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlStep:
-		{
+			{
 			LOG_MSG("RRM_DebugDriver::EControlStep\n");
 
 			err = Step((TUint32)a1,(TUint32)a2);
 			break;
-		}
+			}
 		case RRM_DebugDriver::EControlKillProcess:
-		{
+			{
 			LOG_MSG("RRM_DebugDriver::EControlKillProcess\n");
 
 			err = KillProcess((TUint32)a1,(TUint32)a2);
 			break;
-		}
+			}
 		default:
-		{
+			{
 			err = KErrGeneral;
+			}
 		}
-	}
 
 	if (KErrNone != err)
-	{
+		{
 		LOG_MSG2("Error %d from control function", err);
-	}
-
-   if (threadObj)
-   {
-       // Close the thread handle which has been opened by DebugUtils::OpenThreadHandle
-       threadObj->Close(NULL);
-   }
+		}
+
+	if (threadObj)
+		{
+		// Close the thread handle which has been opened by DebugUtils::OpenThreadHandle
+		threadObj->Close(NULL);
+		}
 
 	return err;
-}
+	}
 
 void DRM_DebugChannel::HandleMsg(TMessageBase* aMsg)
-{
+	{
 	LOG_MSG("DRM_DebugChannel::HandleMsg()");
 
 	TThreadMessage& m = *(TThreadMessage*)aMsg;
 	TInt id = m.iValue;
 
 	if (id == (TInt)ECloseMsg)
-	{
+		{
 		if (iEventHandler)
-		{
+			{
 			iEventHandler->Stop();
 			iEventHandler->Close();
 			iEventHandler = NULL;
-		}
+			}
 		m.Complete(KErrNone, EFalse);
 		return;
-	}
+		}
 
 	if (id == KMaxTInt)
-	{
+		{
 		// DoCancel
 		DoCancel(m.Int0());
 		m.Complete(KErrNone, ETrue);
 		return;
-	}
+		}
 
 	if (id < 0)
-	{
+		{
 		// DoRequest
 		TRequestStatus* pStatus = (TRequestStatus*)m.Ptr0();
 		DoRequest(~id, pStatus, m.Ptr1(), m.Ptr2());
 		m.Complete(KErrNone, ETrue);
-	}
+		}
 	else
-	{
+		{
 		// DoControl
 		TInt err = DoControl(id, m.Ptr0(), m.Ptr1());
 		m.Complete(err, ETrue);
+		}
 	}
-}
 
 //
 // DRM_DebugChannel::RemoveProcess
 //
 TBool DRM_DebugChannel::RemoveProcess(TAny* a1, TAny* a2)
 	{
-	LOG_EVENT_MSG("DRM_DebugChannel::RemoveProcess()");
+	LOG_MSG("DRM_DebugChannel::RemoveProcess()");
 
 	DProcess *aProcess = (DProcess*)a1;
 
@@ -797,7 +820,6 @@
 			{
 			LOG_MSG2("Error in getting memory info: %d", err);
 			}
-
 		}
 
 	if (!codeAddress || !codeSize)
@@ -831,7 +853,7 @@
 // DRM_DebugChannel::StartThread
 //
 TBool DRM_DebugChannel::StartThread(TAny* a1, TAny* a2)
-{
+	{
 	LOG_EVENT_MSG("DRM_DebugChannel::StartThread()");
 
 	DThread *aThread = (DThread*)a1;
@@ -881,13 +903,13 @@
 			}
 		}
 	return EFalse;
-}
+	}
 
 //
 // DRM_DebugChannel::HandleAddProcessEvent
 //
 TBool DRM_DebugChannel::HandleAddProcessEvent(TAny* a1, TAny* a2)
-{
+	{
 	LOG_EVENT_MSG("DRM_DebugChannel::AddProcess()");
 
 	DProcess *aProcess = (DProcess*)a1;
@@ -905,7 +927,7 @@
 	info.iEventType = EEventsAddProcess;
 	info.iProcessId = aProcess->iId;
 
-    info.iCreatorThreadId  = aThread ? aThread->iId : 0;
+	info.iCreatorThreadId  = aThread ? aThread->iId : 0;
 	info.iProcessIdValid = ETrue;
 
 	// Copy TUids
@@ -945,14 +967,14 @@
 		}
 
 	return EFalse;
-}
+	}
 
 //
 // DRM_DebugChannel::HandleRemoveProcessEvent
 //
 TBool DRM_DebugChannel::HandleRemoveProcessEvent(TAny* a1, TAny* a2)
-{
-	LOG_EVENT_MSG("DRM_DebugChannel::RemoveProcess()");
+	{
+	LOG_MSG("DRM_DebugChannel::HandleRemoveProcessEvent()");
 
 	DProcess *aProcess = (DProcess*)a1;
 	if(!aProcess)
@@ -1004,13 +1026,13 @@
 		}
 
 	return EFalse;
-}
+	}
 
 //
 // DRM_DebugChannel::AddLibrary
 //
 TBool DRM_DebugChannel::AddLibrary(TAny* a1, TAny* a2)
-{
+	{
 	LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary()");
 
 	DLibrary *aLibrary = (DLibrary*)a1;
@@ -1018,24 +1040,24 @@
 
 	// sanity check
 	if (!aLibrary)
-	{
+		{
 		LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary called with no library specified");
 		return EFalse;
-	}
+		}
 
 	if (!aThread)
-	{
+		{
 		LOG_EVENT_MSG("DRM_DebugChannel::AddLibrary called with no thread specified");
 		return EFalse;
-	}
+		}
 
 	LOG_EVENT_MSG2(("Lib loaded: %S"), aLibrary->iName);
 
 	if (aThread)
-	{
+		{
 		// make sure this is not the debugger thread
 		if ((aThread != iClientThread) && (aThread->iOwningProcess->iId != iClientThread->iOwningProcess->iId))
-		{
+			{
 			TDriverEventInfo info;
 
 			info.iEventType = EEventsAddLibrary;
@@ -1047,10 +1069,10 @@
 			//get the code address
 			DCodeSeg* codeSeg = aLibrary->iCodeSeg;
 			if (!codeSeg)
-			{
+				{
 				LOG_EVENT_MSG2("Code segment not available for library %S", aLibrary->iName);
 				return EFalse;
-			}
+				}
 
 			// Uid3
 			info.iUids = codeSeg->iUids;
@@ -1059,10 +1081,10 @@
 			TModuleMemoryInfo memoryInfo;
 			TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL); //NULL for DProcess should be ok;
 			if (err != KErrNone)
-			{
+				{
 				LOG_EVENT_MSG2("Error in getting memory info: %d", err);
 				return EFalse;
-			}
+				}
 
 			info.iCodeAddress = memoryInfo.iCodeBase;
 			info.iDataAddress = memoryInfo.iInitialisedDataBase;
@@ -1073,11 +1095,11 @@
 			info.iArg1 = a1;
 			info.iArg2 = a2;
 			NotifyEvent(info);
+			}
+
 		}
-
+	return EFalse;
 	}
-	return EFalse;
-}
 
 //
 // DRM_DebugChannel::RemoveLibrary
@@ -1164,16 +1186,17 @@
 // DRM_DebugChannel::HandleEventKillThread
 //
 TBool DRM_DebugChannel::HandleEventKillThread(TAny* a1, TAny* a2)
-{
-	LOG_EVENT_MSG("DRM_DebugChannel::HandleEventKillThread");
+	{
+
+	LOG_MSG2("DRM_DebugChannel::HandleEventKillThread(Thread a1=0x%08x)", a1 );
 
 	DThread* currentThread = &Kern::CurrentThread();
 	if (!currentThread)
-	{
+		{
 		LOG_MSG("Error getting current thread");
 		__NK_ASSERT_DEBUG(currentThread);
 		return EFalse;
-	}
+		}
 
 	// a1 should point to the current thread, check this to make sure it does
 	__NK_ASSERT_DEBUG((DThread*)a1 == currentThread);
@@ -1187,14 +1210,14 @@
 	// 14 should probably be replaced by PC_REGISTER, for some reason PC_REGISTER had been replaced with 14 in the code
 	TInt err = ReadKernelRegisterValue(currentThread, 14, info.iCurrentPC);
 	if(err != KErrNone)
-	{
+		{
 		LOG_EVENT_MSG2("DRM_DebugChannel::HandleEventKillThread - Non-zero error code discarded: %d", err);
-	}
+		}
 
 	if (currentThread->iExitType == EExitPanic)
-	{
+		{
 		info.iPanicCategory.Copy(currentThread->iExitCategory);
-	}
+		}
 	info.iExceptionNumber = currentThread->iExitReason;
 	info.iExitType = currentThread->iExitType;
 	info.iEventType = EEventsKillThread;
@@ -1226,13 +1249,13 @@
 	NotifyEvent(info);
 
 	return ETrue;
-}
+	}
 
 //
 // DRM_DebugChannel::HandleSwException
 //
 TBool DRM_DebugChannel::HandleSwException(TAny* a1, TAny* a2)
-{
+	{
 	LOG_EVENT_MSG("DRM_DebugChannel::HandleSwException");
 	TExcType aExcType = (TExcType)(TInt)a1;
 
@@ -1240,11 +1263,11 @@
 
 	DThread* currentThread = &Kern::CurrentThread();
 	if (!currentThread)
-	{
+		{
 		LOG_MSG("Error getting current thread");
 		__NK_ASSERT_DEBUG(currentThread);
 		return EFalse;
-	}
+		}
 
 	info.iProcessId = currentThread->iOwningProcess->iId;
 	info.iProcessIdValid = ETrue;
@@ -1252,9 +1275,9 @@
 	info.iThreadIdValid = ETrue;
 	TInt err = ReadKernelRegisterValue(currentThread, PC_REGISTER, info.iCurrentPC);
 	if(err != KErrNone)
-	{
+		{
 		LOG_EVENT_MSG2("DRM_DebugChannel::HandleSwException - Non-zero error code discarded: %d", err);
-	}
+		}
 	info.iExceptionNumber = aExcType;
 	info.iEventType = EEventsSwExc;
 	info.iArg1 = a1;
@@ -1263,35 +1286,33 @@
 	NotifyEvent(info);
 
 	return EFalse;
-}
+	}
 
 //
 // DRM_DebugChannel::HandleHwException
 //
 TBool DRM_DebugChannel::HandleHwException(TAny* a1, TAny* a2)
-{
-	LOG_EVENT_MSG("DRM_DebugChannel::HandleHwException()");
+	{
 	TArmExcInfo* aExcInfo = (TArmExcInfo*)a1;
 
 	// sanity check
 	if (!aExcInfo)
-	{
+		{
 		LOG_MSG("DRM_DebugChannel::HandleHwException called with no aExcInfo");
 		__NK_ASSERT_DEBUG(aExcInfo);
 		return EFalse;
-	}
+		}
 
 	TDriverEventInfo info;
 
 	DThread* currentThread = &Kern::CurrentThread();
-	LOG_EVENT_MSG2("DRM_DebugChannel::HandleHwException current thread = 0x%x", currentThread);
 
 	if (!currentThread)
-	{
+		{
 		LOG_MSG("Error getting current thread");
 		__NK_ASSERT_DEBUG(currentThread);
 		return EFalse;
-	}
+		}
 
 	info.iProcessId = currentThread->iOwningProcess->iId;
 	info.iProcessIdValid = ETrue;
@@ -1299,8 +1320,10 @@
 	info.iThreadIdValid = ETrue;
 	info.iRmdArmExcInfo.iFaultAddress= aExcInfo->iFaultAddress;
 	info.iRmdArmExcInfo.iFaultStatus= aExcInfo->iFaultStatus;
-	LOG_EVENT_MSG3("DRM_DebugChannel::HandleHwException iFaultAddress=0x%x, iFaultStatus=0x%x",
-			aExcInfo->iFaultAddress, aExcInfo->iFaultStatus);
+
+	LOG_MSG5("DRM_DebugChannel::HandleHwException current thread = 0x%08x, CritSect count=%d,\n"
+		" iFaultAddress=0x%08x, iFaultStatus=0x%08x",
+		currentThread, currentThread->iNThread.iCsCount, aExcInfo->iFaultAddress, aExcInfo->iFaultStatus);
 
 	info.iRmdArmExcInfo.iR0= aExcInfo->iR0;
 	info.iRmdArmExcInfo.iR1= aExcInfo->iR1;
@@ -1320,18 +1343,16 @@
 	info.iRmdArmExcInfo.iR13= aExcInfo->iR13;
 	info.iRmdArmExcInfo.iR14= aExcInfo->iR14;
 	info.iRmdArmExcInfo.iR15= aExcInfo->iR15;
-	LOG_EVENT_MSG5(" R12=0x%x, R13=0x%x, R14=0x%x, R15=0x%x ",
-			aExcInfo->iR12, aExcInfo->iR13, aExcInfo->iR14, aExcInfo->iR15);
 
 	info.iRmdArmExcInfo.iCpsr= aExcInfo->iCpsr;
 	info.iRmdArmExcInfo.iR13Svc= aExcInfo->iR13Svc;
 	info.iRmdArmExcInfo.iR14Svc= aExcInfo->iR14Svc;
 	info.iRmdArmExcInfo.iSpsrSvc= aExcInfo->iSpsrSvc;
-	LOG_EVENT_MSG5(" iCpsr=0x%x, iR13Svc=0x%x, iR14Svc=0x%x, iSpsrSvc=0x%x ",
-			aExcInfo->iCpsr, aExcInfo->iR13Svc, aExcInfo->iR14Svc, aExcInfo->iSpsrSvc);
+	LOG_MSG5(" iCpsr=0x%x, iExcCode=0x%x, R14=0x%x, R15=0x%x",
+			aExcInfo->iCpsr, aExcInfo->iExcCode, aExcInfo->iR14, aExcInfo->iR15);
 
 	switch (aExcInfo->iExcCode)
-	{
+		{
 		case 0:
 			info.iExceptionNumber = EExcCodeAbort;
 			LOG_EVENT_MSG(" iExcCode == 0 => EExcCodeAbort");
@@ -1348,8 +1369,8 @@
 			// new event? Something gone wrong?
 			__NK_ASSERT_DEBUG(EFalse);
 			return EFalse;
-
-	}
+		}
+
 	info.iEventType = EEventsHwExc;
 
 	info.iArg1 = a1;
@@ -1362,22 +1383,22 @@
 
 	NotifyEvent(info);
 	return EFalse;
-}
+	}
 
 //
 // DRM_DebugChannel::HandUserTrace
 //
 TBool DRM_DebugChannel::HandleUserTrace(TAny* a1, TAny* a2)
-{
+	{
 	LOG_EVENT_MSG("DRM_DebugChannel::HandleUserTrace()");
 
 	DThread* currentThread = &Kern::CurrentThread();
 	if (!currentThread)
-	{
+		{
 		LOG_EVENT_MSG("Error getting current thread");
 		__NK_ASSERT_DEBUG(currentThread);
 		return EFalse;
-	}
+		}
 
 	TDriverEventInfo info;
 	info.iProcessId = currentThread->iOwningProcess->iId;
@@ -1402,14 +1423,14 @@
 	NotifyEvent(info);
 
 	return EFalse;
-}
+	}
 
 //
 // DRM_DebugChannel::HandleException
 //
 TBool DRM_DebugChannel::HandleInvalidOpCodeException(TDriverEventInfo& aEventInfo, DThread* aCurrentThread)
-{
-	LOG_EVENT_MSG("DRM_DebugChannel::HandleInvalidOpCodeException()");
+	{
+	LOG_MSG("DRM_DebugChannel::HandleInvalidOpCodeException()");
 
 	TInt err = KErrNone;
 
@@ -1420,38 +1441,39 @@
 	TUint32 regValue;
 	err = ReadKernelRegisterValue(aCurrentThread, STATUS_REGISTER, regValue);
 	if(err != KErrNone)
-	{
-		LOG_EVENT_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException - Non-zero error code discarded: %d", err);
-	}
+		{
+		LOG_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException - Non-zero error code discarded: %d", err);
+		}
+
 	if (regValue & ECpuThumb)
-	{
+		{
 		inst = KThumbBreakPoint;
 		instSize = 2;
-	}
+		}
 
 	TUint32 instruction = 0;
 	err = Kern::ThreadRawRead(aCurrentThread, (TUint32 *)aEventInfo.iRmdArmExcInfo.iR15, (TUint8 *)&instruction, instSize);
 
 	if (KErrNone != err)
-		LOG_EVENT_MSG2("Error reading instruction at currentpc: %d", err);
+		LOG_MSG2("Error reading instruction at currentpc: %d", err);
 
 	if (!memcompare((TUint8 *)&inst, instSize, (TUint8 *)&instruction, instSize))
-	{
+		{
 		TInt err = DoSuspendThread(aCurrentThread);
 		if(! ((KErrNone == err) || (KErrAlreadyExists == err)) )
 			{
-			LOG_EVENT_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException() Thread with id 0x%08x could not be suspended.", aCurrentThread->iId);
+			LOG_MSG2("DRM_DebugChannel::HandleInvalidOpCodeException() Thread with id 0x%08x could not be suspended.", aCurrentThread->iId);
 			return EFalse;
 			}
 
 		// the exception was a breakpoint instruction.  see if we have a breakpoint at that address
 		TBreakEntry* breakEntry = NULL;
 		do
-		{
+			{
 			breakEntry = iBreakManager->GetNextBreak(breakEntry);
 			if (breakEntry && ((breakEntry->iThreadSpecific && breakEntry->iId == aEventInfo.iThreadId) || (!breakEntry->iThreadSpecific && breakEntry->iId == aEventInfo.iProcessId)) && breakEntry->iAddress == aEventInfo.iRmdArmExcInfo.iR15)
-			{
-				LOG_EVENT_MSG2("Breakpoint with Id %d has been hit", breakEntry->iBreakId);
+				{
+				LOG_MSG2("Breakpoint with Id %d has been hit", breakEntry->iBreakId);
 
 				TBreakEntry tempBreakEntry = *breakEntry;
 
@@ -1465,7 +1487,7 @@
 
 				// see if this is a temp breakpoint
 				if (iBreakManager->IsTemporaryBreak(*breakEntry))
-				{
+					{
 					// this was a temp breakpoint, so we need to clear it now
 					err = iBreakManager->DoClearBreak(breakEntry->iBreakId);
 					if (KErrNone != err)
@@ -1476,36 +1498,36 @@
 					// reduce the number of steps to complete by 1
 					tempBreakEntry.iNumSteps--;
 
-					LOG_EVENT_MSG2("There are %d steps remaining\n", tempBreakEntry.iNumSteps);
+					LOG_MSG2("There are %d steps remaining\n", tempBreakEntry.iNumSteps);
 
 					// New. If we have not finished do all the steps, continue stepping and don't notify event
 					if (tempBreakEntry.iNumSteps)
-					{
-						LOG_EVENT_MSG("Continuing stepping...not telling the agent yet\n");
+						{
+						LOG_MSG("Continuing stepping...not telling the agent yet\n");
 						err = DoStepRange(aCurrentThread, aEventInfo.iRmdArmExcInfo.iR15, aEventInfo.iRmdArmExcInfo.iR15, ETrue, tempBreakEntry.iResumeOnceOutOfRange /*EFalse*/, tempBreakEntry.iNumSteps, ETrue);
 						if (err != KErrNone)
-						{
+							{
 							LOG_EVENT_MSG("Failed to continue stepping\n");
 
 							// what do we do? might as well stop here and tell the user
 							NotifyEvent(aEventInfo);
 
 							return ETrue;
-						}
+							}
 
 						// continue as though no event occured. No need to suspend/resume anything...
-						LOG_EVENT_MSG("Continuing to step\n");
+						LOG_MSG("Continuing to step\n");
 						return ETrue;
-					}
+						}
 
 					// Is this a case where we just want to continue?
 					if (tempBreakEntry.iResumeOnceOutOfRange)
-					{
-					LOG_EVENT_MSG("PC is out of range, continuing thread");
+						{
+						LOG_MSG("PC is out of range, continuing thread");
 						DoResumeThread(aCurrentThread);
 
 						return ETrue;
-    					}
+						}
 					}
 
 				// if the breakpoint is thread specific, make sure it's the right thread
@@ -1517,49 +1539,49 @@
 					(!tempBreakEntry.iThreadSpecific && tempBreakEntry.iId != aEventInfo.iProcessId);
 
 				if (needToResume)
-				{
-					LOG_EVENT_MSG("breakpoint does not match threadId, calling DoResumeThread");
+					{
+					LOG_MSG("breakpoint does not match threadId, calling DoResumeThread");
 					err = DoResumeThread(aCurrentThread);
 					if (KErrNone != err)
-						LOG_EVENT_MSG2("Error in DoResumeThread: %d", err);
+						LOG_MSG2("Error in DoResumeThread: %d", err);
 
 					return EFalse;
-				}
+					}
 
 				//normal user break point, just notify the event
 				break;
-			}
-		} while(breakEntry);
-	}
+				}
+			} while(breakEntry);
+		}
 
 	NotifyEvent(aEventInfo);
 
 	return (aEventInfo.iEventType == EEventsBreakPoint) || (aEventInfo.iEventType == EEventsProcessBreakPoint);
-}
+	}
 
 //
 // DRM_DebugChannel::SetBreak
 //
 TInt DRM_DebugChannel::SetBreak(TSetBreakInfo* aBreakInfo)
-{
+	{
 	LOG_MSG("DRM_DebugChannel::SetBreak()");
 
 	TInt err = KErrNone;
 
 	if (!aBreakInfo)
-	{
+		{
 		LOG_MSG("DRM_DebugChannel::SetBreak() was passed a NULL argument");
 		return KErrArgument;
-	}
+		}
 
 	//User side memory is not accessible directly
 	TSetBreakInfo info;
 	err = Kern::ThreadRawRead(iClientThread, aBreakInfo, (TUint8*)&info, sizeof(TSetBreakInfo));
 	if (err != KErrNone)
-	{
+		{
 		LOG_MSG("DRM_DebugChannel::SetBreak() was passed a bad argument");
 		return err;
-	}
+		}
 
 	DProcess* process = NULL;
 	if(info.iThreadSpecific)
@@ -1583,11 +1605,13 @@
 		{
 		process = DebugUtils::OpenProcessHandle(info.iId);
 		}
+
 	if(!process)
 		{
 		LOG_MSG2("DRM_DebugChannel::SetBreak() Process with id 0x%08x not found", process->iId);
 		return KErrNotFound;
 		}
+
 	TBool found = EFalse;
 	for(TInt i=0; i<iDebugProcessList.Count(); i++)
 		{
@@ -1596,6 +1620,7 @@
 			found = ETrue;
 			}
 		}
+
 	if(!found)
 		{
 		DCodeSeg* codeSeg = process->iCodeSeg;
@@ -1623,24 +1648,25 @@
 		return KErrArgument;
 
 	if (err == KErrNone)
-	{
+		{
 		TInt32 iBreakId;
 
 		err = iBreakManager->DoSetBreak(iBreakId, info.iId, info.iThreadSpecific, info.iAddress, info.iMode );
 
 		if (err == KErrNone)
-		{
+			{
 			err = Kern::ThreadRawWrite(iClientThread, (TUint8 *)info.iBreakId, &iBreakId, sizeof(TInt32), iClientThread);
+			}
 		}
-	}
+
 	return err;
-}
+	}
 
 //
 // DRM_DebugChannel::StepRange
 //
 TInt DRM_DebugChannel::StepRange(DThread* aThread, TRM_DebugStepInfo* aStepInfo)
-{
+	{
 	LOG_MSG("DRM_DebugChannel::StepRange()");
 
 	TInt err = KErrNone;
@@ -1663,7 +1689,7 @@
 	err = DoStepRange(aThread, info.iStartAddress, info.iStopAddress, info.iStepInto, EFalse, ETrue);
 
 	return err;
-}
+	}
 
 /**
 Read memory from a target thread and return the data to the client. If the
@@ -1680,7 +1706,7 @@
         or another of the system wide error codes
 */
 TInt DRM_DebugChannel::ReadMemory(DThread* aThread, TRM_DebugMemoryInfo* aMemoryInfo)
-{
+	{
 	LOG_MSG("DRM_DebugChannel::ReadMemory()");
 
 	TInt err = KErrNone;
@@ -1700,9 +1726,9 @@
 	TUint8 *data = (TUint8*)Kern::Alloc(info.iLength);
 	NKern::ThreadLeaveCS();
 	if (!data)
-	{
+		{
 		return KErrNoMemory;
-	}
+		}
 
 	TPtr8 dataDes(data, info.iLength);
 
@@ -1717,7 +1743,7 @@
 	NKern::ThreadLeaveCS();
 
 	return err;
-}
+	}
 
 /**
 Attempt to write memory to aThread's address space
@@ -1734,7 +1760,7 @@
 	or another of the system wide error codes
 */
 TInt DRM_DebugChannel::WriteMemory(DThread* aThread, TRM_DebugMemoryInfo* aMemoryInfo)
-{
+	{
 	LOG_MSG("DRM_DebugChannel::WriteMemory()");
 
 	TInt err = KErrNone;
@@ -1754,30 +1780,30 @@
 	TUint8 *data = (TUint8*)Kern::Alloc(info.iLength);
 	NKern::ThreadLeaveCS();
 	if (!data)
-	{
+		{
 		return KErrNoMemory;
-	}
+		}
 
 	TPtr8 dataDes(data, info.iLength);
 
 	err = Kern::ThreadDesRead(iClientThread, info.iData, dataDes, 0);
 	if (err == KErrNone)
-	{
+		{
 		err = DoWriteMemory(aThread, info.iAddress, info.iLength, dataDes);
-	}
+		}
 
 	NKern::ThreadEnterCS();
 	Kern::Free(data);
 	NKern::ThreadLeaveCS();
 
 	return err;
-}
+	}
 
 //
 // DRM_DebugChannel::ReadRegisters
 //
 TInt DRM_DebugChannel::ReadRegistersLegacy(DThread* aThread, TRM_DebugRegisterInfo* aRegisterInfo)
-{
+	{
 	LOG_MSG("DRM_DebugChannel::ReadRegistersLegacy()");
 
 	TInt err = KErrNone;
@@ -1799,24 +1825,24 @@
 	TUint8 *values = (TUint8*)Kern::Alloc(length);
 	NKern::ThreadLeaveCS();
 	if (!values)
-	{
+		{
 		return KErrNoMemory;
-	}
+		}
 
 	TPtr8 valuesDes(values, length);
 
 	err = DoReadRegisters(aThread, info.iFirstRegister, info.iLastRegister, valuesDes);
 	if (err == KErrNone)
-	{
+		{
 		err = Kern::ThreadDesWrite(iClientThread, info.iValues, valuesDes, 0, KChunkShiftBy0, iClientThread);
-	}
+		}
 
 	NKern::ThreadEnterCS();
 	Kern::Free(values);
 	NKern::ThreadLeaveCS();
 
 	return err;
-}
+	}
 
 /**
 Get listing information.
@@ -1922,6 +1948,7 @@
 		//if no error then write the buffer back
 		err = Kern::ThreadDesWrite(iClientThread, info.iBuffer, buffer, 0, KChunkShiftBy0, iClientThread);
 		}
+
 	//write back the size of the data regardless of any error
 	TInt writeErr = Kern::ThreadRawWrite(iClientThread, info.iDataSize, (TUint8*)&dataSize, sizeof(TUint32), iClientThread);
 	if(writeErr != KErrNone)
@@ -1956,7 +1983,7 @@
         KErrDied, if the thread with thread ID aThreadId is dead
 */
 TInt DRM_DebugChannel::ReadRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) const
-{
+	{
 	LOG_MSG("DRM_DebugChannel::ReadRegisters()");
 
 	TInt err = KErrNone;
@@ -1978,11 +2005,11 @@
 	if(err != KErrNone)
 		{
 		if(err == KErrNoMemory)
-		{
+			{
 			NKern::ThreadEnterCS();
 			Kern::Free((TAny*)ids.Ptr());
 			NKern::ThreadLeaveCS();
-		}
+			}
 		return err;
 		}
 
@@ -1992,10 +2019,12 @@
 	if(err != KErrNone)
 		{
 		if(err == KErrNoMemory)
-		{	NKern::ThreadEnterCS();
+			{
+			NKern::ThreadEnterCS();
 			Kern::Free((TAny*)values.Ptr());
 			NKern::ThreadLeaveCS();
-		}
+			}
+
 		NKern::ThreadEnterCS();
 		Kern::Free((TAny*)ids.Ptr());
 		NKern::ThreadLeaveCS();
@@ -2008,11 +2037,11 @@
 	if(err != KErrNone)
 		{
 		if(err == KErrNoMemory)
-		{
+			{
 			NKern::ThreadEnterCS();
 			Kern::Free((TAny*)flags.Ptr());
 			NKern::ThreadLeaveCS();
-		}
+			}
 		NKern::ThreadEnterCS();
 		Kern::Free((TAny*)ids.Ptr());
 		Kern::Free((TAny*)values.Ptr());
@@ -2037,13 +2066,13 @@
 	NKern::ThreadLeaveCS();
 
 	return err;
-}
+	}
 
 /**
 @deprecated use DRM_DebugChannel::WriteRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) instead
 */
 TInt DRM_DebugChannel::WriteRegistersLegacy(DThread* aThread, const TRM_DebugRegisterInfo* aRegisterInfo)
-{
+	{
 	LOG_MSG("DRM_DebugChannel::WriteRegistersLegacy()");
 
 	TInt err = KErrNone;
@@ -2065,24 +2094,24 @@
 	TUint8 *values = (TUint8*)Kern::Alloc(length);
 	NKern::ThreadLeaveCS();
 	if (!values)
-	{
+		{
 		return KErrNoMemory;
-	}
+		}
 
 	TPtr8 valuesDes(values, length);
 
 	err = Kern::ThreadDesRead(iClientThread, info.iValues, valuesDes, 0);
 	if (err == KErrNone)
-	{
+		{
 		err = DoWriteRegisters(aThread, info.iFirstRegister, info.iLastRegister, valuesDes);
-	}
+		}
 
 	NKern::ThreadEnterCS();
 	Kern::Free(values);
 	NKern::ThreadLeaveCS();
 
 	return err;
-}
+	}
 
 /**
 Write registers and store flags data in aRegisterInfo
@@ -2103,7 +2132,7 @@
         KErrDied, if the thread with thread ID aThreadId is dead
 */
 TInt DRM_DebugChannel::WriteRegisters(DThread* aThread, TRM_DebugRegisterInformation* aRegisterInfo) const
-{
+	{
 	LOG_MSG("DRM_DebugChannel::WriteRegisters()");
 
 	TInt err = KErrNone;
@@ -2181,7 +2210,7 @@
 	NKern::ThreadLeaveCS();
 
 	return err;
-}
+	}
 
 /**
 Suspends execution of the specified thread.
@@ -2239,6 +2268,7 @@
 				}
 			}
 		} while(breakEntry);
+
 	return TheDProcessTracker.ResumeThread(aThread);
 	}
 
@@ -2246,7 +2276,7 @@
 // DRM_DebugChannel::DoStepRange
 //
 TInt DRM_DebugChannel::DoStepRange(DThread *aThread, const TUint32 aStartAddress, const TUint32 aStopAddress, TBool aStepInto, TBool aResumeOnceOutOfRange, const TUint32 aNumSteps, TBool aUserRequest)
-{
+	{
 	LOG_MSG("DRM_DebugChannel::DoStepRange()");
 
 	if (!aThread)
@@ -2285,7 +2315,7 @@
 	LOG_MSG("DRM_DebugChannel::DoStepRange() - resuming thread\n");
 
 	return TheDProcessTracker.ResumeThread(aThread);
-}
+	}
 
 /**
 Read memory from the specified addres into the aData descriptor. If there is a
@@ -2382,7 +2412,7 @@
 	TInt err = KErrNone;
 
 	// trap exceptions in case the address is invalid
-	XTRAPD(r, XT_DEFAULT,  err = TryToWriteMemory(aThread, (TAny *)aAddress, (TAny *)aData.Ptr(), aLength));
+	XTRAPD(r, XT_DEFAULT, err = TryToWriteMemory(aThread, (TAny *)aAddress, (TAny *)aData.Ptr(), aLength));
 
 	err = (KErrNone == r) ? err : r;
 
@@ -2436,8 +2466,8 @@
 // DRM_DebugChannel::DoReadRegisters
 //
 TInt DRM_DebugChannel::DoReadRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDes8 &aValues)
-{
-	LOG_MSG("DRM_DebugChannel::DoReadRegisters()");
+	{
+	LOG_EVENT_MSG("DRM_DebugChannel::DoReadRegisters()");
 
 	// make sure the parameters are valid
 	if (!aThread || (aFirstRegister < 0) || (aLastRegister >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
@@ -2448,19 +2478,19 @@
 		return KErrArgument;
 
 	TArmRegSet regSet;
-    TUint32 unused;
+	TUint32 unused;
 
 	NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, unused);
 
 	LOG_MSG2( "DRM_DebugChannel::DoReadRegistersLegacy() : unused = 0x%X\n", unused );
 
-    TArmReg *reg = &regSet.iR0;
+	TArmReg *reg = &regSet.iR0;
 
 	if (!reg)
 		return KErrGeneral;
 
-    for (TInt16 i = aFirstRegister; i <= aLastRegister; i++)
-    	aValues.Append((TUint8 *)&reg[i], sizeof(TArmReg));
+	for (TInt16 i = aFirstRegister; i <= aLastRegister; i++)
+		aValues.Append((TUint8 *)&reg[i], sizeof(TArmReg));
 
 	return KErrNone;
 }
@@ -2510,7 +2540,7 @@
         KErrGeneral if there was a problem initialising the register set
 */
 TInt DRM_DebugChannel::DoReadRegisters(DThread *aThread, const TDesC8 &aRegisterIds, TDes8 &aRegisterValues, TDes8& aRegisterFlags) const
-{
+	{
 	LOG_MSG("DRM_DebugChannel::DoReadRegisters()");
 
 	// make sure the parameters are valid
@@ -2613,13 +2643,13 @@
 			}
 		}
 	return KErrNone;
-}
+	}
 
 //
 // DRM_DebugChannel::DoWriteRegisters
 //
 TInt DRM_DebugChannel::DoWriteRegisters(DThread *aThread, const TInt16 aFirstRegister, const TInt16 aLastRegister, TDesC8 &aValues)
-{
+	{
 	LOG_MSG("DRM_DebugChannel::DoWriteRegisters()");
 
 	// make sure the parameters are valid
@@ -2643,7 +2673,7 @@
 	NKern::ThreadSetUserContext(&aThread->iNThread, &regSet);
 
 	return KErrNone;
-}
+	}
 
 /**
 Write registers and store flags indicating which registers could be read in
@@ -2662,7 +2692,7 @@
         KErrGeneral if there was a problem initialising the register set
 */
 TInt DRM_DebugChannel::DoWriteRegisters(DThread *aThread, const TDesC8 &aRegisterIds, TDesC8 &aRegisterValues, TDes8 &aRegisterFlags) const
-{
+	{
 	LOG_MSG("DRM_DebugChannel::DoWriteRegisters()");
 
 	// make sure the parameters are valid
@@ -2765,23 +2795,23 @@
 // DRM_DebugChannel::DoSecurityCheck
 //
 TBool DRM_DebugChannel::DoSecurityCheck()
-{
+	{
 	LOG_MSG("DRM_DebugChannel::DoSecurityCheck");
 	DProcess* clientProcess = iClientThread->iOwningProcess;
 	if (clientProcess)
-	{
+		{
 		SSecurityInfo secureInfo = clientProcess->iS;
 
 		LOG_MSG2("DoSecurityCheck - client secure id is 0x%08x",secureInfo.iSecureId);
 
 		// Ensure we really are communicating with the Debug Security Server
 		if (secureInfo.iSecureId == KUidDebugSecurityServer.iUid )
-		{
+			{
 			return ETrue;
+			}
 		}
+	return EFalse;
 	}
-	return EFalse;
-}
 
 /**
 Attempt to read memory from aThread's address space
@@ -2795,7 +2825,7 @@
 	or another of the system wide error codes
 */
 TInt DRM_DebugChannel::TryToReadMemory(const DThread *aThread, const TAny *aSrc, TAny *aDest, const TUint32 aLength) const
-{
+	{
 	LOG_MSG("DRM_DebugChannel::TryToReadMemory()");
 
 	// make sure the parameters are valid
@@ -2814,7 +2844,7 @@
 
 	LOG_MSG2("Using Kern::ThreadRawRead to read memory at address %x", aSrc);
 	return Kern::ThreadRawRead((DThread *)aThread, aSrc, aDest, aLength);
-}
+	}
 
 /**
 Attempt to write memory to aThread's address space
@@ -2828,7 +2858,7 @@
         error codes
 */
 TInt DRM_DebugChannel::TryToWriteMemory(const DThread *aThread, TAny *aDest, const TAny *aSrc, const TUint32 aLength)
-{
+	{
 	LOG_MSG("DRM_DebugChannel::TryToWriteMemory()");
 
 	//check that the thread is suspended before writing the memory
@@ -2840,30 +2870,30 @@
 
 	LOG_MSG2("Using Kern::ThreadRawWrite to write memory at address %x", (TUint32)aDest);
 	return Kern::ThreadRawWrite((DThread *)aThread, aDest, aSrc, aLength, iClientThread);
-}
+	}
 
 /**
 @deprecated use DRM_DebugChannel::ReadKernelRegisterValue(DThread *aThread, const TArmReg aKernelRegisterId, T4ByteRegisterValue &aValue) instead
 */
 TInt32 DRM_DebugChannel::ReadRegister(DThread *aThread, TInt aNum)
-{
+	{
 	LOG_MSG("DRM_DebugChannel::ReadRegister()");
 
 	if (!aThread || (aNum < 0) || (aNum >= (TInt16)(sizeof(TArmRegSet)/sizeof(TArmReg))))
-	{
+		{
 		LOG_MSG2("Invalid register number (%d) passed to ReadRegister", aNum);
 		return 0;
-	}
+		}
 
 	TArmRegSet regSet;
-    TUint32 unused;
+	TUint32 unused;
 
 	NKern::ThreadGetUserContext(&aThread->iNThread, &regSet, unused);
 
-    TArmReg *reg = &regSet.iR0;
+	TArmReg *reg = &regSet.iR0;
 
 	return ((TUint32 *)reg)[aNum];
-}
+	}
 
 /**
 Given a TArmReg register ID, read the value of the register. The register value
@@ -2879,7 +2909,7 @@
         or a return value from DRM_DebugChannel::ReadDebugRegisterValue()
 */
 TInt32 DRM_DebugChannel::ReadKernelRegisterValue(DThread *aThread, const TArmReg aKernelRegisterId, T4ByteRegisterValue &aValue) const
-{
+	{
 	//get register ID as a TRegisterInfo ID
 	TRegisterInfo regId;
 	TInt err = GetDebugRegisterId(aKernelRegisterId, regId);
@@ -2906,33 +2936,34 @@
         or a return value from DRM_DebugChannel::DoReadRegisters
 */
 TInt32 DRM_DebugChannel::ReadDebugRegisterValue(DThread *aThread, const TRegisterInfo aDebugRegisterId, T4ByteRegisterValue &aValue) const
-{
+	{
 	//allocate temporary buffers to store data
 	NKern::ThreadEnterCS();
 	TUint8* id = (TUint8*)Kern::Alloc(sizeof(TRegisterInfo));
 	NKern::ThreadLeaveCS();
 	if(id == NULL)
-	{
+		{
 		return KErrNoMemory;
-	}
+		}
+
 	TPtr8 idPtr(id, sizeof(TRegisterInfo));
 
 	NKern::ThreadEnterCS();
 	TUint8* value = (TUint8*)Kern::Alloc(sizeof(T4ByteRegisterValue));
 	NKern::ThreadLeaveCS();
 	if(value == NULL)
-	{
+		{
 		return KErrNoMemory;
-	}
+		}
 	TPtr8 valuePtr(value, sizeof(T4ByteRegisterValue));
 
 	NKern::ThreadEnterCS();
 	TUint8* flag = (TUint8*)Kern::Alloc(sizeof(TUint8));
 	NKern::ThreadLeaveCS();
 	if(flag == NULL)
-	{
+		{
 		return KErrNoMemory;
-	}
+		}
 	TPtr8 flagPtr(flag, sizeof(TUint8));
 
 	//store register id in buffer
@@ -2941,18 +2972,18 @@
 	//read registers
 	TInt err = DoReadRegisters(aThread, idPtr, valuePtr, flagPtr);
 	if(err == KErrNone)
-	{
+		{
 		if(*flag == EValid)
-		{
+			{
 			//register could be read so store value
 			aValue = *(T4ByteRegisterValue*)value;
-		}
+			}
 		else
-		{
+			{
 			//register couldn't be read for some reason
 			err = *flag;
+			}
 		}
-	}
 
 	//free memory
 	NKern::ThreadEnterCS();
@@ -2962,13 +2993,13 @@
 	NKern::ThreadLeaveCS();
 
 	return err;
-}
+	}
 
 //
 // DRM_DebugChannel::NotifyEvent
 //
 void DRM_DebugChannel::NotifyEvent(const TDriverEventInfo& aEventInfo)
-{
+	{
 	LOG_EVENT_MSG("DRM_DebugChannel::NotifyEvent()");
 
 	// Look for the relevant DTargetProcess
@@ -3016,7 +3047,7 @@
 		}
 
 	foundProcess->NotifyEvent(aEventInfo);
-}
+	}
 
 #ifndef __LAUNCH_AS_EXTENSION__
 DECLARE_STANDARD_LDD()
@@ -3112,23 +3143,23 @@
  * to both co-exist and exist independantly of the existing one *
  */
 DDebuggerInfo::DDebuggerInfo():
-    iObjectOffsetTable(NULL),
-    iObjectOffsetTableCount(NULL),
-    iThreadContextTable(NULL),
-    iStopModeExtension(new DStopModeExtension()),
-    iContainers(NULL),
-    iCodeSegLock(NULL),
-    iCodeSegGlobalList(NULL),
-    iScheduler(NULL),
-    iShadowPages(NULL),
-    iShadowPageCount(0),
-    iCurrentThread(NULL),
-    iEventMask(),
-    iEventHandlerBreakpoint(0),
-    iMemModelObjectOffsetTable(NULL),
-    iMemModelObjectOffsetTableCount(0)
-    {
-    }
+	iObjectOffsetTable(NULL),
+	iObjectOffsetTableCount(NULL),
+	iThreadContextTable(NULL),
+	iStopModeExtension(new DStopModeExtension()),
+	iContainers(NULL),
+	iCodeSegLock(NULL),
+	iCodeSegGlobalList(NULL),
+	iScheduler(NULL),
+	iShadowPages(NULL),
+	iShadowPageCount(0),
+	iCurrentThread(NULL),
+	iEventMask(),
+	iEventHandlerBreakpoint(0),
+	iMemModelObjectOffsetTable(NULL),
+	iMemModelObjectOffsetTableCount(0)
+	{
+	}
 
 /**
  * Installs the stop-mode debugger extension
@@ -3136,9 +3167,9 @@
  * existence in the superpage
 */
 void DStopModeExtension::Install(DStopModeExtension* aExt)
-    {
-    Kern::SuperPage().iDebuggerInfo->iStopModeExtension = aExt;
-    }
+	{
+	Kern::SuperPage().iDebuggerInfo->iStopModeExtension = aExt;
+	}
 
 #endif
 
@@ -3342,7 +3373,7 @@
 */
 TBool DRM_DebugChannel::GetFlagAtOffset(const TUint32 aFlags, const TArmReg aIndex) const
 	{
-	return ( aFlags & (1<<aIndex) ) ? ETrue : EFalse;
+	return aFlags & (1<<aIndex);
 	}
 
 /* Register the attachment of a debug agent to a process to be debugged
@@ -3475,38 +3506,38 @@
 	TUint8* buffer = (TUint8*)Kern::AllocZ(length);
 	NKern::ThreadLeaveCS();
 	if (buffer==NULL)
-	{
+		{
 		// Out of memory
 		return KErrNoMemory;
-	}
+		}
 
 	TPtr8 targetProcessName(buffer,length,length);
 
 	// Read the user-side data into targetProcessName
 	err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
 	if (err != KErrNone)
-	{
+		{
 		// Something bad happened so free the memory and return
 		NKern::ThreadEnterCS();
 		Kern::Free(buffer);
 		NKern::ThreadLeaveCS();
 
 		return err;
-	}
+		}
 
 	// Obtain the AgentId
 	TUint64 debugAgentId = 0;
 
 	err = Kern::ThreadRawRead(iClientThread,a2,&debugAgentId,sizeof(debugAgentId));
 	if (err != KErrNone)
-	{
+		{
 		// Something bad happened so free the memory and return
 		NKern::ThreadEnterCS();
 		Kern::Free(buffer);
 		NKern::ThreadLeaveCS();
 
 		return err;
-	}
+		}
 
 	// Remove the process from our list of tracked processes
 	err = TheDProcessTracker.DetachProcess(targetProcessName, debugAgentId);
@@ -3531,9 +3562,9 @@
 
 	TInt err = Kern::ThreadRawRead(iClientThread,a1,&debugAgentId,sizeof(debugAgentId));
 	if (err != KErrNone)
-	{
+		{
 		return err;
-	}
+		}
 
 	// Remove the process from our list of tracked processes
 	return TheDProcessTracker.DetachAgent(debugAgentId);
@@ -3578,30 +3609,30 @@
 	TUint8* buffer = (TUint8*)Kern::AllocZ(length);
 	NKern::ThreadLeaveCS();
 	if (buffer==NULL)
-	{
+		{
 		// Out of memory
 		return KErrNoMemory;
-	}
+		}
 	TPtr8 targetProcessName(buffer,length,length);
 
 	// Read the user-side data into targetProcessName
 	err = Kern::ThreadDesRead(iClientThread,a1,targetProcessName,0,KChunkShiftBy0);
 	if (err != KErrNone)
-	{
+		{
 		// Something bad happened so free the memory and return
 		NKern::ThreadEnterCS();
 		Kern::Free(buffer);
 		NKern::ThreadLeaveCS();
 
 		return err;
-	}
+		}
 
 	// Read the Event and Action from the user-side
 	TRM_DebugEventActionInfo info(0,0,0);
 
 	err = Kern::ThreadRawRead(iClientThread, a2, &info, sizeof(info));
 	if (err != KErrNone)
-	{
+		{
 		// Could not read event action data from the user-side
 
 		// Free memory used for targetProcessName
@@ -3610,12 +3641,12 @@
 		NKern::ThreadLeaveCS();
 
 		return err;
-	}
+		}
 
 	// Find the target process
 	DTargetProcess* pProcess = TheDProcessTracker.FindProcess(targetProcessName);
 	if (pProcess == NULL)
-	{
+		{
 		// Could not find this process
 
 		// Free memory used for targetProcessName
@@ -3624,14 +3655,14 @@
 		NKern::ThreadLeaveCS();
 
 		return KErrArgument;
-	}
+		}
 
 	TUint64 debugAgentId = info.iAgentId;
 
 	// Find the agent
 	DDebugAgent* debugAgent = pProcess->Agent(debugAgentId);
 	if (debugAgent == NULL)
-	{
+		{
 		// Bad agent means there is no tracking agent
 		LOG_MSG2("Cannot locate debug agent with pid 0x%0x16lx",info.iAgentId);
 
@@ -3641,7 +3672,7 @@
 		NKern::ThreadLeaveCS();
 
 		return KErrGeneral;
-	}
+		}
 
 	// Set the event action
 	debugAgent->SetEventAction((TEventType)info.iEvent,(TKernelEventAction)info.iAction);
@@ -3752,9 +3783,9 @@
 		}
 
 	if (err == KErrNone)
-	{
+		{
 		LOG_MSG2("DRM_DebugChannel::IsDebuggable(aProcessId 0x%08x) - Yes it is debuggable\n",aProcessId);
-	}
+		}
 
 	return err;
 	}
--- a/kernel/eka/drivers/dma/dmapil.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/dma/dmapil.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -1,4 +1,4 @@
-// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2002-2010 Nokia Corporation and/or its subsidiary(-ies).
 // All rights reserved.
 // This component and the accompanying materials are made available
 // under the terms of the License "Eclipse Public License v1.0"
@@ -861,7 +861,11 @@
 		// release threads doing CancelAll()
 		waiters->Signal();
 		}
-	else if (!error && iController->IsIdle(*this) && !iReqQ.IsEmpty() && !iDfc.Queued())
+	// (iController may be NULL here if the channel was closed in the client callback.)
+	else if (!error &&
+			 iController && iController->IsIdle(*this) &&
+			 !iReqQ.IsEmpty() &&
+			 !iDfc.Queued())
 		{
 		// Wait for a bit. If during that time the condition goes away then it
 		// was a 'spurious missed interrupt', in which case we just do nothing.
--- a/kernel/eka/drivers/media/base_e32_drivers_media.mrp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/media/base_e32_drivers_media.mrp	Mon Mar 15 12:45:50 2010 +0200
@@ -23,8 +23,6 @@
 source	\sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\stackbody.cpp
 source	\sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\stackbody.h
 source	\sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\distribution.policy.s60
-source	\sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\sdcard\Obtaining_PSL_Software_Source_Code.txt
-source	\sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\sdcard\distribution.policy.s60
 source	\sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\sdcard\sdcard3c\sdcard.cpp
 source	\sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\sdcard\sdcard3c\epbussd.mmp
 source	\sf\os\kernelhwsrv\kernel\eka\drivers\pbus\mmc\sdcard\sdcard3c\distribution.policy.s60
--- a/kernel/eka/drivers/pbus/spbus.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/pbus/spbus.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -1111,6 +1111,9 @@
 	OstTraceFunctionEntry1( DPBUSSOCKET_DOORCLOSEEVENT_ENTRY, this );
 	__KTRACE_OPT(KPBUS1,Kern::Printf(">DPBusSocket(%d)::DoorCloseEvent state %d",iSocketNumber,iState));
 	OstTraceExt2(TRACE_INTERNALS, DPBUSSOCKET_DOORCLOSEEVENT , "iSocketNumber=%d; iState=%d",iSocketNumber,iState);
+	
+	if (iPostponedEvents & EMediaChange)
+		iPostponedEvents &= ~EMediaChange;
 
 	// NB If there are multiple doors then the bus may already be powererd up, 
 	// so it's not possible to determine the bus state.
--- a/kernel/eka/drivers/usbc/d_usbc.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/usbc/d_usbc.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -1959,7 +1959,12 @@
             // Parcel out the memory between endpoints
             TUint8* newAddr = reinterpret_cast<TUint8*>(chunk->LinearAddress());
             __KTRACE_OPT(KUSB, Kern::Printf("SetupInterfaceMemory alloc new chunk=0x%x, size=%d", newAddr,bufSizes[chunkInd]));
-            chunkChanged = (newAddr != oldAddr);
+            // The check is important to avoid chunkChanged to be corrupted.
+            // This code change is to fix the problem that one chunk is used by multiple interfaces.
+            if(!chunkChanged)
+            	{
+            	chunkChanged = (newAddr != oldAddr);
+            	}            
             aHwChunks[chunkInd] = chunk;
             }
         chunkInd++;
--- a/kernel/eka/drivers/usbcc/ps_usbc.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/drivers/usbcc/ps_usbc.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -180,11 +180,13 @@
 		}
 	DeActivateHardwareController();					 // turn off UDC altogether
 	iStackIsActive = EFalse;
+	// Notify registered clients on the user side about a USB device state
+	// change event and a transition to the "Undefined" state.
+	// Note: the state should be changed to "Undefined" before calling RunClientCallbacks(), 
+	//       otherwise the "Undefined" state will probably be lost.
+	NextDeviceState(EUsbcDeviceStateUndefined);
 	// Complete all pending requests, returning KErrDisconnected
 	RunClientCallbacks();
-	// Notify registered clients on the user side about a USB device state
-	// change event and a transition to the "Undefined" state.
-	NextDeviceState(EUsbcDeviceStateUndefined);
 	}
 
 
--- a/kernel/eka/include/drivers/rm_debug_eventhandler.h	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/include/drivers/rm_debug_eventhandler.h	Mon Mar 15 12:45:50 2010 +0200
@@ -27,14 +27,24 @@
 		TInt Start();
 		TInt Stop();
 		
+		inline void DRM_DebugEventHandler::LockDataAccess()
+		    {
+		    Kern::SemaphoreWait(*iProtectionLock);
+		    }
+
+		inline void DRM_DebugEventHandler::ReleaseDataAccess()
+		    {
+		    Kern::SemaphoreSignal(*iProtectionLock);
+		    }
+		
 	private:
 		static TUint EventHandler(TKernelEvent aEvent, TAny* a1, TAny* a2, TAny* aThis);
 		TUint HandleEvent(TKernelEvent aType, TAny* a1, TAny* a2);
 		TBool HandleSpecificEvent(TKernelEvent aType, TAny* a1, TAny* a2);
 		
 	private:
-		/** Lock serialising calls to event handler */
-		DSemaphore* iLock;
+		/** Used to serialise access data structures */
+		DSemaphore* iProtectionLock;
 
 		TBool iTracking;
 
--- a/kernel/eka/include/e32ver.h	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/include/e32ver.h	Mon Mar 15 12:45:50 2010 +0200
@@ -28,7 +28,7 @@
 
 const TInt KE32MajorVersionNumber=2;
 const TInt KE32MinorVersionNumber=0;
-const TInt KE32BuildVersionNumber=2083;
+const TInt KE32BuildVersionNumber=2091;
 
 const TInt KMachineConfigurationMajorVersionNumber=1;
 const TInt KMachineConfigurationMinorVersionNumber=0;
--- a/kernel/eka/include/nkern/nk_priv.h	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/include/nkern/nk_priv.h	Mon Mar 15 12:45:50 2010 +0200
@@ -541,10 +541,12 @@
 #define MASK_NOT_IDFC 0x800 
 #define MASK_NOT_THREAD 0x1000
 #define MASK_NO_CRITICAL_IF_USER 0x2000
+#define MASK_ALWAYS_FAIL 0x4000
+#define	MASK_NO_RESCHED 0x8000
+#define MASK_NO_KILL_OR_SUSPEND	0x10000
+
 #define MASK_THREAD_STANDARD ( MASK_NO_FAST_MUTEX | MASK_KERNEL_UNLOCKED | MASK_INTERRUPTS_ENABLED | MASK_NOT_ISR | MASK_NOT_IDFC )
 #define MASK_THREAD_CRITICAL ( MASK_THREAD_STANDARD | MASK_CRITICAL )
-#define MASK_ALWAYS_FAIL 0x4000
-#define	MASK_NO_RESCHED 0x8000
 
 #if defined(__STANDALONE_NANOKERNEL__) || (!defined (__KERNEL_APIS_CONTEXT_CHECKS_WARNING__)&&!defined (__KERNEL_APIS_CONTEXT_CHECKS_FAULT__))
 #define CHECK_PRECONDITIONS(mask,function)
--- a/kernel/eka/include/nkernsmp/nk_priv.h	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/include/nkernsmp/nk_priv.h	Mon Mar 15 12:45:50 2010 +0200
@@ -810,10 +810,12 @@
 #define MASK_NOT_IDFC 0x800 
 #define MASK_NOT_THREAD 0x1000
 #define MASK_NO_CRITICAL_IF_USER 0x2000
+#define MASK_ALWAYS_FAIL 0x4000
+#define	MASK_NO_RESCHED 0x8000
+#define MASK_NO_KILL_OR_SUSPEND	0x10000
+
 #define MASK_THREAD_STANDARD ( MASK_NO_FAST_MUTEX | MASK_KERNEL_UNLOCKED | MASK_INTERRUPTS_ENABLED | MASK_NOT_ISR | MASK_NOT_IDFC )
 #define MASK_THREAD_CRITICAL ( MASK_THREAD_STANDARD | MASK_CRITICAL )
-#define MASK_ALWAYS_FAIL 0x4000
-#define	MASK_NO_RESCHED 0x8000
 
 #if defined(__STANDALONE_NANOKERNEL__) || (!defined (__KERNEL_APIS_CONTEXT_CHECKS_WARNING__)&&!defined (__KERNEL_APIS_CONTEXT_CHECKS_FAULT__))
 #define CHECK_PRECONDITIONS(mask,function)
--- a/kernel/eka/kernel/server.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/kernel/server.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -1009,7 +1009,7 @@
 */
 EXPORT_C void DBase::AsyncDelete()
 	{
-	CHECK_PRECONDITIONS(MASK_KERNEL_UNLOCKED | MASK_INTERRUPTS_ENABLED | MASK_NOT_ISR | MASK_NOT_IDFC | MASK_CRITICAL, "DObject::AsyncDelete");
+	CHECK_PRECONDITIONS(MASK_NO_KILL_OR_SUSPEND | MASK_INTERRUPTS_ENABLED | MASK_NOT_ISR | MASK_NOT_IDFC, "DObject::AsyncDelete");
 	__KTRACE_OPT(KSERVER,Kern::Printf("DBase::AsyncDelete() %08x",this));
 	
 	DBase* oldHead = K::AsyncDeleteHead;
@@ -1039,22 +1039,14 @@
 // Asynchronously free a kernel heap cell (must be >=4 bytes in length)
 //
 	{
-	CHECK_PRECONDITIONS(MASK_KERNEL_UNLOCKED | MASK_INTERRUPTS_ENABLED | MASK_NOT_ISR | MASK_NOT_IDFC | MASK_CRITICAL, "Kern::AsyncFree");
+	CHECK_PRECONDITIONS(MASK_NO_KILL_OR_SUSPEND | MASK_INTERRUPTS_ENABLED | MASK_NOT_ISR | MASK_NOT_IDFC, "Kern::AsyncFree");
 	__KTRACE_OPT(KSERVER,Kern::Printf("Kern::AsyncFree(%08x)",aPtr));
-	DThread* pT=TheCurrentThread;
-
-	// if we are already running in the kernel server, just free the cell now
-	if (pT==K::TheKernelThread)
-		Kern::Free(aPtr);
-	else
-		{
-		TAny* oldHead = K::AsyncFreeHead;
-		do	{
-			*(TAny**)aPtr = oldHead;	// use first word of cell as link field
-			} while (!__e32_atomic_cas_rel_ptr(&K::AsyncFreeHead, &oldHead, aPtr));
-		if (!oldHead)
-			K::AsyncFreeDfc.Enque();
-		}
+	TAny* oldHead = K::AsyncFreeHead;
+	do	{
+		*(TAny**)aPtr = oldHead;	// use first word of cell as link field
+		} while (!__e32_atomic_cas_rel_ptr(&K::AsyncFreeHead, &oldHead, aPtr));
+	if (!oldHead)
+		K::AsyncFreeDfc.Enque();
 	}
 
 
--- a/kernel/eka/kernel/sutils.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/kernel/sutils.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -2967,12 +2967,17 @@
 		else if (!nt || nt->iCsCount==0)
 			m &= ~MASK_NO_CRITICAL;
 		}
-	if (m & MASK_CRITICAL)
+	if (m & (MASK_CRITICAL|MASK_NO_KILL_OR_SUSPEND))
 		{
 		if (t && (t->iThreadType!=EThreadUser || nt->iCsCount>0))
-			m &= ~MASK_CRITICAL;
+			m &= ~(MASK_CRITICAL|MASK_NO_KILL_OR_SUSPEND);
 		else if (!nt || nt->iCsCount>0)
-			m &= ~MASK_CRITICAL;
+			m &= ~(MASK_CRITICAL|MASK_NO_KILL_OR_SUSPEND);
+		}
+	if (m & MASK_NO_KILL_OR_SUSPEND)
+		{
+		if (!nt || NKern::KernelLocked() || NKern::HeldFastMutex())
+			m &= ~MASK_NO_KILL_OR_SUSPEND;
 		}
 	if (m & MASK_KERNEL_LOCKED)
 		{
@@ -3074,6 +3079,8 @@
 		Kern::Printf("Assertion failed");
 	if (m & MASK_NO_RESCHED)
 		Kern::Printf("Assertion failed: Don't call from thread with kernel unlocked");
+	if (m & MASK_NO_KILL_OR_SUSPEND)
+		Kern::Printf("Assertion failed: Must not be suspended or killed here");
 
 #ifdef __KERNEL_APIS_CONTEXT_CHECKS_FAULT__
 	if (aFunction)
--- a/kernel/eka/memmodel/emul/win32/mprocess.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/memmodel/emul/win32/mprocess.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -191,14 +191,18 @@
 	
 	TInt count=0;
 	TInt err = KErrNone;
-	data.iDataCopy = Kern::Alloc(seg->iRealDataSize);
-	data.iBssCopy = Kern::Alloc(seg->iRealBssSize);
+
+	// Scheduling must be disabled while we are allocating memory from Windows' heap
+	NKern::Lock();
+	data.iDataCopy = GlobalAlloc(GMEM_FIXED, seg->iRealDataSize);
+	data.iBssCopy = GlobalAlloc(GMEM_FIXED, seg->iRealBssSize);
+	NKern::Unlock();
 	if (!data.iDataCopy || !data.iBssCopy)
 		{
 		err = KErrNoMemory;
 		goto failed;
 		}
-		
+
 	memcpy(data.iDataCopy, seg->iDataCopy, seg->iRealDataSize);	// start with init data
 	memclr(data.iBssCopy, seg->iRealBssSize);					// initialized to zeros
 
@@ -215,8 +219,11 @@
 	return KErrNone;	
 
 failed:
-	Kern::Free(data.iDataCopy);
-	Kern::Free(data.iBssCopy);
+	// Scheduling must be disabled while we are freeing memory from Windows' heap
+	NKern::Lock();
+	GlobalFree(data.iDataCopy);
+	GlobalFree(data.iBssCopy);
+	NKern::Unlock();
 
 	return err;
 	}
@@ -245,9 +252,13 @@
 	
 	if (ix < 0)
 		return;
-	
-	Kern::Free(data.iDataCopy);
-	Kern::Free(data.iBssCopy);
+
+	// Scheduling must be disabled while we are freeing memory from Windows' heap
+	NKern::Lock();
+	GlobalFree(data.iDataCopy);
+	GlobalFree(data.iBssCopy);
+	NKern::Unlock();
+
 	__KTRACE_OPT(KDLL,Kern::Printf("Process %O UnmapCodeSeg(%C)", this, aSeg));
 	}
 
@@ -261,10 +272,10 @@
 		NKern::Lock();
 		if (data.iCodeSeg->iLiveProcess == this)
 			data.iCodeSeg->iLiveProcess = NULL;
+		iDllData.Remove(ii);
+		GlobalFree(data.iDataCopy);
+		GlobalFree(data.iBssCopy);
 		NKern::Unlock();
-		iDllData.Remove(ii);
-		Kern::Free(data.iDataCopy);
-		Kern::Free(data.iBssCopy);
 		}
 	}
 
--- a/kernel/eka/memmodel/epoc/flexible/mmu/mm.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/memmodel/epoc/flexible/mmu/mm.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -204,17 +204,18 @@
 
 void DReferenceCountedObject::Open()
 	{
-	__ASSERT_CRITICAL
-	TBool ok = __e32_atomic_tas_ord32(&iReferenceCount, 1, 1, 0);
-	__NK_ASSERT_ALWAYS(ok);
+	CHECK_PRECONDITIONS(MASK_NO_KILL_OR_SUSPEND, "DReferenceCountedObject::Open");
+	TInt orig = __e32_atomic_tas_ord32(&iReferenceCount, 1, 1, 0);
+	if (orig <= 0)
+		__crash();
 	}
 
 
 TBool DReferenceCountedObject::TryOpen()
 	{
-	__ASSERT_CRITICAL
-	TBool ok = __e32_atomic_tas_ord32(&iReferenceCount, 1, 1, 0);
-	return ok;
+	CHECK_PRECONDITIONS(MASK_NO_KILL_OR_SUSPEND, "DReferenceCountedObject::Open");
+	TInt orig = __e32_atomic_tas_ord32(&iReferenceCount, 1, 1, 0);
+	return (orig>0);
 	}
 
 
@@ -245,20 +246,23 @@
 
 void DReferenceCountedObject::Close()
 	{
-	__ASSERT_CRITICAL
 	__NK_ASSERT_DEBUG(CheckCloseIsSafe());
-	__NK_ASSERT_DEBUG(iReferenceCount>0);
-	if (__e32_atomic_tas_ord32(&iReferenceCount, 1, -1, 0) == 1)
+	TInt orig = __e32_atomic_tas_ord32(&iReferenceCount, 1, -1, 0);
+	if (orig == 1)
 		delete this;
+	else if (orig <= 0)
+		__crash();
 	}
 
 
 void DReferenceCountedObject::AsyncClose()
 	{
-	__ASSERT_CRITICAL
-	__NK_ASSERT_DEBUG(iReferenceCount>0);
-	if (__e32_atomic_tas_ord32(&iReferenceCount, 1, -1, 0) == 1)
+	CHECK_PRECONDITIONS(MASK_NO_KILL_OR_SUSPEND, "DReferenceCountedObject::AsyncClose");
+	TInt orig = __e32_atomic_tas_ord32(&iReferenceCount, 1, -1, 0);
+	if (orig == 1)
 		AsyncDelete();
+	else if (orig <= 0)
+		__crash();
 	}
 
 
--- a/kernel/eka/nkern/win32/ncsched.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/nkern/win32/ncsched.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -835,6 +835,61 @@
 
 #include <winnt.h>
 
+// Uncomment the following line to turn on tracing when we examine the call stack
+// #define DUMP_STACK_BACKTRACE
+
+#ifdef DUMP_STACK_BACKTRACE
+
+#include <psapi.h>
+
+typedef BOOL (WINAPI GMIFunc)(HANDLE hProcess, HMODULE hModule, LPMODULEINFO lpmodinfo, DWORD cb);
+typedef BOOL (WINAPI EPMFunc)(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded);
+typedef DWORD (WINAPI GMBNFunc)(HANDLE hProcess, HMODULE hModule, LPSTR lpBaseName, DWORD nSize);
+
+void PrintAllModuleInfo()
+	{
+	HMODULE psapiLibrary = LoadLibraryA("psapi.dll");
+	__NK_ASSERT_ALWAYS(psapiLibrary != NULL);
+
+	EPMFunc* epmFunc = (EPMFunc*)GetProcAddress(psapiLibrary, "EnumProcessModules");
+	__NK_ASSERT_ALWAYS(epmFunc != NULL);
+	
+	GMIFunc* gmiFunc = (GMIFunc*)GetProcAddress(psapiLibrary, "GetModuleInformation");
+	__NK_ASSERT_ALWAYS(gmiFunc != NULL);
+	
+	GMBNFunc* gmbnFunc = (GMBNFunc*)GetProcAddress(psapiLibrary, "GetModuleBaseNameA");
+	__NK_ASSERT_ALWAYS(gmbnFunc != NULL);
+
+	const TInt maxModules = 256;
+	HMODULE modules[maxModules];
+
+	DWORD spaceNeeded;
+	BOOL r = epmFunc(GetCurrentProcess(), modules, sizeof(HMODULE) * maxModules, &spaceNeeded);
+	__NK_ASSERT_ALWAYS(r);
+	__NK_ASSERT_ALWAYS(spaceNeeded <= sizeof(HMODULE) * maxModules);
+
+	for (TUint i = 0 ; i < spaceNeeded / sizeof(HMODULE) ; ++i)
+		{
+		HMODULE library = modules[i];
+		
+		const TUint maxNameLen = 64;
+		char name[maxNameLen];
+		WORD len = gmbnFunc(GetCurrentProcess(), library, name, sizeof(name));
+		__NK_ASSERT_ALWAYS(len > 0 && len < maxNameLen);
+		
+		MODULEINFO info;
+		r = gmiFunc(GetCurrentProcess(), library, &info, sizeof(info));
+		__NK_ASSERT_ALWAYS(r);
+		
+		DEBUGPRINT("Module %s found at %08x to %08x", name, (TUint)info.lpBaseOfDll, (TUint)info.lpBaseOfDll + info.SizeOfImage);
+		}
+
+	r = FreeLibrary(psapiLibrary);
+	__NK_ASSERT_ALWAYS(r);
+	}
+
+#endif
+
 const TInt KWin32NonPreemptibleFunctionCount = 2;
 
 struct TWin32FunctionInfo
@@ -845,14 +900,37 @@
 
 static TWin32FunctionInfo Win32NonPreemptibleFunctions[KWin32NonPreemptibleFunctionCount];
 
-TWin32FunctionInfo Win32FindExportedFunction(const char* aModuleName, const char* aFunctionName)
+HMODULE GetFirstLoadedModuleHandleA(const char* aModuleName1, const char* aModuleName2)
+	{
+	HMODULE result = GetModuleHandleA(aModuleName1);
+	return result ? result : GetModuleHandleA(aModuleName2);
+	}
+
+TWin32FunctionInfo Win32FindExportedFunction(const char* aFunctionName, ...)
 	{
-	HMODULE library = GetModuleHandleA(aModuleName);
+	const char *libname;
+	HMODULE library = NULL;
+
+	va_list arg;
+	va_start(arg, aFunctionName);
+
+	// Loop through arguments until we find a library we can get a handle to.  List of library names
+	// is NULL-terminated.
+	while ((libname = va_arg(arg, const char *)) != NULL)
+		{
+		library = GetModuleHandleA(libname);
+		if (library != NULL)
+			break;
+		}
+
+	va_end(arg);
+
+	// Make sure we did get a valid library
 	__NK_ASSERT_ALWAYS(library != NULL);
-
+	
 	// Find the start address of the function
 	TUint start = (TUint)GetProcAddress(library, aFunctionName);
-	__NK_ASSERT_ALWAYS(start);
+	__NK_ASSERT_ALWAYS(start != 0);
 
 	// Now have to check all other exports to find the end of the function
 	TUint end = 0xffffffff;
@@ -867,15 +945,26 @@
 		++i;
 		}
 	__NK_ASSERT_ALWAYS(end != 0xffffffff);
-
+	
 	TWin32FunctionInfo result = { start, end - start };
+	
+#ifdef DUMP_STACK_BACKTRACE
+	DEBUGPRINT("Function %s found at %08x to %08x", aFunctionName, start, end);
+#endif
+	
 	return result;
 	}
 
 void Win32FindNonPreemptibleFunctions()
 	{
-	Win32NonPreemptibleFunctions[0] = Win32FindExportedFunction("kernel32.dll", "RaiseException");
-	Win32NonPreemptibleFunctions[1] = Win32FindExportedFunction("ntdll.dll", "KiUserExceptionDispatcher");
+#ifdef DUMP_STACK_BACKTRACE
+	PrintAllModuleInfo();
+#endif
+
+	TUint i = 0;
+	Win32NonPreemptibleFunctions[i++] = Win32FindExportedFunction("RaiseException", "kernelbase.dll", "kernel32.dll", NULL);
+	Win32NonPreemptibleFunctions[i++] = Win32FindExportedFunction("KiUserExceptionDispatcher", "ntdll.dll", NULL);
+	__NK_ASSERT_ALWAYS(i == KWin32NonPreemptibleFunctionCount);
 	}
 	
 TBool Win32IsThreadInNonPreemptibleFunction(HANDLE aWinThread, TLinAddr aStackTop)
@@ -892,9 +981,17 @@
 	TUint ebp = c.Ebp;
 	TUint lastEbp = c.Esp;
 
+	#ifdef DUMP_STACK_BACKTRACE
+	DEBUGPRINT("Stack backtrace for thread %x", aWinThread);
+	#endif	
+
 	// Walk the call stack
 	for (TInt i = 0 ; i < KMaxSearchDepth ; ++i)
 		{
+		#ifdef DUMP_STACK_BACKTRACE
+		DEBUGPRINT("  %08x", eip);
+		#endif
+		
 		for (TInt j = 0 ; j < KWin32NonPreemptibleFunctionCount ; ++j)
 			{
 			const TWin32FunctionInfo& info = Win32NonPreemptibleFunctions[j];
--- a/kernel/eka/release.txt	Fri Mar 12 15:50:11 2010 +0200
+++ b/kernel/eka/release.txt	Mon Mar 15 12:45:50 2010 +0200
@@ -1,3 +1,96 @@
+Version 2.00.2091
+=================
+(Made by vfebvre 25/02/2010)
+
+1.	gcochran
+	1.	DEF144355  t_context locks up on Vasco/HW79
+
+2.	davegord
+	1.	DEF144641 Data import/export across DLL boundaries doesn't work in all cases
+		Implements REQ417-62614 "Data exports across DLL boundaries"
+
+
+Version 2.00.2090
+=================
+(Made by vfebvre 24/02/2010)
+
+1.	jcoppear
+	1.	PDEF144517: Emulator crashes when run under Carbide debugger on Windows 7
+
+2.	hengrant
+	1.	DEF144604 Incorrect trace metadata included in medsd.mmp
+
+
+Version 2.00.2089
+=================
+(Made by vfebvre 23/02/2010)
+
+1.	vfebvre
+	1.	DEF142659 T_SHBUF failures on X86GCC/FMM (t_shbuf:2835)
+
+
+Version 2.00.2088
+=================
+(Made by vfebvre 22/02/2010)
+
+1.	kingzhan
+	1.	DEF144531 for submission: TSW defect TSW TRLM-82BCNG
+		TSW TRLM-82BCNG: t_usb_device test fails
+
+
+2.	mipetzol
+	1.	DEF144549: Rapu Base Port DMA tests failing
+		The DMA channel DFC now takes into account that the channel might get
+		closed by the client in the transfer completion callback.
+
+3.	martai
+	1.	DEF144546: DBase Reference counting contains incorrect debug assertions
+
+
+Version 2.00.2087
+=================
+(Made by vfebvre 22/02/2010)
+
+1.	vfebvre
+	1.	DEF144532 [System Build]: Build failed for TB92SF_1052 due to missing .mrp change  
+
+
+Version 2.00.2086
+=================
+(Made by vfebvre 18/02/2010)
+
+1.	jimhofe
+	1.	MINOR_CHANGE: Removing obsolete txt file
+
+
+Version 2.00.2085
+=================
+(Made by vfebvre 15/02/2010)
+
+1.	ferporta
+	1.	DEF142026 Core Dump Server not getting events after attaching to more than one executable
+	2.	PDEF143992 E32TEST T_RMDEBUG2_OEM fails on Navi-Engine with WDP enabled 
+	3.	DEF143480 t_rmdebug2_oem, t_rmdebug2 test fails on production hw79/vasco with debug server
+
+2.	paconway
+	1.	DEF144234 SD mounting issue due to postponed door-open media change
+
+
+Version 2.00.2084
+=================
+(Made by vfebvre 11/02/2010)
+
+1.	kingzhan
+	1.	DEF144402 - for base submission: fix defect YXIO-824BQL RUsb::DeviceStateNotification doesn'
+		TSW YXIO-824BQL:RUsb::DeviceStateNotification doesn't notify any device status
+		change after failing to TryStart USB stack
+
+2.	coliward
+	1.	DEF144164: WSD data is allocated incorrectly on the kernel heap
+		WSD was being allocated on the kernel heap, which was causing large Qt
+		programs to fail to start up, given that the kernel heap is limited to 16 MB.
+
+
 Version 2.00.2083
 =================
 (Made by vfebvre 10/02/2010)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/bmarm/t_wsd_dl1.def	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,4 @@
+EXPORTS
+	ExportedData @ 1 NONAME ; TInt32 ExportedData
+	CheckExportedDataAddress__FPv @ 2 NONAME ; void CheckExportedDataAddress(void* aDataAddr)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/bmarm/t_wsd_dl2.def	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,4 @@
+EXPORTS
+	GetAddressOfDataProxy__FRiRPvT1 @ 1 NONAME R3UNUSED ; GetAddressOfDataProxy(int &, void *&, void *&)
+	CheckWritableStaticData__Fv @ 2 NONAME ; CheckWritablStaticData(void)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/bmarm/t_wsd_dl3.def	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,7 @@
+EXPORTS
+	GetAddressOfData__FRiRPvT1 @ 1 NONAME R3UNUSED ; GetAddressOfData(int &, void *&, void *&)
+	TestDataSize @ 2 NONAME ; (null)
+	WritableTestData @ 3 NONAME ; (null)
+	PointerToStaticData @ 4 NONAME ; (null)
+	PointerToWritableData @ 5 NONAME ; (null)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/bwins/t_wsd_dl1.def	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,4 @@
+EXPORTS
+	?ExportedData@@3JA @ 1 NONAME ; TInt32 ExportedData
+	?CheckExportedDataAddress@@YAHPAX@Z @2 NONAME ; void CheckExportedDataAddress(void* aDataAddr)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/bwins/t_wsd_dl2.def	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,4 @@
+EXPORTS
+	?GetAddressOfDataProxy@@YAPAPAXAAHAAPAX1@Z @ 1 NONAME ; void * * GetAddressOfDataProxy(int &, void * &, void * &)
+	?CheckWritableStaticData@@YAHXZ @ 2 NONAME ; void CheckWritablStaticData(void)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/bwins/t_wsd_dl3.def	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,7 @@
+EXPORTS
+	?GetAddressOfData@@YAPAPAXAAHAAPAX1@Z @ 1 NONAME ; void * * GetAddressOfData(int &, void * &, void * &)
+	?TestDataSize@@3JA @ 2 NONAME ; long TestDataSize
+	?WritableTestData@@3PAPAXA @ 3 NONAME ; void * * WritableTestData
+	?PointerToStaticData@@3PBQBXB @ 4 NONAME ; void const * * PointerToStaticData
+	?PointerToWritableData@@3PAPAXA @ 5 NONAME ; void * * PointerToWritableData
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/bx86/t_wsd_dl1.def	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,4 @@
+EXPORTS
+	?ExportedData@@3JA @ 1 NONAME ; TInt32 ExportedData
+	?CheckExportedDataAddress@@YAHPAX@Z @2 NONAME ; void CheckExportedDataAddress(void* aDataAddr)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/bx86/t_wsd_dl2.def	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,4 @@
+EXPORTS
+	?GetAddressOfDataProxy@@YAPAPAXAAHAAPAX1@Z @ 1 NONAME ; void * * GetAddressOfDataProxy(int &, void * &, void * &)
+	?CheckWritableStaticData@@YAHXZ @ 2 NONAME ; void CheckWritablStaticData(void)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/bx86/t_wsd_dl3.def	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,7 @@
+EXPORTS
+	?GetAddressOfData@@YAPAPAXAAHAAPAX1@Z @ 1 NONAME ; void * * GetAddressOfData(int &, void * &, void * &)
+	?TestDataSize@@3JA @ 2 NONAME ; long TestDataSize
+	?WritableTestData@@3PAPAXA @ 3 NONAME ; void * * WritableTestData
+	?PointerToStaticData@@3PBQBXB @ 4 NONAME ; void const * * PointerToStaticData
+	?PointerToWritableData@@3PAPAXA @ 5 NONAME ; void * * PointerToWritableData
+
--- a/kerneltest/e32test/debug/context.cia	Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/e32test/debug/context.cia	Mon Mar 15 12:45:50 2010 +0200
@@ -72,9 +72,9 @@
 __NAKED__ TInt ThreadContextHwExc(TAny*)
 	{
 	asm("stmdb sp!, {r4-r11,lr} ");
-	asm("mov r1, #0x80000000");
+	asm("mov r1, #0x00000000");
 	asm("bl SetRegs");
-	asm("ldr r0,[r13, #1]");   // Cause alignment fault
+	asm("ldr r0,[r0]");        // Cause data abort with null access, SetRegs will have set r0=0	
 	asm("ThreadContextHwExc_pc:");
 	asm("mov r0, #0 ");
 	asm("ldmia sp!, {r4-r11,pc} ");
--- a/kerneltest/e32test/dma/d_dma.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/e32test/dma/d_dma.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -1,4 +1,4 @@
-// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2002-2010 Nokia Corporation and/or its subsidiary(-ies).
 // All rights reserved.
 // This component and the accompanying materials are made available
 // under the terms of the License "Eclipse Public License v1.0"
@@ -185,6 +185,8 @@
 	TInt Execute(const TDesC8& aDes);
 	static void Dfc(DDmaRequest::TResult aResult, TAny* aArg);
 	TInt DoGetInfo(TAny* aInfo);
+	void FreeDmaRequests();
+	void FreeClientRequests();
 private:
 	TUint32 iCookie;
 	TBufferMgr iBufMgr;
@@ -193,6 +195,7 @@
 	DDmaRequest* iRequests[KMaxRequests];
 	TClientRequest* iClientRequests[KMaxRequests];
 	DDmaTestChannel* iMap[KMaxRequests];
+	TBool iCloseInCb[KMaxRequests];
 	TUint32 iMemMemPslInfo;
 	DThread* iClient;
 	TDynamicDfcQue* iDfcQ;
@@ -277,6 +280,8 @@
 				}
 			if (! iRequests[i])
 				return KErrNoMemory;
+
+			iCloseInCb[i] = EFalse;
 			}
 		return KErrNone;
 		}
@@ -288,13 +293,10 @@
 	if (iChannel)
 		{
 		iChannel->CancelAll();
-		TInt i;
-		for (i=0; i<KMaxRequests; ++i)
-			delete iRequests[i];
+		FreeDmaRequests();
 		iChannel->Close();
-		for (i=0; i<KMaxRequests; ++i)
-			Kern::DestroyClientRequest(iClientRequests[i]);
 		}
+	FreeClientRequests();
 	if (iDfcQ)
 		{
 		iDfcQ->Destroy();
@@ -302,6 +304,23 @@
 	iBufMgr.FreeAll();
 	}
 
+void DDmaTestChannel::FreeDmaRequests()
+	{
+	for (TInt i=0; i<KMaxRequests; ++i)
+		{
+		delete iRequests[i];
+		iRequests[i] = NULL;
+		}
+	}
+
+void DDmaTestChannel::FreeClientRequests()
+	{
+	for (TInt i=0; i<KMaxRequests; ++i)
+		{
+		Kern::DestroyClientRequest(iClientRequests[i]);
+		}
+	}
+
 
 TInt DDmaTestChannel::Request(TInt aFunction, TAny* a1, TAny* a2)
 	{
@@ -401,9 +420,23 @@
 			{
 		case 'Q':
 			{
-			TInt arg = *p++ - '0';
-			__ASSERT_DEBUG(0 <= arg && arg < KMaxRequests, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
-			iRequests[arg]->Queue();
+			__ASSERT_DEBUG(p < pEnd, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
+			TInt nextChar = *p++;
+			TInt channel = -1;
+
+			if(nextChar == 'X')
+				{
+				// Channel should be closed in callback
+				__ASSERT_DEBUG(p < pEnd, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
+				channel = *p++ - '0';
+				iCloseInCb[channel] = ETrue;
+				}
+			else
+				{
+				channel = nextChar - '0';
+				}
+			__ASSERT_DEBUG(0 <= channel && channel < KMaxRequests, Kern::PanicCurrentThread(KClientPanicCat, __LINE__));
+			iRequests[channel]->Queue();
 			break;
 			}
 		case 'C':
@@ -424,6 +457,17 @@
 	TInt i = ppC - pC->iMap;
 	TClientRequest* req = pC->iClientRequests[i];
 	TInt r = (aResult==DDmaRequest::EOk) ? KErrNone : KErrGeneral;
+
+	if(pC->iCloseInCb[i])
+		{
+		pC->iCloseInCb[i] = EFalse;
+		__KTRACE_OPT(KDMA, Kern::Printf("Close channel in callback"));
+
+		pC->FreeDmaRequests();
+		pC->iChannel->Close();
+		pC->iChannel = NULL;
+		}
+
 	if (req->IsReady())
 		Kern::QueueRequestComplete(pC->iClient, req, r);
 	}
--- a/kerneltest/e32test/dma/t_dma.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/e32test/dma/t_dma.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -1,4 +1,4 @@
-// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2002-2010 Nokia Corporation and/or its subsidiary(-ies).
 // All rights reserved.
 // This component and the accompanying materials are made available
 // under the terms of the License "Eclipse Public License v1.0"
@@ -193,6 +193,30 @@
 	const TInt iTotalTransferSize;
 	};
 
+/**
+Test that it is possible to close a channel from a callback
+*/
+class CCloseInCb : public CTest
+	{
+public:
+	CCloseInCb()
+		: CTest(NULL, 1), iTransferSize(4 * KKilo)
+		{}
+
+	TInt virtual DoRunTest();
+
+	virtual void AnnounceTest(TDes& aDes)
+		{
+		aDes.AppendFormat(_L("CCloseInCb"));
+		CTest::AnnounceTest(aDes);
+		}
+
+	CTest* Clone() const
+		{return new CCloseInCb(*this);}
+private:
+	const TInt iTransferSize;
+
+	};
 
 //
 // Active object used to create a tester thread, log on to it and
@@ -346,6 +370,44 @@
 	return KErrNone;
 	}
 
+TInt CCloseInCb::DoRunTest()
+	{
+	TInt r = KErrNone;
+	RTest test(_L("CCloseInCb test"));
+
+	r = OpenChannel(1);
+	test_KErrNone(r);
+
+	const TInt KRequest = 0;
+	const TInt KSrcBuf = 0;
+	const TInt KDestBuf = 1;
+
+	const TInt size = Min(iTransferSize, Info.iMaxTransferSize);
+
+	r = iChannel.AllocBuffer(KSrcBuf, size);
+	test_KErrNone(r);
+	iChannel.FillBuffer(KSrcBuf, 'A');
+	r = iChannel.AllocBuffer(KDestBuf, size);
+	test_KErrNone(r);
+	iChannel.FillBuffer(KDestBuf, '\0');
+
+	TRequestStatus rs = KRequestPending;
+	r = iChannel.Fragment(KRequest, KSrcBuf, KDestBuf, size, &rs);
+	test_KErrNone(r);
+
+	// "X" will cause channel to be closed during callback
+	r = iChannel.Execute(_L8("QX0"));
+	test_KErrNone(r);
+
+	User::WaitForRequest(rs);
+	test_KErrNone(rs.Int());
+
+	test(iChannel.CheckBuffer(KDestBuf, 'A'));
+	iChannel.FreeAllBuffers();
+
+	test.Close();
+	return KErrNone;
+	}
 
 // Called when thread completed.
 void CTesterThread::RunL()
@@ -964,6 +1026,13 @@
 	test.Next(_L("Getting channel info"));
 	GetChannelInfo();
 
+	test.Next(_L("Test that channel can be closed from callback"));
+	test.Next(_L("sb"));
+	RunSbTest(maxchannel, new CCloseInCb() );
+	test.Next(_L("db"));
+	RunDbTest(maxchannel, new CCloseInCb() );
+	test.Next(_L("sg"));
+	RunSgTest(maxchannel, new CCloseInCb() );
 	// Size for the single transfer test
 	TInt totalTransferSize = 64 * KKilo;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/eabi/t_wsd_dl1.def	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,4 @@
+EXPORTS
+	ExportedData @ 1 NONAME DATA 4 ; TInt32 ExportedData
+	_Z24CheckExportedDataAddressPv @ 2 NONAME ; void CheckExportedDataAddress(void* aDataAddr)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/eabi/t_wsd_dl2.def	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,4 @@
+EXPORTS
+	_Z21GetAddressOfDataProxyRiRPvS1_ @ 1 NONAME
+	_Z23CheckWritableStaticDatav @ 2 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/eabi/t_wsd_dl3.def	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,7 @@
+EXPORTS
+	_Z16GetAddressOfDataRiRPvS1_ @ 1 NONAME
+	TestDataSize @ 2 NONAME DATA 4
+	WritableTestData @ 3 NONAME DATA 65536
+	PointerToStaticData @ 4 NONAME DATA 4
+	PointerToWritableData @ 5 NONAME DATA 4
+
--- a/kerneltest/e32test/group/bld.inf	Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/e32test/group/bld.inf	Mon Mar 15 12:45:50 2010 +0200
@@ -468,6 +468,29 @@
 t_wsdextension	support
 #endif
 
+// t_wsd_* suffixes:
+//   x => XIP; runs from ROM
+//   c => code loads & runs in RAM
+//   p => pagedcode
+//   u => unpagedcode
+t_wsd_dl3_xp	support
+t_wsd_dl3_xu	support
+t_wsd_dl2_xp	support
+t_wsd_dl2_xu	support
+t_wsd_dl1_xp	support
+t_wsd_dl1_xu	support
+t_wsd_tst_xp
+t_wsd_tst_xu
+
+t_wsd_dl3_cp	support
+t_wsd_dl3_cu	support
+t_wsd_dl2_cp	support
+t_wsd_dl2_cu	support
+t_wsd_dl1_cp	support
+t_wsd_dl1_cu	support
+t_wsd_tst_cp
+t_wsd_tst_cu
+
 // /e32test/ethernet
 ../ethernet/pump/etherpump  manual
 ../ethernet/macset/macset   manual
@@ -963,22 +986,41 @@
 #endif
 
 #if defined(MARM_ARMV5) || defined(MARM_ARMV4)
-t_trkdummyapp
+../rm_debug/group/t_trkdummyapp
 #endif
 
 #if defined(MARM_ARMV5)
-t_rmdebug_dll support
-t_rmdebug_security0 support
-t_rmdebug_security1 support
-t_rmdebug_security2 support
-t_rmdebug_security3 support
-t_rmdebug_app support
-t_rmdebug2
-t_rmdebug2_oem
-t_rmdebug2_oemtoken support
-t_rmdebug2_oem2
-t_rmdebug2_oemtoken2 support
-t_crashmonitor_lib
+../rm_debug/group/t_rmdebug_dll support
+../rm_debug/group/t_rmdebug_security0 support
+../rm_debug/group/t_rmdebug_security1 support
+../rm_debug/group/t_rmdebug_security2 support
+../rm_debug/group/t_rmdebug_security3 support
+../rm_debug/group/t_rmdebug_app support
+../rm_debug/group/t_rmdebug2
+../rm_debug/group/t_rmdebug2_oem
+../rm_debug/group/t_rmdebug2_oemtoken support
+../rm_debug/group/t_rmdebug2_oem2
+../rm_debug/group/t_rmdebug2_oemtoken2 support
+../rm_debug/group/t_crashmonitor_lib
+
+../rm_debug/group/t_rmdebug_app1 support
+../rm_debug/group/t_rmdebug_app2 support
+../rm_debug/group/t_rmdebug_app3 support
+../rm_debug/group/t_rmdebug_app4 support
+../rm_debug/group/t_rmdebug_app5 support
+../rm_debug/group/t_rmdebug_app6 support
+../rm_debug/group/t_rmdebug_app7 support
+../rm_debug/group/t_rmdebug_app8 support
+../rm_debug/group/t_rmdebug_app9 support
+../rm_debug/group/t_rmdebug_app10 support
+
+../rm_debug/group/t_rmdebug_target_launcher support
+../rm_debug/group/t_rmdebug_multi_target
+
+../rm_debug/group/t_rmdebug_multi_agent support
+../rm_debug/group/t_multi_agent_launcher
+
+
 #endif
 
 t_stacksize
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl1.mmh	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,30 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_dl1.mmh
+
+targettype			dll
+sourcepath			../mmu
+source				t_wsd_dl1.cpp
+deffile				t_wsd_dl1.def
+nostrictdef
+capability			all
+vendorid			0x70000001
+library				euser.lib
+
+macro T_WSD_DL1
+epocallowdlldata
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+UNPAGEDDATA
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl1_cp.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,22 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_dl1_cp.mmp
+// 
+// This binary goes in ram and is paged
+
+ROMTARGET
+RAMTARGET			+
+PAGEDCODE
+target				t_wsd_dl1_cp.dll
+#include			"t_wsd_dl1.mmh"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl1_cu.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,22 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_dl1_cu.mmp
+// 
+// This binary goes in ram and is unpaged
+
+ROMTARGET
+RAMTARGET			+
+UNPAGEDCODE
+target				t_wsd_dl1_cu.dll
+#include			"t_wsd_dl1.mmh"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl1_xp.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,21 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_dl1_xp.mmp
+// 
+// This binary goes in rom and is paged
+
+ROMTARGET			+
+PAGEDCODE
+target				t_wsd_dl1_xp.dll
+#include			"t_wsd_dl1.mmh"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl1_xu.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,21 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_dl1_xu.mmp
+// 
+// This binary goes in rom and is unpaged
+
+ROMTARGET			+
+UNPAGEDCODE
+target				t_wsd_dl1_xu.dll
+#include			"t_wsd_dl1.mmh"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl2.mmh	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,30 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_dl2.mmh
+
+targettype			dll
+sourcepath			../mmu
+source				t_wsd_dl2.cpp
+deffile				t_wsd_dl2.def
+nostrictdef
+capability			all
+vendorid			0x70000001
+library				euser.lib
+
+macro T_WSD_DL2
+// epocallowdlldata
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+UNPAGEDDATA
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl2_cp.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,23 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_dl2_cp.mmp
+// 
+// This binary goes in ram and is paged
+
+ROMTARGET
+RAMTARGET			+
+PAGEDCODE
+target				t_wsd_dl2_cp.dll
+library				t_wsd_dl3_cp.lib
+#include			"t_wsd_dl2.mmh"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl2_cu.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,23 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_dl2_cu.mmp
+// 
+// This binary goes in ram and is unpaged
+
+ROMTARGET
+RAMTARGET			+
+UNPAGEDCODE
+target				t_wsd_dl2_cu.dll
+library				t_wsd_dl3_cu.lib
+#include			"t_wsd_dl2.mmh"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl2_xp.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,22 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_dl2_xp.mmp
+// 
+// This binary goes in rom and is paged
+
+ROMTARGET			+
+PAGEDCODE
+target				t_wsd_dl2_xp.dll
+library				t_wsd_dl3_xp.lib
+#include			"t_wsd_dl2.mmh"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl2_xu.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,22 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_dl2_xu.mmp
+// 
+// This binary goes in rom and is unpaged
+
+ROMTARGET			+
+UNPAGEDCODE
+target				t_wsd_dl2_xu.dll
+library				t_wsd_dl3_xu.lib
+#include			"t_wsd_dl2.mmh"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl3.mmh	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,30 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_dl3.mmh
+
+targettype			dll
+sourcepath			../mmu
+source				t_wsd_dl3.cpp
+deffile				t_wsd_dl3.def
+nostrictdef
+capability			all
+vendorid			0x70000001
+library				euser.lib
+
+macro T_WSD_DL3
+epocallowdlldata
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+UNPAGEDDATA
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl3_cp.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,22 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_dl3_cp.mmp
+// 
+// This binary goes in ram and is paged
+
+ROMTARGET
+RAMTARGET			+
+PAGEDCODE
+target				t_wsd_dl3_cp.dll
+#include			"t_wsd_dl3.mmh"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl3_cu.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,22 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_dl3_cu.mmp
+// 
+// This binary goes in ram and is unpaged
+
+ROMTARGET
+RAMTARGET			+
+UNPAGEDCODE
+target				t_wsd_dl3_cu.dll
+#include			"t_wsd_dl3.mmh"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl3_xp.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,21 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_dl3_xp.mmp
+// 
+// This binary goes in rom and is paged
+
+ROMTARGET			+
+PAGEDCODE
+target				t_wsd_dl3_xp.dll
+#include			"t_wsd_dl3.mmh"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_dl3_xu.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,21 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_dl3_xu.mmp
+// 
+// This binary goes in rom and is unpaged
+
+ROMTARGET			+
+UNPAGEDCODE
+target				t_wsd_dl3_xu.dll
+#include			"t_wsd_dl3.mmh"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_tst.mmh	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,26 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_tst.mmh
+
+targettype			exe
+sourcepath			../mmu
+source				t_wsd_tst.cpp
+library				euser.lib
+library				efsrv.lib
+capability			all
+vendorid			0x70000001
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+UNPAGEDDATA
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_tst_cp.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,23 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_tst_cp.mmp
+// 
+// This binary goes in ram and is paged
+
+ROMTARGET
+RAMTARGET			+
+PAGEDCODE
+target				t_wsd_tst_cp.exe
+library				t_wsd_dl1_cp.lib
+#include			"t_wsd_tst.mmh"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_tst_cu.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,23 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_tst_cu.mmp
+// 
+// This binary goes in ram and is unpaged
+
+ROMTARGET
+RAMTARGET			+
+UNPAGEDCODE
+target				t_wsd_tst_cu.exe
+library				t_wsd_dl1_cu.lib
+#include			"t_wsd_tst.mmh"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_tst_xp.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,22 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_tst_xp.mmp
+// 
+// This binary goes in rom and is paged
+
+ROMTARGET			+
+PAGEDCODE
+target				t_wsd_tst_xp.exe
+library				t_wsd_dl1_xp.lib
+#include			"t_wsd_tst.mmh"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/group/t_wsd_tst_xu.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,22 @@
+// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test/group/t_wsd_tst_xu.mmp
+// 
+// This binary goes in rom and is unpaged
+
+ROMTARGET			+
+UNPAGEDCODE
+target				t_wsd_tst_xu.exe
+library				t_wsd_dl1_xu.lib
+#include			"t_wsd_tst.mmh"
--- a/kerneltest/e32test/mmu/t_shbuf.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/e32test/mmu/t_shbuf.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -2819,6 +2819,11 @@
 	test_KErrNone(r);
 	r = HAL::Get(HAL::EMemoryRAM, ram);
 	test_KErrNone(r);
+	test_Compare(ram, >, 0);
+	// Total system RAM returned by EMemoryRAM should always be < 2GB anyway
+	TUint uram = (TUint) ram;
+	test.Printf(_L("Total system RAM: %u bytes\n"), uram);
+	test.Printf(_L("Page size: %d bytes\n"), pagesize);
 
 	RShPool pool;
 	{ TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, 0, 0); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); }
@@ -2835,9 +2840,7 @@
 	{ TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, 4096, 10); inf.SetExclusive(); r = pool.Create(inf, KDefaultPoolHandleFlags); test_Equal(KErrNotSupported, r); pool.Close(); }
 	{ TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 4096, 10, 12); r = pool.Create(inf, KDefaultPoolHandleFlags); test_Equal(KErrNone, r); pool.Close(); }
 	{ TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 4096, 10, 12); inf.SetExclusive(); r = pool.Create(inf, KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); pool.Close(); }
-#ifndef __WINS__
-	{ TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, 128 * pagesize, (ram / (128 * pagesize)) + 1); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrNoMemory, r); }
-#endif
+	{ TShPoolCreateInfo inf(TShPoolCreateInfo::EPageAlignedBuffer, 128 * pagesize, (uram / (128 * pagesize)) + 1); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrNoMemory, r); }
 	{ TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 0, 0, 0); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); }
 	{ TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 100, 0, 0); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); }
 	{ TShPoolCreateInfo inf(TShPoolCreateInfo::ENonPageAlignedBuffer, 0, 100, 0); r = pool.Create(inf,KDefaultPoolHandleFlags); test_Equal(KErrArgument, r); }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/mmu/t_wsd_dl1.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,30 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test\mmu\t_wsd_dl1.cpp
+//
+
+// MMH file will define	T_WSD_DL1
+#include "t_wsd_tst.h"
+
+// Exported writable static data
+EXPORT_D TInt32 ExportedData = 0x717a1ee7;
+
+// Exported Function
+EXPORT_C TInt CheckExportedDataAddress(void* aDataAddr)
+	{
+	RDebug::Printf("CheckExportedDataAddress: ExportedData@%08x, aDataAddr %08x",
+		&ExportedData, aDataAddr);
+	return aDataAddr == (void*)&ExportedData ? KErrNone : KErrGeneral;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/mmu/t_wsd_dl2.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,65 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test\mmu\t_wsd_dl2.cpp
+// 
+
+// MMH file will define	T_WSD_DL2
+#include "t_wsd_tst.h"
+
+// Ordinal 1
+EXPORT_C void** GetAddressOfDataProxy(TInt& aSize, void*& aCodeAddr, void*& aDataAddr)
+	{
+	return GetAddressOfData(aSize, aCodeAddr, aDataAddr);
+	}
+
+// Ordinal 2
+EXPORT_C TInt CheckWritableStaticData(void)
+	{
+	RDebug::Printf("CheckWritableStaticData: start");
+	TInt err = KErrNone;
+	TInt size;
+	void* codeAddr;
+	void* dataAddr;
+	const void*** dataPtrPtr = (const void***)GetAddressOfData(size, codeAddr, dataAddr);
+
+	RDebug::Printf("CheckWritableStaticData: size %d, codeAddr %08x, dataAddr %08x",
+		size, codeAddr, dataAddr);
+	RDebug::Printf("CheckWritableStaticData: dataPtrPtr %08x, PointerToStaticData is at %08x",
+		dataPtrPtr, &PointerToStaticData);
+
+	if (dataPtrPtr != (const void***)&PointerToStaticData)
+		err = KErrGeneral;
+	const void** p1 = *dataPtrPtr;
+	RDebug::Printf("CheckWritableStaticData: *dataPtrPtr %08x", p1);
+	const void* const* p2 = PointerToStaticData;
+	RDebug::Printf("CheckWritableStaticData: PointerToStaticData %08x", p2);
+	if (p1 != (const void**)p2)
+		err = KErrGeneral;
+	if (p1 != (const void**)dataAddr)
+		err = KErrGeneral;
+
+	RDebug::Printf("CheckWritableStaticData: TestDataSize is at %08x", &TestDataSize);
+	TInt sz = TestDataSize;
+	RDebug::Printf("CheckWritableStaticData: TestDataSize is %d", sz);
+	if (sz != size)
+		err = KErrGeneral;
+
+	void** p3 = WritableTestData;
+	void** p4 = PointerToWritableData;
+	if (p3 != p4)
+		err = KErrGeneral;
+
+	return err;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/mmu/t_wsd_dl3.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,80 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test\mmu\t_wsd_dl3.cpp
+//
+
+// MMH file will define	T_WSD_DL3
+#include "t_wsd_tst.h"
+
+#define C 		((void*)DummyFn)
+#define D 		((void*)TestData)
+#define A4W		C, D, C, D												// 4 words
+#define A16W	A4W, A4W, A4W, A4W										// 16 words
+#define A64W 	A16W, A16W, A16W, A16W									// 64 words
+#define A256W 	A64W, A64W, A64W, A64W									// 256 words
+#define A1KW	A256W, A256W, A256W, A256W								// 1Kwords
+#define A4KW	A1KW, A1KW, A1KW, A1KW									// 4Kwords
+
+// Non-exported dummy function whose address is put in the initialised
+// data, to check that it gets relocated correctly
+void DummyFn(void)
+	{
+	}
+
+// Non-exported const data, which should end up in the text segment
+// but doesn't on some platforms :(
+static const void* const TestData[] = { A4KW, A4KW };					// 8Kwords
+const TInt KSizeOfTestData = sizeof(TestData);							// 32Kbytes
+
+// Exported Ordinals 2-5
+EXPORT_D TInt32 TestDataSize = KSizeOfTestData;
+EXPORT_D void* WritableTestData[] = { A4KW, A4KW };
+EXPORT_D const void* const* PointerToStaticData = TestData;
+EXPORT_D void** PointerToWritableData = WritableTestData;
+
+// Dummy function, just so that this DLL contains more than one page of
+// text even on platforms where the read-only data ends up in the data
+// rather than the text segment ...
+TUint AddEmUp()
+	{
+	const void* const* p = TestData;
+	TUint sum = 0;
+
+#define	ADD1W	{ sum += (TUint)*p++; }									// 1 word
+#define	ADD4W	{ ADD1W; ADD1W; ADD1W; ADD1W; }							// 4 words
+#define	ADD16W	{ ADD4W; ADD4W; ADD4W; ADD4W; }							// 16 words
+#define	ADD64W	{ ADD16W; ADD16W; ADD16W; ADD16W; }						// 64 words
+#define	ADD256W	{ ADD64W; ADD64W; ADD64W; ADD64W; }						// 256 words
+#define	ADD1KW	{ ADD256W; ADD256W; ADD256W; ADD256W; }					// 1K words
+
+	// The macro ADD1KW should expand to ~2K instructions i.e. ~8Kb of inline code
+	for (TUint i = 0; i < sizeof(TestData)/(1024*sizeof(void*)); ++i)
+		ADD1KW;
+
+	// We've added up all 8Kwords (32kb) of the test data ...
+	return sum;
+	}
+
+// Exported Ordinal 1
+EXPORT_C void** GetAddressOfData(TInt& aSize, void*& aCodeAddr, void*& aDataAddr)
+	{
+	TAny* p = User::Alloc(KSizeOfTestData);
+	aSize = AddEmUp();
+	aSize = KSizeOfTestData;
+	aCodeAddr = C;
+	aDataAddr = D;
+	User::Free(p);
+	return (void**)&PointerToStaticData;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/mmu/t_wsd_tst.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,466 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test\mmu\t_wsd_tst.cpp
+// Test exporting and importing writable static data in DLLs.
+// This test relies on three dlls:
+// - t_wsd_dl1_[cx][pu]		Which is statically linked, and exports both code & data
+// - t_wsd_dl2_[cx][pu]		Which is dyanamically loaded, and imports code & writable static data from
+// - t_wsd_dl3_[cx][pu]		Which exports code and writable static data
+// The [cx] suffix indicates code-in-RAM vs XIP (ROM), and [pu] indicate paged or unpaged code.
+//
+
+//! @SYMTestCaseID			KBASE-T_CODEPAGING-0335
+//! @SYMTestType			UT
+//! @SYMPREQ				PREQ1110
+//! @SYMTestCaseDesc		Demand Paging Code Paging tests.
+//! @SYMTestActions			001 Code paging tests
+//! @SYMTestExpectedResults All tests should pass.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+
+#define __E32TEST_EXTENSION__
+#include <e32test.h>
+#include <e32math.h>
+#include <f32file.h>
+#include <f32dbg.h>
+
+#include "mmudetect.h"
+#include "t_wsd_tst.h"
+
+// Global data /////////////////////////////////////////////////////////////////
+
+_LIT(KSearchPathTemplate, "%c:\\sys\\bin");		// drive letter
+_LIT(KLibraryName, "t_wsd_dl%d_%c%c");			// [23] [cx] [pu]
+
+TInt TheFailure = KErrNone;
+TChar CurrentDrive = 'Z';
+
+void SetCurrentDrive(TChar aDrive)
+	{
+	CurrentDrive = aDrive;
+	}
+
+class TPagingDriveInfo
+	{
+public:
+	TChar iDriveLetter;
+	TDriveInfo iDriveInfo;
+	};
+
+RArray<TPagingDriveInfo> SupportedDrives;
+
+// RTest stuff /////////////////////////////////////////////////////////////////
+
+RTest test(_L("T_WSD"));
+
+#define test_noError(x) { TInt _r = (x); if (_r < 0) HandleError(_r, __LINE__); }
+#define test_notNull(x) { TAny* _a = (TAny*)(x); if (_a == NULL) HandleNull(__LINE__); }
+#define test_equal(e, a) { TInt _e = TInt(e); TInt _a = TInt(a); if (_e != _a) HandleNotEqual(_e, _a, __LINE__); }
+
+void HandleError(TInt aError, TInt aLine)
+	{
+	test.Printf(_L("Error %d\n"), aError);
+	test.operator()(EFalse, aLine);
+	}
+
+void HandleNull(TInt aLine)
+	{
+	test.Printf(_L("Null value\n"));
+	test.operator()(EFalse, aLine);
+	}
+
+void HandleNotEqual(TInt aExpected, TInt aActual, TInt aLine)
+	{
+	test.Printf(_L("Expected 0x%x but got 0x%x\n"), aExpected, aActual);
+	test.operator()(EFalse, aLine);
+	}
+
+// Utility functions ///////////////////////////////////////////////////////////
+
+TPtrC16 GetMediaType(TInt aMediaType)
+	{
+	_LIT(KMediaNotPresent, "MediaNotPresent");
+	_LIT(KMediaUnknown, "MediaUnknown");
+	_LIT(KMediaFloppy, "MediaFloppy");
+	_LIT(KMediaHardDisk, "MediaHardDisk");
+	_LIT(KMediaCdRom, "MediaCdRom");
+	_LIT(KMediaRam, "MediaRam");
+	_LIT(KMediaFlash, "MediaFlash");
+	_LIT(KMediaRom, "MediaRom");
+	_LIT(KMediaRemote, "MediaRemote");
+	_LIT(KMediaNANDFlash, "MediaNANDFlash");
+	_LIT(KMediaUnKnown, "MediaUnKnown");
+
+	switch (aMediaType)
+		{
+	case EMediaNotPresent:
+		return KMediaNotPresent();
+	case EMediaUnknown:
+		return KMediaUnknown();
+	case EMediaFloppy:
+		return KMediaFloppy();
+	case EMediaHardDisk:
+		return KMediaHardDisk();
+	case EMediaCdRom:
+		return KMediaCdRom();
+	case EMediaRam:
+		return KMediaRam();
+	case EMediaFlash:
+		return KMediaFlash();
+	case EMediaRom:
+		return KMediaRom();
+	case EMediaRemote:
+		return KMediaRemote();
+	case EMediaNANDFlash:
+		return KMediaNANDFlash();
+	default:
+		return KMediaUnKnown();
+		}
+	}
+
+// Get the list of testable drives
+void GetSupportedDrives(TBool aVerbose = EFalse)
+	{
+	TUint32 memModelAttributes = UserSvr::HalFunction(EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL);
+	TBool codePagingSupported = (memModelAttributes & EMemModelAttrCodePaging) != 0;
+	TUint32 pagingPolicy = E32Loader::PagingPolicy();
+	TBool pagingPolicyAllowsPaging = pagingPolicy != EKernelConfigCodePagingPolicyNoPaging;
+	test_Equal(codePagingSupported, pagingPolicyAllowsPaging);
+	if (codePagingSupported)
+		test.Printf(_L("Code paging is enabled.\n"));
+	else
+		test.Printf(_L("Code paging is NOT enabled.\n"));
+
+	if (aVerbose)
+		{
+		test.Printf(_L("Available drives:\n"));
+		test.Printf(_L("     Type             Attr     MedAttr  Filesystem\n"));
+		}
+
+	RFs fs;
+	test_noError(fs.Connect());
+
+	TDriveList driveList;
+	TInt r = fs.DriveList(driveList);
+	test_noError(r);
+
+	TBool NandPageableMediaFound = EFalse;
+	for (TInt drvNum=0; drvNum<KMaxDrives; ++drvNum)
+		{
+		if (!driveList[drvNum])
+			continue;   //-- skip unexisting drive
+
+		TDriveInfo driveInfo;
+		r = fs.Drive(driveInfo, drvNum);
+		test_noError(r);
+
+		TChar ch;
+		r = fs.DriveToChar(drvNum, ch);
+		test_noError(r);
+
+		TBuf<256> fileSystemName;
+		r = fs.FileSystemName(fileSystemName, drvNum);
+		test_noError(r);
+
+		// Decide which drives to exclude:
+		//		Locked/nonwritable drives, except the Z: ROM drive
+		//		Win32 drives on the emulator
+		//		Remote/nonlocal, removable/noninternal, redirected, substed drives
+		//	All others are included by default iff code paging is supported
+		//	If not, only the Z: ROM/XIP drive is tested
+		_LIT(KWin32FS, "Win32");
+		TBool include = codePagingSupported;
+		if (driveInfo.iDriveAtt & KDriveAttRom)
+			include = (ch == 'Z');
+		else if (driveInfo.iMediaAtt & (KMediaAttWriteProtected|KMediaAttLocked))
+			include = EFalse;
+		else if (fileSystemName == KWin32FS())
+			include = EFalse;
+		else if (driveInfo.iDriveAtt & (KDriveAttRedirected|KDriveAttSubsted|KDriveAttRemovable|KDriveAttRemote))
+			include = EFalse;
+		else if ((KDriveAttInternal|KDriveAttLocal) & ~driveInfo.iDriveAtt)
+			include = EFalse;
+
+		if (include)
+			{
+			TPagingDriveInfo pagingDriveInfo;
+			pagingDriveInfo.iDriveLetter = ch;
+			pagingDriveInfo.iDriveInfo = driveInfo;
+			r = SupportedDrives.Append(pagingDriveInfo);
+			test_noError(r);
+			}
+
+		TBool pageable = EFalse;
+		if (driveInfo.iDriveAtt & KDriveAttPageable)
+			{
+			pageable = ETrue;
+			if (driveInfo.iType == EMediaNANDFlash)
+				NandPageableMediaFound = ETrue;
+			}
+
+		// If we've already found a pageable NAND drive, then assume the
+		// Z: drive is pageable too if it's got a composite file system
+		_LIT(KCompositeName,"Composite");
+		if (NandPageableMediaFound && fileSystemName == KCompositeName())
+			pageable = ETrue;
+
+		if (aVerbose)
+			{
+			TPtrC16 mediaType = GetMediaType(driveInfo.iType);
+			_LIT(KPageable, "pageable");
+			test.Printf(_L("%c  %c: %16S %08x %08x %10S %S\n"),
+						include ? '*' : ' ', (TUint)ch, &mediaType,
+						driveInfo.iDriveAtt, driveInfo.iMediaAtt,
+			            &fileSystemName, (pageable ? &KPageable : &KNullDesC));
+			}
+		}
+
+	fs.Close();
+	}
+
+const TDesC& LibrarySearchPath(TChar aDrive)
+	{
+	static TBuf<64> path;
+	path.Format(KSearchPathTemplate, (TUint)aDrive);
+	return path;
+	}
+
+const TDesC& LibraryName(TChar aDrive, TInt aLibNo, TBool aRam, TBool aPaged)
+	{
+	// this gives DLL#2 a different name on each drive so we can be sure we're loading the right one
+	static TBuf<64> name;
+	name.Format(KLibraryName, aLibNo, aRam ? 'c' : 'x', aPaged ? 'p' : 'u');
+	if (aLibNo == 2 && aDrive != 'Z')
+		name.AppendFormat(_L("_%c"), (TUint)aDrive);
+	return name;
+	}
+
+const TDesC& LibraryFilename(TChar aDrive, TInt aLibNo, TBool aRam, TBool aPaged)
+	{
+	static TBuf<64> filename;
+	filename = LibrarySearchPath(aDrive);
+	filename.AppendFormat(_L("\\%S.dll"), &LibraryName(aDrive, aLibNo, aRam, aPaged));
+	return filename;
+	}
+
+TInt LoadSpecificLibrary(RLibrary& aLibrary, TChar aDrive, TInt aLibNo, TBool aRam, TBool aPaged)
+	{
+	const TDesC& path = LibrarySearchPath(aDrive);
+	const TDesC& name = LibraryName(aDrive, aLibNo, aRam, aPaged);
+	TInt err = aLibrary.Load(name, path);
+	TBuf<256> message;
+	message.Format(_L("Loading %S\\%S.dll returns %d\n"), &path, &name, err);
+	test.Printf(message);
+	return err;
+	}
+
+// Test functions //////////////////////////////////////////////////////////////
+
+void CopyDllToCurrentDrive(RFs& aFs, TBool aPaged, TInt aLibNo)
+	{
+	TBuf<64> source = LibraryFilename('Z', aLibNo, ETrue, aPaged);
+	TBuf<64> dest = LibraryFilename(CurrentDrive, aLibNo, ETrue, aPaged);
+	test.Printf(_L("Copying %S to %S\n"), &source, &dest);
+
+	TInt r = aFs.MkDirAll(dest);
+	test(r == KErrNone || r == KErrAlreadyExists);
+
+	TBuf<64> tempName(dest);
+	tempName.Append(_L(".tmp"));
+
+	RFile in, out, temp;
+	test_noError(in.Open(aFs, source, EFileRead));
+	test_noError(out.Replace(aFs, dest, EFileWrite));
+	test_noError(temp.Replace(aFs, tempName, EFileWrite));
+
+	const TInt KBufferSize = 3333;
+	TBuf8<KBufferSize> buffer;
+
+	test_noError(temp.Write(buffer));
+	test_noError(temp.Flush());
+
+	TInt size;
+	test_noError(in.Size(size));
+	TInt pos = 0;
+	while (pos < size)
+		{
+		test_noError(in.Read(buffer));
+		test_noError(out.Write(buffer));
+		test_noError(out.Flush());
+		test_noError(temp.Write(buffer));
+		test_noError(temp.Flush());
+		pos += buffer.Length();
+		}
+
+	out.SetAtt(KEntryAttNormal, KEntryAttReadOnly|
+								KEntryAttHidden|
+								KEntryAttSystem|
+								KEntryAttArchive|
+								KEntryAttXIP);
+
+	in.Close();
+	out.Close();
+	temp.Close();
+	}
+
+void CopyDllsToCurrentDrive()
+	{
+	RFs fs;
+	test_noError(fs.Connect());
+
+	CopyDllToCurrentDrive(fs, EFalse, 2);		// Unpaged library 2
+	CopyDllToCurrentDrive(fs, EFalse, 3);		// Unpaged library 3
+	CopyDllToCurrentDrive(fs, ETrue, 2);		// Paged library 2
+	CopyDllToCurrentDrive(fs, ETrue, 3);		// Paged library 3
+
+	fs.Close();
+	}
+
+void EraseDllsFromCurrentDrive()
+	{
+	RFs fs;
+	test_noError(fs.Connect());
+
+	CTrapCleanup* cleanup = CTrapCleanup::New();
+	test_notNull(cleanup);
+
+	CFileMan* fileMan = NULL;
+	TRAPD(r, fileMan = CFileMan::NewL(fs));
+	test_noError(r);
+
+	TBuf<64> libdir = LibrarySearchPath(CurrentDrive);
+	test.Printf(_L("Erasing %S\n"), &libdir);
+	fileMan->RmDir(libdir);
+
+	delete fileMan;
+	delete cleanup;
+	fs.Close();
+	}
+
+void CheckRelocatableData(RLibrary& library)
+	{
+	TGetAddressOfDataFunction func = (TGetAddressOfDataFunction)library.Lookup(KGetAddressOfDataFunctionOrdinal);
+	test_notNull(func);
+
+	TInt size;
+	void* codeAddr;
+	void* dataAddr;
+	void*** dataPtrPtr = (void***)func(size, codeAddr, dataAddr);
+	void **dp = (void **)dataAddr;
+
+	for (TInt i = 0; i < size/4; i += 2)
+		{
+		test_equal(dp[i], codeAddr);
+		test_equal(dp[i+1], dataAddr);
+		}
+
+	test_equal(*dataPtrPtr, dp);
+	}
+
+void CheckWritableStaticData(RLibrary& library)
+	{
+	TInt (*func)(void) = (TInt (*)(void))library.Lookup(KCheckWritableStaticDataFunctionOrdinal);
+	RDebug::Printf("CheckWritableStaticData() is export %d at %08x", KCheckWritableStaticDataFunctionOrdinal, func);
+	test_notNull(func);
+	TInt err = func();
+	RDebug::Printf("CheckWritableStaticData() returned %d", err);
+	// test_noError(err);
+	if (TheFailure == KErrNone)
+		TheFailure = err;
+	}
+
+void RunPerDriveTests(TBool aPaged, TBool aRam)
+	{
+	TBuf<64> message = _L("Running ");
+	if (!aPaged)
+		message.Append(_L("un"));
+	message.AppendFormat(_L("paged R%cM tests on drive %c:"),
+		aRam ? 'A' : 'O', (TUint)CurrentDrive);
+	test.Next(message);
+
+	RFs fs;
+	test_noError(fs.Connect());
+	fs.SetDebugRegister(KFLDR);
+
+	// Explicitly loading dl2 will implicitly load dl3 as well
+	RLibrary dl2;
+	test_noError(LoadSpecificLibrary(dl2, CurrentDrive, 2, aRam, aPaged));
+	CheckRelocatableData(dl2);
+	CheckWritableStaticData(dl2);
+	dl2.Close();
+
+	fs.SetDebugRegister(0);
+	fs.Close();
+	}
+
+TInt E32Main()
+	{
+	test.Title();
+	test.Start(_L("WSD tests"));
+
+	// Check static linkage to dl1
+	test_noError(CheckExportedDataAddress(&ExportedData));
+
+	GetSupportedDrives(ETrue);
+	test(SupportedDrives.Count() > 0);
+
+	// Turn off evil lazy dll unloading
+	RLoader l;
+	test(l.Connect()==KErrNone);
+	test(l.CancelLazyDllUnload()==KErrNone);
+	l.Close();
+
+	// Make sure there aren't any DLLs left over from earlier tests
+	TInt i = SupportedDrives.Count();
+	while (--i >= 0)
+		{
+		SetCurrentDrive(SupportedDrives[i].iDriveLetter);
+		if (CurrentDrive != 'Z')
+				EraseDllsFromCurrentDrive();
+		}
+
+	// We want to test all supported drives in order of increasing priority, so
+	// that the CurrentDrive is always the hghest priority of those tested so far.
+	// Therefore, if Z (XIP ROM, lowest priority) is a valid test drive, do it first
+	i = SupportedDrives.Count();
+	if (--i >= 0)
+		{
+		SetCurrentDrive(SupportedDrives[i].iDriveLetter);
+		if (CurrentDrive == 'Z')
+			{
+			// ROM (XIP) tests can only be run from Z:
+			RunPerDriveTests(EFalse, EFalse);		// Unpaged ROM
+			RunPerDriveTests(ETrue, EFalse);		// Paged ROM
+			RunPerDriveTests(EFalse, ETrue);		// Unpaged RAM
+			RunPerDriveTests(ETrue, ETrue);			// Paged RAM
+			}
+		}
+
+	// Now run the RAM-based versions from each remaining drive in turn
+	for (i = 0; i < SupportedDrives.Count(); ++i)
+		{
+		SetCurrentDrive(SupportedDrives[i].iDriveLetter);
+		if (CurrentDrive != 'Z')
+			{
+			CopyDllsToCurrentDrive();
+			RunPerDriveTests(EFalse, ETrue);			// Unpaged RAM
+			RunPerDriveTests(ETrue, ETrue);				// Paged RAM
+			}
+		}
+
+	test_noError(TheFailure);
+	test.End();
+	return 0;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/mmu/t_wsd_tst.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,74 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// e32test\mmu\t_wsd_tst.h
+//
+
+#include <e32std.h>
+#include <e32debug.h>
+
+#ifndef __T_WSD_TST_H__
+#define __T_WSD_TST_H__
+
+#if		defined(__MARM_ARM4__)
+// ARM4: definition of IMPORT_D is wrong?
+#undef	IMPORT_D
+#define	IMPORT_D	 __declspec(dllimport)
+#endif	// defined(__MARM_ARM4__)
+
+#if		defined(__MARM_ARMV5__)
+// ARMV5: definition of IMPORT_D is wrong?
+#undef	IMPORT_D
+#define	IMPORT_D	 __declspec(dllimport)
+#endif	// defined(__MARM_ARMV5__)
+
+#if		defined(__MSVC6__)
+// MSVC6: definition of IMPORT_D is wrong?
+#undef	IMPORT_D
+#define	IMPORT_D	 __declspec(dllimport)
+#endif	// defined(__MSVC6__)
+
+#if		defined(__WINS__)
+// WINSCW: definition of IMPORT_D is wrong?
+#undef	IMPORT_D
+#define	IMPORT_D	 __declspec(dllimport)
+#endif	// defined(__WINS__)
+
+// Exports of DLL1
+#ifdef	T_WSD_DL1
+#else
+IMPORT_D TInt32 ExportedData;
+IMPORT_C TInt CheckExportedDataAddress(void *aDataAddr);
+#endif	// T_WSD_DL1
+
+// Exports of DLL2
+#ifdef	T_WSD_DL2
+#else
+typedef void** (*TGetAddressOfDataFunction)(TInt&, void*&, void*&);
+const TInt KGetAddressOfDataFunctionOrdinal = 1;
+IMPORT_C void** GetAddressOfDataProxy(TInt& aSize, void*& aCodeAddr, void*& aDataAddr);
+const TInt KCheckWritableStaticDataFunctionOrdinal = 2;
+IMPORT_C TInt CheckWritableStaticData(void);
+#endif	// T_WSD_DL2
+
+// Exports of DLL3
+#ifdef	T_WSD_DL3
+#else
+IMPORT_C void** GetAddressOfData(TInt& aSize, void*& aCodeAddr, void*& aDataAddr);
+IMPORT_D TInt32 TestDataSize;
+IMPORT_D void* WritableTestData[1 /* refer TestDataSize */];
+IMPORT_D const void* const* PointerToStaticData;
+IMPORT_D void** PointerToWritableData;
+#endif	// T_WSD_DL3
+
+#endif	// __T_WSD_TST_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/basic_tests/r_kernel_low_memory_security_svr_session.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,39 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Implementation of RKernelLowMemorySecuritySvrSession
+// 
+//
+
+#include "r_kernel_low_memory_security_svr_session.h"
+
+void RKernelLowMemorySecuritySvrSession::FailAlloc(const TInt aCount)
+	{
+	__KHEAP_FAILNEXT(aCount);
+	}
+
+void RKernelLowMemorySecuritySvrSession::HeapReset()
+	{
+	__KHEAP_RESET;
+	}
+
+void RKernelLowMemorySecuritySvrSession::MarkHeap()
+	{
+	__KHEAP_MARK;
+	}
+
+void RKernelLowMemorySecuritySvrSession::MarkHeapEnd()
+	{
+	__KHEAP_MARKEND;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/basic_tests/r_kernel_low_memory_security_svr_session.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,39 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Version of security server session to enable testing of low memory conditions on kernel side
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef R_KERNEL_LOW_MEMORY_SECURITY_SVR_SESSION_H
+#define R_KERNEL_LOW_MEMORY_SECURITY_SVR_SESSION_H
+
+#include "r_low_memory_security_svr_session.h"
+
+class RKernelLowMemorySecuritySvrSession : public RLowMemorySecuritySvrSession
+	{
+protected:
+	void FailAlloc(const TInt aCount);
+	void HeapReset();
+	void MarkHeap();
+	void MarkHeapEnd();
+	};
+
+#endif //R_KERNEL_LOW_MEMORY_SECURITY_SVR_SESSION_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/basic_tests/r_low_memory_security_svr_session.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,86 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Implementation of RLowMemorySecuritySvrSession
+// 
+//
+
+#include "r_low_memory_security_svr_session.h"
+#include <e32debug.h>
+
+// test the effects of heap failure on global RSecuritySvrSession::GetList() in debug mode,
+// in release mode normal call is made (heap checking not applicable)
+TInt RLowMemorySecuritySvrSession::GetList(const Debug::TListId aListId, TDes8& aListData, TUint32& aDataSize)
+	{
+	TInt failAt = 0;
+	TInt err = KErrNoMemory;
+	while(err == KErrNoMemory)
+		{
+		failAt++;
+		FailAlloc(failAt);
+		MarkHeap();
+		err = this->RSecuritySvrSession::GetList(aListId, aListData, aDataSize);
+		if(KErrNoMemory == err)
+			{
+			MarkHeapEnd();
+			}
+		HeapReset();
+		//RDebug::Printf("Debug::RLowMemorySecuritySvrSession::GetList(): failAt: %d, err: %d", failAt, err);
+		}
+	return err;
+	}
+
+// test the effects of heap failure on thread-specific RSecuritySvrSession::GetList() in debug mode,
+// in release mode normal call is made (heap checking not applicable)
+TInt RLowMemorySecuritySvrSession::GetList(const TThreadId aThreadId, const Debug::TListId aListId, TDes8& aListData, TUint32& aDataSize)
+	{
+	TInt failAt = 0;
+	TInt err = KErrNoMemory;
+	while(err == KErrNoMemory)
+		{
+		failAt++;
+		FailAlloc(failAt);
+		MarkHeap();
+		err = this->RSecuritySvrSession::GetList(aThreadId, aListId, aListData, aDataSize);
+		if(KErrNoMemory == err)
+			{
+			MarkHeapEnd();
+			}
+		HeapReset();
+		//RDebug::Printf("Debug::RLowMemorySecuritySvrSession::GetList(TThreadId): failAt: %d, err: %d", failAt, err);
+		}
+	return err;
+	}
+
+// test the effects of heap failure on process-specific RSecuritySvrSession::GetList() in debug mode,
+// in release mode normal call is made (heap checking not applicable)
+TInt RLowMemorySecuritySvrSession::GetList(const TProcessId aProcessId, const Debug::TListId aListId, TDes8& aListData, TUint32& aDataSize)
+	{
+	TInt failAt = 0;
+	TInt err = KErrNoMemory;
+	while(err == KErrNoMemory)
+		{
+		failAt++;
+		FailAlloc(failAt);
+		MarkHeap();
+		err = this->RSecuritySvrSession::GetList(aProcessId, aListId, aListData, aDataSize);
+		if(KErrNoMemory == err)
+			{
+			MarkHeapEnd();
+			}
+		HeapReset();
+		//RDebug::Printf("Debug::RLowMemorySecuritySvrSession::GetList(TProcessId): failAt: %d, err: %d", failAt, err);
+		}
+	return err;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/basic_tests/r_low_memory_security_svr_session.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,43 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Version of security server session to enable testing of low memory conditions
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef R_LOW_MEMORY_SECURITY_SVR_SESSION_H
+#define R_LOW_MEMORY_SECURITY_SVR_SESSION_H
+
+#include <rm_debug_api.h>
+
+class RLowMemorySecuritySvrSession : public Debug::RSecuritySvrSession
+	{
+public:
+	TInt GetList(const Debug::TListId aListId, TDes8& aListData, TUint32& aDataSize);
+	TInt GetList(const TThreadId aThreadId, const Debug::TListId aListId, TDes8& aListData, TUint32& aDataSize);
+	TInt GetList(const TProcessId aProcessId, const Debug::TListId aListId, TDes8& aListData, TUint32& aDataSize);
+protected:
+	virtual void FailAlloc(const TInt aCount) = 0;
+	virtual void HeapReset() = 0;
+	virtual void MarkHeap() = 0;
+	virtual void MarkHeapEnd() = 0;
+	};
+
+#endif //R_LOW_MEMORY_SECURITY_SVR_SESSION_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/basic_tests/r_user_low_memory_security_svr_session.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,54 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// r_kernel_low_memory_security_svr_session.cpp
+// Implementation of RUserLowMemorySecuritySvrSession
+// 
+//
+
+#include "r_user_low_memory_security_svr_session.h"
+#include <rm_debug_api.h>
+#ifdef _DEBUG
+#include "low_mem_requests.h"
+#endif
+
+void RUserLowMemorySecuritySvrSession::FailAlloc(const TInt aCount)
+	{
+#ifdef _DEBUG
+	TIpcArgs args(aCount);
+	SendReceive(EDebugServFailAlloc, args);
+#endif
+	}
+
+void RUserLowMemorySecuritySvrSession::HeapReset()
+	{
+#ifdef _DEBUG
+	TIpcArgs args(0);
+	SendReceive(EDebugServFailAlloc, args);
+#endif
+	}
+
+void RUserLowMemorySecuritySvrSession::MarkHeap()
+	{
+#ifdef _DEBUG
+	SendReceive(EDebugServMarkHeap);
+#endif
+	}
+
+void RUserLowMemorySecuritySvrSession::MarkHeapEnd()
+	{
+#ifdef _DEBUG
+	SendReceive(EDebugServMarkEnd);
+#endif
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/basic_tests/r_user_low_memory_security_svr_session.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,39 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Version of security server session to enable testing of low memory conditions on user side
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef R_USER_LOW_MEMORY_SECURITY_SVR_SESSION_H
+#define R_USER_LOW_MEMORY_SECURITY_SVR_SESSION_H
+
+#include "r_low_memory_security_svr_session.h"
+
+class RUserLowMemorySecuritySvrSession : public RLowMemorySecuritySvrSession
+	{
+protected:
+	void FailAlloc(const TInt aCount);
+	void HeapReset();
+	void MarkHeap();
+	void MarkHeapEnd();
+	};
+
+#endif //R_USER_LOW_MEMORY_SECURITY_SVR_SESSION_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/basic_tests/t_rmdebug2.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,4488 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Tests the functionality of the run mode debug device driver.
+//
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <e32test.h>
+#include <e32ldr.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <f32dbg.h>
+#include <f32file.h>
+#include <hal.h>
+#include <u32hal.h>
+#include <e32property.h>
+
+#include "t_rmdebug_dll.h"
+
+#include <rm_debug_api.h>
+#include "d_rmdebugthread2.h"
+#include "t_rmdebug2.h"
+#include "t_rmdebug_app.h"
+
+#ifdef __MARM_ARMV4__
+#include "d_rmdebug_step_test_armv4.h"
+#endif
+
+#ifdef __MARM_ARMV5__
+#include "d_rmdebug_step_test.h"
+#endif
+
+#include "d_demand_paging.h"
+
+#ifdef KERNEL_OOM_TESTING
+	#ifdef USER_OOM_TESTING
+		#error "Cannot define both KERNEL_OOM_TESTING and USER_OOM_TESTING"
+	#endif
+#endif
+
+_LIT8(KCrashDummyData, "This is a sample write");
+
+using namespace Debug;
+
+const TVersion securityServerVersion(0,1,1);
+
+const TVersion testVersion(2,1,0);
+
+IMPORT_C TInt StartDebugThread(RThread& aServerThread, const TDesC& aDebugThreadName);
+IMPORT_D extern TInt TestData;
+IMPORT_D extern TTestFunction FunctionChooser;
+IMPORT_D extern TBuf8<SYMBIAN_RMDBG_MEMORYSIZE> gMemoryAccessBytes;
+IMPORT_C TInt TestFunction();
+IMPORT_C void TestPagedCode();
+IMPORT_C extern TInt RMDebugDemandPagingTest();
+
+// Device driver name
+_LIT(KDebugDriverFileName,"rm_debug.ldd");
+
+#ifdef SYMBIAN_STANDARDDEBUG
+LOCAL_D RTest test(_L("T_RMDEBUG2"));
+#endif
+
+#ifdef SYMBIAN_OEMDEBUG
+LOCAL_D RTest test(_L("T_RMDEBUG2_OEM"));
+#endif
+
+#ifdef SYMBIAN_OEM2DEBUG
+LOCAL_D RTest test(_L("T_RMDEBUG2_OEM2"));
+#endif
+
+TBool gUseDelay;
+
+CRunModeAgent::CRunModeAgent()
+//
+// CRunModeAgent constructor
+//
+	{
+	FillArray();
+	RProcess thisProcess;
+	iFileName = thisProcess.FileName();
+	thisProcess.Close();
+	}
+
+CRunModeAgent* CRunModeAgent::NewL()
+//
+// CRunModeAgent::NewL
+//
+	{
+	CRunModeAgent* self = new(ELeave) CRunModeAgent();
+
+  	self->ConstructL();
+
+	return self;
+	}
+
+CRunModeAgent::~CRunModeAgent()
+//
+// CRunModeAgent destructor
+//
+	{
+	User::FreeLogicalDevice(KDebugDriverFileName);
+	iServSession.Close();
+	iDebugThread.Close();
+	}
+
+void CRunModeAgent::ConstructL()
+//
+// CRunModeAgent::ConstructL
+//
+	{
+	// nothing to do here
+	}
+
+void CRunModeAgent::SetupAndAttachToDSS()
+//
+// CRunModeAgent::SetupAndAttachToDSS
+//
+	{
+	TInt err = StartDebugThread(iDebugThread, KDebugThreadName);
+
+	// get the thread id for use in the tests
+	iThreadID = iDebugThread.Id();
+
+	if (err != KErrNone)
+		{
+		User::Panic(_L("Can't start debug thread"), err);
+		}
+
+	err = iServSession.Connect(securityServerVersion);
+	if (err != KErrNone)
+		{
+		User::Panic(_L("Can't open server session"), err);
+		}
+	}
+
+CRunModeAgent *RunModeAgent;
+
+// helper function to check whether the listing of type aListId is supported for a scope of aListScope
+TBool CRunModeAgent::ListingSupported(const TListId aListId, const TListScope aListScope)
+	{
+	TTag tag = GetTag(ETagHeaderList, aListId);
+
+	return (tag.iValue) & aListScope;
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0426
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test getting the list of XIP libraries
+//! @SYMTestActions The XIP library list should be successfully obtained
+//! @SYMTestExpectedResults The specified ldd file should be present in the obtained listing
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestGetXipLibrariesList()
+	{
+	test.Next(_L("TestGetXipLibrariesList\n"));
+
+	test(ListingSupported(EXipLibraries, EScopeGlobal));
+	test(!ListingSupported(EXipLibraries, EScopeProcessSpecific));
+	test(!ListingSupported(EXipLibraries, EScopeThreadSpecific));
+
+	//allocate a very small buffer so the GetList call initially fails
+	RBuf8 buffer;
+	test(KErrNone == buffer.Create(1));
+	TUint32 size = 0;
+
+	//get the list data
+	DoGetList(EXipLibraries, EScopeGlobal, buffer, size);
+
+	//search the buffer for entry corresponding to the debug kernel driver
+	//which should be in the rom
+	_LIT(KRmDebugLddName, "z:\\sys\\bin\\rm_debug.ldd");
+
+	//iterate through the buffer and set found to ETrue if we find the driver
+	TBool found = EFalse;
+	TUint8* ptr = (TUint8*)buffer.Ptr();
+	const TUint8* ptrEnd = ptr + size;
+	while(ptr < ptrEnd)
+		{
+		TXipLibraryListEntry& xipLibrary = *(TXipLibraryListEntry*)ptr;
+
+		//get the name of the library
+		TPtr name(&xipLibrary.iName[0], xipLibrary.iNameLength, xipLibrary.iNameLength);
+		if(name.CompareF(KRmDebugLddName()) == 0)
+			{
+			//found the library but continue reading the rest of the buffer to
+			//check nothing bad happens towards the end
+			found = ETrue;
+			}
+		//move pointer on to next library
+		ptr += Align4(xipLibrary.GetSize());
+		}
+	test(found);
+
+	//do cleanup
+	buffer.Close();
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0427
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test getting the list of executables
+//! @SYMTestActions The list of debuggable executable files should be obtained
+//! @SYMTestExpectedResults The client exe should appear in the list
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestGetExecutablesList()
+	{
+	test.Next(_L("TestGetExecutablesList\n"));
+
+	test(ListingSupported(EExecutables, EScopeGlobal));
+	test(!ListingSupported(EExecutables, EScopeProcessSpecific));
+	test(!ListingSupported(EExecutables, EScopeThreadSpecific));
+
+	//allocate a very small buffer so the GetList call initially fails
+	RBuf8 buffer;
+	test(KErrNone == buffer.Create(1));
+	TUint32 size = 0;
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	//get the list data
+	DoGetList(EExecutables, EScopeGlobal, buffer, size);
+
+	//get this process' name
+	RProcess thisProcess;
+	TFileName thisProcessName = thisProcess.FileName();
+
+	//look through the buffer and check if the target debug thread is there
+	TBool found = EFalse;
+	TUint8* ptr = (TUint8*)buffer.Ptr();
+	const TUint8* ptrEnd = ptr + size;
+	while(ptr < ptrEnd)
+		{
+		TExecutablesListEntry& entry = *(TExecutablesListEntry*)ptr;
+		//get name
+		TPtr name(&entry.iName[0], entry.iNameLength, entry.iNameLength);
+		if( (entry.iIsActivelyDebugged != 0) && (0 == thisProcessName.CompareF(name)) )
+			{
+			//found this process and asserted it is being actively debugged
+			found = ETrue;
+			}
+		//move pointer on to next entry
+		ptr += Align4(entry.GetSize());
+		}
+	test(found);
+
+	//clean up
+	buffer.Close();
+
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0428
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test error conditions for the GetList calls
+//! @SYMTestActions Multiple calls to test calling GetList with bad arguments
+//! @SYMTestExpectedResults All tests should fail with the appropriate error codes
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestGetListInvalidData()
+	{
+	test.Next(_L("TestGetListInvalidData\n"));
+
+	//allocate a buffer, the size should not matter as expecting all calls to fail
+	RBuf8 buffer;
+	test(KErrNone == buffer.Create(1));
+	TUint32 size = 0;
+
+	//test what happens if we ask for an unsupported list type globally
+	test(KErrNotSupported == iServSession.GetList((TListId)1234, buffer, size));
+
+	//test what happens if we ask for an unsupported list type
+	test(KErrNotSupported == iServSession.GetList(RThread().Id(), (TListId)1234, buffer, size));
+
+	//test what happens if we try to get a non-global libraries list
+	test(KErrArgument == iServSession.GetList(RThread().Id(), EXipLibraries, buffer, size));
+
+	//test what happens if we try to get a non-global executables list
+	test(KErrArgument == iServSession.GetList(RThread().Id(), EExecutables, buffer, size));
+
+	//test what happens if we try to get a non-global process list
+	test(KErrArgument == iServSession.GetList(RThread().Id(), EProcesses, buffer, size));
+
+	//check that using a process id fails
+	test(KErrArgument == iServSession.GetList(RProcess().Id(), EProcesses, buffer, size));
+
+	//check that specifying a non-existant thread id fails
+	test(KErrArgument == iServSession.GetList((TThreadId)0x12345678, EThreads, buffer, size));
+
+	//check that specifying a non-existant process id fails
+	test(KErrArgument == iServSession.GetList((TProcessId)0x12345678, EThreads, buffer, size));
+
+	//check that specifying a non-existant thread id fails
+	test(KErrArgument == iServSession.GetList((TThreadId)0x12345678, ECodeSegs, buffer, size));
+
+	//check that specifying a non-existant process id fails
+	test(KErrArgument == iServSession.GetList((TProcessId)0x12345678, ECodeSegs, buffer, size));
+
+	//cleanup
+	buffer.Close();
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0429
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test getting the process list
+//! @SYMTestActions Get the process listing
+//! @SYMTestExpectedResults The process listing should be successfully obtained and the current process should be present in the list
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestGetProcessList()
+	{
+	test.Next(_L("TestGetProcessList\n"));
+
+	test(ListingSupported(EProcesses, EScopeGlobal));
+	test(!ListingSupported(EProcesses, EScopeProcessSpecific));
+	test(!ListingSupported(EProcesses, EScopeThreadSpecific));
+
+	//allocate a very small buffer so the GetList call fails
+	RBuf8 buffer;
+	test(KErrNone == buffer.Create(1));
+	TUint32 size = 0;
+
+	//get the list data
+	DoGetList(EProcesses, EScopeGlobal, buffer, size);
+
+	//initialise data about the target debug thread to compare the kernel's data against
+	RProcess thisProcess;
+	TFileName thisProcessName = thisProcess.FileName();
+	TUint32 processId = thisProcess.Id().Id();
+
+	//look through the buffer and check if the target debug thread is there
+	TBool found = EFalse;
+	TUint8* ptr = (TUint8*)buffer.Ptr();
+	const TUint8* ptrEnd = ptr + size;
+	while(ptr < ptrEnd)
+		{
+		TProcessListEntry& entry = *(TProcessListEntry*)ptr;
+		if( (RProcess().Id().Id() == entry.iProcessId) &&
+			(0 == thisProcessName.CompareF(TPtr(&(entry.iNames[0]), entry.iFileNameLength, entry.iFileNameLength))) &&
+		 	(0 == thisProcess.FullName().CompareF(TPtr(&(entry.iNames[0]) + entry.iFileNameLength, entry.iDynamicNameLength, entry.iDynamicNameLength))) &&
+			0x4321bbbb /* Magic */ == entry.iUid3)
+			{
+			//if all match then we've found it
+			found = ETrue;
+			}
+		ptr += Align4(entry.GetSize());
+		}
+
+	//check whether the expected result happened
+	test(found);
+
+	//clean up
+	buffer.Close();
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0430
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test getting the thread list
+//! @SYMTestActions Get the thread listing globally and for a specified thread or process
+//! @SYMTestExpectedResults The thread listings should all be successfully obtained and the current thread should be present in all listings
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestGetThreadList()
+	{
+	test.Next(_L("TestGetThreadList\n"));
+
+	test(ListingSupported(EThreads, EScopeGlobal));
+	test(ListingSupported(EThreads, EScopeProcessSpecific));
+	test(ListingSupported(EThreads, EScopeThreadSpecific));
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+	//test getting the global list, ETrue as should find the target debug thread
+	DoTestGetThreadList(ETrue, EScopeGlobal);
+
+	//test getting this thread's thread list, ETrue as should find the target debug thread
+	DoTestGetThreadList(ETrue, EScopeThreadSpecific, RThread().Id().Id());
+
+	//test getting this process's thread list, ETrue as should find the target debug thread
+	DoTestGetThreadList(ETrue, EScopeProcessSpecific, RProcess().Id().Id());
+
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+void CRunModeAgent::DoTestGetThreadList(const TBool aShouldPass, const TListScope aListScope, const TUint64 aTargetId)
+	{
+	test.Next(_L("DoTestGetThreadList\n"));
+
+	//create data to pass
+	RBuf8 buffer;
+	TUint32 size = 0;
+
+	//perform the call to get the Code segs
+	DoGetList(EThreads, aListScope, buffer, size, aTargetId);
+
+	//initialise data about the target debug thread to compare the kernel's data against
+	TFileName name = iDebugThread.FullName();
+	RProcess thisProcess;
+	TUint64 processId = thisProcess.Id();
+	TUint64 threadId = iDebugThread.Id();
+
+	//look through the buffer and check if the target debug thread is there
+	TBool found = EFalse;
+	TUint8* ptr = (TUint8*)buffer.Ptr();
+	const TUint8* ptrEnd = ptr + size;
+	while(ptr < ptrEnd)
+		{
+		TThreadListEntry* entry = (TThreadListEntry*)ptr;
+		TPtr entryName(&(entry->iName[0]), entry->iNameLength, entry->iNameLength);
+		if( (threadId == entry->iThreadId) && (processId == entry->iProcessId) && (0 == name.CompareF(entryName)) )
+			{
+			test(entry->iSupervisorStackBaseValid);
+			test(entry->iSupervisorStackSizeValid);
+			//if all match then we've found it
+			found = ETrue;
+			}
+
+		ptr += Align4(entry->GetSize());
+		}
+
+	//check whether the expected result happened
+	test(found == aShouldPass);
+
+	//clean up
+	buffer.Close();
+
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0431
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test getting the code segment list
+//! @SYMTestActions Get the code segment list global and for a specified thread
+//! @SYMTestExpectedResults The listings should be returned successfully
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestGetCodeSegsList()
+	{
+	test.Next(_L("TestGetCodeSegsList\n"));
+
+	test(ListingSupported(ECodeSegs, EScopeGlobal));
+	test(ListingSupported(ECodeSegs, EScopeProcessSpecific));
+	test(ListingSupported(ECodeSegs, EScopeThreadSpecific));
+
+	// Cannot perform this test with OEM2 debug token, as the t_rmdebug2 app
+	// needs AllFiles, and the OEM2 debug token does not authorise this.
+	// It seems reasonable to suppose that it would work anyway
+
+#ifndef SYMBIAN_OEM2DEBUG
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+ 	//test getting the global list, ETrue as should find this process' main codeSeg
+	DoTestGetCodeSegsList(ETrue, EScopeGlobal);
+
+	//test getting this process' codeSegs, ETrue as should find this process' main codeSeg
+	DoTestGetCodeSegsList(ETrue, EScopeProcessSpecific, RProcess().Id().Id());
+
+	//test getting this thread's codeSegs, ETrue as should find this process' main codeSeg
+	DoTestGetCodeSegsList(ETrue, EScopeThreadSpecific, RThread().Id().Id());
+
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+#endif // SYMBIAN_OEM2DEBUG
+
+	}
+
+void CRunModeAgent::DoTestGetCodeSegsList(const TBool aShouldPass, const TListScope aListScope, const TUint64 aTargetId)
+	{
+	//create data to pass
+	RBuf8 buffer;
+	TUint32 size = 0;
+
+	//perform the call to get the Code segs
+	DoGetList(ECodeSegs, aListScope, buffer, size, aTargetId);
+
+	//create memoryInfo to contain info about this process
+	RProcess thisProcess;
+	TModuleMemoryInfo memoryInfo;
+	test(KErrNone == thisProcess.GetMemoryInfo(memoryInfo));
+
+	// check whether this process came from a file in ROM so we know whether to
+	// expect the code seg to be XIP or not.
+	RFs fs;
+	test(KErrNone == fs.Connect());
+	TBool thisFileIsInRom = EFalse;
+	if(fs.IsFileInRom(iFileName))
+		{
+		thisFileIsInRom = ETrue;
+		}
+
+	//look through the buffer to find this process' main code seg
+	TBool found = EFalse;
+	TUint8* ptr = (TUint8*)buffer.Ptr();
+	const TUint8* ptrEnd = ptr + size;
+	while(ptr < ptrEnd)
+		{
+		TCodeSegListEntry* codeSeg = (TCodeSegListEntry*)ptr;
+
+		if( (codeSeg->iIsXip == thisFileIsInRom) && (0 == iFileName.CompareF(TPtr(&(codeSeg->iName[0]), codeSeg->iNameLength, codeSeg->iNameLength))) )
+			{
+			if( (memoryInfo.iCodeBase == codeSeg->iCodeBase) &&
+					(memoryInfo.iCodeSize == codeSeg->iCodeSize) &&
+					(memoryInfo.iConstDataSize == codeSeg->iConstDataSize) &&
+					(memoryInfo.iInitialisedDataBase == codeSeg->iInitialisedDataBase) &&
+					(memoryInfo.iInitialisedDataSize == codeSeg->iInitialisedDataSize) &&
+					(memoryInfo.iUninitialisedDataSize == codeSeg->iUninitialisedDataSize))
+				{
+				//all matched so means we've found the codeSeg we're looking for
+				found = ETrue;
+				}
+			}
+		ptr += Align4(codeSeg->GetSize());
+		}
+
+	//check whether the result was as expected
+	test(found == aShouldPass);
+
+	// only care about rm_debug.ldd if we have global scope (belongs to the system not this process)
+	if (aListScope == EScopeGlobal)
+	{
+		// Search for rm_debug.ldd library and check its UID3 is correct
+		found = EFalse;
+
+_LIT(KRMDebugDriverFileName,"Z:\\sys\bin\\rm_debug.ldd");
+
+		TFileName rmdebugFilename(KRMDebugDriverFileName);
+
+		// reset the Ptr
+		ptr = (TUint8*)buffer.Ptr();
+		ptrEnd = ptr+size;
+		while(ptr < ptrEnd)
+		{
+			TCodeSegListEntry* codeSeg = (TCodeSegListEntry*)ptr;
+
+			if( rmdebugFilename.CompareF(TPtr(&(codeSeg->iName[0]), codeSeg->iNameLength, codeSeg->iNameLength)))
+				{
+				if(codeSeg->iUid3 == 0x101f7157 /* Magic */)
+					{
+					//all matched so means we've found the codeSeg we're looking for
+					found = ETrue;
+					}
+				}
+			ptr += Align4(codeSeg->GetSize());
+		}
+		test((TUint32)found == (TUint32)ETrue);
+	}
+
+	//clean up
+	buffer.Close();
+
+	}
+
+void CRunModeAgent::DoGetList(const TListId aListId, const TListScope aListScope, RBuf8& aBuffer, TUint32& aSize, const TUint64 aTargetId)
+	{
+	//close the buffer in case there's stuff allocated in it
+	aBuffer.Close();
+	//initialise it to be one byte big, which will guarantee data won't fit in it
+	test(KErrNone == aBuffer.Create(1));
+	aSize = 0;
+
+	//should pass this test (assuming we've passed in sensible arguments above...)
+	if(EScopeGlobal == aListScope)
+		{
+		test(KErrTooBig == iServSession.GetList(aListId, aBuffer, aSize));
+		}
+	else if(EScopeThreadSpecific == aListScope)
+		{
+		test(KErrTooBig == iServSession.GetList((TThreadId)aTargetId, aListId, aBuffer, aSize));
+		}
+	else if(EScopeProcessSpecific == aListScope)
+		{
+		test(KErrTooBig == iServSession.GetList((TProcessId)aTargetId, aListId, aBuffer, aSize));
+		}
+	else
+		{
+		// unknown list scope
+		test(0);
+		}
+
+	//keep allocating larger buffers, beginning with the aSize returned by the above call,
+	//and hopefully we'll eventually make a large enough one
+	test(KErrNone == aBuffer.ReAlloc(aSize));
+
+	for(;;)
+		{
+		TInt err = KErrNone;
+		if(EScopeGlobal == aListScope)
+			{
+			err = iServSession.GetList(aListId, aBuffer, aSize);
+			}
+		else if(EScopeThreadSpecific == aListScope)
+			{
+			err = iServSession.GetList((TThreadId)aTargetId, aListId, aBuffer, aSize);
+			}
+		else if(EScopeProcessSpecific == aListScope)
+			{
+			err = iServSession.GetList((TProcessId)aTargetId, aListId, aBuffer, aSize);
+			}
+		else
+			{
+			// unknown list scope
+			test(0);
+			}
+		if(err == KErrTooBig)
+			{
+			//wasn't big enough so double it
+			aSize = aSize << 1;
+			err = aBuffer.ReAlloc(aSize);
+			if(err != KErrNone)
+				{
+				//print out a message if couldn't allocate memory and quit
+				test.Printf(_L("Out ot memory when attempting to allocate %d bytes."), aSize);
+				test(KErrNone == err);
+				}
+
+			//fairly arbitrary test, we don't have a max size for these calls.
+			//In reality a list would have to have many thousands of elements
+			//to break this test which shouldn't really happen
+			test(aSize <= 0x4000);
+			}
+		else
+			{
+			test(KErrNone == err);
+			test(aBuffer.Length() == aSize);
+			//break out of the loop if the list has been successfully read in
+			break;
+			}
+		}
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0432
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test reading and writing memory
+//! @SYMTestActions Multiple calls to read and write memory, with various sizes and at various locations.
+//!	Also test that bad input values cause appropriate errors to be returned.
+//! @SYMTestExpectedResults All tests should pass and the target process should be left unaffected
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestMemoryAccess()
+{
+	TInt err;
+
+	test.Next(_L("TestMemoryAccess - Read Memory\n"));
+
+	//initialise buffer
+	gMemoryAccessBytes.SetLength(0);
+	for (TInt i=0; i<SYMBIAN_RMDBG_MEMORYSIZE; i++)
+		{
+		gMemoryAccessBytes.Append(i);
+		}
+
+	TUint32 address = (TUint32)(&gMemoryAccessBytes[0]);
+	TUint32 dataSize = SYMBIAN_RMDBG_MEMORYSIZE;
+
+	//create size for buffer that is rounded up to nearest 4 bytes if not
+	//already 4 byte aligned
+	TUint32 size = dataSize;
+	if(size % 4 != 0)
+		{
+		size += (4 - (size % 4));
+		}
+
+	RBuf8 dataBlock;
+	err = dataBlock.Create(size);
+	test(err==KErrNone);
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	//suspend the thread prior to memory operations
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+	err = iServSession.ReadMemory(iThreadID, address, size, dataBlock, EAccess32, EEndLE8);
+	test(err==KErrNone);
+
+	for (TInt i=0; i<dataSize; i++)
+		{
+		test(dataBlock.Ptr()[i] == gMemoryAccessBytes[i]);
+		}
+
+	test.Next(_L("TestMemoryAccess - Write Memory\n"));
+
+	// Now reset the buffer
+	for (TInt i=0; i<dataSize; i++)
+		{
+		gMemoryAccessBytes[i] = 0;
+		}
+
+	// Write our data into the buffer
+	err = iServSession.WriteMemory(iThreadID, address, size, dataBlock, EAccess32, EEndLE8);
+	test(err==KErrNone);
+
+	for (TInt i=0; i<dataSize; i++)
+		{
+		test(dataBlock.Ptr()[i] == gMemoryAccessBytes[i]);
+		}
+
+	//final test that everything's not been going wrong
+	test(gMemoryAccessBytes[5] != 0);
+
+	test.Next(_L("TestMemoryAccess - Invalid arguments\n"));
+	test.Printf(_L("This test may emit crash-like information. This is intended.\n"));
+
+	//test address that is not 32 bit aligned
+	err = iServSession.ReadMemory(iThreadID, address + 1, size, dataBlock, EAccess32, EEndLE8);
+	test(err == KErrArgument);
+
+	//test size that is not multiple of 4 bytes
+	err = iServSession.WriteMemory(iThreadID, address, size + 2, dataBlock, EAccess32, EEndLE8);
+	test(err == KErrArgument);
+
+	//test size > max block size
+	err = iServSession.ReadMemory(iThreadID, address, (1<<15), dataBlock, EAccess32, EEndLE8);
+	test(err == KErrArgument);
+
+	//test access size == 2 bytes
+	err = iServSession.ReadMemory(iThreadID, address, size, dataBlock, EAccess16, EEndLE8);
+	test(err == KErrNotSupported);
+
+	//test access size == 1 byte
+	err = iServSession.WriteMemory(iThreadID, address, size, dataBlock, EAccess8, EEndLE8);
+	test(err == KErrNotSupported);
+
+	//test endianess == EEndBE8
+	err = iServSession.ReadMemory(iThreadID, address, size, dataBlock, EAccess32, EEndBE8);
+	test(err == KErrNotSupported);
+
+	//test endianess == EEndBE32
+	err = iServSession.WriteMemory(iThreadID, address, size, dataBlock, EAccess32, EEndBE32);
+	test(err == KErrNotSupported);
+
+	//test reading off end of memory
+	err = iServSession.ReadMemory(iThreadID, 0xffffff00, 0x00000101, dataBlock, EAccess32, EEndLE8);
+	test(err == KErrArgument);
+
+	//The following three tests check that edge conditions in the range check are handled correctly.
+	err = iServSession.ReadMemory(iThreadID, 0xffffff00, 0x000000FF, dataBlock, EAccess32, EEndLE8);
+	test(err == KErrArgument);
+
+	err = iServSession.ReadMemory(iThreadID, 0xffffff00, 0x000000F0, dataBlock, EAccess32, EEndLE8);
+	test(err == KErrBadDescriptor);
+
+	//Third range check test. Check that range check is handled correctly even when base + size wraps to 0.
+	err = iServSession.ReadMemory(iThreadID, 0xffffff00, 0x00000100, dataBlock, EAccess32, EEndLE8);
+	test(err == KErrBadDescriptor);
+	//end of range check tests
+
+	//test size == 0
+	err = iServSession.WriteMemory(iThreadID, address, 0, dataBlock, EAccess32, EEndLE8);
+	test(err == KErrArgument);
+
+	//attempt to write to address outside of process data segments,
+	//this address corresponds to the vectors so shouldn't be able to write
+	err = iServSession.WriteMemory(iThreadID, 0xffff0000, size, dataBlock, EAccess32, EEndLE8);
+	test(err == KErrBadDescriptor);
+
+	//attempt to read and write to address in process code segment
+
+	//open a handle to the thread
+	RThread debugThread;
+	test(debugThread.Open(iThreadID) == KErrNone);
+
+	//get a reference to the debug process
+	RProcess debugProcess;
+	test(debugThread.Process(debugProcess) == KErrNone);
+
+	//get the memory info for the process
+	TProcessMemoryInfo info;
+	test(debugProcess.GetMemoryInfo(info) == KErrNone);
+
+	address = info.iCodeBase;
+	if(size <= info.iCodeSize)
+		{
+		test(KErrNone == iServSession.ReadMemory(iThreadID, address, size, dataBlock, EAccess32, EEndLE8));
+		test(KErrBadDescriptor == iServSession.WriteMemory(iThreadID, address, size, dataBlock, EAccess32, EEndLE8));
+		}
+
+	// Some performance tests now
+	TUint32 bytesRead = 0;
+
+	// Allocate a data buffer
+	TUint32* p = (TUint32*)User::Alloc(size);
+	test(p != 0);
+
+	TInt nanokernel_tick_period;
+	HAL::Get(HAL::ENanoTickPeriod, nanokernel_tick_period);
+	test (nanokernel_tick_period != 0);
+
+	static const TInt KOneMillion = 1000000;
+
+	TInt nkTicksPerSecond = KOneMillion/nanokernel_tick_period;
+
+	TUint32 stopTickCount = User::NTickCount() + nkTicksPerSecond;
+
+	while (User::NTickCount() < stopTickCount)
+		{
+		err = iServSession.ReadMemory(iThreadID, (TUint32)p, size, dataBlock, EAccess32, EEndLE8);
+		test(err==KErrNone);
+
+		// Increase the count of bytes read
+		bytesRead += size;
+		}
+
+	test(bytesRead != 0);
+	iMemoryReadKbytesPerSecond = bytesRead/1024;
+
+	// write memory test
+	TUint32 bytesWritten = 0;
+
+	stopTickCount = User::NTickCount() + nkTicksPerSecond;
+
+	while (User::NTickCount() < stopTickCount)
+		{
+		err = iServSession.WriteMemory(iThreadID, (TUint32)p, size, dataBlock, EAccess32, EEndLE8);
+		test(err==KErrNone);
+
+		// Increase the count of bytes read
+		bytesWritten += size;
+		}
+
+	test (bytesWritten != 0);
+	iMemoryWriteKbytesPerSecond = bytesWritten/1024;
+
+	User::Free(p);
+
+	//resume the thread
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+
+	debugThread.Close();
+	dataBlock.Close();
+
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0433
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test suspending and resuming threads
+//! @SYMTestActions Multiple calls to suspend and resume threads with and without attaching to the thread
+//! @SYMTestExpectedResults All tests should pass and the target process should be left unaffected
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestSuspendResume()
+	{
+	TInt err;
+
+	test.Next(_L("TestSuspendResume - Suspend\n"));
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	// Suspend the thread
+	err = iServSession.SuspendThread(iThreadID);
+	test(err==KErrNone);
+	TInt localtestdata;
+	localtestdata = TestData;
+
+	// Wait 3 seconds (suspends this thread) and hopefully resumes the
+	// thread we are controlling via the iServSession.SuspendThread request
+	User::After(3000000);
+
+	// Now check data hasnt changed
+	test(localtestdata==TestData);
+
+	// Resume the thread
+	test.Next(_L("TestSuspendResume - Resume\n"));
+	err = iServSession.ResumeThread(iThreadID);
+	test(err==KErrNone);
+
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+
+	// Wait 3 seconds (suspends this thread) and hopefully resumes the
+	// thread we are controlling via the iServSession.SuspendThread request
+	User::After(3000000);
+
+	// Now check that the thread being controlled has resumed and is
+	// updating the variable
+	test(localtestdata!=TestData);
+
+	// check that agent can resume thread which it previously detached from
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+
+	// check that agent cannot suspend thread which it previously suspended and then detached from
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	test(KErrAlreadyExists == iServSession.SuspendThread(iThreadID));
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0434
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test getting the debug functionality from the driver
+//! @SYMTestActions Get the size and contents of the debug functionality block
+//! @SYMTestExpectedResults All tests should pass and the expected data should appear in the functionality block
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestDebugFunctionality()
+	{
+
+	TInt err;
+
+	test.Next(_L("TestDebugFunctionality - GetDebugFunctionalityBufSize\n"));
+
+	TUint32 bufsize = 0;	// Safe default size
+
+	// Get functionality block size
+	err = iServSession.GetDebugFunctionalityBufSize(&bufsize);
+	test(err==KErrNone);
+	test.Next(_L("TestDebugFunctionality - GetDebugFunctionality\n"));
+
+	// Ensure we have a finite buffer size
+	test(bufsize!=0);
+
+	// Allocate space for the functionality data
+	HBufC8* dftext = HBufC8::NewLC(bufsize);
+
+	// create an empty TPtr8 refering to dftext
+	TPtr8 dftextPtr(dftext->Des());
+
+	// Get the functionality block
+	err = iServSession.GetDebugFunctionality(dftextPtr);
+	test(err==KErrNone);
+
+	// Check that the first entry is correct
+	TTagHeader RefHdr =
+	{
+		ETagHeaderIdCore,ECoreLast,
+	};
+
+	// First header passed from rm_debug.ldd
+	TTagHeader* TestHdr = (TTagHeader*)dftextPtr.Ptr();
+
+	// Check
+	test(RefHdr.iTagHdrId==TestHdr->iTagHdrId);
+	// this test might fail if the agent is used with a Debug Security Server different from
+	// the one it was compiled against. So removing it for now.
+	//test(RefHdr.iNumTags==TestHdr->iNumTags);
+
+	// read a value from the data to check it has come through as expected
+	TTagHeader* header = GetTagHdr(dftext->Des(), ETagHeaderIdApiConstants);
+	test(header != NULL);
+	TTag* tag = GetTag(header, EApiConstantsTEventInfoSize);
+	test(tag != NULL);
+	// this test might fail if the agent is used with a Debug Security Server different from
+	// the one it was compiled against. So removing it for now.
+	//test(sizeof(TEventInfo) == tag->iValue);
+
+	// Remove our temporary buffer
+	CleanupStack::PopAndDestroy(dftext);
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0435
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test setting and clearing consecutive breakpoints
+//! @SYMTestActions Set and clear consecutive breakpoints of all combinations of breakpoint types
+//! @SYMTestExpectedResults All breakpoints should be set and cleared without error
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestConsecutiveBreakPoints()
+	{
+	test.Next(_L("TestConsecutiveBreakPoints\n"));
+
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+	// just a temporary structure for storing info about a breakpoint
+	struct TBreakPoint
+		{
+	public:
+		TBreakPoint()
+			:iId(0),
+			iMode((TArchitectureMode)0),
+			iAddress(0)
+			{}
+		TBreakId iId;
+		TArchitectureMode iMode;
+		TUint32 iAddress;
+		inline TInt Size() { return (EArmMode == iMode) ? 4 : 2; }
+		};
+
+	//an address in the target debug thread
+	TUint32 address = (TUint32)(&TestFunction);
+
+	// there are six orders in which three breakpoints can be set, these are looped
+	// through below to check setting and clearing consecutive breakpoints works
+	TUint8 order[6][3] =
+		{
+			{0,1,2},
+			{0,2,1},
+			{1,0,2},
+			{1,2,0},
+			{2,0,1},
+			{2,1,0}
+		};
+
+	// The following code checks that setting and clearing consecutive breakpoints works correctly:
+	// It checks that setting all combinations of three arm and thumb breakpoints succeeds, and check that the
+	// breakpoints can be set in any order, and then cleared in any order
+
+	// the 3 least significant bits of i control whether each of the three breakpoints should be arm or thumb
+	for(TInt i=0; i<8; i++)
+		{
+		// controls the order in which the breakpoints should be set
+		for(TInt j=0; j<6; j++)
+			{
+			// create the three breakpoints and set their modes
+			TBreakPoint bp[3];
+			bp[0].iMode = (i&1) ? EArmMode : EThumbMode;
+			bp[1].iMode = (i&2) ? EArmMode : EThumbMode;
+			bp[2].iMode = (i&4) ? EArmMode : EThumbMode;
+
+			// set the address of each of the breakpoints
+			bp[0].iAddress = address;
+			if(EArmMode == bp[0].iMode)
+				{ // if an arm breakpoint then must be on a four byte boundary
+				bp[0].iAddress = Align4(bp[0].iAddress);
+				}
+			bp[1].iAddress = bp[0].iAddress + bp[0].Size();
+			if(EArmMode == bp[1].iMode)
+				{ // if an arm breakpoint then must be on a four byte boundary
+				bp[1].iAddress = Align4(bp[1].iAddress);
+				}
+			bp[2].iAddress = bp[1].iAddress + bp[1].Size();
+			if(EArmMode == bp[2].iMode)
+				{ // if an arm breakpoint then must be on a four byte boundary
+				bp[2].iAddress = Align4(bp[2].iAddress);
+				}
+			for(TInt k=0; k<6; k++)
+				{
+				// set the three breakpoints in the order defined by j and then clear them in the order defined by k
+				test(KErrNone==iServSession.SetBreak(bp[order[j][0]].iId, iThreadID, bp[order[j][0]].iAddress, bp[order[j][0]].iMode));
+				test(KErrNone==iServSession.SetBreak(bp[order[j][1]].iId, iThreadID, bp[order[j][1]].iAddress, bp[order[j][1]].iMode));
+				test(KErrNone==iServSession.SetBreak(bp[order[j][2]].iId, iThreadID, bp[order[j][2]].iAddress, bp[order[j][2]].iMode));
+				test(KErrNone==iServSession.ClearBreak(bp[order[k][0]].iId));
+				test(KErrNone==iServSession.ClearBreak(bp[order[k][1]].iId));
+				test(KErrNone==iServSession.ClearBreak(bp[order[k][2]].iId));
+				}
+			}
+		}
+
+	// resume the thread
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0436
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test breakpoint functionality
+//! @SYMTestActions Multiple calls to set and clear breakpoints. Checking bad input produces appropriate errors.
+//! @SYMTestExpectedResults All tests should pass and the target debug thread should be left unaffected
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestBreakPoints()
+	{
+	TInt err;
+
+	test.Next(_L("TestBreakPoints - Set\n"));
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	TestConsecutiveBreakPoints();
+
+	//an address in the target debug thread
+	TUint32 address = (TUint32)(&TestFunction);
+
+	/*
+	 * Ensure that breakpoint operations don't
+	 * affect memory read/write by checking that reads/writes
+	 * in locations containing breakpoints don't change behaviour
+	 * because of the breakpoints.
+	 */
+
+	TUint32 size = SYMBIAN_RMDBG_MEMORYSIZE;
+
+	RBuf8 originalDataBlock;
+	err = originalDataBlock.Create(size);
+	test(err==KErrNone);
+
+	//suspend the thread
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+	err = iServSession.ReadMemory(iThreadID, address, size, originalDataBlock, EAccess32, EEndLE8);
+	test(err==KErrNone);
+
+	// Test data block for comparison
+	RBuf8 testDataBlock;
+	err = testDataBlock.Create(size);
+	test(err==KErrNone);
+
+	/*
+	 * set an arm breakpoint
+	 */
+	TBreakId armBreakId = 0;
+	err = iServSession.SetBreak(armBreakId, iThreadID, address, EArmMode);
+	test(err == KErrNone);
+
+	// Ensure that memory read is not corrupted
+	err = iServSession.ReadMemory(iThreadID, address, size, testDataBlock, EAccess32, EEndLE8);
+	test(err==KErrNone);
+
+	test (testDataBlock == originalDataBlock);
+
+	/*
+	 * set a thumb breakpoint
+	 */
+	TBreakId thumbBreakId = 0;
+	err = iServSession.SetBreak(thumbBreakId, iThreadID, address+4, EThumbMode);
+	test(err == KErrNone);
+
+	/*
+	 * set a thumb2EE breakpoint
+	 */
+	TBreakId thumb2EEBreakId = 0;
+	err = iServSession.SetBreak(thumb2EEBreakId, iThreadID, address+8, EThumb2EEMode);
+	test(err == KErrNotSupported);
+
+	/*
+	 * overlapping breakpoint (same address/threadId/mode)
+	 */
+	TBreakId overlapBreakId = 0;
+	err = iServSession.SetBreak(overlapBreakId, iThreadID, address, EArmMode);
+	test(err == KErrAlreadyExists);
+
+	/*
+	 * overlapping breakpoint (different address/same threadId/different mode)
+	 *
+	 * address - EArmBreakpoint
+	 * address+2 - EThumbBreakpoint
+	 */
+	TBreakId overlap2BreakId = 0;
+	err = iServSession.SetBreak(overlap2BreakId, iThreadID, address+2, EThumbMode);
+	test(err == KErrAlreadyExists);
+
+	/*
+	 * Un-aligned address (arm)
+	 */
+	TBreakId armUnalignedBreakId = 0;
+	err = iServSession.SetBreak(armUnalignedBreakId, iThreadID, address+6, EArmMode);
+	test(err == KErrArgument);
+
+	/*
+	 * Un-aligned address (thumb)
+	 */
+	TBreakId thumbUnalignedBreakId = 0;
+	err = iServSession.SetBreak(thumbUnalignedBreakId, iThreadID, address+7, EThumbMode);
+	test(err == KErrArgument);
+
+	/*
+	 * Invalid address (arm)
+	 */
+	TBreakId armBadAddressBreakId = 0;
+	err = iServSession.SetBreak(armBadAddressBreakId, iThreadID, 0 /* address */, EThumbMode);
+	test(err == KErrBadDescriptor);
+
+	/*
+	 * Different thread, same address. Should fail for the same process, but succeed
+	 * for a different process.
+	 */
+
+	/*
+	 * Invalid thread
+	 */
+	TBreakId invalidThreadBreakId = 0;
+	err = iServSession.SetBreak(invalidThreadBreakId, 0xbabababa, address, EThumbMode);
+	test(err == KErrPermissionDenied);
+
+	// Clear the ARM breakpoint
+	err = iServSession.ClearBreak(armBreakId);
+	test(err == KErrNone);
+
+	// Clear the Thumb breakpoint
+	err = iServSession.ClearBreak(thumbBreakId);
+	test(err == KErrNone);
+
+	// to do : two threads at the same address
+	// to do : two processes at the same address
+
+	// Ensure that memory read is not corrupted after clearing the breakpoints
+	err = iServSession.ReadMemory(iThreadID, address, size, testDataBlock, EAccess32, EEndLE8);
+	test(err==KErrNone);
+
+	test (testDataBlock == originalDataBlock);
+
+	/*
+	 * How fast can we set breakpoints?
+	 *
+	 * Measure the time by setting/clearing breakpoints for 1 second.
+     */
+	TInt nanokernel_tick_period;
+	HAL::Get(HAL::ENanoTickPeriod, nanokernel_tick_period);
+	test (nanokernel_tick_period != 0);
+
+	TInt nkTicksPerSecond = HelpTicksPerSecond();
+
+	TInt breaksPerSecond = 0;
+
+	TUint32 stopTickCount = User::NTickCount() + nkTicksPerSecond;
+
+	while (User::NTickCount() < stopTickCount)
+		{
+		// set the breakpoint
+		TBreakId armBreakId = 0;
+		err = iServSession.SetBreak(armBreakId, iThreadID, address, EArmMode);
+		test(err == KErrNone);
+
+		// Clear the breakpoint
+		err = iServSession.ClearBreak(armBreakId);
+		test(err == KErrNone);
+
+		// Update the count of breakpoints
+		breaksPerSecond++;
+
+		// Gone wrong if we wrap to negative breakpoints (cannot set 2billion/second!)
+		test(breaksPerSecond >0);
+		}
+
+	// Store the results for later
+	iBreakpointsPerSecond = breaksPerSecond;
+
+	/*
+	 * How many breakpoints can we set?
+	 */
+
+	TBool done = EFalse;
+
+	// We assume all the breakpoints id's are issued in ascending order
+	TInt maxBreakPoints = 0;
+
+	// Temporary buffer
+	RArray<TBreakId> breakIdList;
+
+	TUint32 testAddress = address;
+
+	while(!done)
+		{
+		TBreakId breakId = 0;
+
+		// set the breakpoint
+		testAddress += 4;	// ensure the addresses don't overlap
+
+		err = iServSession.SetBreak(breakId, iThreadID, testAddress, EArmMode);
+		test (err == KErrNone || err == KErrOverflow);
+		if (err != KErrNone)
+			{
+			// we've reached the limit of the number of breaks we can set
+			done = ETrue;
+			break;
+			}
+
+		// store the id of this breakpoint
+		breakIdList.Append(breakId);
+
+		// Increase the count of breakpoints
+		maxBreakPoints++;
+		test(maxBreakPoints > 0);
+		}
+
+	// How many breakpoints can we set?
+	iMaxBreakpoints = maxBreakPoints;
+
+	// now clear all those breakpoints again
+	while(breakIdList.Count() != 0)
+		{
+		// Place it into a TBreakId
+		TBreakId id = breakIdList[0];
+
+		err = iServSession.ClearBreak(id);
+		test(err == KErrNone);
+
+		// next id
+		breakIdList.Remove(0);
+		}
+
+	breakIdList.Close();
+
+	// close our temporary buffers
+	originalDataBlock.Close();
+	testDataBlock.Close();
+
+	err = iServSession.ResumeThread(iThreadID);
+	test (err == KErrNone);
+
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0437
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test modifying breakpoints
+//! @SYMTestActions Several calls to modify breakpoints
+//! @SYMTestExpectedResults Valid requests should result in the breakpoints being changed, invalid requests should return errors
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestModifyBreak()
+	{
+	test.Next(_L("TestModifyBreak\n"));
+
+	DoTestModifyBreak(ETrue);
+	DoTestModifyBreak(EFalse);
+	}
+
+void CRunModeAgent::DoTestModifyBreak(TBool aThreadSpecific)
+	{
+	test.Printf(_L("DoTestModifyBreak: aThreadSpecific: %d\n"), aThreadSpecific?1:0);
+
+	TInt err;
+
+	RProcess process;
+	TProcessId processId = process.Id();
+	process.Close();
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	//suspend the thread
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+	//an address in the target debug thread
+	TUint32 address = (TUint32)(&TestFunction);
+
+	//set an arm mode break point
+	TBreakId armBreakId = 0;
+	err = aThreadSpecific
+		? iServSession.SetBreak(armBreakId, iThreadID, address, EArmMode)
+		: iServSession.SetProcessBreak(armBreakId, processId, address, EArmMode);
+	test(err == KErrNone);
+
+	/*
+	 * Invalid thread
+	 */
+	err = aThreadSpecific
+		? iServSession.ModifyBreak(armBreakId, 0xbabababa, address, EArmMode)
+		: iServSession.ModifyProcessBreak(armBreakId, 0xbabababa, address, EArmMode);
+	test(err == KErrPermissionDenied);
+
+	/*
+	 * Valid address
+	 */
+	err = aThreadSpecific
+		? iServSession.ModifyBreak(armBreakId, iThreadID, address+4, EArmMode)
+		: iServSession.ModifyProcessBreak(armBreakId, processId, address+4, EArmMode);
+	test(err == KErrNone);
+
+	/*
+	 * Invalid address
+	 */
+	err = aThreadSpecific
+		? iServSession.ModifyBreak(armBreakId, iThreadID, 0, EArmMode)
+		: iServSession.ModifyProcessBreak(armBreakId, processId, 0, EArmMode);
+	test(err == KErrBadDescriptor);
+
+	/*
+	 * Thumb mode
+	 */
+	err = aThreadSpecific
+		? iServSession.ModifyBreak(armBreakId, iThreadID, address, EThumbMode)
+		: iServSession.ModifyProcessBreak(armBreakId, processId, address, EThumbMode);
+	test(err == KErrNone);
+
+	/*
+	 * Thumb2EE mode
+	 */
+	err = aThreadSpecific
+		? iServSession.ModifyBreak(armBreakId, iThreadID, address, EThumb2EEMode)
+		: iServSession.ModifyProcessBreak(armBreakId, processId, address, EThumb2EEMode);
+	test(err == KErrNotSupported);
+
+	/*
+	 * Arm mode
+	 */
+	err = aThreadSpecific
+		? iServSession.ModifyBreak(armBreakId, iThreadID, address, EArmMode)
+		: iServSession.ModifyProcessBreak(armBreakId, processId, address, EArmMode);
+	test(err == KErrNone);
+
+	// Finally, clear the breakpoint
+	err = iServSession.ClearBreak(armBreakId);
+	test(err == KErrNone);
+
+	//resume the thread
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0438
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test extracting information about breakpoints
+//! @SYMTestActions Several calls to get information about breakpoints
+//! @SYMTestExpectedResults All tests should pass and the target process should be left unaffected
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestBreakInfo()
+	{
+	test.Next(_L("TestBreakInfo\n"));
+
+	DoTestBreakInfo(ETrue);
+	DoTestBreakInfo(EFalse);
+	}
+
+void CRunModeAgent::DoTestBreakInfo(TBool aThreadSpecific)
+	{
+	test.Printf(_L("DoTestModifyBreak: aThreadSpecific: %d\n"), aThreadSpecific?1:0);
+
+	TInt err;
+
+	RProcess process;
+	TProcessId processId = process.Id();
+	process.Close();
+
+	//an address in the target debug thread
+	TUint32 address = (TUint32)(&TestFunction);
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	//suspend thread
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+	//set an arm mode break point
+	TBreakId armBreakId = 0;
+	err = aThreadSpecific
+		? iServSession.SetBreak(armBreakId, iThreadID, address, EArmMode)
+		: iServSession.SetProcessBreak(armBreakId, processId, address, EArmMode);
+	test(err == KErrNone);
+
+	// Read back the information and check it is correct
+	TThreadId testThreadId = TThreadId(0);
+	TProcessId testProcessId = TProcessId(0);
+	TUint32 testAddress = 0;
+	TArchitectureMode testMode = EArmMode;
+
+	err = aThreadSpecific
+		? iServSession.BreakInfo(armBreakId,testThreadId,testAddress, testMode)
+		: iServSession.ProcessBreakInfo(armBreakId, testProcessId, testAddress, testMode);
+	test (err == KErrNone);
+	test (aThreadSpecific ? (testThreadId == iThreadID) : (testProcessId == processId));
+	test (testAddress == address);
+	test (testMode == EArmMode);
+
+	//change the address
+	TUint32 changeAddress = address + 64;
+	err = aThreadSpecific
+		? iServSession.ModifyBreak(armBreakId, iThreadID, changeAddress,EArmMode)
+		: iServSession.ModifyProcessBreak(armBreakId, processId, changeAddress, EArmMode);
+	test(err == KErrNone);
+
+	// Check the address has changed
+	err = aThreadSpecific
+		? iServSession.BreakInfo(armBreakId,testThreadId,testAddress, testMode)
+		: iServSession.ProcessBreakInfo(armBreakId, testProcessId, testAddress, testMode);
+	test (err == KErrNone);
+	test (testAddress == changeAddress);
+
+	// change the architecture type
+	TArchitectureMode checkMode = EThumbMode;
+	err = aThreadSpecific
+		? iServSession.ModifyBreak(armBreakId, iThreadID, address,checkMode)
+		: iServSession.ModifyProcessBreak(armBreakId, processId, address, checkMode);
+	test (err == KErrNone);
+
+	// Check the mode has changed
+	err = aThreadSpecific
+		? iServSession.BreakInfo(armBreakId,testThreadId,testAddress,testMode)
+		: iServSession.ProcessBreakInfo(armBreakId, testProcessId, testAddress, testMode);
+	test (err == KErrNone);
+	test (testMode == checkMode);
+
+	// clear the breakpoint again
+	err = iServSession.ClearBreak(armBreakId);
+	test (err == KErrNone);
+
+	//resume thread
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+// Needed for the RunToBreak test
+IMPORT_C extern void RMDebug_BranchTst1();
+IMPORT_C extern void RMDebug_BranchTst2();
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-0439
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test hitting various types of breakpoints
+//! @SYMTestActions Several calls to register to observe breakpoints and to hit breakpoints of different types
+//! @SYMTestExpectedResults All tests should pass and the target process should be left unaffected
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestRunToBreak()
+	{
+	test.Next(_L("TestRunToBreak\n"));
+
+	DoTestRunToBreak(ETrue);
+	DoTestRunToBreak(EFalse);
+	}
+
+void CRunModeAgent::DoTestRunToBreak(TBool aThreadSpecific)
+	{
+	test.Printf(_L("DoTestRunToBreak: aThreadSpecific: %d\n"), aThreadSpecific?1:0);
+
+	TInt err = KErrNone;
+
+	RProcess process;
+	TProcessId processId = process.Id();
+	process.Close();
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	// we should suspend the thread first, then set the breakpoint
+	err = iServSession.SuspendThread(iThreadID);
+	test (err == KErrNone);
+
+	// Try to set the breakpoint
+	TBreakId armBreakId;
+	TUint32 address = (TUint32)(&RMDebug_BranchTst1);
+
+	err = aThreadSpecific
+		? iServSession.SetBreak(armBreakId,iThreadID,address,EArmMode)
+		: iServSession.SetProcessBreak(armBreakId, processId, address, EArmMode);
+	test(err == KErrNone);
+
+	err = aThreadSpecific
+		? iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionContinue)
+		: iServSession.SetEventAction(iFileName,EEventsProcessBreakPoint, EActionContinue);
+	test (err == KErrNone);
+
+	// Continue the thread
+	err = iServSession.ResumeThread(iThreadID);
+	test (err == KErrNone);
+
+	// wait for the breakpoint to be hit
+	TEventInfo info;
+	static TRequestStatus status;
+
+	TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+
+	iServSession.GetEvent(iFileName,status,infoPtr);
+
+	// Wait for notification of the breakpoint hit event
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	// info should now be filled with the details
+	test(info.iEventType == (aThreadSpecific ? EEventsBreakPoint : EEventsProcessBreakPoint));
+	test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == address);
+	test(info.iProcessIdValid);
+	test(info.iThreadIdValid);
+
+	// Not interested in breakpoint events any more
+	err = aThreadSpecific
+		? iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionIgnore)
+		: iServSession.SetEventAction(iFileName, EEventsProcessBreakPoint, EActionIgnore);
+	test (err == KErrNone);
+
+	// Clear the breakpoint again
+	err = iServSession.ClearBreak(armBreakId);
+	test(err == KErrNone);
+
+	// continue the thread again
+	err = iServSession.ResumeThread(iThreadID);
+	test (err == KErrNone);
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0440
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Test access to target user-side registers.
+//! @SYMTestActions     Suspends a target thread, and reads/writes target thread register contents
+//!
+//! @SYMTestExpectedResults KErrNone. Should access target registers without problems.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestRegisterAccess()
+	{
+	TInt err;
+
+	test.Next(_L("TestRegisterAccess - Read\n"));
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	//suspend the thread to read registers
+	err = iServSession.SuspendThread(iThreadID);
+	test(err==KErrNone);
+
+	//we'll try to read/write registers ERegisterR0 - ERegisterCPSR and ERegisterR13_IRQ
+	//this way should get valid register values back, invalid ones and not supported ones, and it
+	//means that the register IDs are not completely contiguous
+
+	TInt firstRegister = 0;
+	TInt lastRegister = 17;
+	TInt numberOfRegisters = (lastRegister - firstRegister) + 1;
+
+	RBuf8 ids;
+	err = ids.Create(numberOfRegisters * sizeof(TRegisterInfo));
+	test(err == KErrNone);
+
+	for(TInt i=0; i<numberOfRegisters - 1; i++)
+		{
+		TRegisterInfo reg = (TRegisterInfo)((i + firstRegister)<<8);
+		ids.Append(reinterpret_cast<const TUint8*>(&reg), sizeof(TRegisterInfo));
+		}
+
+	TRegisterInfo reg = ERegisterR13Irq;
+	ids.Append(reinterpret_cast<const TUint8*>(&reg), sizeof(TRegisterInfo));
+
+	//create a buffer to store the register values in
+	RBuf8 originalValues;
+	err = originalValues.Create(numberOfRegisters*sizeof(TUint32));
+	test(err == KErrNone);
+
+	//create a buffer to store the register flags in
+	RBuf8 originalFlags;
+	err = originalFlags.Create(numberOfRegisters*sizeof(TUint8));
+	test(err == KErrNone);
+
+	//read register values
+	err = iServSession.ReadRegisters(iThreadID, ids, originalValues, originalFlags);
+	test(err == KErrNone);
+
+	//create a buffer containing data to write into the registers
+	RBuf8 tempValues;
+	err = tempValues.Create(numberOfRegisters*sizeof(TUint32));
+	test(err == KErrNone);
+
+	TUint cpsrId = 16;
+	for(TUint8 i=0; i<numberOfRegisters*sizeof(TUint32); i++)
+		{
+		if(i/sizeof(TUint32) == cpsrId)
+			{
+			//For the CPSR we wish to write data that makes sense - for USR mode we are
+			//allowed change all except the mode, ie. we must stay in usr mode. We try that here
+			//(allowedCPSRValue[4:0] = 10000) thus not changing the mode.
+			TUint32 allowedCPSRValue = 0x50000010;
+			tempValues.Append((TUint8*)&allowedCPSRValue, 4);
+			i += 3;
+			}
+		else
+			{
+			tempValues.Append(&i, 1);
+			}
+		}
+
+	test.Next(_L("TestRegisterAccess - Write\n"));
+
+	//create a buffer to store the register flags in
+	RBuf8 tempWriteFlags;
+	err = tempWriteFlags.Create(numberOfRegisters*sizeof(TUint8));
+	test(err == KErrNone);
+
+	//write the temp data into the registers
+	err = iServSession.WriteRegisters(iThreadID, ids, tempValues, tempWriteFlags);
+	test(err == KErrNone);
+
+	//create another buffer to store the register flags in
+	RBuf8 tempReadFlags;
+	err = tempReadFlags.Create(numberOfRegisters*sizeof(TUint8));
+	test(err == KErrNone);
+
+	RBuf8 tempReadValues;
+	err = tempReadValues.Create(numberOfRegisters*sizeof(TUint32));
+	test(err == KErrNone);
+
+	//read the temp data out again
+	err = iServSession.ReadRegisters(iThreadID, ids, tempReadValues, tempReadFlags);
+	test(err == KErrNone);
+
+	//check values are correct
+	for(TInt i=0; i<numberOfRegisters; i++)
+		{
+		TRegisterFlag writeFlag;
+		err = GetFlag(tempWriteFlags, i, writeFlag);
+		test(err == KErrNone);
+
+		TRegisterFlag readFlag;
+		err = GetFlag(tempReadFlags, i, readFlag);
+		test(err == KErrNone);
+
+		if((writeFlag == EValid) && (readFlag == EValid))
+			{
+			TUint8 offset = i * sizeof(TUint32);
+			for(TUint j = offset; j< offset + sizeof(TUint32); j++)
+				{
+				test(tempValues.Ptr()[j] == tempReadValues.Ptr()[j]);
+				}
+			}
+		}
+
+	//write the original data into the registers
+	err = iServSession.WriteRegisters(iThreadID, ids, originalValues, originalFlags);
+	test(err == KErrNone);
+
+	//read the data out again
+	err = iServSession.ReadRegisters(iThreadID, ids, tempValues, tempReadFlags);
+	test(err == KErrNone);
+
+	//check values are correct
+	for(TInt i=0; i<numberOfRegisters; i++)
+		{
+		TRegisterFlag writeFlag;
+		err = GetFlag(originalFlags, i, writeFlag);
+		test(err == KErrNone);
+
+		TRegisterFlag readFlag;
+		err = GetFlag(tempReadFlags, i, readFlag);
+		test(err == KErrNone);
+
+		if((writeFlag == EValid) && (readFlag == EValid))
+			{
+			TUint8 offset = i * sizeof(TUint32);
+			for(TUint j = offset; j< offset + sizeof(TUint32); j++)
+				{
+				test(tempValues.Ptr()[j] == originalValues.Ptr()[j]);
+				}
+			}
+		}
+
+	test.Next(_L("TestRegisterAccess - Invalid data\n"));
+
+	//create a buffer of max size 1
+	RBuf8 emptyBuffer;
+	emptyBuffer.Create(1);
+
+	//test register IDs buffer not being a multiple of sizeof(TRegisterInfo)
+	err = iServSession.ReadRegisters(iThreadID, emptyBuffer, tempValues, tempReadFlags);
+	test(err == KErrArgument);
+
+	//test register values buffer not being a multiple of sizeof(TUint32)
+	err = iServSession.ReadRegisters(iThreadID, ids, emptyBuffer, tempReadFlags);
+	test(err == KErrArgument);
+
+	//test flags buffer being representing different number of registers from other two
+	err = iServSession.ReadRegisters(iThreadID, ids, tempValues, emptyBuffer);
+	test(err == KErrArgument);
+
+	//set max length to 0
+	emptyBuffer.ReAlloc(0);
+
+	//test ids buffer being of 0 max length
+	err = iServSession.ReadRegisters(iThreadID, emptyBuffer, tempValues, tempReadFlags);
+	test(err == KErrArgument);
+
+	//do cleanup
+	emptyBuffer.Close();
+	tempValues.Close();
+	tempWriteFlags.Close();
+	tempReadFlags.Close();
+	tempReadValues.Close();
+
+	test.Next(_L("TestRegisterAccess - Setting PC value\n"));
+
+	//create buffer containing PC register ID
+	RBuf8 pcId;
+	err = pcId.Create(sizeof(TRegisterInfo));
+	test(err == KErrNone);
+	TRegisterInfo reg1 = (TRegisterInfo)0x00000f00;
+	pcId.Append(reinterpret_cast<const TUint8*>(&reg1), sizeof(TRegisterInfo));
+
+	//create buffer containing desired PC value
+	RBuf8 pcValue;
+	err = pcValue.Create(sizeof(TUint32));
+	test(err == KErrNone);
+	TUint32 address = (TUint32)(&TestFunction);
+	pcValue.Append(reinterpret_cast<const TUint8*>(&address), sizeof(TUint32));
+
+	//craete buffer for PC flag value
+	RBuf8 pcFlag;
+	err = pcFlag.Create(sizeof(TUint8));
+
+	//write the new PC value
+	err = iServSession.WriteRegisters(iThreadID, pcId, pcValue, pcFlag);
+	test(err==KErrNone);
+
+	//get the flag and check the PC value was written ok
+	TRegisterFlag flag = ENotSupported;
+	err = GetFlag(pcFlag, 0, flag);
+	test(err==KErrNone);
+
+	if(flag == EValid)
+		{
+		/* The PC value was changed to execute the function TestFunction.
+		* TestFunction changes the value of TestData to a given value and 
+		* then calls RMDebug_BranchTst1.
+		* We place a breakpoint on RMDebug_BranchTst1 so that to we are able 
+		* to test the value of TestData.
+		*/
+
+		test(KErrNone == iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionSuspend));
+		TBreakId armBreakId;
+		TUint32 address = (TUint32)(&RMDebug_BranchTst1);
+		test(KErrNone == iServSession.SetBreak(armBreakId,iThreadID,address,EArmMode));
+
+		// Continue the thread
+		test(KErrNone == iServSession.ResumeThread(iThreadID));
+
+		// wait for the breakpoint to be hit
+		TEventInfo info;
+		static TRequestStatus status;
+
+		TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+		iServSession.GetEvent(iFileName,status,infoPtr);
+
+		// Wait for notification of the breakpoint hit event
+		User::WaitForRequest(status);
+		test(status==KErrNone);
+
+		// info should now be filled with the details
+		test(info.iEventType == EEventsBreakPoint);
+		test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == address);
+		test(info.iProcessIdValid);
+		test(info.iThreadIdValid);
+
+		test(KErrNone == iServSession.ClearBreak(armBreakId));
+
+		// Finally test the value
+		test(TestData == 0xffeeddcc);
+		}
+
+	//Make sure we cannot change the CPSR
+	test.Next(_L("Verifying we cannot change the CPSR mode from USR Mode"));
+
+	TUint32 disallowedCpsr = 0x50000013;
+
+	RBuf8 cpsrRegId;
+	err = cpsrRegId.Create(sizeof(TUint32));
+	test(err == KErrNone);
+
+	TRegisterInfo cpsr = (TRegisterInfo)((cpsrId + firstRegister)<<8);
+	cpsrRegId.Append(reinterpret_cast<const TUint8*>(&cpsr), sizeof(TRegisterInfo));
+
+	RBuf8 cpsrRegFlags;
+	err = cpsrRegFlags.Create(sizeof(TUint8));
+	test(err == KErrNone);
+
+	RBuf8 cpsrVal;
+	err = cpsrVal.Create(sizeof(TUint32));
+	test(err == KErrNone);
+
+	cpsrVal.Append((TUint8*)&disallowedCpsr, 4);
+
+	//attempt to write disallowed CPSR in
+	err = iServSession.WriteRegisters(iThreadID, cpsrRegId, cpsrVal, cpsrRegFlags);
+	test(err == KErrNone);
+
+	RBuf8 cpsrReadVal;
+	err = cpsrReadVal.Create(sizeof(TUint32));
+	test(err == KErrNone);
+
+	//Read back the CPSR
+	err = iServSession.ReadRegisters(iThreadID, cpsrRegId, cpsrReadVal, cpsrRegFlags);
+	test(err == KErrNone);
+
+	//Make sure we havent switched modes ie. its not what we wrote
+	TUint32* readVal = (TUint32*)cpsrReadVal.Ptr();
+	test(*readVal != disallowedCpsr);
+
+	cpsrRegId.Close();
+	cpsrRegFlags.Close();
+	cpsrVal.Close();
+	cpsrReadVal.Close();
+
+	//write the original values back into here
+	err = iServSession.WriteRegisters(iThreadID, ids, originalValues, originalFlags);
+	test(err == KErrNone);
+
+	// Resume the thread
+	err = iServSession.ResumeThread(iThreadID);
+	test(err==KErrNone);
+
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+
+	//do cleanup
+	pcId.Close();
+	pcValue.Close();
+	pcFlag.Close();
+	ids.Close();
+	originalValues.Close();
+	originalFlags.Close();
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0441
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Test registration/de-registration of debug interest in target exe with the Debug Security Server
+//! @SYMTestActions     As per description
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestAttachExecutable()
+	{
+
+	test.Next(_L("TestAttachExecutable - Attach\n"));
+
+	//attach to process passively
+	test(KErrNone == iServSession.AttachExecutable(iFileName, ETrue));
+
+	//make a thread id for a non-existent thread
+	TThreadId threadId(0x12345678);
+
+	//get a handle to the target thread
+	RThread targetThread;
+	TInt err = targetThread.Open(threadId);
+	test(err != KErrNone);
+
+	//not registered for this thread's process (as it doesn't exist)
+	//so should fail security check
+	err = iServSession.ResumeThread(threadId);
+	test(err==KErrPermissionDenied);
+
+	//try to attach to the same process (and fail)
+	test(KErrAlreadyExists == iServSession.AttachExecutable(iFileName, EFalse));
+
+	test.Next(_L("TestAttachExecutable - Detach\n"));
+
+	//detach from process
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+
+	//attach non-passively
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	//not registered for this thread's process (as it doesn't exist)
+	//so should fail security check
+	err = iServSession.ResumeThread(0x12345678);
+	test(err==KErrPermissionDenied);
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0442
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests single-stepping target threads.
+//! @SYMTestActions     Steps target thread assembly level instructions, mainly branch/change PC
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestStep()
+	{
+	test.Next(_L("TestStep\n"));
+
+	DoTestStep(EFalse);
+	DoTestStep(ETrue);
+	}
+
+void CRunModeAgent::DoTestStep(TBool aThreadSpecific)
+	{
+	test.Printf(_L("DoTestStep: aThreadSpecific: %d\n"), aThreadSpecific?1:0);
+
+	TInt err = KErrNone;
+
+	RProcess process;
+	TProcessId processId = process.Id();
+	process.Close();
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	//set the target thread to execute the stepping functions
+	test(KErrNone == SwitchTestFunction(EStepFunction));
+
+	err = iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionContinue);
+	test (err == KErrNone);
+
+	if(!aThreadSpecific)
+		{
+		err = iServSession.SetEventAction(iFileName, EEventsProcessBreakPoint, EActionContinue);
+		test (err == KErrNone);
+		}
+
+	TUint32	startAddress;
+	TUint32	endAddress;
+
+	/*
+	 * RMDebug_StepTest_Non_PC_Modifying
+	 */
+	test.Next(_L("TestStep - Non-PC modifying\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Non_PC_Modifying);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Non_PC_Modifying_OK);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1, EFalse, processId);
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_Branch
+	 */
+	test.Next(_L("TestStep - Branch\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Branch);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Branch_1);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1, EFalse, processId);
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_Branch_And_Link
+	 */
+	test.Next(_L("TestStep - Branch_And_Link\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Branch_And_Link_1);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Branch_And_Link_2);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1, EFalse, processId);
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_MOV_PC
+	 */
+	test.Next(_L("TestStep - MOV PC,X\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_MOV_PC_1);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_MOV_PC_2);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1, EFalse, processId);
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_LDR_PC
+	 */
+	test.Next(_L("TestStep - LDR PC\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_LDR_PC);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_LDR_PC_1);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1, EFalse, processId);
+	test(err==KErrNone);
+
+// thumb and interworking tests are not supported on armv4
+#ifdef __MARM_ARMV5__
+
+	/*
+	 * RMDebug_StepTest_Thumb_Non_PC_Modifying
+	 */
+	test.Next(_L("TestStep - Thumb Non PC-Modifying\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Thumb_Non_PC_Modifying_1);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Thumb_Non_PC_Modifying_2);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1, EFalse, processId);
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_Thumb_Branch
+	 */
+	test.Next(_L("TestStep - Thumb Branch\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Thumb_Branch_1);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Thumb_Branch_2);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1, EFalse, processId);
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_Thumb_Branch_And_Link
+	 */
+	test.Next(_L("TestStep - Thumb Branch_And_Link\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Thumb_Branch_And_Link_2);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Thumb_Branch_And_Link_3);
+
+	TInt muid=0;
+    test(HAL::Get(HAL::EMachineUid, muid)==KErrNone);
+
+	// check if running on ARMv7 core
+	if(muid==HAL::EMachineUid_OmapH6 || muid==HAL::EMachineUid_OmapZoom || muid==HAL::EMachineUid_EmuBoard)
+        {
+        // Note: ARMv7 treats BL instructions as single 32-bit instructions
+        err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1, EFalse, processId);
+        }
+    else
+	    {
+        // Note: Due to the fact that the stepper treats BL instructions
+		// as two instructions (as the hardware does), then we must step
+		// the first half instruction first)
+
+		err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,startAddress+2,EThumbMode,1)
+		: HelpTestStep(iThreadID,startAddress,startAddress+2,EThumbMode,1, EFalse, processId);
+		test(err==KErrNone);
+
+	// Now we actually do the BL
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress+2,endAddress,EThumbMode,1)
+		: HelpTestStep(iThreadID,startAddress+2,endAddress,EThumbMode,1, EFalse, processId);
+        }
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_Thumb_Back_Branch_And_Link
+	 */
+	test.Next(_L("TestStep - Thumb Back_Branch_And_Link\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Thumb_Back_Branch_And_Link_2);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Thumb_Back_Branch_And_Link_3);
+
+	// check if running on ARMv7 core
+	if(muid==HAL::EMachineUid_OmapH6 || muid==HAL::EMachineUid_OmapZoom || muid==HAL::EMachineUid_EmuBoard)
+		{
+		// Note: ARMv7 treats BL instructions as single 32-bit instructions
+		err = aThreadSpecific
+			? HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1)
+			: HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1, EFalse, processId);
+		}
+	else
+		{
+		// Note: Due to the fact that the stepper treats BL instructions
+		// as two instructions (as the hardware does), then we must step
+		// the first half instruction first)
+
+		err = aThreadSpecific
+	   		? HelpTestStep(iThreadID,startAddress,startAddress+2,EThumbMode,1)
+			: HelpTestStep(iThreadID,startAddress,startAddress+2,EThumbMode,1, EFalse, processId);
+		test(err==KErrNone);
+
+	   	// Now we actually do the BL
+		err = aThreadSpecific
+   			? HelpTestStep(iThreadID,startAddress+2,endAddress,EThumbMode,1)
+			: HelpTestStep(iThreadID,startAddress+2,endAddress,EThumbMode,1, EFalse, processId);
+		}
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_Thumb_AddPC
+	 */
+	test.Next(_L("TestStep - Thumb ADD PC, PC, R0\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Thumb_AddPC_2);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Thumb_AddPC_3);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1, EFalse, processId);
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_Interwork ARM to Thumb
+	 */
+	test.Next(_L("TestStep - Interworking ARM to Thumb - BLX \n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Interwork_1);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Interwork_2);
+
+	err = aThreadSpecific // nb initial breakpoint in ARM code
+		? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,1, EFalse, processId);
+
+	test(err==KErrNone);
+
+	/*
+	 * RMDebug_StepTest_Interwork Thumb to ARM
+	 */
+	test.Next(_L("TestStep - Interworking Thumb to ARM - BLX\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_Interwork_2);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_Interwork_3);
+
+	// check if running on ARMv7 core
+	if(muid==HAL::EMachineUid_OmapH6 || muid==HAL::EMachineUid_OmapZoom || muid==HAL::EMachineUid_EmuBoard)
+        {
+        // ARMv7 treats BLX instructions as single 32-bit instructions
+        err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EThumbMode,1, EFalse, processId);
+        }
+    else
+        {
+    	// Stepper treats this as a two-stage instruction (just like the hardware)
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,startAddress+2,EThumbMode,1)
+		: HelpTestStep(iThreadID,startAddress,startAddress+2,EThumbMode,1, EFalse, processId);
+	test(err == KErrNone);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress+2,endAddress,EThumbMode,1)
+		: HelpTestStep(iThreadID,startAddress+2,endAddress,EThumbMode,1, EFalse, processId);
+        }
+	test(err == KErrNone);
+
+#endif // __MARM_ARMV5__
+
+	/*
+	 * Test multiple-step of ARM code
+	 */
+	test.Next(_L("TestStep - ARM Multiple instruction step\n"));
+
+	startAddress = (TUint32)(&RMDebug_StepTest_ARM_Step_Multiple);
+
+	endAddress = (TUint32)(&RMDebug_StepTest_ARM_Step_Multiple_1);
+
+	err = aThreadSpecific
+		? HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,5)
+		: HelpTestStep(iThreadID,startAddress,endAddress,EArmMode,5, EFalse, processId);
+	test(err == KErrNone);
+	// stepping performance
+	test.Next(_L("TestStep - Steps per second\n"));
+
+	// run until we reach RMDebug_StepTest_Count_1
+	TBreakId stepBreakId;
+	startAddress = (TUint32)(&RMDebug_StepTest_Count_1);
+	endAddress = (TUint32)(&RMDebug_StepTest_Count_2);
+
+	err = aThreadSpecific
+		? HelpTestStepSetBreak(stepBreakId,iThreadID,startAddress,EArmMode)
+		: HelpTestStepSetBreak(stepBreakId,iThreadID,startAddress,EArmMode,EFalse,processId);
+	test (err == KErrNone);
+
+	// wait until we hit the breakpoint
+	TEventInfo info;
+	err = HelpTestStepWaitForBreak(iFileName,info);
+	test (err == KErrNone);
+
+	// Now clear the breakpoint
+	err = iServSession.ClearBreak(stepBreakId);
+	test(err == KErrNone);
+
+	if(aThreadSpecific)
+		{
+		// now step the code
+		TInt stepsPerSecond = 0;
+
+		TUint32 stopTickCount = User::NTickCount() + HelpTicksPerSecond();
+
+		while (User::NTickCount() < stopTickCount)
+			{
+			err = iServSession.Step(iThreadID,1);
+			test (err == KErrNone);
+
+			// we need to wait now until the step completes before asking for the next step
+				{
+				TEventInfo info;
+				static TRequestStatus status;
+
+				TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+
+				iServSession.GetEvent(iFileName,status,infoPtr);
+
+				// Wait for notification of the breakpoint hit event
+				User::WaitForRequest(status);
+				test(status==KErrNone);
+				}
+
+			// Update the count of steps
+			stepsPerSecond += 1;
+
+			// Gone wrong if we do too many
+			test(stepsPerSecond < 10000);
+			}
+
+		iStepsPerSecond = stepsPerSecond;
+		test(iStepsPerSecond != 0);
+		}
+
+	// finally resume the thread
+	err = iServSession.ResumeThread(iThreadID);
+	test (err == KErrNone);
+
+	err = iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionIgnore);
+	test (err == KErrNone);
+
+	if(!aThreadSpecific)
+		{
+		err = iServSession.SetEventAction(iFileName, EEventsProcessBreakPoint, EActionIgnore);
+		test (err == KErrNone);
+		}
+
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0443
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests registration and occurrence of target thread event (in this case panic)
+//! @SYMTestActions     Registers for a panic in the target thread, causes it, and catches the panic notification.
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestEvents()
+	{
+	TInt err = KErrNone;
+
+	test.Next(_L("TestEvents\n"));
+
+	TInt panicReason = 12345;
+
+	test.Printf(_L("Thread t_rmdebug.exe::DebugThread should panic with reason %d.\n"), panicReason);
+
+	//attach non-passively
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	RThread threadToPanic;
+	test(KErrNone == StartDebugThread(threadToPanic, _L("EventsThread")));
+	TThreadId threadToPanicId = threadToPanic.Id();
+	TEventInfo info;
+
+	// Set things up to wait for a thread kill event
+	err = iServSession.SetEventAction(iFileName, EEventsKillThread, EActionContinue);
+	test(err==KErrNone);
+
+	// Wait for an event to occur in this process - nothing should have happened yet.
+	static TRequestStatus status;
+
+	TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+
+	iServSession.GetEvent(iFileName,status,infoPtr);
+
+	// Test Request cancellation
+	err = iServSession.CancelGetEvent(iFileName);
+	test (err==KErrNone);
+
+	// Again wait for an event to occur in our process - we will provoke the
+	// thread kill event by panic'ing the test thread.
+	iServSession.GetEvent(iFileName,status,infoPtr);
+
+	// Panic the debug thread to cause a thread kill event
+	threadToPanic.Panic(_L("t_rmdebug panic thread test"), panicReason);
+
+	// Wait for notification of the Thread Kill event
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	// Check we are really recieving information about the panic
+	test(info.iProcessIdValid);
+	test(info.iThreadIdValid);
+	test(info.iProcessId==RProcess().Id());
+	test(info.iThreadId==threadToPanicId);
+	test(info.iEventType==EEventsKillThread);
+	test(info.iThreadKillInfo.iExitType==EExitPanic);
+
+	// Ignore other panic events
+	err = iServSession.SetEventAction(iFileName, EEventsKillThread, EActionIgnore);
+	test(err==KErrNone);
+
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0444
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests registration and occurence of target thread events in separate process.
+//! @SYMTestActions     Registers for a hardware exception and kill thread events, and receives them.
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+void CRunModeAgent::TestEventsForExternalProcess()
+	{
+	test.Next(_L("TestEventsForExternalProcess\n"));
+
+	for(TInt main=0; main<3; main++)
+		{
+		for(TInt extra=0; extra<3; extra++)
+			{
+			TestEventsWithExtraThreads((TKernelEventAction)main, (TKernelEventAction)extra, 0);
+			TestEventsWithExtraThreads((TKernelEventAction)main, (TKernelEventAction)extra, 2);
+			}
+		}
+	}
+
+void CRunModeAgent::TestEventsWithExtraThreads(TKernelEventAction aActionMain, TKernelEventAction aActionExtra, TUint32 aExtraThreads)
+	{
+	const TInt KNumberOfTypes = 8;
+	struct TEventStruct
+		{
+		public:
+		TDebugFunctionType iDebugFunctionType;
+		TEventType iEventType;
+		};
+
+	TEventStruct type[KNumberOfTypes] =
+		{
+			{EStackOverflowFunction, EEventsHwExc},
+			{EUserPanicFunction, EEventsKillThread},
+			{EPrefetchAbortFunction, EEventsHwExc},
+			{EDataAbortFunction, EEventsHwExc},
+			{EUndefInstructionFunction, EEventsHwExc},
+			{EDataReadErrorFunction, EEventsHwExc},
+			{EDataWriteErrorFunction, EEventsHwExc},
+			{EUserExceptionFunction, EEventsSwExc},
+		};
+
+	for(TInt j=0; j<KNumberOfTypes; j++)
+		{
+		if( gUseDelay ) User::After(500000);
+
+		RDebug::Printf("CRunModeAgent::TestEventsWithExtraThreads type: %d, main action: %d, extra action: %d, extraThreads: %d", 
+			j, (TUint32)aActionMain, (TUint32)aActionExtra, aExtraThreads);
+
+		// do this check as it seems to hard to do these cases with the current set up
+		if(EEventsKillThread == type[j].iEventType)
+			{
+			if(EActionSuspend != aActionMain)
+				{
+				if(aActionMain != aActionExtra)
+					{
+					return;
+					}
+				}
+			}
+		// attach to KRMDebugTestApplication
+		test(KErrNone == iServSession.AttachExecutable(KRMDebugTestApplication, EFalse));
+
+		// Set things up to wait for the expected exception in KRMDebugTestApplication
+		test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication, type[j].iEventType, aActionMain));
+
+		if(EActionSuspend != aActionMain)
+			{
+			test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication, EEventsKillThread, aActionExtra));
+			}
+
+		// declare a TRequestStatus object for asynchronous calls
+		TRequestStatus status;
+
+		TEventInfo info;
+		TPtr8 infoBuffer = TPtr8((TUint8*)&info,0,sizeof(TEventInfo));
+		if(EActionIgnore != aActionMain)
+			{
+			iServSession.GetEvent(KRMDebugTestApplication(), status, infoBuffer);
+			}
+
+		// launch the target process to trigger the expected exception
+		RProcess targetProcess;
+		test(KErrNone == LaunchProcess(targetProcess, KRMDebugTestApplication(), type[j].iDebugFunctionType, 0, aExtraThreads));
+		TProcessId processId(targetProcess.Id());
+		targetProcess.Close();
+
+		if(EActionIgnore != aActionMain)
+			{
+			// wait for notification of the exception
+			User::WaitForRequest(status);
+			test(KErrNone == status.Int());
+
+			// check that this is the event we were expecting
+			test(info.iProcessIdValid);
+			test(info.iThreadIdValid);
+			test(info.iProcessId==processId);
+			test(info.iEventType==type[j].iEventType);
+			}
+
+		if(EActionSuspend == aActionMain)
+			{
+			//RDebug::Printf("CRunModeAgent::TestEventsWithExtraThreads EActionSuspend == aActionMain, j=%d", j);
+			// read the thread list, partly to check the call works, and partly to check the thread still exists
+			test(ThreadExistsForProcess(info.iThreadId, info.iProcessId));
+
+			// register to catch all the thread kills which will occur
+			test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication, EEventsKillThread, aActionExtra));
+			// we specified EActionSuspend earlier so need to call resume on this thread
+			test(KErrNone == iServSession.ResumeThread(info.iThreadId));
+			}
+
+		// find out how many threads there are in the process and catch all the thread kill events,
+		// the number of kill thread events should correspond to the number of extra threads launched,
+		// plus one if the main thread panicked with a Sw/Hw exception
+		if(EActionIgnore != aActionExtra)
+			{
+			TInt dyingThreads = aExtraThreads + ( (type[j].iEventType != EEventsKillThread) ? 1 : 0);
+			for(TInt k=0; k<dyingThreads; k++)
+				{
+				//RDebug::Printf("CRunModeAgent::TestEventsWithExtraThreads dyingThreads, k=%d, j=%d", k,j);
+				iServSession.GetEvent(KRMDebugTestApplication(), status, infoBuffer);
+
+				// wait for notification of the kill thread
+				User::WaitForRequest(status);
+				test(KErrNone == status.Int());
+
+				// check that this is the event we were expecting
+				test(info.iProcessIdValid);
+				test(info.iThreadIdValid);
+				test(info.iProcessId==processId);
+				test(info.iEventType==EEventsKillThread);
+				if(EActionSuspend == aActionExtra)
+					{
+					// do some calls to check listings work ok at this stage
+					test(ProcessExists(info.iProcessId));
+					test(ThreadExistsForProcess(info.iThreadId, info.iProcessId));
+					// we specified EActionSuspend earlier so need to call resume on this thread
+					test(KErrNone == iServSession.ResumeThread(info.iThreadId));
+					}
+				}
+			}
+
+		if( gUseDelay ) User::After(500000);
+
+		// reset the thread kill event
+		test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication(), EEventsKillThread, EActionIgnore));
+
+		// reset events for KRMDebugTestApplication
+		test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication(), type[j].iEventType, EActionIgnore));
+
+		// finished debugging KRMDebugTestApplication so detach
+		test(KErrNone == iServSession.DetachExecutable(KRMDebugTestApplication()));
+	
+		// want to validate that the process has really exited, i.e. we're not accidentally keeping a handle to it...
+		TInt waitCount = 10;
+		while((waitCount-- > 0) && ProcessExists(processId))
+			{
+			/* Wait a little while and try again, just in case the process is still being removed.
+			This can happen on a very busy system or when a popup for the events is still active
+			*/
+			RDebug::Printf("CRunModeAgent::TestEventsWithExtraThreads. ProcessExists(id=%d), waiting for it to exit %d", 
+				I64LOW(processId), waitCount);
+			User::After(500);
+			}
+		test(!ProcessExists(processId));
+		}
+	}
+
+// helper function to check whether a thread with id aThreadId exists in the process with id aProcessId
+TBool CRunModeAgent::ThreadExistsForProcess(const TThreadId aThreadId, const TProcessId aProcessId)
+	{
+	TUint32 size;
+	RBuf8 buffer;
+	test(KErrNone == buffer.Create(1024));
+	TInt err = iServSession.GetList(aProcessId, EThreads, buffer, size);
+	while(KErrTooBig == err)
+		{
+		size*=2;
+		test(size<=16*1024);
+		test(KErrNone == buffer.ReAlloc(size));
+		err = iServSession.GetList(aProcessId, EThreads, buffer, size);
+		}
+	test(KErrNone == err);
+
+	//look through the buffer and check if the target debug thread is there
+	TUint8* ptr = (TUint8*)buffer.Ptr();
+	const TUint8* ptrEnd = ptr + size;
+	while(ptr < ptrEnd)
+		{
+		TThreadListEntry& entry = *(TThreadListEntry*)ptr;
+		if(aThreadId.Id() == entry.iThreadId)
+			{
+			buffer.Close();
+			return ETrue;
+			}
+		ptr += Align4(entry.GetSize());
+		}
+	buffer.Close();
+	return EFalse;
+	}
+
+// helper function to check whether a process with id aProcessId exists
+TBool CRunModeAgent::ProcessExists(const TProcessId aProcessId)
+	{
+	TUint32 size;
+	RBuf8 buffer;
+	test(KErrNone == buffer.Create(1024));
+	TInt err = iServSession.GetList(EProcesses, buffer, size);
+	while(KErrTooBig == err)
+		{
+		size*=2;
+		test(size<=16*1024);
+		test(KErrNone == buffer.ReAlloc(size));
+		err = iServSession.GetList(EProcesses, buffer, size);
+		}
+	test(KErrNone == err);
+
+	//look through the buffer and check if the target debug thread is there
+	TUint8* ptr = (TUint8*)buffer.Ptr();
+	const TUint8* ptrEnd = ptr + size;
+	while(ptr < ptrEnd)
+		{
+		TProcessListEntry& entry = *(TProcessListEntry*)ptr;
+		if(aProcessId.Id() == entry.iProcessId)
+			{
+			buffer.Close();
+			return ETrue;
+			}
+		ptr += Align4(entry.GetSize());
+		}
+	buffer.Close();
+	return EFalse;
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0445
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests basic debug functions work on demand-paged target threads
+//! @SYMTestActions     Checks it can r/w memory, set breakpoints etc in a demand paged target.
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestDemandPaging(void)
+	{
+	test.Next(_L("TestDemandPaging\n"));
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+	// get the address of a function in code that will be paged in
+	TUint32 address = (TUint32)(&RMDebugDemandPagingTest);
+	const TUint32 armInstSize = 4;
+
+	// read the memory at &RMDebugDemandPagingTest to check that reading memory in demand paged code works
+	TUint32 demandPagedInst = 0;
+	TPtr8 demandPagedInstBuf((TUint8*)&demandPagedInst, armInstSize);
+	test(KErrNone == iServSession.ReadMemory(iThreadID, address, armInstSize, demandPagedInstBuf, EAccess32, EEndLE8));
+
+	// this is the MOVS instruction that we expect to find in RMDebugDemandPagingTest
+	TUint32 expectedDemandPagedInst = 0xe1b02000;
+
+	// check that the instruction we read is as expected
+	test(demandPagedInst == expectedDemandPagedInst);
+
+	// set event action for break points
+	test(KErrNone == iServSession.SetEventAction(RProcess().FileName(), EEventsBreakPoint, EActionContinue));
+
+	// set an arm breakpoint on RMDebugDemandPagingTest
+	TBreakId armBreakId = 0;
+	test(KErrNone == iServSession.SetBreak(armBreakId, iThreadID, address, EArmMode));
+
+	// Ensure that after setting the breakpoint the memory read returns the correct value
+	TUint32 demandPagedInstWithBreakPoint = 0;
+	TPtr8 spinForeverInstWithBreakPointBuf((TUint8*)&demandPagedInstWithBreakPoint, armInstSize);
+	test(KErrNone == iServSession.ReadMemory(iThreadID, address, armInstSize, spinForeverInstWithBreakPointBuf, EAccess32, EEndLE8));
+	test(demandPagedInst == demandPagedInstWithBreakPoint);
+
+	// switch the target thread to run the demand paging function
+	test(KErrNone == SwitchTestFunction(EDemandPagingFunction));
+
+	// set up event watcher to catch breakpoint being hit in demand paged code
+	TEventInfo info;
+	static TRequestStatus status;
+	TPtr8 infoPtr((TUint8*)&info,sizeof(TEventInfo));
+	iServSession.GetEvent(RProcess().FileName(), status, infoPtr);
+
+	// resume the thread
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+	// wait for notification of the breakpoint hit event
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	// info should now be filled with the details
+	test(info.iProcessIdValid);
+	test(info.iThreadIdValid);
+	test(info.iEventType == EEventsBreakPoint);
+	test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == address);
+
+	// remove the break point and resume the thread
+	test(KErrNone == iServSession.ClearBreak(armBreakId));
+
+	// switch the target thread to run the default function
+	test(KErrNone == SwitchTestFunction(EDefaultFunction));
+
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+// Names of some test programs used for testing security
+_LIT(KRMDebugSecurity0FileName,"z:\\sys\\bin\\t_rmdebug_security0.exe"); // Debuggable
+_LIT(KRMDebugSecurity1FileName,"z:\\sys\\bin\\t_rmdebug_security1.exe"); // Not debuggable
+_LIT(KRMDebugSecurity2FileName,"z:\\sys\\bin\\t_rmdebug_security2.exe"); // AllFiles
+_LIT(KRMDebugSecurity3FileName,"z:\\sys\\bin\\t_rmdebug_security3.exe"); // TCB AllFiles
+
+// include the test header file here
+#include "rm_debug_kerneldriver.h"
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0446
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests Debug Device Driver is locked to the SID of the Debug Security Svr.
+//! @SYMTestActions     Loads rm-debug.ldd and tries to open a handle to it. This should fail.
+//!
+//! @SYMTestExpectedResults KErrPermissionDenied.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestDriverSecurity(void)
+	{
+	test.Next(_L("TestDriverSecurity\n"));
+
+	RRM_DebugDriver kernelDriver;
+
+	// Load the debug device driver
+	TInt err = User::LoadLogicalDevice( KDebugDriverFileName );
+	test((KErrNone == err) || (KErrAlreadyExists == err));
+
+	// we were allowed to load the driver, or its already loaded.
+
+	// Try to open a handle to the driver - this should return KErrPermissionDenied as we don't have the DSS SID
+	TRM_DebugDriverInfo driverInfo;
+	driverInfo.iUserLibraryEnd = 0;
+	err = kernelDriver.Open(driverInfo);
+	test((err == KErrInUse) || (err == KErrPermissionDenied));
+
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0447
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests Debug driver can only be access via the DSS. Also tests DSS cannot
+//!						be subverted. Tests functionality of two representative OEM Debug Tokens.
+//! @SYMTestActions     Tries to open rm_debug.ldd (should fail). Tries to debug various processes
+//!						(only debuggable one should succeed).
+//!
+//! @SYMTestExpectedResults KErrPermissionDenied.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestSecurity(void)
+	{
+	// Things to test
+	//
+	// try to use debug driver directly ( should have the wrong UID/SID value!)
+	test.Next(_L("TestSecurity - Bypass Debug Security Server to Debug Device Driver - DSS running\n"));
+
+	// Things to test
+	//
+	// Load the debug device driver
+	RRM_DebugDriver kernelDriver;
+	TInt err = User::LoadLogicalDevice( KDebugDriverFileName );
+	test((KErrNone == err) || (KErrAlreadyExists == err));
+
+	// we were allowed to load the driver, or its already loaded.
+
+	// Try to open handle a to the driver - this should return KErrPermission/KErrInUse as we don't have the DSS SID
+	// and we expect the DSS to already be using it.
+	TRM_DebugDriverInfo driverInfo;
+	driverInfo.iUserLibraryEnd = 0;
+	err = kernelDriver.Open(driverInfo);
+	test(err == KErrInUse);
+
+	//
+	// Attach to the Debug Security Server (passive)
+	//
+	test.Next(_L("TestSecurity - Attach to the Debug Security Server (passive)\n"));
+
+	_LIT(KSecurityServerProcessName, "z:\\sys\\bin\\rm_debug_svr.exe");
+
+	test(KErrPermissionDenied == iServSession.AttachExecutable(KSecurityServerProcessName, ETrue));
+
+	//
+	// Attach to the Debug Security Server (active)
+	//
+	test.Next(_L("TestSecurity - Attach to the Debug Security Server (active)\n"));
+
+	test(KErrPermissionDenied == iServSession.AttachExecutable(KSecurityServerProcessName, EFalse));
+
+	//
+	// Attach to Process 0
+	//
+	// Target: Debuggable
+	//
+	test.Next(_L("TestSecurity - Attach to test process 0\n"));
+
+	// Agent can debug the target app as it is marked debuggable - ie capabilities are ignored)
+	HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity0FileName,ETrue);
+
+	//
+	// Attach to Process - 1
+	//
+	// Target: Non-debuggable for ordinary debug agent, debuggable for OEM/OEM2 token authorised agent
+	//
+	// Note: This target app has no PlatSec capabilities
+	//
+	// Agent cannot debug the app unless it has an OEM/OEM2 Debug Token
+	test.Next(_L("TestSecurity - Attach to test process 1\n"));
+
+#ifdef SYMBIAN_STANDARDDEBUG
+	HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity1FileName,EFalse);
+#endif
+
+#ifdef SYMBIAN_OEMDEBUG
+	HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity1FileName,ETrue);
+#endif
+
+#ifdef SYMBIAN_OEM2DEBUG
+	HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity1FileName,ETrue);
+#endif
+
+	//
+	// Attach to Process - 2
+	//
+	// Target: Non-debuggable for ordinary debug agent, non-debuggable for OEM2 authorised agent (insufficient caps)
+	//
+	// Note: This target app has AllFiles capability
+	//
+	// Agent cannot debug the app unless it has an OEM Debug Token
+	test.Next(_L("TestSecurity - Attach to test process 2\n"));
+
+#ifdef SYMBIAN_STANDARDDEBUG
+	HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity2FileName,EFalse);
+#endif
+
+#ifdef SYMBIAN_OEMDEBUG
+	HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity2FileName,ETrue);
+#endif
+
+#ifdef SYMBIAN_OEM2DEBUG
+	HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity2FileName,EFalse);
+#endif
+
+	//
+	// Attach to Process - 3
+	//
+	// Target: Non-debuggable for ordinary debug agent, non-debuggable for OEM authorised agent (insufficient caps)
+	//
+	// Note: This target app has AllFiles and TCB and NetworkControl capabilities
+	//
+	test.Next(_L("TestSecurity - Attach to test process 3\n"));
+
+	HelpTestSecurityAttachDetachExecutable(KRMDebugSecurity3FileName,EFalse);
+
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0543
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Validates that a dll can be built which #include's the rm_debug_api.h header, i.e. rm_debug_api.h contains no static data.
+//! @SYMTestActions     Calls a dummy function in t_rmdebug_dll.dll which implies the dll has been built correctly.
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+void CRunModeAgent::TestDllUsage(void)
+	{
+	test.Next(_L("TestDllUsage\n"));
+	test(KUidDebugSecurityServer == GetDSSUid());
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0812
+//! @SYMTestType
+//! @SYMPREQ            PREQ1700
+//! @SYMTestCaseDesc    Writes a known data to the crash flash and validates the data written
+//!						using the read operation and finally erase the data. In the absence
+//!						of an OEM debug token, access to the crash partition should not be allowed
+//! @SYMTestActions     Invoke the flash write method in DSS and call the read method in DSS
+//!						to validate the data is written correctly and then erase the written area
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+void CRunModeAgent::TestCrashFlash(void)
+	{
+#if  defined (SYMBIAN_STANDARDDEBUG)  || defined (SYMBIAN_OEM2DEBUG)
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-006 Testing We cannot Erase the Crash Flash with insufficient privileges"));
+
+	TUint32 size = 0;
+	TInt err = iServSession.EraseCrashLog(0, 1);
+	test(KErrPermissionDenied == err);
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-005 Testing We can't Write to the Crash Flash with insufficient privileges"));
+
+	err = iServSession.WriteCrashConfig(0, KCrashDummyData, size);
+	test(KErrPermissionDenied == err);
+	test(size == 0);
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-008 Testing We can't Read from the Crash Flash with insufficient privileges"));
+
+	TUint32 readSize = 0x10;
+	RBuf8 buf;
+	buf.CleanupClosePushL();
+	err = buf.Create(readSize);
+
+	test(err == KErrNone);
+
+	err = iServSession.ReadCrashLog(0, buf, readSize);
+	test(KErrPermissionDenied == err);
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-004 Testing Writing To an invalid location"));
+
+	TUint32 writeSize = 0;
+	err = iServSession.WriteCrashConfig(0xFFFFFFFF, KCrashDummyData, writeSize);
+
+	test(err == KErrPermissionDenied);
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-003 Testing Reading from an invalid location"));
+
+	buf.FillZ();
+	err = iServSession.ReadCrashLog(0, buf, writeSize);
+
+	test(err == KErrPermissionDenied);
+
+	CleanupStack::PopAndDestroy(&buf);
+
+#endif
+
+#ifdef SYMBIAN_OEMDEBUG
+
+	TInt err = KErrNone;
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-007 Testing We can Erase the Crash Flash with sufficient privileges"));
+
+	err = iServSession.EraseCrashLog(0, 1);
+
+	// For platforms where NAND flash is not currently supported we get a KErrNotSupported - this is still a pass
+	if (KErrNotSupported == err)
+		{
+		test.Printf(_L("Nand flash not supported - continue"));
+		return;
+		}
+
+ 	//For platforms without a flash partition we get KErrNotFound - this is still a pass
+ 	if(KErrNotFound == err)
+ 		{
+ 		test.Printf(_L("Platform has no flash partition - continue"));
+ 		return;
+ 		}
+
+	test(KErrNone == err);
+
+	//Read back the start of the block to make sure its 0xFFFFFFFF
+	const TUint numBytesToCheck = 0x80;  //We dont know the block size
+	TBuf8<numBytesToCheck> eraseCheck;
+	eraseCheck.SetLength(numBytesToCheck);
+
+	err = iServSession.ReadCrashLog(0, eraseCheck, numBytesToCheck);
+	test(err == KErrNone);
+
+	TBool dataIsOk = ETrue;
+	for(TUint cnt = 0; cnt < numBytesToCheck; cnt++)
+		{
+		if(eraseCheck[cnt] != 0xFF)
+			{
+			dataIsOk = EFalse;
+			}
+		}
+
+	test(dataIsOk);
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-002 Testing We can Write to the Crash Flash with sufficient privileges"));
+
+	TUint32 writeSize = 0;
+	err = iServSession.WriteCrashConfig(0, KCrashDummyData, writeSize);
+
+	test(writeSize == KCrashDummyData().Length());
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-001 Testing We can Read from the Crash Flash with sufficient privileges"));
+
+	RBuf8 buf;
+	buf.CleanupClosePushL();
+	err = buf.Create(writeSize);
+
+	test(err == KErrNone);
+
+	buf.FillZ();
+
+	err = iServSession.ReadCrashLog(0, buf, writeSize);
+
+	test(0 == buf.Compare(KCrashDummyData));
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-004 Testing Writing To an invalid location"));
+
+	writeSize = 0;
+	err = iServSession.WriteCrashConfig(0xFFFFFFFF, KCrashDummyData, writeSize);
+
+	test(err == KErrArgument);
+
+	test.Next(_L("@SYMTestCaseID:DT-debug-securityserver-003 Testing Reading from an invalid location"));
+
+	buf.FillZ();
+	err = iServSession.ReadCrashLog(0xFFFFFFFF, buf, writeSize);
+
+	test(err == KErrArgument);
+
+	CleanupStack::PopAndDestroy(&buf);
+
+#endif
+	}
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0735
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests the Kill Process functionality. Only can kill a debuggable process.
+//! @SYMTestActions     Launches a debuggable and non-debuggable process and tries to kill both.
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+void CRunModeAgent::TestKillProcess(void)
+	{
+	test.Next(_L("TestKillProcess\n"));
+
+	// Kill a debuggable process
+
+	// check that killing a process is supported
+	TTag tag = GetTag(ETagHeaderIdKillObjects, EFunctionalityKillProcess);
+	test(tag.iValue);
+	// check that killing a thread is not supported
+	tag = GetTag(ETagHeaderIdKillObjects, EFunctionalityKillThread);
+	test(!tag.iValue);
+
+	// attach first!
+	TInt err = iServSession.AttachExecutable(KRMDebugTestApplication, EFalse /* Active */);
+	test(err == KErrNone);
+
+	// first launch a debuggable process
+	RProcess process;
+	err = LaunchProcess(process, KRMDebugTestApplication(),ESpinForever, 0, 0);
+	test (err == KErrNone);
+
+	// try to find the process in the list
+_LIT(KRMDebugAppName, "t_rmdebug_app");
+
+	TBool found = ProcessExists(KRMDebugAppName);
+	test (found);
+
+	TInt processId = process.Id();
+	process.Close();
+
+	// program now running, so try to kill it
+	err = iServSession.KillProcess(processId, 0 /* kill reason */);
+	test(err == KErrNone);
+
+	User::After(2000000);	// should die within two seconds.
+
+	// can we still find it? Should be gone
+	found = ProcessExists(KRMDebugAppName);
+	test (!found);
+
+	// release the program again.
+	err = iServSession.DetachExecutable(KRMDebugTestApplication);
+	test(err == KErrNone);
+
+	// Try to kill a non-debuggable process and fail.
+
+	// first launch a non-debuggable process
+	RProcess process2;
+	err = LaunchProcess(process2, KRMDebugSecurity1FileName(),ESpinForever, 0, 0);
+	test (err == KErrNone);
+
+	// try to find the process in the list
+_LIT(KRMDebugAppName2, "t_rmdebug_security1");
+
+	TBool found2 = ProcessExists(KRMDebugAppName2);
+	test (found2);
+
+	TInt process2Id = process2.Id();
+	process2.Close();
+
+	// program now running, so try to kill it
+	err = iServSession.KillProcess(process2Id, 0 /* kill reason */);
+	test(err == KErrPermissionDenied);
+
+	User::After(2000000);	// should die within two seconds if it is going to die.
+
+	// can we still find it? Should be still around!
+	found2 = ProcessExists(KRMDebugAppName2);
+	test (found2);
+
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-1388
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests the correct operation of the AddProcess and Remove Process
+//! @SYMTestActions     1. Registers for AddProcess and Remove Process events
+//!                     2. Starts a test process z:\sys\bin\t_rmdebug_security0.exe
+//!                     3. Wait for the AddProcess event to be reported
+//!                     4. Kill the newly started test process
+//!                     5. Wait for the RemoveProcess event to be reported
+//!                     6. Tell the DSS it is no longer interested in AddProcess and RemoveProcess events
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestAddRemoveProcessEvents()
+	{
+	test.Next(_L("TestAddRemoveProcessEvents\n"));
+
+	// attach to a process (e.g. one of the simple security test programs)
+	// launch the security program
+	// wait for the add event
+	// continue the program.
+	// wait for the remove event
+	// detach process
+
+	test(KErrNone == iServSession.AttachExecutable(KRMDebugSecurity0FileName, EFalse));
+
+	test(KErrNone == iServSession.SetEventAction(KRMDebugSecurity0FileName,EEventsAddProcess, EActionContinue));
+
+	test(KErrNone == iServSession.SetEventAction(KRMDebugSecurity0FileName,EEventsRemoveProcess, EActionContinue));
+
+	// Creator thread ID of the current thread (to be creator of test application)
+	TInt creatorThreadId = RThread().Id();
+
+	RProcess process;
+	TInt err = process.Create(KRMDebugSecurity0FileName, KNullDesC, EOwnerProcess);
+	test (err == KErrNone);
+
+	// Rendezvous with process
+	TRequestStatus status;
+	process.Rendezvous(status);
+
+	// Start the test program
+	process.Resume();
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	// Wait for the addprocess event
+	TEventInfo info;
+	TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+
+	iServSession.GetEvent(KRMDebugSecurity0FileName,status,infoPtr);
+
+	// Wait for notification of the addprocess hit event
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	// Check this was the right kind of event
+	test(info.iEventType == EEventsAddProcess);
+
+	const TInt uid3offset = 2;
+
+	// Get UID3 for current process
+	TUint32 Uid3 = process.Type()[uid3offset].iUid;
+
+	// Check correct UID3 is returned from the driver
+    test(info.iAddProcessInfo.iUid3 == Uid3);
+
+    // Check correct creator ID for test application is returned from the driver
+    test(info.iAddProcessInfo.iCreatorThreadId == creatorThreadId);
+
+	// Kill the process, as we don't need it anymore
+	process.Kill(KErrNone);
+
+	// Wait for the remove process event
+	iServSession.GetEvent(KRMDebugSecurity0FileName,status,infoPtr);
+
+	// Wait for notification of the remove process hit event
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	// Check this was the right kind of event
+	test(info.iEventType == EEventsRemoveProcess);
+
+	test(KErrNone == iServSession.SetEventAction(KRMDebugSecurity0FileName,EEventsRemoveProcess, EActionIgnore));
+
+	test(KErrNone == iServSession.SetEventAction(KRMDebugSecurity0FileName,EEventsAddProcess, EActionIgnore));
+
+	test(KErrNone == iServSession.DetachExecutable(KRMDebugSecurity0FileName));
+
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-0736
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Checks that process break points can be set, and that they can co-exist alongside thread breakpoints
+//! @SYMTestActions     Checks that process break points can be set, and that they can co-exist alongside thread breakpoints
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+void CRunModeAgent::TestProcessBreakPoints(void)
+	{
+	test.Next(_L("TestProcessBreakPoints\n"));
+
+	// check that process breakpoints are supported
+	TTag tag = GetTag(ETagHeaderIdBreakpoints, EBreakpointProcess);
+	test(tag.iValue);
+
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+	// Try to set the breakpoint
+	TBreakId breakId;
+	TUint32 address = (TUint32)(&RMDebug_BranchTst1);
+	RProcess process;
+	TProcessId processId = process.Id();
+	process.Close();
+
+	test(KErrNone == iServSession.SetProcessBreak(breakId, processId, address, EArmMode));
+	test(KErrAlreadyExists == iServSession.SetBreak(breakId, iThreadID, address, EArmMode));
+	test(KErrAlreadyExists == iServSession.SetBreak(breakId, iThreadID, address, EThumbMode));
+	test(KErrAlreadyExists == iServSession.SetProcessBreak(breakId, processId, address, EArmMode));
+	test(KErrAlreadyExists == iServSession.SetProcessBreak(breakId, processId, address, EThumbMode));
+	test(KErrNone == iServSession.ClearBreak(breakId));
+
+	test(KErrNone == iServSession.SetBreak(breakId, iThreadID, address, EArmMode));
+	test(KErrAlreadyExists == iServSession.SetProcessBreak(breakId, processId, address, EArmMode));
+	test(KErrAlreadyExists == iServSession.SetProcessBreak(breakId, processId, address, EThumbMode));
+	test(KErrNone == iServSession.ClearBreak(breakId));
+
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-RMDEBUG2-1309
+//! @SYMTestType
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Checks that in the case of multiple low priority events (user traces in this case) we can still receive higher
+//!				priority events should the buffer reach a critical level
+//! @SYMTestActions     Run to first breakpoint in our test code. Then multiple trace events are issued. We should still be able to hit
+//!				the second breakpoint
+//!
+//! @SYMTestExpectedResults KErrNone.
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestMultipleTraceEvents(void)
+	{
+	test.Next(_L("TestMultipleTraceEvents\n"));
+
+	//attach to target debug process
+	test(KErrNone == iServSession.AttachExecutable(iFileName, EFalse));
+
+	//and suspend the thread
+	test(KErrNone == iServSession.SuspendThread(iThreadID));
+
+	//register interest in BP's & trace events and trace ignored events
+	test(KErrNone == iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionSuspend));
+	test(KErrNone == iServSession.SetEventAction(iFileName,EEventsUserTrace, EActionContinue));
+	test(KErrNone == iServSession.SetEventAction(iFileName,EEventsUserTracesLost, EActionContinue));
+
+	// Try to set the breakpoints
+	TBreakId armBreakId;
+	TBreakId armBreakId2;
+	TUint32 address = (TUint32)(&RMDebug_BranchTst1);
+	TUint32 address2 = (TUint32)(&RMDebug_StepTest_Non_PC_Modifying);
+
+	test(KErrNone == iServSession.SetBreak(armBreakId,iThreadID,address,EArmMode));
+	test(KErrNone == iServSession.SetBreak(armBreakId2,iThreadID,address2,EArmMode));
+
+	//set the target thread to execute the trace test function
+	test(KErrNone == SwitchTestFunction(EMultipleTraceCalls));
+
+	// Continue the thread
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+
+	// wait for the breakpoint to be hit
+	TEventInfo info;
+	static TRequestStatus status;
+
+	TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+	iServSession.GetEvent(iFileName,status,infoPtr);
+
+	// Wait for notification of the 1st breakpoint hit event
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	// info should now be filled with the details
+	test(info.iEventType == EEventsBreakPoint);
+	test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == address);
+	test(info.iProcessIdValid);
+	test(info.iThreadIdValid);
+
+	// Continue the thread
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+
+	//Now we try to hit the second breakpoint. This will occur after a number of trace calls. If we hit this breakpoint it
+	//means many trace calls are not preventing us hitting breakpoints.
+	iServSession.GetEvent(iFileName,status,infoPtr);
+
+	// Wait for notification of the 2nd breakpoint hit event
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	TBool receivedTracesLost = EFalse;
+
+	while(info.iEventType == EEventsUserTrace || info.iEventType == EEventsUserTracesLost)
+		{
+		//ensure we get told traces are being thrown away - we generate enough to flood the buffer
+		if(info.iEventType == EEventsUserTracesLost)
+			{
+			receivedTracesLost = ETrue;
+
+			// Now stop the target thread from generating trace events
+			test(KErrNone == SwitchTestFunction(EDoNothing));
+			}
+		else
+			{
+			// Its EEventsUserTrace, so delay us in getting the next event so that it will be more 
+			// likely to get a EEventsUserTracesLost next time. 
+			// This is important on SMP since the platform can process lots of events, and thus
+			// withouth the delay it is difficult for this test to reproduce the abnormal situation of 
+			// lost trace packets
+			User::After(200000);
+			}
+
+		iServSession.GetEvent(iFileName,status,infoPtr);
+
+		// Wait for notification of the 2nd breakpoint hit event
+		User::WaitForRequest(status);
+		test(status==KErrNone);
+		}
+
+	//make sure we got told traces were lost
+	test(receivedTracesLost != EFalse);
+
+	// info should now be filled with the details of our breakpoint.
+	test(info.iEventType == EEventsBreakPoint);
+	test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == address2);
+	test(info.iProcessIdValid);
+	test(info.iThreadIdValid);
+
+	//dont care for breakpoints or trace events no more
+	test(KErrNone == iServSession.SetEventAction(iFileName,EEventsBreakPoint, EActionIgnore));
+	test(KErrNone == iServSession.SetEventAction(iFileName,EEventsUserTrace, EActionIgnore));
+	test(KErrNone == iServSession.SetEventAction(iFileName,EEventsUserTracesLost, EActionIgnore));
+
+	//clear the breaks we set
+	test(KErrNone == iServSession.ClearBreak(armBreakId));
+	test(KErrNone == iServSession.ClearBreak(armBreakId2));
+
+	// Continue the thread
+	test(KErrNone == iServSession.ResumeThread(iThreadID));
+
+	//attach to target debug process
+	test(KErrNone == iServSession.DetachExecutable(iFileName));
+
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID KBase-T-RMDEBUG2-2441
+//! @SYMTestType
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test clearing of a process breakpoint once the process has been killed.
+//! @SYMTestActions Creates a new process then tries to set a process breakpoint and then kills the process which should clear the previously set breakpoint. Then repeat the step once again.
+//! @SYMTestExpectedResults KErrNone
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//----------------------------------------------------------------------------------------------
+
+void CRunModeAgent::TestProcessKillBreakpoint(void)
+	{
+	test.Next(_L("TestProcessKillBreakpoint\n"));
+	//SID retrieved, used in Define/Attach of the property
+	iMySid.iUid = RProcess().SecureId();
+
+	static _LIT_SECURITY_POLICY_PASS(KAllowAllPolicy);
+
+	//define a property to pass on the address from the other process we would try to debug
+	test ( KErrNone == RProperty::Define(iMySid, EMyPropertyInteger, RProperty::EInt, KAllowAllPolicy, KAllowAllPolicy));
+	    //define a global semaphore to synchronise with debuggable process publishing the property
+	test ( KErrNone == iAddressGlobSem.CreateGlobal(_L("RMDebugGlobSem"), 0) );
+
+	DoTestProcessKillBreakpoint();
+	// called once again
+	// to check if we can set the breakpoint once again after the process gets killed
+	DoTestProcessKillBreakpoint();
+
+	//delete the property
+	test ( KErrNone == RProperty::Delete(iMySid, EMyPropertyInteger));
+	//close the semaphore
+	iAddressGlobSem.Close();
+	}
+
+void CRunModeAgent::DoTestProcessKillBreakpoint()
+	{
+	test.Printf(_L("\nDoTestProcessKillBreakpoint\n"));
+
+	TInt err = KErrNone;
+
+	// check that killing a process is supported
+	TTag tag = GetTag(ETagHeaderIdKillObjects, EFunctionalityKillProcess);
+	test(tag.iValue);
+	// check that killing a thread is not supported
+	tag = GetTag(ETagHeaderIdKillObjects, EFunctionalityKillThread);
+	test(!tag.iValue);
+
+	// attach first!
+	test ( KErrNone == iServSession.AttachExecutable(KRMDebugTestApplication, EFalse/*  Active */));
+
+	// first launch a debuggable process
+	RProcess processDebug;
+	test ( KErrNone == LaunchProcess(processDebug, KRMDebugTestApplication(),ESpinForeverWithBreakPoint, 0, 0));
+
+	// try to find the process in the list
+	_LIT(KRMDebugAppName, "t_rmdebug_app");
+	TBool found = ProcessExists(KRMDebugAppName);
+	test (found);
+
+	//search for the main thread created
+   _LIT(KThreadWildCard, "t_rmdebug_app*");
+	TProcessId processDebugId = processDebug.Id();
+	TThreadId threadDebugId;
+
+   	TFindThread find(KThreadWildCard);
+	TFullName name;
+	found = EFalse;
+	while(find.Next(name)==KErrNone && !found)
+		{
+		RThread thread;
+		err = thread.Open(find);
+       	if (err == KErrNone)
+			{
+			RProcess process;
+			thread.Process(process);
+			if (((TUint32)process.Id() == processDebugId))
+				{
+				TFullName fullname = thread.FullName();
+				test.Printf(_L("Match Found Name %lS Process ID%ld Thread Id %ld"), &fullname, process.Id().Id(), thread.Id().Id());
+				found = ETrue;
+				threadDebugId = thread.Id();
+				}
+			process.Close();
+			}
+			thread.Close();
+   		}
+
+	test (found); //check if we actually found the thread we want to debug
+
+	//get the value(property) for the breakpoint address for the process to debug
+	TInt address;
+	RProperty integerProperty;
+	test ( KErrNone == integerProperty.Attach(iMySid, EMyPropertyInteger, EOwnerThread));
+
+	//waiting on semaphore to be sure that the property is set
+	iAddressGlobSem.Wait();
+
+	test ( KErrNone == integerProperty.Get(address));
+	integerProperty.Close();
+
+	test.Printf(_L("Address retrieved to set breakpoint 0x%8x"), address);
+
+	//suspend the thread before we set a breakpoint
+	test ( KErrNone == iServSession.SuspendThread(threadDebugId));
+
+	//set a process breakpoint
+	TBreakId breakId;
+	test(KErrNone == iServSession.SetProcessBreak(breakId, processDebugId, address, EArmMode));
+
+	test(KErrNone ==iServSession.SetEventAction(KRMDebugTestApplication,EEventsProcessBreakPoint, EActionContinue));
+
+	//resume the thread now
+	test(KErrNone == iServSession.ResumeThread(threadDebugId));
+
+	// wait for the breakpoint to be hit
+	static TRequestStatus status;
+	TEventInfo info;
+	TPtr8 infoPtr((TUint8*)&info,0,sizeof(TEventInfo));
+	iServSession.GetEvent(KRMDebugTestApplication,status,infoPtr);
+	// Wait for notification of the breakpoint hit event
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	// info should now be filled with the details
+	test(info.iEventType ==  EEventsProcessBreakPoint);
+	test(info.iThreadBreakPointInfo.iRmdArmExcInfo.iR15 == address);
+	test(info.iProcessIdValid);
+	test(info.iThreadIdValid);
+
+	// Not interested in breakpoint events any more
+	test(KErrNone == iServSession.SetEventAction(KRMDebugTestApplication, EEventsProcessBreakPoint, EActionIgnore));
+
+	// program now running, so try to kill it which should clear all the breakpoints
+	test(KErrNone == iServSession.KillProcess(processDebugId, 0  /* kill reason */ ));
+
+	processDebug.Close();
+	User::After(2000000);	// should die within two seconds.
+
+	// can we still find it? Should be gone
+	found = ProcessExists(KRMDebugAppName);
+	test (!found);
+
+	// release the program again
+	test(KErrNone == iServSession.DetachExecutable(KRMDebugTestApplication));
+
+	}
+
+void CRunModeAgent::HelpTestSecurityAttachDetachExecutable(const TDesC& aProcessName, TBool aExpectSuccess)
+	{
+	RProcess process;
+	TInt err = process.Create(aProcessName, KNullDesC, EOwnerProcess);
+	test (err == KErrNone);
+
+	// rendezvous with process
+	TRequestStatus status;
+	process.Rendezvous(status);
+
+	// start the test program
+	process.Resume();
+	User::WaitForRequest(status);
+	test(status==KErrNone);
+
+	// attach to the program (passively)
+	err = iServSession.AttachExecutable(aProcessName, EFalse);
+
+	if( gUseDelay ) User::After(500000);
+
+	// Do we expect to successfully attach
+	if (aExpectSuccess)
+	{
+		// Yes
+		test(KErrNone == err);
+
+		// Now detach again
+		test(KErrNone == iServSession.DetachExecutable(aProcessName));
+		if( gUseDelay ) User::After(500000);
+	}
+	else
+	{
+		// No
+		test(KErrPermissionDenied == err);
+
+		// Just to be sure, try active attachment
+		test(KErrPermissionDenied == iServSession.AttachExecutable(aProcessName, ETrue));
+		if( gUseDelay ) User::After(500000);
+	}
+
+	// Kill the process, as we don't need it anymore
+	process.Kill(KErrNone);
+	if( gUseDelay ) User::After(500000);
+	}
+
+void CRunModeAgent::ReportPerformance(void)
+//
+// Reports performance metrics from all the tests
+//
+	{
+	test.Printf(_L("\nPerformance\n"));
+	test.Printf(_L("========================\n"));
+
+	// Memory
+	test.Printf(_L("Memory read: %d KBytes/sec\n"),iMemoryReadKbytesPerSecond);
+	test.Printf(_L("Memory write: %d KBytes/sec\n"),iMemoryWriteKbytesPerSecond);
+
+	// Registers
+	// to do
+
+	// events
+	// to do
+
+	// Breakpoints
+	test.Printf(_L("Breakpoint set/clear: %d/sec\n"),iBreakpointsPerSecond);
+	test.Printf(_L("Maximum number of breakpoints: %d\n"),iMaxBreakpoints);
+
+	// Stepping
+	test.Printf(_L("Stepping speed: %d/sec\n"),iStepsPerSecond);
+
+	// Runtime
+	TInt ticks = HelpGetTestTicks();
+	test (ticks != 0);
+
+	TInt nkTicksPerSecond = HelpTicksPerSecond();
+	test (nkTicksPerSecond != 0);
+
+	test.Printf(_L("Total test runtime: %d seconds\n"),ticks/nkTicksPerSecond);
+
+	// Final sizes of executables/rom/ram etc
+	// to do
+
+	test.Printf(_L("\n"));
+	}
+
+/**
+ * Helper code for the stepping tests. Sets a breakpoint in a running thread.
+ * It suspends the thread, sets the breakpoint, and resumes the thread.
+ *
+ * @param aBreakId - Reference to a TBreakId which will be set when the breakpoint is set
+ * @param aThreadId - The thread id for which we should set the breakpoint.
+ * @param aBreakAddress - The address to set the breakpoint
+ * @param aMode - The architecture of the breakpoint to be set (ARM/Thumb/Thumb2EE)
+ * @return KErrNone if successful. One of the other system wide error codes otherwise.
+ */
+TInt CRunModeAgent::HelpTestStepSetBreak(TBreakId& aBreakId, TThreadId aThreadId, const TUint32 aBreakAddress, TArchitectureMode aMode, TBool aThreadSpecific, TProcessId aProcessId)
+	{
+	TInt err = KErrNone;
+
+	// Suspend the thread
+	err = iServSession.SuspendThread(aThreadId);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStepSetBreak - Failed to suspend thread\n"));
+		return err;
+		}
+
+	// Set the breakpoint
+	err = aThreadSpecific
+		? iServSession.SetBreak(aBreakId,aThreadId,aBreakAddress,aMode)
+		: iServSession.SetProcessBreak(aBreakId, aProcessId, aBreakAddress, aMode);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStepSetBreak - Failed to set breakpoint\n"));
+		return err;
+		}
+
+	// Continue the thread
+	err = iServSession.ResumeThread(aThreadId);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStepSetBreak - Failed to resume thread\n"));
+		return err;
+		}
+
+	return KErrNone;
+	}
+
+/**
+ * Helper code for the stepping tests. Clears a breakpoint in a running thread.
+ * It suspends the thread, clears the breakpoint, and resumes the thread.
+ *
+ * @param aBreakId - Reference to a TBreakId which will be set when the breakpoint is set
+ * @return KErrNone if successful. One of the other system wide error codes otherwise.
+ */
+TInt CRunModeAgent::HelpTestStepClearBreak(TBreakId aBreakId, const TThreadId aThreadId, TBool aThreadSpecific)
+	{
+	TInt err = KErrNone;
+
+	// Find out what thread id we need to suspend
+	TThreadId threadId;
+	TProcessId processId;
+	TUint32 address;
+	TArchitectureMode mode;
+
+	err = aThreadSpecific
+		? iServSession.BreakInfo(aBreakId, threadId, address, mode)
+		: iServSession.ProcessBreakInfo(aBreakId, processId, address, mode);
+	if (err != KErrNone )
+		{
+		test.Printf(_L("HelpTestStepClearBreak - failed to obtain information for breakpoint\n"));
+		return err;
+		}
+	if(aThreadSpecific && aThreadId != threadId)
+		{
+		test.Printf(_L("HelpTestStepClearBreak - mismatched thread Ids\n"));
+		return KErrGeneral;
+		}
+
+	// Suspend the thread
+	err = iServSession.SuspendThread(aThreadId);
+	if (!(err == KErrNone || err == KErrAlreadyExists))
+		{
+		test.Printf(_L("HelpTestStepClearBreak - failed to suspend thread\n"));
+		return err;
+		}
+
+	// Clear the breakpoint
+	err = iServSession.ClearBreak(aBreakId);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStepClearBreak - failed to clear breakpoint\n"));
+		return err;
+		}
+
+	// Continue the thread
+	err = iServSession.ResumeThread(aThreadId);
+	if (!(err == KErrNone || err == KErrNotFound))
+		{
+		test.Printf(_L("HelpTestStepClearBreak - failed to resume thread\n"));
+		return err;
+		}
+
+	return KErrNone;
+	}
+
+/**
+ * Helper code for the stepping tests. Waits for a previously set breakpoint to be hit.
+ *
+ * @param aProcessName - The name of the process in which the breakpoint is set. E.g. z:\sys\bin\app.exe
+ * @param aEventInfo - The event information block which is filled in when the breakpoint is hit.
+ * @return KErrNone if successful. One of the other system wide error codes otherwise.
+ */
+TInt CRunModeAgent::HelpTestStepWaitForBreak(const TDesC& aProcessName, TEventInfo& aEventInfo)
+	{
+	static TRequestStatus status;
+
+	TPtr8 infoPtr((TUint8*)&aEventInfo,0,sizeof(TEventInfo));
+
+	iServSession.GetEvent(aProcessName,status,infoPtr);
+
+	// Wait for notification of the breakpoint hit event
+	User::WaitForRequest(status);
+	if (status == KErrNone)
+		{
+		return KErrNone;
+		}
+	else
+		{
+		return KErrGeneral;
+		}
+	}
+
+/**
+ * Helper code for the stepping tests. Reads the current target PC for a given thread.
+ *
+ * @param aThreadId - Thread id for which to read the current target PC.
+ * @param aPc - Reference to a TUint32 which will be set to the current target PC.
+ * @return KErrNone if successful. One of the other system wide error codes otherwise.
+ */
+TInt CRunModeAgent::HelpTestStepReadPC(TThreadId aThreadId, TUint32& aPC)
+	{
+	TInt err = KErrNone;
+
+	//create buffer containing PC register ID
+	RBuf8 pcId;
+	err = pcId.Create(sizeof(TRegisterInfo));
+	if (err != KErrNone)
+		{
+		return err;
+		}
+
+	TRegisterInfo reg1 = (TRegisterInfo)0x00000f00;
+	pcId.Append(reinterpret_cast<const TUint8*>(&reg1), sizeof(TRegisterInfo));
+
+	//create buffer containing desired PC value
+	TPtr8 pcValue((TUint8*)&aPC,4,4);
+
+	//create buffer for PC flag value
+	RBuf8 pcFlag;
+	err = pcFlag.Create(sizeof(TUint8));
+
+	//read the new PC value
+	err = iServSession.ReadRegisters(aThreadId, pcId, pcValue, pcFlag);
+	if (err != KErrNone)
+		{
+		//delete temporary buffers
+		pcId.Close();
+		pcFlag.Close();
+		return err;
+		}
+
+	//get the flag and check the PC value was read ok
+	TRegisterFlag flag = ENotSupported;
+	err = GetFlag(pcFlag, 0, flag);
+	if (err != KErrNone)
+		{
+		//delete temporary buffers
+		pcId.Close();
+		pcFlag.Close();
+		return err;
+		}
+
+	if (flag == EValid)
+		{
+		//delete temporary buffers
+		pcId.Close();
+		pcFlag.Close();
+		return KErrNone;
+		}
+	else
+		{
+		//delete temporary buffers
+		pcId.Close();
+		pcFlag.Close();
+		return err;
+		}
+	}
+
+/**
+ * Helper code for the stepping tests. Single steps a given thread from aStartAddress to aEndAddress. Note
+ * that it reaches aStartAddress by setting a breakpoint at that address and waiting until it is hit.
+ *
+ * @param aThreadId - Thread id for which to read the current target PC.
+ * @param aStartAddress - The target address at which stepping will start.
+ * @param aEndAddress - The target address at which stepping will end.
+ * @param aMode - The architecture of the breakpoint which must be set at the start address (ARM/Thumb/Thumb2EE).
+ * @return KErrNone if successful. One of the other system wide error codes otherwise.
+ */
+TInt CRunModeAgent::HelpTestStep(TThreadId aThreadId, TUint32 aStartAddress, TUint32 aEndAddress, TArchitectureMode aMode, TUint aNumSteps, TBool aThreadSpecific, TProcessId aProcessId)
+	{
+	TInt err = KErrNone;
+
+	// Ensure that the supplied addresses are word/half-word aligned as appropriate.
+	if (aMode == EArmMode)
+		{
+		// ARM breakpoints must be word-aligned (2 lsb must be zero)
+		aStartAddress &= 0xFFFFFFFC;
+		aEndAddress &= 0xFFFFFFFC;
+		}
+	else if (aMode == EThumbMode)
+		{
+		// Thumb breakpoints must be half-word aligned (lsb must be zero)
+		aStartAddress &= 0xFFFFFFFE;
+		aEndAddress	 &= 0xFFFFFFFE;
+		}
+	else if (aMode == EThumb2EEMode)
+	{
+		// Thumb2EE breakpoints are not currently supported
+		return KErrNotSupported;
+	}
+
+	// Set breakpoint at the start address
+	TBreakId tempBreakId;
+	TEventInfo info;
+
+	err = HelpTestStepSetBreak(tempBreakId,aThreadId,aStartAddress,aMode,aThreadSpecific,aProcessId);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStep - Failed to set breakpoint at aStartAddress 0x%08x\n"),aStartAddress);
+		return err;
+		}
+
+	// wait for the breakpoint to be hit
+	err = HelpTestStepWaitForBreak(iFileName,info);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStep - Failed to hit the breakpoint at aStartAddress 0x%08x\n"),aStartAddress);
+		return err;
+		}
+
+	// Check the PC == aStartAddress
+	TUint32 pc = 0;
+	err = HelpTestStepReadPC(aThreadId,pc);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStep - Failed to read the PC after hitting breakpoint at aStartAddress 0x%08x\n"),aStartAddress);
+		return err;
+		}
+
+	if (pc != aStartAddress)
+		{
+		test.Printf(_L("HelpTestStep - Incorrect PC value after hitting breakpoint (expected 0x%08x actual 0x%08x)\n"),aStartAddress,pc);
+		return KErrGeneral;
+		}
+
+	err = iServSession.Step(aThreadId,aNumSteps);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStep - Failed to do step from 0x%08x to 0x%08x\n"),aStartAddress,aEndAddress,aNumSteps);
+		return err;
+		}
+
+	// only one 'completed step' event in the buffer.
+	err = HelpTestStepWaitForBreak(iFileName,info);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStep - Could not read breakpoint event info after stepping"));
+		return err;
+		}
+	// end
+
+	// Check PC == aEndAddress
+	err = HelpTestStepReadPC(aThreadId,pc);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStep - failed read the PC after stepping\n"));
+		return err;
+		}
+	if (pc != aEndAddress)
+		{
+		test.Printf(_L("HelpTestStep - Incorrect PC value after stepping (expected 0x%08x actual 0x%08x)\n"),aEndAddress,pc);
+		return KErrGeneral;
+		}
+
+	// Clear the breakpoint
+	err = HelpTestStepClearBreak(tempBreakId, aThreadId, aThreadSpecific);
+	if (err != KErrNone)
+		{
+		test.Printf(_L("HelpTestStep - failed to clear temporary breakpoint\n"));
+		return err;
+		}
+
+	return KErrNone;
+	}
+
+/**
+ * Helper code for the stepping tests. Returns the number of nanokernel ticks in one second.
+ *
+ * @return Number of nanokernel ticks. 0 if unsuccesful.
+ */
+TInt CRunModeAgent::HelpTicksPerSecond(void)
+	{
+	TInt nanokernel_tick_period;
+	HAL::Get(HAL::ENanoTickPeriod, nanokernel_tick_period);
+
+	ASSERT(nanokernel_tick_period != 0);
+
+	static const TInt KOneMillion = 1000000;
+
+	return KOneMillion/nanokernel_tick_period;
+	}
+
+/**
+  Given aTestNumber runs the appropriate test inside heap markers
+
+  @param aTestNumber test to run, corresponds to an entry in iTestArray
+
+  @panic Panic if aTestNumber is not in valid range
+  */
+void CRunModeAgent::RunTest(TInt aTestNumber)
+	{
+	if( (aTestNumber<0) || (aTestNumber>=KMaxTests) )
+		{
+		User::Panic(_L("Test number out of range"), aTestNumber);
+		}
+	__UHEAP_MARK;
+	(this->*(iTestArray[aTestNumber].iFunctionPtr))();
+	__UHEAP_MARKEND;
+	}
+
+void CRunModeAgent::PrintVersion()
+	{
+	test.Printf(_L("\nt_rmdebug2.exe\nVersion: %S\n"), &(testVersion.Name()));
+	test.Printf(_L("Press any key...\n"));
+	test.Getch();
+	}
+
+void CRunModeAgent::PrintUsage()
+	{
+	test.Printf(_L("Invoke with arguments:\n"));
+	test.Printf(_L("-r: run specified tests in reverse order\n"));
+	test.Printf(_L("-h: display usage information\n"));
+	test.Printf(_L("-v: display version\n"));
+	test.Printf(_L("-d: use delays\n"));
+	test.Printf(_L("<number>: test number to run, can specify more than one from the following list:\n"));
+	test.Printf(_L("Press any key for list...\n"));
+	test.Getch();
+	// if there are too many of these they won't fit on the screen! Stick another Getch() in if there get too many
+	for(TInt i=0; i<KMaxTests; i++)
+		{
+		test.Printf(_L("%2d: %S\n"), i, &(iTestArray[i].iFunctionName));
+		}
+	test.Printf(_L("Press any key...\n"));
+	test.Getch();
+	}
+
+/**
+  Parse the command line, see CRunModeAgent::PrintUsage for syntax
+  */
+void CRunModeAgent::ParseCommandLineL(TUint32& aMode, RArray<TInt>& aTests)
+	{
+	// get the length of the command line arguments
+	TInt argc = User::CommandLineLength();
+
+	// allocate a buffer for the command line arguments and extract the data to it
+	HBufC* commandLine = HBufC::NewLC(argc);
+	TPtr commandLineBuffer = commandLine->Des();
+	User::CommandLine(commandLineBuffer);
+
+	// reset mode
+	aMode = (TTestMode)0;
+
+	// create a lexer and read through the command line
+	TLex lex(*commandLine);
+	while (!lex.Eos())
+		{
+		// expecting the first character to be a '-'
+		if (lex.Get() == '-')
+			{
+			TChar arg = lex.Get();
+			switch (arg)
+				{
+				case 'v':
+					//print out the help
+					aMode |= EModeVersion;
+					break;
+				case 'h':
+					//print out the help
+					aMode |= EModeHelp;
+					break;
+				case 'r':
+					//store the fact that we want to run in reverse
+					aMode |= EModeReverse;
+					break;
+				case 'd':
+					//store the fact that we want to run in reverse
+					gUseDelay = EFalse;
+					RDebug::Printf("Not using delays");
+					break;
+				default:
+					// unknown argument so leave
+					User::Leave(KErrArgument);
+				}
+			}
+		else
+			{
+			lex.UnGet();
+			TInt testNumber;
+			User::LeaveIfError(lex.Val(testNumber));
+			if( (testNumber<0) || (testNumber>=KMaxTests) )
+				{
+				User::Leave(KErrArgument);
+				}
+			aTests.AppendL(testNumber);
+			}
+		lex.SkipSpace();
+		}
+	// if no tests specified then run them all
+	if(aTests.Count() == 0)
+		{
+		aMode |= EModeAll;
+		}
+
+	// do clean up
+	CleanupStack::PopAndDestroy(commandLine);
+	}
+
+void CRunModeAgent::ClientAppL()
+//
+// Performs each test in turn
+//
+	{
+	test.Start(_L("ClientAppL"));
+
+	RArray<TInt> testsToRun;
+	TUint32 testMode = 0;
+	ParseCommandLineL(testMode, testsToRun);
+
+	//if help or version mode specified then just print out the relevant stuff and quit
+	if((testMode & EModeHelp) || (testMode & EModeVersion))
+		{
+		if(testMode & EModeHelp)
+			{
+			PrintUsage();
+			}
+		if(testMode & EModeVersion)
+			{
+			PrintVersion();
+			}
+		test.End();
+		return;
+		}
+
+	if(testMode & EModeAll)
+		{
+		for(TInt i=0; i<KMaxTests; i++)
+			{
+			testsToRun.AppendL(i);
+			}
+		}
+
+	// if EModeReverse specified then reverse the array elements
+	TInt numberOfTests = testsToRun.Count();
+	if(testMode & EModeReverse)
+		{
+		for(TInt i=0; i<(numberOfTests>>1); i++)
+			{
+			TInt temp = testsToRun[i];
+			testsToRun[i] = testsToRun[numberOfTests - (i+1)];
+			testsToRun[numberOfTests - (i+1)] = temp;
+			}
+		}
+
+	__UHEAP_MARK;
+	SetupAndAttachToDSS();
+	__UHEAP_MARKEND;
+
+	HelpStartTestTimer();
+	for(TInt i=0; i<numberOfTests; i++)
+		{
+		RunTest(testsToRun[i]);
+		if( gUseDelay ) User::After(500000);
+		}
+	testsToRun.Close();
+
+	HelpStopTestTimer();
+
+	ReportPerformance();
+
+	test.End();
+	}
+
+/**
+  Fill the test array with pointers to each test.
+  */
+void CRunModeAgent::FillArray()
+	{
+	iTestArray[0].iFunctionPtr = &CRunModeAgent::TestDriverSecurity;
+	iTestArray[0].iFunctionName = _L("TestDriverSecurity");
+	iTestArray[1].iFunctionPtr = &CRunModeAgent::TestDllUsage;
+	iTestArray[1].iFunctionName = _L("TestDllUsage");
+	iTestArray[2].iFunctionPtr = &CRunModeAgent::TestSecurity;
+	iTestArray[2].iFunctionName = _L("TestSecurity");
+	iTestArray[3].iFunctionPtr = &CRunModeAgent::TestAttachExecutable;
+	iTestArray[3].iFunctionName = _L("TestAttachExecutable");
+	iTestArray[4].iFunctionPtr = &CRunModeAgent::TestGetExecutablesList;
+	iTestArray[4].iFunctionName = _L("TestGetExecutablesList");
+	iTestArray[5].iFunctionPtr = &CRunModeAgent::TestGetProcessList;
+	iTestArray[5].iFunctionName = _L("TestGetProcessList");
+	iTestArray[6].iFunctionPtr = &CRunModeAgent::TestGetXipLibrariesList;
+	iTestArray[6].iFunctionName = _L("TestGetXipLibrariesList");
+	iTestArray[7].iFunctionPtr = &CRunModeAgent::TestGetThreadList;
+	iTestArray[7].iFunctionName = _L("TestGetThreadList");
+	iTestArray[8].iFunctionPtr = &CRunModeAgent::TestGetCodeSegsList;
+	iTestArray[8].iFunctionName = _L("TestGetCodeSegsList");
+	iTestArray[9].iFunctionPtr = &CRunModeAgent::TestGetListInvalidData;
+	iTestArray[9].iFunctionName = _L("TestGetListInvalidData");
+	iTestArray[10].iFunctionPtr = &CRunModeAgent::TestMemoryAccess;
+	iTestArray[10].iFunctionName = _L("TestMemoryAccess");
+	iTestArray[11].iFunctionPtr = &CRunModeAgent::TestDebugFunctionality;
+	iTestArray[11].iFunctionName = _L("TestDebugFunctionality");
+	iTestArray[12].iFunctionPtr = &CRunModeAgent::TestSuspendResume;
+	iTestArray[12].iFunctionName = _L("TestSuspendResume");
+	iTestArray[13].iFunctionPtr = &CRunModeAgent::TestBreakPoints;
+	iTestArray[13].iFunctionName = _L("TestBreakPoints");
+	iTestArray[14].iFunctionPtr = &CRunModeAgent::TestModifyBreak;
+	iTestArray[14].iFunctionName = _L("TestModifyBreak");
+	iTestArray[15].iFunctionPtr = &CRunModeAgent::TestBreakInfo;
+	iTestArray[15].iFunctionName = _L("TestBreakInfo");
+	iTestArray[16].iFunctionPtr = &CRunModeAgent::TestRunToBreak;
+	iTestArray[16].iFunctionName = _L("TestRunToBreak");
+	iTestArray[17].iFunctionPtr = &CRunModeAgent::TestRegisterAccess;
+	iTestArray[17].iFunctionName = _L("TestRegisterAccess");
+	iTestArray[18].iFunctionPtr = &CRunModeAgent::TestStep;
+	iTestArray[18].iFunctionName = _L("TestStep");
+	iTestArray[19].iFunctionPtr = &CRunModeAgent::TestDemandPaging;
+	iTestArray[19].iFunctionName = _L("TestDemandPaging");
+	iTestArray[20].iFunctionPtr = &CRunModeAgent::TestEventsForExternalProcess;
+	iTestArray[20].iFunctionName = _L("TestEventsForExternalProcess");
+	iTestArray[21].iFunctionPtr = &CRunModeAgent::TestEvents;
+	iTestArray[21].iFunctionName = _L("TestEvents");
+	iTestArray[22].iFunctionPtr = &CRunModeAgent::TestKillProcess;
+	iTestArray[22].iFunctionName = _L("TestKillProcess");
+	iTestArray[23].iFunctionPtr = &CRunModeAgent::TestProcessBreakPoints;
+	iTestArray[23].iFunctionName = _L("TestProcessBreakPoints");
+	iTestArray[24].iFunctionPtr = &CRunModeAgent::TestMultipleTraceEvents;
+	iTestArray[24].iFunctionName = _L("TestMultipleTraceEvents");
+	iTestArray[25].iFunctionPtr = &CRunModeAgent::TestAddRemoveProcessEvents;
+	iTestArray[25].iFunctionName = _L("TestAddRemoveProcessEvents");
+	iTestArray[26].iFunctionPtr = &CRunModeAgent::TestCrashFlash;
+	iTestArray[26].iFunctionName = _L("TestCrashFlash");
+	iTestArray[27].iFunctionPtr = &CRunModeAgent::TestProcessKillBreakpoint;
+	iTestArray[27].iFunctionName = _L("TestProcessKillBreakpoint");
+	};
+
+GLDEF_C TInt E32Main()
+//
+// Entry point for run mode debug driver test
+//
+	{
+   TInt ret = KErrNone;
+
+	// client
+	CTrapCleanup* trap = CTrapCleanup::New();
+	if (!trap)
+		return KErrNoMemory;
+   	test.Title();
+   RunModeAgent = CRunModeAgent::NewL();
+   if (RunModeAgent != NULL)
+       {
+        __UHEAP_MARK;
+	    TRAP(ret,RunModeAgent->ClientAppL());
+	    __UHEAP_MARKEND;
+
+	    delete RunModeAgent;
+       }
+
+	delete trap;
+
+	return ret;
+	}
+
+/**
+Helper function to get the aOffset'th value from aFlags
+
+@param aFlags descriptor containing TRegisterFlag type flags
+@param aOffset index of flag value to extract from aFlags
+@param aFlagValue the flag value if function returned successfully
+
+@return KErrNone if value was read successfully, KErrTooBig if aOffset is
+        greater than aFlags.Length()
+*/
+TInt CRunModeAgent::GetFlag(const TDes8& aFlags, const TUint aOffset, TRegisterFlag &aFlagValue) const
+	{
+	//get pointer to data
+	const TUint8 *ptr = aFlags.Ptr();
+
+	//check aOffset is valid
+	TUint length = aFlags.Length();
+	if(aOffset >= length)
+		return KErrTooBig;
+
+	//get flag value
+	aFlagValue = (TRegisterFlag)ptr[aOffset];
+	return KErrNone;
+	}
+
+/**
+  Helper function to set the value of FunctionChooser in the target debug thread.
+
+  @param aTestFunction TTestFunction enum to set FunctionChooser to
+
+  @return KErrNone if the value was set correctly, or one of the other system wide error codes
+  */
+TInt CRunModeAgent::SwitchTestFunction(TTestFunction aTestFunction)
+	{
+	//suspend the target thread
+	TInt suspendError = iServSession.SuspendThread(iThreadID);
+	if(! ( (suspendError == KErrNone) || (suspendError == KErrAlreadyExists) ) )
+		{
+		//the thread is not suspended so exit
+		return suspendError;
+		}
+
+	//get the address of FunctionChooser
+	TUint32 functionChooserAddress = (TUint32)&FunctionChooser;
+	//put the new value for FunctionChooser into a descriptor
+	TPtr8 functionBuf((TUint8*)&aTestFunction, sizeof(TTestFunction), sizeof(TTestFunction));
+	//write the new value into the target thread
+	TInt writeError = iServSession.WriteMemory(iThreadID, functionChooserAddress, sizeof(TTestFunction), functionBuf, EAccess32, EEndLE8);
+
+	if(KErrNone == suspendError)
+		{
+		//if this function suspended the target thread then we need to resume it
+		TInt resumeError = iServSession.ResumeThread(iThreadID);
+		if(KErrNone != resumeError)
+			{
+			//resuming failed so return the error
+			return resumeError;
+			}
+		}
+
+	//suspending and resuming was successful so return the error code from the WriteMemory call
+	return writeError;
+	}
+
+/**
+  Launch a separate process to debug.
+
+  @param aProcess the RProcess object to use to create the process
+  @param aFileName file name of the executable to create the process from
+  @param aFunctionType function that the target process should call on execution
+  @param aDelay delay before the new process should call the function represented by aFunctionType
+  @param aExtraThreads number of extra threads to create in the child process
+
+  @return KErrNone on success, or one of the other system wide error codes
+  */
+TInt CRunModeAgent::LaunchProcess(RProcess& aProcess, const TDesC& aFileName, TDebugFunctionType aFunctionType, TUint32 aDelay, TUint32 aExtraThreads)
+	{
+	// at the moment we support two arguments, this number might have to be increased to support arguments
+	const TUint KMaxCommandLineLength = 32;
+
+	// create a command line buffer
+	RBuf commandLine;
+	commandLine.Create(KMaxCommandLineLength);
+
+	// append the command line arguments to the buffer
+	_LIT(KFArg, "-f");
+	commandLine.Append(KFArg());
+	commandLine.AppendNum(aFunctionType);
+
+	_LIT(KSpace, " ");
+	commandLine.Append(KSpace());
+
+	_LIT(KDArg, "-d");
+	commandLine.Append(KDArg());
+	commandLine.AppendNum(aDelay);
+
+	commandLine.Append(KSpace());
+
+	_LIT(KEArg, "-e");
+	commandLine.Append(KEArg());
+	commandLine.AppendNum(aExtraThreads);
+
+	// create the new process, matching on file name only, not specifying uid values
+	TInt err = aProcess.Create(aFileName, commandLine);	// owned by the process
+
+	// check that there was no error raised
+	if(err != KErrNone)
+		{
+		commandLine.Close();
+		return err;
+		}
+
+	TRequestStatus status = KRequestPending;
+	aProcess.Rendezvous(status);
+
+	commandLine.Close();	// after target thread starts
+
+	if(KRequestPending != status.Int())
+		{
+		// startup failed so kill the process
+		aProcess.Kill(KErrNone);
+		return status.Int();
+		}
+	else
+		{
+		// start up succeeded so resume the process
+		aProcess.Resume();
+		User::WaitForRequest(status);
+		if(KErrNone != status.Int())
+			{
+			aProcess.Kill(KErrNone);
+			}
+		return status.Int();
+		}
+	}
+
+/**
+  Helper function to read a tag header from a debug functionality block
+
+  @param aDebugFunctionalityBlock block to read header from
+  @param aTagHdrId header type to find
+
+  @return pointer to the header, or NULL if not available
+  */
+TTagHeader* CRunModeAgent::GetTagHdr(const TDesC8& aDebugFunctionalityBlock, const TTagHeaderId aTagHdrId) const
+	{
+	TUint8* ptr = (TUint8*) aDebugFunctionalityBlock.Ptr();
+	TUint8* blockEnd = ptr + aDebugFunctionalityBlock.Size();
+
+	while(ptr < blockEnd)
+		{
+		TTagHeader* header = (TTagHeader*)ptr;
+		if(header->iTagHdrId == aTagHdrId)
+			{
+			return header;
+			}
+		ptr += sizeof(TTagHeader) + (header->iNumTags * sizeof(TTag));
+		}
+	return NULL;
+	}
+
+/**
+  Helper function to read a tag from a debug functionality block
+
+  @param aTagHdr pointer to a tag header in a debug functionality block
+  @param aElement element to return from the header's data
+
+  @return pointer to the tag, or NULL if not available
+  */
+TTag* CRunModeAgent::GetTag(const TTagHeader* aTagHdr, const TInt aElement) const
+	{
+	TUint8* ptr = (TUint8*)aTagHdr + sizeof(TTagHeader);
+	TUint8* blockEnd = ptr + (aTagHdr->iNumTags * sizeof(TTag));
+
+	while(ptr < blockEnd)
+		{
+		TTag* tag = (TTag*)ptr;
+		if(tag->iTagId == aElement)
+			{
+			return tag;
+			}
+		ptr += sizeof(TTag);
+		}
+	return NULL;
+	}
+
+TTag CRunModeAgent::GetTag(const TTagHeaderId aTagHdrId, const TInt aElement)
+	{
+	TUint32 bufsize = 0;	// Safe default size
+
+	// Get functionality block size
+	test(KErrNone == iServSession.GetDebugFunctionalityBufSize(&bufsize));
+
+	// Ensure we have a finite buffer size
+	test(bufsize!=0);
+
+	// Allocate space for the functionality data
+	HBufC8* dftext = HBufC8::NewLC(bufsize);
+
+	// create an empty TPtr8 refering to dftext
+	TPtr8 dftextPtr(dftext->Des());
+
+	// Get the functionality block
+	test(KErrNone == iServSession.GetDebugFunctionality(dftextPtr));
+
+	// read a value from the data to check it has come through as expected
+	TTagHeader* header = GetTagHdr(dftext->Des(), aTagHdrId);
+	test(header != NULL);
+	TTag* tag = GetTag(header, aElement);
+	test(tag != NULL);
+
+	TTag tagToReturn = *tag;
+
+	// Remove our temporary buffer
+	CleanupStack::PopAndDestroy(dftext);
+
+	return tagToReturn;
+	}
+
+/**
+  Helper function which returns a Boolean indicating with a process with the
+  specified name is currently running.
+
+  @param aProcessName - Name of the process to find
+  @return ETrue if found, EFalse otherwise
+  */
+TBool CRunModeAgent::ProcessExists(const TDesC& aProcessName)
+	{
+	TInt    err=KErrNone;
+	TBool	found = FALSE;
+
+_LIT(KWildCard,"*");
+
+	TFindProcess find(KWildCard);
+	TFullName name;
+	while(find.Next(name)==KErrNone)
+		{
+		RProcess process;
+		err = process.Open(find);
+		if (err == KErrNone)
+			{
+			if (name.Find(aProcessName) != KErrNotFound)
+				{
+					found = TRUE;
+				}
+			process.Close();
+			}
+	   }
+
+	return found;
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/basic_tests/t_rmdebug2.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,189 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Definitions for the run mode debug tests
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef RMDEBUG_H
+#define RMDEBUG_H
+
+#include "t_rmdebug_app.h"
+#include "r_user_low_memory_security_svr_session.h"
+#include "r_kernel_low_memory_security_svr_session.h"
+
+
+class CRunModeAgent;
+
+// Create a pointer to function type
+typedef void (CRunModeAgent::*testFunction)();
+
+class TFunctionData
+	{
+public:
+	testFunction iFunctionPtr;
+	TBuf<40> iFunctionName;
+	};
+
+//number of test functions that we have
+const TInt KMaxTests = 28;
+
+//
+// class CRunModeAgent
+//
+// The basic run mode agent.
+//
+class CRunModeAgent : public CBase
+	{
+public:
+	static CRunModeAgent* NewL();
+	~CRunModeAgent();
+	void ClientAppL();
+
+private:
+	CRunModeAgent();
+	void ConstructL();
+	void SetupAndAttachToDSS();
+
+	TInt TestStartup();
+	TInt TestShutdown();
+
+	void TestGetExecutablesList();
+	void TestGetProcessList();
+	void TestGetThreadList();
+	void TestGetCodeSegsList();
+	void TestGetXipLibrariesList();
+	void TestGetListInvalidData();
+
+	void DoTestGetThreadList(const TBool aShouldPass, const Debug::TListScope aListScope, const TUint64 aTargetId=0);
+	void DoTestGetCodeSegsList(const TBool aShouldPass, const Debug::TListScope aListScope, const TUint64 aTargetId=0);
+
+	void DoGetList(const Debug::TListId aListId, const Debug::TListScope aListScope, RBuf8& aBuffer, TUint32& aSize, const TUint64 aTargetId=0);
+
+	void TestMemoryAccess();
+	void TestSuspendResume();
+	void TestBreakPoints();
+	void TestConsecutiveBreakPoints();
+	void TestModifyBreak();
+	void DoTestModifyBreak(TBool aThreadSpecific);
+	void TestBreakInfo();
+	void DoTestBreakInfo(TBool aThreadSpecific);
+	void TestRunToBreak();
+	void DoTestRunToBreak(TBool aThreadSpecific);
+	void TestRegisterAccess();
+	void TestAttachExecutable();
+	void TestDebugFunctionality();
+	void TestStep();
+	void DoTestStep(TBool aThreadSpecific);
+	void TestDriverSecurity();
+	void TestSecurity();
+	void TestEvents();
+	void TestEventsForExternalProcess();
+	void TestDemandPaging();
+	void TestTraceSecurity();
+	void TestDllUsage();
+	void TestKillProcess();
+	void TestProcessBreakPoints();
+	void TestMultipleTraceEvents();
+	void TestAddRemoveProcessEvents();
+	void TestProcessKillBreakpoint();
+	void DoTestProcessKillBreakpoint();
+
+	//crash flash test functions
+	void TestCrashFlash();
+		
+	TInt GetFlag(const TDes8 &aFlags, const TUint aOffset, Debug::TRegisterFlag &aFlagValue) const;
+
+	void ReportPerformance(void);
+
+	// helper functions
+	void HelpTestSecurityAttachDetachExecutable(const TDesC& aProcessName, TBool aExpectSuccess);
+
+	TInt HelpTestStepSetBreak(Debug::TBreakId& aBreakId, TThreadId aThreadId, const TUint32 aBreakAddress, Debug::TArchitectureMode aMode, TBool aThreadSpecific=ETrue, TProcessId aProcessId=0);
+	TInt HelpTestStepClearBreak(const Debug::TBreakId aBreakId, const TThreadId aThreadId, TBool aThreadSpecific);
+	TInt HelpTestStepWaitForBreak(const TDesC& aProcessName, Debug::TEventInfo& aEventInfo);
+	TInt HelpTestStepReadPC(TThreadId aThreadId, TUint32& aPC);
+	TInt HelpTestStep(TThreadId aThreadId, TUint32 aStartAddress, TUint32 aEndAddress, Debug::TArchitectureMode aMode, TUint aNumSteps, TBool aThreadSpecific=ETrue, TProcessId=0);
+
+	TInt HelpTicksPerSecond(void);
+
+	// helper functions
+	void HelpStartTestTimer(void) { iStartTick = User::NTickCount(); iStopTick = 0; };
+	void HelpStopTestTimer(void) { iStopTick = User::NTickCount(); };
+	TInt HelpGetTestTicks(void) { return (iStopTick - iStartTick); };
+	TInt SwitchTestFunction(TTestFunction aTestFunction);
+	TInt LaunchProcess(RProcess& aProcess, const TDesC& aFileName, TDebugFunctionType aFunctionType, TUint32 aDelay=0, TUint32 aExtraThreads=0);
+	Debug::TTagHeader* GetTagHdr(const TDesC8& aDebugFunctionalityBlock, const Debug::TTagHeaderId aTagHdrId) const;
+	Debug::TTag* GetTag(const Debug::TTagHeader* aTagHdr, const TInt aElement) const;
+	Debug::TTag GetTag(const Debug::TTagHeaderId aTagHdrId, const TInt aElement);
+	TBool ProcessExists(const TProcessId aProcessId);
+	TBool ThreadExistsForProcess(const TThreadId aThreadId, const TProcessId aProcessId);
+	TBool ListingSupported(const Debug::TListId aListId, const Debug::TListScope aListScope);
+	void TestEventsWithExtraThreads(Debug::TKernelEventAction aActionMain, Debug::TKernelEventAction aActionExtra, TUint32 aExtraThreads);
+	void FillArray();
+	void PrintUsage();
+	void PrintVersion();
+
+	enum TTestMode 
+		{
+		//run all the tests
+		EModeAll = 1<<0,
+		//run the specified tests in reverse order
+		EModeReverse = 1<<1,
+		//print out help
+		EModeHelp = 1<<2,
+		//print out help
+		EModeVersion = 1<<3
+		};
+
+	void RunTest(TInt aTestNumber);
+	void ParseCommandLineL(TUint32& aMode, RArray<TInt>& aTests);
+
+	TBool ProcessExists(const TDesC& aProcessName);
+
+private:
+
+	TFunctionData iTestArray[KMaxTests];
+#if defined(KERNEL_OOM_TESTING)
+	RKernelLowMemorySecuritySvrSession iServSession;
+#elif defined (USER_OOM_TESTING)
+	RUserLowMemorySecuritySvrSession iServSession;
+#else
+	Debug::RSecuritySvrSession iServSession;
+#endif
+	RThread	iDebugThread;
+	RProcess iDSSProcess;
+	RSemaphore iAddressGlobSem;
+	TThreadId iThreadID;
+	TFileName iFileName;
+	TUid iMySid;
+
+	// Performance data
+	TInt iMemoryReadKbytesPerSecond;	
+	TInt iMemoryWriteKbytesPerSecond;	
+	TInt iBreakpointsPerSecond;
+	TInt iMaxBreakpoints;
+	TInt iStepsPerSecond;
+
+	// Timing information
+	TInt iStartTick;
+	TInt iStopTick;
+	};
+
+#endif // RMDEBUG_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/basic_tests/t_rmdebug2_oemtoken.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,32 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#include <e32base.h>
+#include <e32base_private.h>
+
+GLDEF_C TInt E32Main()
+	{
+	// No need to do anything, the only requirement is that
+	// this executable can be loaded and runs to completion
+	return 0;
+	}
+
+// End of file - t_rmdebug2_oemtoken.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/common/t_target_launcher.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,217 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Helper app to launch debug targets. Uses command-line parameters as follows using a + sign:
+//  +n<number of applications to launch>
+//  +m<number of times to launch each application>
+//  +o<order of launch, 1 means launch in reverse order>
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <e32test.h>
+#include <e32ldr.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <f32dbg.h>
+#include <f32file.h>
+#include <hal.h>
+#include <u32hal.h>
+#include <e32property.h>
+
+#include "t_target_launcher.h"
+
+
+/**
+  Launch a process
+
+  @param aProcess The RProcess object to use to create the process
+  @param aExeName File name of the executable to create the process from
+  @param aCommandLine The command line to pass to the new process
+  @return KErrNone on success, or one of the other system wide error codes
+  */
+TInt LaunchProcess(RProcess& aProcess, TDesC & aExeName, TPtr & aCommandLine )
+    {
+
+    TPtrC commandLine( aCommandLine );
+
+    TInt err = aProcess.Create( aExeName, commandLine );
+
+    // check that there was no error raised
+    if(err != KErrNone)
+        {
+        return err;
+        }
+
+    TRequestStatus status = KRequestPending;
+    aProcess.Rendezvous(status);
+
+    if(KRequestPending != status.Int())
+        {
+        // startup failed so kill the process
+        RDebug::Printf( "> RProcess Rendezvous() failed with %d. Killing process", status.Int() );
+        aProcess.Kill(KErrNone);
+        return status.Int();
+        }
+    else
+        {
+        // start up succeeded so resume the process
+        aProcess.Resume();
+        User::WaitForRequest(status);
+        if(KErrNone != status.Int())
+            {
+            RDebug::Printf( "> RProcess Resume() failed with %d. Killing process", status.Int() );
+            aProcess.Kill(KErrNone);
+            }
+        return status.Int();
+        }
+    }
+
+/**
+ * Read command line parameters and control the launching of targets. 
+ * Create global launch semaphore KLaunchMutexName
+ */
+void MainL()
+    {
+
+    TInt numApps = KNumApps;
+    TInt numLaunches = KNumLaunches;
+    TInt launchControl = 0;
+
+    TInt argc = User::CommandLineLength();
+    HBufC* commandLine = NULL;
+    RDebug::Printf( ">Launcher Process() argc=%d", argc );
+
+    if( argc )
+        {
+        commandLine = HBufC::NewLC(argc);
+        TPtr commandLineBuffer = commandLine->Des();
+        User::CommandLine(commandLineBuffer);
+
+        RBuf printCommandLine;
+        CleanupClosePushL( printCommandLine );
+        printCommandLine.CreateL( commandLine->Des().Length() );
+        printCommandLine.Copy( commandLine->Des() );
+        printCommandLine.Collapse();
+        RDebug::Printf( ">command line = %S", &printCommandLine );
+        CleanupStack::PopAndDestroy( &printCommandLine );
+
+        // create a lexer and read through the command line
+        TLex lex(*commandLine);
+        while (!lex.Eos())
+            {
+            // only look for options with first character '+', other switches are for the targets
+            if (lex.Get() == '+')
+                {
+                TChar arg = lex.Get();
+                switch (arg)
+                    {
+                    case 'n':
+                        lex.Val( numApps );
+                        RDebug::Printf("parsed numApps as %d", numApps);
+                        break;
+                    case 'm':
+                        lex.Val( numLaunches );
+                        RDebug::Printf("parsed numLaunches as %d", numLaunches );
+                        break;
+                    case 'o':
+                        lex.Val( launchControl );
+                        RDebug::Printf("parsed launchControl as %d", launchControl);
+                        break;
+                    default:
+                        // unknown argument ignore it
+                        break;             
+                    }//switch
+                }// if +
+            }//while
+        }//if argc
+
+   RSemaphore launchMutex;
+   TInt ret = KErrNone;
+   CleanupClosePushL( launchMutex );
+   ret = launchMutex.CreateGlobal( KLaunchMutexName, 0 );
+   RDebug::Printf( ">Target Launcher : RSemaphore.CreateGlobal ret %d", ret);
+   User::LeaveIfError( ret );
+
+   ret = launchMutex.OpenGlobal( KLaunchMutexName );
+   RDebug::Printf( ">Target Launcher : RSemaphore.OpenGlobal ret %d", ret);
+   User::LeaveIfError( ret );
+
+   //Now launch the requested number of apps for the requested number of launches
+   for( ; numLaunches > 0; numLaunches-- )
+       { 
+       for( TInt launchIndex = numApps; launchIndex > 0; launchIndex-- )  
+           {
+           RDebug::Printf( ">Target Launcher:  Mutex wait app %d, launch %d", launchIndex, numLaunches );
+           launchMutex.Wait();
+
+           RBuf targetName;
+           CleanupClosePushL( targetName );
+           RDebug::Printf( ">Target Launcher:  targetName.Create %d, launch %d", launchIndex, numLaunches );
+           targetName.Create( KTargetExe().Length() + 2 );
+
+           if( launchControl == 1 )
+               {
+               // Reverse the order of the apps launched by reversing the index in the name
+               RDebug::Printf( ">Target Launcher:  targetName.Format %d, launch %d", numApps - launchIndex + 1, numLaunches );
+               targetName.Format( KTargetExe(), numApps - launchIndex + 1 );
+               }
+           else
+               {
+               RDebug::Printf( ">Target Launcher:  targetName.Format %d, launch %d", launchIndex, numLaunches );
+               targetName.Format( KTargetExe(), launchIndex );
+               }
+
+           RProcess aProc;
+           CleanupClosePushL( aProc ); 
+    
+           RDebug::Printf( ">Target Launcher: LaunchProcess %d, launch %d", launchIndex, numLaunches );
+           RDebug::Printf( ">LaunchProcess %lS", &targetName );
+           TPtr cmdLinePtr( commandLine->Des() );
+           ret = LaunchProcess( aProc, targetName, cmdLinePtr );
+           CleanupStack::PopAndDestroy( &aProc );
+
+           RDebug::Printf( "<Target Launcher: LaunchProcess returned %d", ret );
+           CleanupStack::PopAndDestroy( &targetName );
+
+           User::LeaveIfError( ret );
+
+           //By now the add proc event should have been delivered to the
+           //test app agent.
+           }
+       }
+
+    CleanupStack::PopAndDestroy( &launchMutex );
+
+    if( commandLine )
+       CleanupStack::PopAndDestroy( commandLine );
+ 
+    }
+
+
+GLDEF_C TInt E32Main()
+	{
+	RDebug::Printf( ">Launcher Process()" );
+
+	CTrapCleanup* trap = CTrapCleanup::New();
+	if (!trap)
+		return KErrNoMemory;
+
+	TRAPD(err, MainL());
+	RDebug::Printf( "< Target launching returned %d", err);
+	
+	delete trap;
+	
+	return err;
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/common/t_target_launcher.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,47 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Definitions for target launcher
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef RMDEBUG_TARGET_LAUNCHER_H
+#define RMDEBUG_TARGET_LAUNCHER_H
+
+// Controls how many times the target applications are launched
+const TInt KNumLaunches = 3;
+
+// Controls how many applications are attached and launched
+// If changing this, need to make sure there are enough apps
+// being built. see KTargetExe and t_rmdebug_app*
+const TInt KNumApps = 4;  
+
+_LIT(KLaunchMutexName, "t_rmdebug_launch_mutex");
+_LIT(KLaunchMutexNameSearchString, "t_rmdebug_launch_mutex*");
+_LIT(KTargetExe,"z:\\sys\\bin\\t_rmdebug_app%d.exe");
+_LIT8(KTargetExeName,"t_rmdebug_app%d.exe");
+_LIT(KProcessFinder,"*t_rmdebug_app%d*");
+_LIT(KTargetOptions,"-f%d");
+
+_LIT(KZSysBin,"z:\\sys\\bin\\");
+_LIT(KLauncherExe,"z:\\sys\\bin\\t_rmdebug_target_launcher.exe");
+
+_LIT_SECURITY_POLICY_PASS(KAllowAllPolicy);
+
+#endif // RMDEBUG_TARGET_LAUNCHER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_demand_paging.cia	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,57 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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 <u32std.h>
+
+// unused function that contains enough padding that the test function
+// RMDebugDemandPagingTest starts in a new page.
+__NAKED__ TInt RMDebugDemandPagingPaddingBefore()
+	{
+	asm("movs       r2,r0");
+	asm("adds       r0,r2,r1");
+	asm("bx         lr");
+	// add padding to make this function 4kb in size.
+	// The 4084 corresponds to 2^12 (=4096) - 12,
+	// the 12 being the total size of the movs, adds and bx instructions.
+	asm(".space     4084");
+	}
+
+// test function which is in a page by itself
+__NAKED__ TInt RMDebugDemandPagingTest()
+	{
+	asm("movs       r2,r0");
+	asm("adds       r0,r2,r1");
+	asm("bx         lr");
+	// add padding to make this function 4kb in size.
+	// The 4084 corresponds to 2^12 (=4096) - 12,
+	// the 12 being the total size of the movs, adds and bx instructions.
+	asm(".space     4084");
+	}
+
+// unused function that contains enough padding to ensure that no used code
+// is in the same page as RMDebugDemandPagingTest
+__NAKED__ TInt RMDebugDemandPagingPaddingAfter()
+	{
+	asm("movs       r2,r0");
+	asm("adds       r0,r2,r1");
+	asm("bx         lr");
+	// add padding to make this function 4kb in size.
+	// The 4084 corresponds to 2^12 (=4096) - 12,
+	// the 12 being the total size of the movs, adds and bx instructions.
+	asm(".space     4084");
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_demand_paging.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,22 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// definitions of functions in d_demand_paging.cia
+//
+
+#ifndef D_DEMAND_PAGING_H
+#define D_DEMAND_PAGING_H
+
+TInt RMDebugDemandPagingTest();
+
+#endif // D_DEMAND_PAGING_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebug_step_test.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,81 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// 
+// definitions of functions in d_rmdebug_step_tests.s
+//
+
+#ifndef D_RMDEBUG_STEP_TESTS_H
+#define D_RMDEBUG_STEP_TESTS_H
+
+extern "C"
+{
+	// ARM tests
+	unsigned int RMDebug_StepTest_Non_PC_Modifying(void);
+	unsigned int RMDebug_StepTest_Non_PC_Modifying_OK(void);
+	
+	unsigned int RMDebug_StepTest_Branch(void);
+	unsigned int RMDebug_StepTest_Branch_1(void);
+
+	unsigned int RMDebug_StepTest_Branch_And_Link(void);
+	unsigned int RMDebug_StepTest_Branch_And_Link_1(void);
+	unsigned int RMDebug_StepTest_Branch_And_Link_2(void);
+	
+	unsigned int RMDebug_StepTest_MOV_PC(void);
+	unsigned int RMDebug_StepTest_MOV_PC_1(void);
+	unsigned int RMDebug_StepTest_MOV_PC_2(void);
+	
+	unsigned int RMDebug_StepTest_LDR_PC(void);
+	unsigned int RMDebug_StepTest_LDR_PC_1(void);
+
+	// Thumb tests
+	unsigned int RMDebug_StepTest_Thumb_Non_PC_Modifying(void);
+	unsigned int RMDebug_StepTest_Thumb_Non_PC_Modifying_1(void);
+	unsigned int RMDebug_StepTest_Thumb_Non_PC_Modifying_2(void);
+
+	unsigned int RMDebug_StepTest_Thumb_Branch(void);
+	unsigned int RMDebug_StepTest_Thumb_Branch_1(void);
+	unsigned int RMDebug_StepTest_Thumb_Branch_2(void);
+	
+	unsigned int RMDebug_StepTest_Thumb_Branch_And_Link(void);
+	unsigned int RMDebug_StepTest_Thumb_Branch_And_Link_1(void);
+	unsigned int RMDebug_StepTest_Thumb_Branch_And_Link_2(void);
+	unsigned int RMDebug_StepTest_Thumb_Branch_And_Link_3(void);
+
+	unsigned int RMDebug_StepTest_Thumb_Back_Branch_And_Link(void);
+	unsigned int RMDebug_StepTest_Thumb_Back_Branch_And_Link_1(void);
+	unsigned int RMDebug_StepTest_Thumb_Back_Branch_And_Link_2(void);
+	unsigned int RMDebug_StepTest_Thumb_Back_Branch_And_Link_3(void);
+
+	unsigned int RMDebug_StepTest_Thumb_AddPC(void);
+	unsigned int RMDebug_StepTest_Thumb_AddPC_1(void);
+	unsigned int RMDebug_StepTest_Thumb_AddPC_2(void);
+	unsigned int RMDebug_StepTest_Thumb_AddPC_3(void);
+
+	// ARM<->Thumb interworking tests
+	unsigned int RMDebug_StepTest_Interwork(void);
+	unsigned int RMDebug_StepTest_Interwork_1(void);
+	unsigned int RMDebug_StepTest_Interwork_2(void);
+	unsigned int RMDebug_StepTest_Interwork_3(void);
+
+	// Stepping performance test
+	unsigned int RMDebug_StepTest_Count(void);
+	unsigned int RMDebug_StepTest_Count_1(void);
+	unsigned int RMDebug_StepTest_Count_2(void);
+
+	// Multiple step test
+	unsigned int RMDebug_StepTest_ARM_Step_Multiple(void);
+	unsigned int RMDebug_StepTest_ARM_Step_Multiple_1(void);
+
+}
+#endif // D_RMDEBUG_STEP_TESTS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebug_step_test.s	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,267 @@
+; Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+; All rights reserved.
+; This component and the accompanying materials are made available
+; under the terms of the License "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:
+; 
+;
+
+        AREA |d-rmdebug-bkpt$$Code|, CODE, READONLY, ALIGN=6
+
+	CODE32
+
+	; ARM tests
+	
+; 
+; Non-PC modifying
+;
+	EXPORT RMDebug_StepTest_Non_PC_Modifying
+	EXPORT RMDebug_StepTest_Non_PC_Modifying_OK
+ 
+RMDebug_StepTest_Non_PC_Modifying
+	mov		r0,r0		; nop
+RMDebug_StepTest_Non_PC_Modifying_OK
+	bx		lr			; should return to normal execution of the test thread
+
+;
+; Branch
+;
+	EXPORT RMDebug_StepTest_Branch
+	EXPORT RMDebug_StepTest_Branch_1
+
+RMDebug_StepTest_Branch
+	b		RMDebug_StepTest_Branch_1		
+	mov		r0, #2		; if the pc ends up here, we know its gone wrong
+RMDebug_StepTest_Branch_1
+	bx		lr			; return
+
+;
+; Branch and Link
+;
+	EXPORT RMDebug_StepTest_Branch_And_Link
+	EXPORT RMDebug_StepTest_Branch_And_Link_1
+	EXPORT RMDebug_StepTest_Branch_And_Link_2
+
+RMDebug_StepTest_Branch_And_Link		
+	mov		r0, lr		; preserve lr for the moment
+RMDebug_StepTest_Branch_And_Link_1
+	bl		RMDebug_StepTest_Branch_And_Link_2
+	mov		r1, #1		; insert a gap in the instruction stream so we know we branched.
+RMDebug_StepTest_Branch_And_Link_2
+	mov		lr, r0		; restore lr			
+	bx		lr			; should return to normal execution of the test thread
+
+;
+; MOV PC
+;
+	EXPORT RMDebug_StepTest_MOV_PC
+	EXPORT RMDebug_StepTest_MOV_PC_1
+	EXPORT RMDebug_StepTest_MOV_PC_2
+
+RMDebug_StepTest_MOV_PC
+	mov		r0, #4
+RMDebug_StepTest_MOV_PC_1
+	add		pc, pc, r0	; should be a jump (bear in mind reading pc = current inst + 8bytes for arm)
+	mov		r0, #1		; Simple instructions which allow us to test where the PC really is
+	mov		r0, #2		; just by reading r0.
+RMDebug_StepTest_MOV_PC_2
+	mov		r0, #3		; 
+	mov		r0, #4		; 
+	bx		lr			; should return to normal execution of the test thread
+
+; 
+; LDR PC
+;
+	EXPORT RMDebug_StepTest_LDR_PC
+	EXPORT RMDebug_StepTest_LDR_PC_1
+
+RMDebug_StepTest_LDR_PC
+	ldr		pc, =RMDebug_StepTest_LDR_PC_1
+	mov		r0, #1		;  separate the branch target so we can prove it works
+RMDebug_StepTest_LDR_PC_1
+	bx		lr			; should return to normal execution of the test thread
+	
+;
+; ARM -> Thumb -> ARM interworking test
+;
+; Note: We always start and finish this test
+; in ARM mode.
+	EXPORT RMDebug_StepTest_Interwork
+	EXPORT RMDebug_StepTest_Interwork_1
+	EXPORT RMDebug_StepTest_Interwork_2
+	EXPORT RMDebug_StepTest_Interwork_3	
+RMDebug_StepTest_Interwork
+	mov		r0, lr	; preserve lr
+RMDebug_StepTest_Interwork_1
+	blx		RMDebug_StepTest_Interwork_2
+
+	CODE16
+RMDebug_StepTest_Interwork_2
+	blx		RMDebug_StepTest_Interwork_3
+
+	CODE32
+
+RMDebug_StepTest_Interwork_3
+	bx		r0
+
+;
+; Stepping performance tests
+;
+; This counts down from 100000 to 0
+; This means that for all practical purposes
+; we can single-step as much as we like
+; in less than one second and have some likelyhood
+; that we will not step too far from our loop
+
+	EXPORT RMDebug_StepTest_Count
+	EXPORT RMDebug_StepTest_Count_1
+	EXPORT RMDebug_StepTest_Count_2
+
+RMDebug_StepTest_Count
+	ldr		r2, =100000
+RMDebug_StepTest_Count_1
+	subs	r2, r2, #1
+RMDebug_StepTest_Count_2
+	bne		RMDebug_StepTest_Count_1
+	bx		lr
+
+; Thumb tests
+
+; Thumb non-pc modifying
+;
+;
+RMDebug_StepTest_Thumb_Non_PC_Modifying
+	mov		r0, lr	; preserve lr
+	blx		RMDebug_StepTest_Thumb_Non_PC_Modifying_1
+	bx		r0
+
+;
+; Thumb Branch
+;
+RMDebug_StepTest_Thumb_Branch
+	mov		r0, lr	; preserve lr
+	blx		RMDebug_StepTest_Thumb_Branch_1
+	bx		r0		
+
+;
+; Thumb Branch and link
+;
+RMDebug_StepTest_Thumb_Branch_And_Link
+	mov		r0, lr	; preserve lr
+	blx		RMDebug_StepTest_Thumb_Branch_And_Link_1
+	bx		r0 
+
+;
+; Thumb Back Branch and link
+;
+RMDebug_StepTest_Thumb_Back_Branch_And_Link
+	mov		r0, lr	; preserve lr
+	blx		RMDebug_StepTest_Thumb_Back_Branch_And_Link_1
+	bx		r0 
+
+;
+; Thumb ADD PC,PC, #0
+;
+RMDebug_StepTest_Thumb_AddPC
+	mov		r0, lr	; preserve lr
+	blx		RMDebug_StepTest_Thumb_AddPC_1
+	bx		r0 
+
+	CODE16
+
+	; Thumb tests
+	EXPORT RMDebug_StepTest_Thumb_Non_PC_Modifying
+	EXPORT RMDebug_StepTest_Thumb_Non_PC_Modifying_1
+	EXPORT RMDebug_StepTest_Thumb_Non_PC_Modifying_2
+
+	EXPORT RMDebug_StepTest_Thumb_Branch
+	EXPORT RMDebug_StepTest_Thumb_Branch_1
+	EXPORT RMDebug_StepTest_Thumb_Branch_2
+
+	EXPORT RMDebug_StepTest_Thumb_Branch_And_Link
+	EXPORT RMDebug_StepTest_Thumb_Branch_And_Link_1
+	EXPORT RMDebug_StepTest_Thumb_Branch_And_Link_2
+	EXPORT RMDebug_StepTest_Thumb_Branch_And_Link_3
+
+	EXPORT RMDebug_StepTest_Thumb_Back_Branch_And_Link
+	EXPORT RMDebug_StepTest_Thumb_Back_Branch_And_Link_1
+	EXPORT RMDebug_StepTest_Thumb_Back_Branch_And_Link_2
+	EXPORT RMDebug_StepTest_Thumb_Back_Branch_And_Link_3
+
+RMDebug_StepTest_Thumb_Non_PC_Modifying_1
+	mov		r0, r0	; nop
+RMDebug_StepTest_Thumb_Non_PC_Modifying_2
+	bx		lr	
+
+RMDebug_StepTest_Thumb_Branch_1
+	b		RMDebug_StepTest_Thumb_Branch_2
+	mov		r0, r0
+RMDebug_StepTest_Thumb_Branch_2
+	bx		lr
+
+RMDebug_StepTest_Thumb_Branch_And_Link_1
+	mov		r1, lr
+RMDebug_StepTest_Thumb_Branch_And_Link_2
+	bl		RMDebug_StepTest_Thumb_Branch_And_Link_3
+	mov		r0, r0
+RMDebug_StepTest_Thumb_Branch_And_Link_3
+	bx		r1
+
+RMDebug_StepTest_Thumb_Back_Branch_And_Link_3
+	bx		r1
+
+RMDebug_StepTest_Thumb_Back_Branch_And_Link_1
+	mov		r1, lr
+RMDebug_StepTest_Thumb_Back_Branch_And_Link_2
+	bl		RMDebug_StepTest_Thumb_Back_Branch_And_Link_3
+	bx		r1
+
+;
+; ADD PC
+;
+	EXPORT RMDebug_StepTest_Thumb_AddPC
+	EXPORT RMDebug_StepTest_Thumb_AddPC_1
+	EXPORT RMDebug_StepTest_Thumb_AddPC_2
+	EXPORT RMDebug_StepTest_Thumb_AddPC_3
+
+RMDebug_StepTest_Thumb_AddPC_1
+	mov		r1, lr
+	mov		r2, #4
+RMDebug_StepTest_Thumb_AddPC_2
+	add		pc, pc, r2	; should arrive at RMDebug_StepTest_Thumb_AddPC_3
+	mov		r0, r0
+	mov		r0, r0
+	mov		r0, r0
+RMDebug_StepTest_Thumb_AddPC_3
+	bx		r1
+
+	ALIGN 4
+
+	CODE32
+
+;
+; ARM multiple-step ( 5 steps )
+;
+	EXPORT RMDebug_StepTest_ARM_Step_Multiple
+	EXPORT RMDebug_StepTest_ARM_Step_Multiple_1
+
+RMDebug_StepTest_ARM_Step_Multiple
+	mov		r0,r0		; nop
+	mov		r0,r0		; nop
+	mov		r0,r0		; nop
+	mov		r0,r0		; nop
+	mov		r0,r0		; nop
+RMDebug_StepTest_ARM_Step_Multiple_1
+	bx		lr
+
+	END
+
+; End of file - d_rmdebug_bkpt.s
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebug_step_test_armv4.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,50 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// definitions of functions in d_rmdebug_step_tests_armv4.s
+//
+
+#ifndef D_RMDEBUG_STEP_TESTS_H
+#define D_RMDEBUG_STEP_TESTS_H
+
+extern "C"
+{
+	// ARM tests
+	unsigned int RMDebug_StepTest_Non_PC_Modifying(void);
+	unsigned int RMDebug_StepTest_Non_PC_Modifying_OK(void);
+	
+	unsigned int RMDebug_StepTest_Branch(void);
+	unsigned int RMDebug_StepTest_Branch_1(void);
+
+	unsigned int RMDebug_StepTest_Branch_And_Link(void);
+	unsigned int RMDebug_StepTest_Branch_And_Link_1(void);
+	unsigned int RMDebug_StepTest_Branch_And_Link_2(void);
+	
+	unsigned int RMDebug_StepTest_MOV_PC(void);
+	unsigned int RMDebug_StepTest_MOV_PC_1(void);
+	unsigned int RMDebug_StepTest_MOV_PC_2(void);
+	
+	unsigned int RMDebug_StepTest_LDR_PC(void);
+	unsigned int RMDebug_StepTest_LDR_PC_1(void);
+
+	// Stepping performance test
+	unsigned int RMDebug_StepTest_Count(void);
+	unsigned int RMDebug_StepTest_Count_1(void);
+	unsigned int RMDebug_StepTest_Count_2(void);
+
+	// Multiple step test
+	unsigned int RMDebug_StepTest_ARM_Step_Multiple(void);
+	unsigned int RMDebug_StepTest_ARM_Step_Multiple_1(void);
+
+}
+#endif // D_RMDEBUG_STEP_TESTS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebug_step_test_armv4.s	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,130 @@
+; Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+; All rights reserved.
+; This component and the accompanying materials are made available
+; under the terms of the License "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:
+; 
+;
+
+        AREA |d-rmdebug-bkpt$$Code|, CODE, READONLY, ALIGN=6
+
+	CODE32
+
+	; ARM tests
+	
+; 
+; Non-PC modifying
+;
+	EXPORT RMDebug_StepTest_Non_PC_Modifying
+	EXPORT RMDebug_StepTest_Non_PC_Modifying_OK
+ 
+RMDebug_StepTest_Non_PC_Modifying
+	mov		r0,r0		; nop
+RMDebug_StepTest_Non_PC_Modifying_OK
+	bx		lr			; should return to normal execution of the test thread
+
+;
+; Branch
+;
+	EXPORT RMDebug_StepTest_Branch
+	EXPORT RMDebug_StepTest_Branch_1
+
+RMDebug_StepTest_Branch
+	b		RMDebug_StepTest_Branch_1		
+	mov		r0, #2		; if the pc ends up here, we know its gone wrong
+RMDebug_StepTest_Branch_1
+	bx		lr			; return
+
+;
+; Branch and Link
+;
+	EXPORT RMDebug_StepTest_Branch_And_Link
+	EXPORT RMDebug_StepTest_Branch_And_Link_1
+	EXPORT RMDebug_StepTest_Branch_And_Link_2
+
+RMDebug_StepTest_Branch_And_Link		
+	mov		r0, lr		; preserve lr for the moment
+RMDebug_StepTest_Branch_And_Link_1
+	bl		RMDebug_StepTest_Branch_And_Link_2
+	mov		r1, #1		; insert a gap in the instruction stream so we know we branched.
+RMDebug_StepTest_Branch_And_Link_2
+	mov		lr, r0		; restore lr			
+	bx		lr			; should return to normal execution of the test thread
+
+;
+; MOV PC
+;
+	EXPORT RMDebug_StepTest_MOV_PC
+	EXPORT RMDebug_StepTest_MOV_PC_1
+	EXPORT RMDebug_StepTest_MOV_PC_2
+
+RMDebug_StepTest_MOV_PC
+	mov		r0, #4
+RMDebug_StepTest_MOV_PC_1
+	add		pc, pc, r0	; should be a jump (bear in mind reading pc = current inst + 8bytes for arm)
+	mov		r0, #1		; Simple instructions which allow us to test where the PC really is
+	mov		r0, #2		; just by reading r0.
+RMDebug_StepTest_MOV_PC_2
+	mov		r0, #3		; 
+	mov		r0, #4		; 
+	bx		lr			; should return to normal execution of the test thread
+
+; 
+; LDR PC
+;
+	EXPORT RMDebug_StepTest_LDR_PC
+	EXPORT RMDebug_StepTest_LDR_PC_1
+
+RMDebug_StepTest_LDR_PC
+	ldr		pc, =RMDebug_StepTest_LDR_PC_1
+	mov		r0, #1		;  separate the branch target so we can prove it works
+RMDebug_StepTest_LDR_PC_1
+	bx		lr			; should return to normal execution of the test thread
+	
+;
+; Stepping performance tests
+;
+; This counts down from 100000 to 0
+; This means that for all practical purposes
+; we can single-step as much as we like
+; in less than one second and have some likelyhood
+; that we will not step too far from our loop
+
+	EXPORT RMDebug_StepTest_Count
+	EXPORT RMDebug_StepTest_Count_1
+	EXPORT RMDebug_StepTest_Count_2
+
+RMDebug_StepTest_Count
+	ldr		r2, =100000
+RMDebug_StepTest_Count_1
+	subs	r2, r2, #1
+RMDebug_StepTest_Count_2
+	bne		RMDebug_StepTest_Count_1
+	bx		lr
+
+;
+; ARM multiple-step ( 5 steps )
+;
+	EXPORT RMDebug_StepTest_ARM_Step_Multiple
+	EXPORT RMDebug_StepTest_ARM_Step_Multiple_1
+
+RMDebug_StepTest_ARM_Step_Multiple
+	mov		r0,r0		; nop
+	mov		r0,r0		; nop
+	mov		r0,r0		; nop
+	mov		r0,r0		; nop
+	mov		r0,r0		; nop
+RMDebug_StepTest_ARM_Step_Multiple_1
+	bx		lr
+
+	END
+
+; End of file - d_rmdebug_step_test_armv4.s
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthread.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,106 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Implements a debug thread for testing.
+// 
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include "d_rmdebugthread.h"
+
+EXPORT_C TBuf8<SYMBIAN_RMDBG_MEMORYSIZE> gMemoryAccessBytes;
+extern void RMDebug_BranchTst1();
+
+EXPORT_C TInt TestData;
+
+CDebugServThread::CDebugServThread()
+//
+// Empty constructor
+//
+	{
+	}
+
+GLDEF_C TInt CDebugServThread::ThreadFunction(TAny*)
+//
+// Generic thread function for testing
+//
+	{
+	CTrapCleanup* cleanup=CTrapCleanup::New();
+	if (cleanup == NULL)
+		{
+		User::Leave(KErrNoMemory);
+		}
+
+	RThread::Rendezvous(KErrNone);
+
+	TestData = 1;
+
+	while(1)
+		{
+		RMDebug_BranchTst1();
+
+		TestData++;                   
+
+		// Wait half a second (suspends this thread)
+		User::After(500000);
+
+		if (TestData == 0xFFFFFFFF)
+			{
+			break;
+			}
+		}
+
+	delete cleanup;
+
+	return (KErrNone);
+	}
+
+EXPORT_C TInt StartDebugThread(RThread& aDebugThread)
+//
+// Starts the test thread
+//
+{
+	TInt res=KErrNone;
+
+	// Create the thread
+	res = aDebugThread.Create(	KDebugThreadName,
+								CDebugServThread::ThreadFunction,
+								KDefaultStackSize,
+								KDebugThreadDefaultHeapSize,
+								KDebugThreadDefaultHeapSize,
+								NULL
+								);
+
+	// Check that the creation worked
+	if (res == KErrNone)
+		{
+		TRequestStatus rendezvousStatus;
+
+		aDebugThread.SetPriority(EPriorityNormal);
+		// Make a request for a rendezvous
+		aDebugThread.Rendezvous(rendezvousStatus);
+		// Set the thread as ready for execution
+		aDebugThread.Resume();
+		// Wait for the resumption
+		User::WaitForRequest(rendezvousStatus);
+		}                                 
+	else
+		{
+		// Close the handle.
+		aDebugThread.Close();
+		}
+
+	return res;
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthread.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,38 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// t_rmdebugthread.h
+// Definitions for the run mode debug test thread.
+// 
+//
+
+#ifndef RMDEBUGSVRTHRD_H
+#define RMDEBUGSVRTHRD_H
+
+#define SYMBIAN_RMDBG_MEMORYSIZE    1024*4
+
+// Thread name
+_LIT(KDebugThreadName,"DebugThread");
+
+const TUint KDebugThreadDefaultHeapSize=0x10000;
+
+class CDebugServThread : public CBase
+	{
+	public:
+		CDebugServThread();
+		static TInt ThreadFunction(TAny* aStarted);    
+
+	public:
+	};
+
+#endif // RMDEBUGSVRTHRD_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthread2.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,214 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Implements a debug thread for testing.
+// 
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <e32debug.h>
+#include "d_rmdebugthread2.h"
+
+#include "d_rmdebug_step_test.h"
+#include "d_demand_paging.h"
+
+EXPORT_C TBuf8<SYMBIAN_RMDBG_MEMORYSIZE> gMemoryAccessBytes;
+IMPORT_C extern void RMDebug_BranchTst1();
+IMPORT_C extern TInt RMDebugDemandPagingTest();
+
+EXPORT_C TInt TestData;
+EXPORT_C TTestFunction FunctionChooser;
+
+const TInt 	KNumberOfTraceCalls = 50;
+
+EXPORT_C TInt TestFunction()
+	{
+	// Set TestData to an arbitrary value that can be checked by a tester
+	TestData = 0xffeeddcc;
+	RMDebug_BranchTst1();
+	
+	// Code here may not be executed because tests can change the PC value
+	// at any time, typically once the test passes
+	return 0;
+	}
+
+/**
+  Wrapper around RMDebugDemandPagingTest, need to pause for a short time to
+  allow time in t_rmdebug.cpp to issue a User::WaitForRequest to catch the break point
+  */
+EXPORT_C void TestPagedCode()
+	{
+	User::After(100000);
+
+	// call the function in paged code
+	RMDebugDemandPagingTest();
+	}
+
+EXPORT_C void TestMultipleTraceCalls()
+	{
+	//arbitrary function to set a BP on
+	RMDebug_BranchTst1();
+
+	// The tester will change FunctionChooser once it gets what it needs out of the test
+	for(TInt cnt = KNumberOfTraceCalls; cnt>0 && (FunctionChooser==EMultipleTraceCalls); cnt--)
+		{
+		RDebug::Printf("T");
+		RDebug::Printf("R");
+		RDebug::Printf("A");
+		RDebug::Printf("C");
+		RDebug::Printf("E");
+		}
+	
+	//another arbitrary function to set a BP on
+	RMDebug_StepTest_Non_PC_Modifying();
+	}
+
+CDebugServThread::CDebugServThread()
+//
+// Empty constructor
+//
+	{
+	}
+
+GLDEF_C TInt CDebugServThread::ThreadFunction(TAny*)
+//
+// Generic thread function for testing
+//
+	{
+	// set FunctionChooser to run the default function
+	FunctionChooser = EDefaultFunction;
+
+	CTrapCleanup* cleanup=CTrapCleanup::New();
+	if (cleanup == NULL)
+		{
+		User::Leave(KErrNoMemory);
+		}
+
+	RThread::Rendezvous(KErrNone);
+
+	TestData = 1;
+
+	/* Beware of adding printf or other debug-generating events in this loop because
+	* they interfere with the tests
+	*/
+	while(TestData != 0xFFFFFFFF)
+		{
+		switch(FunctionChooser)
+			{
+			case EDemandPagingFunction:
+				TestPagedCode();
+				break;
+			case EDefaultFunction:
+				// the default function is the stepping test functions
+			case EStepFunction:
+				{
+				RMDebug_BranchTst1();
+
+				// Single stepping test support code
+
+				// ARM tests
+				RMDebug_StepTest_Non_PC_Modifying();
+
+				RMDebug_StepTest_Branch();
+
+				RMDebug_StepTest_Branch_And_Link();
+
+				RMDebug_StepTest_MOV_PC();
+
+				RMDebug_StepTest_LDR_PC();
+ 
+// thumb/interworking tests not supported on armv4
+#ifdef __MARM_ARMV5__
+
+				// Thumb tests
+				RMDebug_StepTest_Thumb_Non_PC_Modifying();
+
+				RMDebug_StepTest_Thumb_Branch();
+
+				RMDebug_StepTest_Thumb_Branch_And_Link();
+
+				RMDebug_StepTest_Thumb_Back_Branch_And_Link();
+
+				// ARM <-> Thumb interworking tests
+				RMDebug_StepTest_Interwork();
+
+				RMDebug_StepTest_Thumb_AddPC();
+
+#endif	// __MARM_ARMV5__
+				
+				// Single-stepping performance
+				RMDebug_StepTest_Count();
+
+				// multiple step test
+				RMDebug_StepTest_ARM_Step_Multiple();
+
+				TestData++;
+
+				// Wait 50mSecs. // (suspends this thread)
+				User::After(50000);
+
+				break;
+				}
+			case EMultipleTraceCalls:
+				TestMultipleTraceCalls();
+				break;
+			default:
+				//do nothing
+				break;
+			}
+		}
+
+	delete cleanup;
+
+	return (KErrNone);
+	}
+
+EXPORT_C TInt StartDebugThread(RThread& aDebugThread, const TDesC& aDebugThreadName)
+//
+// Starts a test thread
+//
+{
+	TInt res=KErrNone;
+
+	// Create the thread
+	res = aDebugThread.Create(	aDebugThreadName,
+								CDebugServThread::ThreadFunction,
+								KDefaultStackSize,
+								KDebugThreadDefaultHeapSize,
+								KDebugThreadDefaultHeapSize,
+								NULL
+								);
+
+	// Check that the creation worked
+	if (res == KErrNone)
+		{
+		TRequestStatus rendezvousStatus;
+
+		aDebugThread.SetPriority(EPriorityNormal);
+		// Make a request for a rendezvous
+		aDebugThread.Rendezvous(rendezvousStatus);
+		// Set the thread as ready for execution
+		aDebugThread.Resume();
+		// Wait for the resumption
+		User::WaitForRequest(rendezvousStatus);
+		}                                 
+	else
+		{
+		// Close the handle.
+		aDebugThread.Close();
+		}
+
+	return res;
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthread2.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,51 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Definitions for the run mode debug test thread.
+// 
+//
+
+#ifndef RMDEBUGSVRTHRD_H
+#define RMDEBUGSVRTHRD_H
+
+#define SYMBIAN_RMDBG_MEMORYSIZE    1024*4
+
+// Thread name
+_LIT(KDebugThreadName,"DebugThread");
+
+const TUint KDebugThreadDefaultHeapSize=0x10000;
+
+// enumeration of functions which the target debug thread can call, the
+// debugger can choose to switch the thread to a different function by
+// writing the appropriate enumeration value into FunctionChooser, the
+// target thread will finish executing the function it is currently running
+// then execute the chosen function.
+enum TTestFunction
+	{
+	EDefaultFunction = 0,
+	EStepFunction = 1,
+	EDemandPagingFunction = 2,
+	EMultipleTraceCalls = 3,
+	EDoNothing = 4
+	};
+
+class CDebugServThread : public CBase
+	{
+	public:
+		CDebugServThread();
+		static TInt ThreadFunction(TAny* aStarted);    
+
+	public:
+	};
+
+#endif // RMDEBUGSVRTHRD_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthreadasm.cia	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,32 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// d_rmdebugthreadasm.h
+// Assembler file for debug thread testing.
+// 
+//
+
+//#include <e32cia.h>
+//#include <e32base.h>
+//#include <e32cons.h>
+//#include "d_rmdebugthread.h"
+
+EXPORT_C __NAKED__ void RMDebug_BranchTst1( void )
+//
+// 
+//
+{
+	asm("mov r0, #0 ");			// aResult==KErrNone
+	asm("bx  lr ");             // Return
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/d_rmdebugthreadasm2.cia	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,35 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// d_rmdebugthreadasm2.h
+// Assembler file for debug thread testing.
+// 
+//
+
+EXPORT_C __NAKED__ void RMDebug_BranchTst1( void )
+//
+// 
+//
+{
+	asm("mov r0, #0 ");			// aResult==KErrNone
+	asm("bx  lr ");             // Return
+}
+
+EXPORT_C __NAKED__ void RMDebug_BranchTst2( void )
+//
+// 
+//
+{
+	asm("mov r0, #0 ");			// aResult==KErrNone
+	asm("bx  lr ");             // Return
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_app.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,380 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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 <e32base.h>
+#include <e32base_private.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <e32debug.h>
+#include <e32property.h> 
+#include <u32hal.h>
+#include <f32file.h>
+
+
+
+#include "t_rmdebug_app.h"
+
+IMPORT_C extern void RMDebug_BranchTst2();
+
+LOCAL_C void ParseCommandLineL(TInt32& aFunctionType, TUint& aDelay, TUint& aExtraThreads, TInt32& aCpuNumber)
+	{
+	// get the length of the command line arguments
+	TInt argc = User::CommandLineLength();
+	RDebug::Printf(" t_rmdebug_app: ParseCommandLineL argc=%d", argc);
+
+	// allocate a buffer for the command line arguments and extract the data to it
+	HBufC* commandLine = HBufC::NewLC(argc);
+	TPtr commandLineBuffer = commandLine->Des();
+	User::CommandLine(commandLineBuffer);
+
+	// create a lexer and read through the command line
+	TLex lex(*commandLine);
+	while (!lex.Eos())
+		{
+		// expecting the first character to be a '-'
+		if (lex.Get() == '-')
+			{
+			TChar arg = lex.Get();
+			switch (arg)
+				{
+				case 'f':
+					// the digits following '-f' give the function type
+					User::LeaveIfError(lex.Val(aFunctionType));
+					RDebug::Printf(" t_rmdebug_app: setting aFunctionType=%d", aFunctionType);
+					break;
+				case 'd':
+					// the digits following '-d' give the delay
+					User::LeaveIfError(lex.Val(aDelay));
+					RDebug::Printf(" t_rmdebug_app: setting aDelay=%d", aDelay);
+					break;
+				case 'e':
+					// the digits following '-e' give the number of extra threads to launch
+					User::LeaveIfError(lex.Val(aExtraThreads));
+					RDebug::Printf(" t_rmdebug_app: setting aExtraThreads=%d", aExtraThreads);
+					break;
+
+				case 'a':
+						// the digits following '-a' gives the cpu on which this thread will execute on
+					User::LeaveIfError(lex.Val(aCpuNumber));
+					RDebug::Printf(" t_rmdebug_app: CPU Number=%d", aCpuNumber);
+					break;
+
+				default:
+					// unknown argument so leave
+					User::Leave(KErrArgument);
+				}
+			lex.SkipSpace();
+			}
+		else
+			{
+			// unknown argument so leave
+			User::Leave(KErrArgument);
+			}
+		}
+
+	// do clean up
+	CleanupStack::PopAndDestroy(commandLine);
+	}
+
+typedef void (*TPfun)();
+
+// test function to call corresponding to EPrefetchAbortFunction
+void PrefetchAbort()
+	{
+	TPfun f = NULL;
+	f();
+	}
+
+// test function to call corresponding to EUserPanicFunction
+void UserPanic()
+	{
+	User::Panic(KUserPanic, KUserPanicCode);
+	}
+
+// calls self repeatedly until stack is used up. Slightly convoluted to prevent UREL optimising this out...
+TUint32 StackOverFlowFunction(TUint32 aInt=0)
+	{
+	TUint32 unusedArray[150];
+	for(TInt i=0; i<150; i++)
+		{
+		unusedArray[i] = StackOverFlowFunction(i);
+		}
+	return unusedArray[0];
+	}
+
+void DataAbort()
+	{
+	TInt* r = (TInt*) 0x1000;
+	*r = 0x42;              
+	}
+
+void UndefInstruction()
+	{
+	TUint32 undef = 0xE6000010;
+	TPfun f = (TPfun) &undef;
+	f();
+	}
+
+TInt DataRead()
+	{
+	TInt* r = (TInt*) 0x1000;
+	TInt rr = (TInt)*r;
+	//include the following line to ensure that rr doesn't get optimised out
+	RDebug::Printf("Shouldn't see this being printed out: %d", rr);
+
+	// Stop compilation warning. Should not get here anyway.
+	rr++;
+	return rr;
+	}
+
+void DataWrite()
+	{
+	TInt* r = (TInt*) 0x1000;
+	*r = 0x42;                
+	}
+
+void UserException()
+	{
+	User::RaiseException(EExcGeneral);
+	}
+
+void SpinForeverWithBreakPoint()
+	{
+
+    // finding the process t_rmdebug2/t_rmdebug2_oem/t_rmdebug2_oem2
+    // we find the process.SID to attach to the property
+	_LIT(KThreadWildCard, "t_rmdebug2*");
+
+	TInt err = KErrNone;
+	TUid propertySid = KNullUid;
+	TFindThread find(KThreadWildCard);
+	TFullName name;
+	TBool found = EFalse;
+	while(find.Next(name)==KErrNone && !found)
+		{
+		RThread thread;
+		err = thread.Open(find);
+		if (err == KErrNone)
+			{
+			RProcess process;
+			thread.Process(process);
+			TFullName fullname = thread.FullName();
+		    //RDebug::Printf("SID Search Match Found Name %lS Process ID%ld Thread Id %ld", &fullname, process.Id().Id(), thread.Id().Id());
+			found = ETrue;
+			//SID saved so that the property can be attached to
+			propertySid = process.SecureId();
+			process.Close();
+			}
+		thread.Close();
+	}
+
+    //attach to the property to publish the address of the RMDebug_BranchTst2 with the correct SID value
+	RProperty integerProperty;
+	err = integerProperty.Attach(propertySid, EMyPropertyInteger, EOwnerThread);
+	if(KErrNone != err)
+		RDebug::Printf("Error Attach to the property %d", err);
+
+	TInt address = (TInt)&RMDebug_BranchTst2;
+	
+	// publish the address where the breakpoint would be set
+	err = integerProperty.Set(address);
+	if(KErrNone != err)
+		RDebug::Printf("Error Set of the property %d", err);
+	integerProperty.Close();
+	
+	//open semaphore to signal the fact we have reached the point where we have to set the property
+	RSemaphore globsem;
+	globsem.OpenGlobal(_L("RMDebugGlobSem"));
+	globsem.Signal();
+	globsem.Close();
+
+	RProcess thisProcess;
+	TFileName thisProcessName = thisProcess.FileName();
+	RDebug::Printf("App Process Name %lS process id %ld thread id %ld", &thisProcessName, thisProcess.Id().Id(), RThread().Id().Id());
+
+	TInt i=0;
+	RThread::Rendezvous(KErrNone);
+	while(i<0xffffffff)
+		{
+		RMDebug_BranchTst2();
+		User::After(10000);
+		}
+	}
+
+void SpinForever()
+	{
+	TInt i=0;
+	RThread::Rendezvous(KErrNone);
+	while(i<0xffffffff)
+		{
+		User::After(10000);
+		}
+	}
+
+void NormalExit()
+    {
+    RDebug::Printf("Target app: NormalExit() function. Returning to MainL" );
+    }
+
+void LaunchThreads(TUint aNumber)
+	{
+	_LIT(KDebugThreadName, "DebugThread");
+	const TUint KDebugThreadDefaultHeapSize=0x10000;
+	for(TInt i=0; i<aNumber; i++)
+		{
+		RThread thread;
+		RBuf threadName;
+		threadName.Create(KDebugThreadName().Length()+10); // the 10 is for appending i to the end of the name
+		threadName.Append(KDebugThreadName());
+		threadName.AppendNum(i);
+		TInt err = thread.Create(threadName, (TThreadFunction)SpinForever, KDefaultStackSize, KDebugThreadDefaultHeapSize, KDebugThreadDefaultHeapSize, NULL);
+		if(err != KErrNone)
+			{
+			RDebug::Printf("Couldn't create thread %d", err);
+			threadName.Close();
+			thread.Close();
+			break;
+			}
+		thread.SetPriority(EPriorityNormal);
+		TRequestStatus status;
+		thread.Rendezvous(status);
+		thread.Resume();
+		User::WaitForRequest(status);
+		thread.Close();
+		threadName.Close();
+		}
+	}
+
+void WaitFiveSecondsThenExit(void)
+	{
+	// wait for 5 seconds
+	User::After(5000000);
+	}
+
+TInt NumberOfCpus()
+	{
+	TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalNumLogicalCpus, 0, 0);
+	return r;
+	}
+
+TInt SetCpuAffinity(TInt aCpuNumber)
+	{
+    TInt TestCpuCount = NumberOfCpus();
+	RDebug::Printf("SetCpuAffinity --> TestCpuCount = %d\n", TestCpuCount);		
+	TUint32 cpu = 0;
+
+	if ((aCpuNumber % TestCpuCount) != 0)
+	cpu = (TUint32)(aCpuNumber % TestCpuCount);
+
+	RDebug::Printf("SetCpuAffinity --> Setting cpu %3d\n", cpu);
+	TInt r = UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny *)cpu, 0);
+	return r;
+	}
+
+// call the function corresponding to aFunctionType
+LOCAL_C void CallFunction(TDebugFunctionType aFunctionType, TUint aDelay, TUint aExtraThreads, TInt32 aCpuNumber)
+	{
+	// pause for aDelay microseconds
+	User::After(aDelay);
+
+	// set cpu on which this thread should execute on
+	if (aCpuNumber)
+		SetCpuAffinity(aCpuNumber);
+
+	// launch the extra threads
+	LaunchThreads(aExtraThreads);
+
+	// call appropriate function
+	switch( aFunctionType )
+		{
+		case EPrefetchAbortFunction:
+			PrefetchAbort();
+			break;
+		case EUserPanicFunction:
+			UserPanic();
+			break;
+		case EStackOverflowFunction:
+			StackOverFlowFunction();
+			break;
+		case EDataAbortFunction:
+			DataAbort();
+			break;
+		case EUndefInstructionFunction:
+			UndefInstruction();
+			break;
+		case EDataReadErrorFunction:
+			DataRead();
+			break;
+		case EDataWriteErrorFunction:
+			DataWrite();
+			break;
+		case EUserExceptionFunction:
+			UserException();
+			break;
+		case EWaitFiveSecondsThenExit:
+			WaitFiveSecondsThenExit();
+			break;
+		case ESpinForever:
+			SpinForever();
+			break;
+		case ESpinForeverWithBreakPoint:
+			SpinForeverWithBreakPoint();
+			break;
+        case ENormalExit:
+            NormalExit();
+            break;			
+		case EDefaultDebugFunction:
+		default:
+			break;
+		}
+	}
+
+void PrintHelp()
+	{
+	RDebug::Printf("Invoke with arguments:\n");
+	RDebug::Printf("\t-d<delay>\n\t: delay in microseconds before calling target function\n");
+	RDebug::Printf("\t-f<function-number>\n\t: enumerator from TDebugFunctionType representing function to call\n");
+	RDebug::Printf("\t-e<number>\n\t: number of extra threads to launch, these threads run endlessly\n");
+	}
+
+
+TInt E32Main()
+	{
+	// setup heap checking and clean up trap
+	__UHEAP_MARK;
+	CTrapCleanup* cleanup=CTrapCleanup::New();
+	RThread().SetPriority(EPriorityNormal);
+	RProcess::Rendezvous(KErrNone);
+
+	// read arguments from command line
+	TUint delay = 0;
+	TInt32 functionTypeAsTInt32 = (TInt32)EDefaultDebugFunction;
+	TUint extraThreads = 0;
+	TInt32 aCpuNumber = -1;
+
+	TRAPD(err, ParseCommandLineL(functionTypeAsTInt32, delay, extraThreads, aCpuNumber));
+
+	if(KErrNone == err)
+		{
+		// if the command line arguments were successfully read then call the appropriate function
+		CallFunction((TDebugFunctionType)functionTypeAsTInt32, delay, extraThreads, aCpuNumber);
+		}
+
+	// perform clean up and return any error which was recorded
+	delete cleanup;
+	__UHEAP_MARKEND;
+	return err;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_app.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,44 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+//
+
+#ifndef T_RMDEBUG_APP_H
+#define T_RMDEBUG_APP_H
+
+_LIT(KRMDebugTestApplication, "z:\\sys\\bin\\t_rmdebug_app.exe");
+_LIT(KUserPanic, "UserPanic");
+const TInt KUserPanicCode = 0x1234ABCD;
+enum TMyPropertyKeys {EMyPropertyInteger};
+
+
+// enumeration of functions to call in test debug application
+enum TDebugFunctionType
+	{
+	EDefaultDebugFunction,
+	EPrefetchAbortFunction,
+	EUserPanicFunction,
+	EStackOverflowFunction,
+	EDataAbortFunction,
+	EUndefInstructionFunction,
+	EDataReadErrorFunction,
+	EDataWriteErrorFunction,
+	EUserExceptionFunction,
+	EWaitFiveSecondsThenExit,
+	ESpinForever,
+	ESpinForeverWithBreakPoint,
+	ENormalExit
+	};
+
+#endif //T_RMDEBUG_APP_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_dll.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,25 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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 <e32std.h>
+#include <e32std_private.h>
+#include <rm_debug_api.h>
+#include "t_rmdebug_dll.h"
+
+EXPORT_C TUid GetDSSUid()
+	{
+	return Debug::KUidDebugSecurityServer;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_dll.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,23 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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 <e32std.h>
+
+/**
+  This is a simple function that uses an element from rm_debug_api.h.
+  If the e32tests can be built and run then this is 'proof' that the
+  rm_debug_api.h header file can be #include'd into a dll
+  */
+IMPORT_C TUid GetDSSUid();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_security.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,100 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Target application to be debugged by t_rmdebug.exe when testing
+// security restrictions. This application is built with various
+// capabilities by the t_rmdebug_securityX.mmp files. This allows
+// the t_rmdebug2 program to ensure that security restrictions are
+// properly enforced by the DSS/DDD subsystem.
+// 
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <e32test.h>
+#include <e32ldr.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include "t_rmdebug_security.h"
+
+CRunModeApp* CRunModeApp::NewL()
+//
+// CRunModeApp::NewL
+//
+	{
+	CRunModeApp* self = new(ELeave) CRunModeApp();
+
+  	self->ConstructL();
+   
+	return self;
+	}
+
+CRunModeApp::CRunModeApp()
+//
+// CRunModeApp constructor
+//
+	{
+	}
+
+CRunModeApp::~CRunModeApp()
+//
+// CRunModeApp destructor
+//
+	{
+	}
+
+void CRunModeApp::ConstructL()
+//
+// CRunModeApp::ConstructL
+//
+	{
+	}
+
+void CRunModeApp::TestWaitDebug()
+//
+// CRunModeApp::TestWaitDebug
+//
+	{
+	RProcess::Rendezvous(KErrNone);
+
+	// Wait a 3secs then quit (long enough to test, but not hang around forever)
+	User::After(3000000);
+	}
+
+GLDEF_C TInt E32Main()
+//
+// Entry point for run mode debug app test program
+//
+	{
+   TInt ret = KErrNone;
+   
+	// client
+	CTrapCleanup* trap = CTrapCleanup::New();
+	if (!trap)
+		return KErrNoMemory;
+
+   CRunModeApp* myApp = CRunModeApp::NewL();
+   if (myApp != NULL)
+       {
+        __UHEAP_MARK;
+	    TRAP(ret,myApp->TestWaitDebug());
+	    __UHEAP_MARKEND;
+
+	    delete myApp;
+       }
+       
+	delete trap;
+
+	return ret;
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/debug_targets/t_rmdebug_security.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,44 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Target application to be debugged by t_rmdebug2.exe when testing
+// security restrictions. This application is built with various
+// capabilities by the t_rmdebug_securityX.mmp files. This allows
+// the t_rmdebug2 program to ensure that security restrictions are
+// properly enforced by the DSS/DDD subsystem.
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef T_RMDEBUG_SECURITY_H
+#define T_RMDEBUG_SECURITY_H
+
+class CRunModeApp : public CBase
+{
+public:
+	static CRunModeApp* NewL();
+	~CRunModeApp();
+
+	void TestWaitDebug();
+
+private:
+	CRunModeApp();
+	void ConstructL();
+};
+
+#endif // T_RMDEBUG_SECURITY_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_crashmonitor_lib.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,44 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Tests the functionality of the System Crash Monitor libraries
+//
+
+ALWAYS_BUILD_AS_ARM
+
+targettype     exe
+ 
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+userinclude    ../../../../kernel/eka/debug/crashMonitor/inc
+sourcepath	   	../crashmonitor
+
+source        	t_crashmonitor.cpp
+
+library	euser.lib
+library hal.lib
+staticlibrary scmusr_lib.lib
+
+target         t_crashmonitor_lib.exe
+
+UID            0x0 0x4321bbbc
+SECUREID       0x2000B26F
+
+capability		none
+
+VENDORID       0x70000001
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_multi_agent_launcher.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,41 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Application that launches multiple agents which in-turn test the ability of 
+// the run mode debug component to debug several targets
+// 
+//
+
+targettype     exe
+target         t_multi_agent_launcher.exe
+
+library		euser.lib hal.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+userinclude    ../debug_targets
+userinclude    ../common
+userinclude    ../multi_agent_tests
+
+sourcepath	   ../multi_agent_tests
+source         t_multi_agent_launcher.cpp 
+
+UID            0x0 0x4321bbbc
+SECUREID       0x1234aaab
+VENDORID       0x70000001
+
+DEBUGGABLE
+
+macro SYMBIAN_STANDARDDEBUG
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,40 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         t_rmdebug.exe
+targettype     exe
+
+sourcepath	   	../metro_trk
+source        	d_rmdebugserver.cpp 
+source        	d_rmdebugthread.cpp 
+source        	t_rmdebug.cpp 
+sourcepath	   	../common
+source			d_rmdebugthreadasm.cia
+
+library		euser.lib
+               
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+UID            0x100039CE 0x101F7159
+SECUREID       0x101F7159
+VENDORID       0x70000001
+
+CAPABILITY 	ALL -TCB
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug2.mmh	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,65 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+targettype     exe
+
+sourcepath	   	..\debug_targets
+
+source        	d_rmdebugthread2.cpp 
+source			d_rmdebugthreadasm2.cia
+
+#if defined(MARM_ARMV5)
+source			d_rmdebug_step_test.s
+#endif
+
+#if defined(MARM_ARMV4)
+source			d_rmdebug_step_test_armv4.s
+#endif
+
+source			d_demand_paging.cia
+
+library		euser.lib
+library         hal.lib
+library         efsrv.lib
+library         t_rmdebug_dll.lib
+
+userinclude    ..\..\..\..\kernel\eka\include\drivers
+userinclude    ..\..\..\..\kernel\eka\debug\securityserver\inc
+userinclude    ..\debug_targets
+
+
+#ifdef SYMBIAN_OLD_EXPORT_LOCATION
+SYMBIAN_BASE_SYSTEMINCLUDE(drivers)
+SYMBIAN_BASE_SYSTEMINCLUDE(kernel)
+#endif
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+PAGED
+
+// To test heap allocation failure uncomment one or other of the following macros.
+// NOTE: Do not uncomment both, the tests will panic if both are defined!
+
+// To test heap allocation failure in the Debug Device Driver uncomment this macro
+//macro KERNEL_OOM_TESTING
+
+// To test heap allocation failure in the Debug Security Server uncomment this macro
+//macro USER_OOM_TESTING
+
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug2.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,35 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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 "t_rmdebug2.mmh"
+
+target         t_rmdebug2.exe
+
+sourcepath	   	../basic_tests
+source        	t_rmdebug2.cpp 
+source		r_low_memory_security_svr_session.cpp
+source		r_kernel_low_memory_security_svr_session.cpp
+source		r_user_low_memory_security_svr_session.cpp
+
+UID            0x0 0x4321bbbb
+SECUREID       0x1234aaaa
+VENDORID       0x70000001
+
+CAPABILITY 	READUSERDATA POWERMGMT ALLFILES
+
+DEBUGGABLE
+
+macro SYMBIAN_STANDARDDEBUG
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug2_oem.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,38 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Same tests as t_rmdebug2.mmp but with OEM rights conferred
+// by the OEMDebug_F123ABCD.exe token file.
+// 
+//
+
+#include "t_rmdebug2.mmh"
+
+target         t_rmdebug2_oem.exe
+
+sourcepath	   	../basic_tests
+source        	t_rmdebug2.cpp 
+source		r_low_memory_security_svr_session.cpp
+source		r_kernel_low_memory_security_svr_session.cpp
+source		r_user_low_memory_security_svr_session.cpp
+
+UID            0x0 0x4321bbbb
+SECUREID       0xF123abcd
+VENDORID       0x70000001
+
+CAPABILITY 	READUSERDATA POWERMGMT ALLFILES
+
+// Used when compiling tests to work in the presence of an
+// OEM Debug Token
+macro SYMBIAN_OEMDEBUG
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug2_oem2.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,38 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Same tests as t_rmdebug2.mmp but with some OEM rights conferred
+// by the OEMDebug_F1234567.exe token file.
+// 
+//
+
+#include "t_rmdebug2.mmh"
+
+target         t_rmdebug2_oem2.exe
+
+sourcepath	   	../basic_tests
+source        	t_rmdebug2.cpp 
+source		r_low_memory_security_svr_session.cpp
+source		r_kernel_low_memory_security_svr_session.cpp
+source		r_user_low_memory_security_svr_session.cpp
+
+UID            0x0 0x4321bbbb
+SECUREID       0xF1234567
+VENDORID       0x70000001
+
+CAPABILITY 	READUSERDATA POWERMGMT
+
+// Used when compiling tests to work in the presence of an
+// OEM Debug Token with AllFiles only capability
+macro SYMBIAN_OEM2DEBUG
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug2_oemtoken.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         OEMDebug_F123ABCD.exe
+targettype     exe
+
+sourcepath	   	../basic_tests
+
+source        	t_rmdebug2_oemtoken.cpp 
+
+library		euser.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+capability PowerMgmt AllFiles Tcb ReadUserData WriteUserData
+
+UID            0x0 0x0
+SECUREID       0x0
+VENDORID       0x70000001
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug2_oemtoken2.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,37 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         OEMDebug_F1234567.exe
+targettype     exe
+
+sourcepath	   	../basic_tests
+
+source        	t_rmdebug2_oemtoken.cpp 
+
+library		euser.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+// Token requires AllFiles
+capability AllFiles ReadUserData PowerMgmt
+
+UID            0x0 0x0
+SECUREID       0x0
+VENDORID       0x70000001
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,35 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// 
+//
+
+target             t_rmdebug_app.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source			   d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app1.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app1.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app10.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app10.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app2.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app2.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app3.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app3.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app4.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app4.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app5.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app5.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app6.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app6.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app7.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app7.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app8.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app8.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_app9.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Target application to be debugged
+// 
+//
+
+target             t_rmdebug_app9.exe
+targettype         exe
+
+sourcepath         ../debug_targets
+source             t_rmdebug_app.cpp 
+source             d_rmdebugthreadasm2.cia
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+library            euser.lib hal.lib
+
+uid                0x0 0x0
+capability         none
+
+always_build_as_arm
+pagedcode
+
+DEBUGGABLE
+
+SMPSAFE
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_dll.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,38 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         t_rmdebug_dll.dll
+targettype     dll
+
+DEFFILE        ../../~/t_rmdebug_dll.def
+
+sourcepath	   	../debug_targets
+
+source        	t_rmdebug_dll.cpp 
+
+library		euser.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+capability PowerMgmt AllFiles ReadUserData
+
+UID            0x0 0x0
+SECUREID       0x0
+VENDORID       0x70000001
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_multi_agent.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,41 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Application that tests the ability of the run mode debug component 
+// to debug multiple targets 
+// 
+//
+
+targettype     exe
+target         t_rmdebug_multi_agent.exe
+
+library		euser.lib hal.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+userinclude    ../debug_targets
+userinclude    ../common
+userinclude    ../multi_agent_tests
+
+sourcepath	   ../multi_agent_tests
+source         t_multi_agent.cpp t_agent_eventhandler.cpp 
+
+UID            0x0 0x4321bbbc
+SECUREID       0x1234aaab
+VENDORID       0x70000001
+
+DEBUGGABLE
+
+macro SYMBIAN_STANDARDDEBUG
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_multi_target.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,43 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Application that tests the ability of the run mode debug component 
+// to debug several targets
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+targettype     exe
+target         t_rmdebug_multi_target.exe
+
+library		euser.lib hal.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+userinclude    ../debug_targets
+userinclude    ../common
+userinclude    ../multi_target_tests
+
+sourcepath	   ../multi_target_tests
+source         t_multi_target.cpp 
+
+UID            0x0 0x4321bbbc
+SECUREID       0x1234aaab
+VENDORID       0x70000001
+
+DEBUGGABLE
+
+macro SYMBIAN_STANDARDDEBUG
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_security0.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,36 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         t_rmdebug_security0.exe
+targettype     exe
+
+sourcepath	   	../debug_targets
+source        	t_rmdebug_security.cpp 
+
+library		euser.lib hal.lib
+               
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+UID            0x100039CE 0xbaaaf00d
+SECUREID       0x101F7159
+VENDORID       0x70000001
+
+DEBUGGABLE
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_security1.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,35 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         t_rmdebug_security1.exe
+targettype     exe
+
+sourcepath	   	../debug_targets
+source        	t_rmdebug_security.cpp 
+
+library		euser.lib hal.lib
+               
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+UID            0x100039CE 0xdeadbaaa
+SECUREID       0x101F7159
+VENDORID       0x70000001
+
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_security2.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,37 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         t_rmdebug_security2.exe
+targettype     exe
+
+sourcepath	   	../debug_targets
+source        	t_rmdebug_security.cpp 
+
+library		euser.lib hal.lib
+               
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+capability AllFiles
+
+UID            0x100039CE 0xdeadbaaa
+SECUREID       0x101F7159
+VENDORID       0x70000001
+
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_security3.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,37 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         t_rmdebug_security3.exe
+targettype     exe
+
+sourcepath	   	../debug_targets
+source        	t_rmdebug_security.cpp 
+
+library		euser.lib hal.lib
+               
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+capability TCB AllFiles NetworkControl
+
+UID            0x100039CE 0xdeadbaaa
+SECUREID       0x101F7159
+VENDORID       0x70000001
+
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_rmdebug_target_launcher.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,38 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Application that test the ability of the run mode debug component 
+// to handle several target applications
+// 
+//
+
+target         t_rmdebug_target_launcher.exe
+targettype     exe
+
+library		     euser.lib
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+userinclude    ../common
+sourcepath	   ../common
+source         t_target_launcher.cpp 
+
+UID            0x0 0x4321bbbd
+SECUREID       0x1234aaac
+VENDORID       0x70000001
+
+DEBUGGABLE
+
+macro SYMBIAN_STANDARDDEBUG
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/group/t_trkdummyapp.mmp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,44 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// t_trkdummyapp.mmp
+// 
+//
+
+ALWAYS_BUILD_AS_ARM
+
+target         t_trkdummyapp.exe
+targettype     exe
+
+sourcepath	   	../trk_blocking
+
+source        	t_trkdummyapp.cpp 
+
+library		euser.lib
+library         hal.lib
+library         efsrv.lib
+library         t_rmdebug_dll.lib
+
+SYMBIAN_BASE_SYSTEMINCLUDE(nkern)
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+UID            0x0 0x0
+SECUREID       0x0
+VENDORID       0x70000001
+
+CAPABILITY 	none
+
+
+
+
+SMPSAFE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/metro_trk/d_rmdebugclient.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,100 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// t_rmdebugclient.h
+// Definitions for the run mode debug agent client side sessions.
+// 
+//
+
+#ifndef RMDEBUGCLIENT_H
+#define RMDEBUGCLIENT_H
+
+class TProcessInfo
+	{
+	public:
+		TUint           iProcessID;
+		TInt            iAttributes;
+		TUint32         iPriority;
+		TBuf<KMaxName> 	iName;    
+	};
+
+class TThreadInfo
+	{
+	public:
+		TUint           iThreadID;
+		TUint8          iPriority;
+		TUint8          iThreadType;
+		TBuf<KMaxName>  iName;
+		TUint           iOwningProcessID;
+
+	// Probably would want a state element here, under debug control, stopped etc
+	// such that additional information could be provided which was only valid for
+	// stopped threads.
+
+	};
+
+class TExecReq
+	{
+	public:
+		TUint32 iRequest;       // Step, Step into, step threads
+		TUint32 iStartAddress;
+		TUint32 iStopAddress;
+
+	};
+
+class TMemoryInfo
+	{
+	public:
+		TUint32 iAddress;
+		TUint32	iSize;
+		TPtr8*	iDataPtr;
+	};
+
+
+// Client Side session
+class RDebugServSession : public RSessionBase
+	{
+	public:
+		RDebugServSession();
+		TVersion Version() const;
+
+		TInt Open();
+		TInt Close();
+
+		TInt ReadMemory(const TUint32 aThreadId, TMemoryInfo* aInfo);
+		TInt WriteMemory(const TUint32 aThreadId, TMemoryInfo* aInfo);
+
+//		TInt ReadThreadInfo(const TInt aIndex, const TInt aOwningProc, TThreadInfo* aInfo);
+//		TInt ReadProcessInfo(const TInt aIndex, TProcessInfo* aInfo);
+		TInt SuspendThread(const TInt ThreadID);
+		TInt ResumeThread(const TInt ThreadID);
+
+	private:
+		RThread iServerThread;       
+	};
+
+// Function codes (opcodes) used in message passing between client and server
+enum TDebugServRqst
+	{
+	EDebugServOpen = 1,
+	EDebugServClose,
+
+	EDebugServSuspendThread,
+	EDebugServResumeThread,
+//	EDebugServReadProcessInfo,
+//	EDebugServReadThreadInfo,
+	EDebugServReadMemory,
+	EDebugServWriteMemory,
+	};
+
+#endif // RMDEBUGCLIENT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/metro_trk/d_rmdebugserver.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,453 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Provides the debug agent server implementation.
+// 
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <trkkerneldriver.h>
+#include "d_rmdebugserver.h"
+#include "d_rmdebugclient.h"
+#include "t_rmdebug.h"
+
+
+CDebugServServer::CDebugServServer(CActive::TPriority aActiveObjectPriority)
+   : CServer2(aActiveObjectPriority)
+//
+// Server constructor
+//
+	{
+	}
+
+CSession2* CDebugServServer::NewSessionL(const TVersion& /*aVersion*/, const RMessage2& /*aMessage*/) const
+//
+// Session constructor
+//
+	{
+	// make sure the kernel side device driver is not already loaded
+   TInt err;
+	err = User::LoadLogicalDevice(KDebugDriverFileName);
+	if ((KErrNone == err) || (KErrAlreadyExists == err))
+       {
+       return new(ELeave) CDebugServSession();
+       }
+   else
+       {
+       return (NULL);
+       }
+	}   
+
+CDebugServSession::CDebugServSession()
+// Session implementation
+	{
+   TInt err;
+	TMetroTrkDriverInfo info;
+   info.iUserLibraryEnd = 0;
+   err = iKernelDriver.Open(info);
+   if (KErrNone != err)
+		{
+ 		User::Leave(err);
+		}          
+	}
+
+CDebugServSession::~CDebugServSession()
+//
+// Session destructor
+//
+	{
+	// stop the kernel side driver
+	iKernelDriver.Close();
+
+	User::FreeLogicalDevice(KDebugDriverName);
+	}
+
+
+void CDebugServSession::ServiceL(const RMessage2& aMessage)
+//
+// Session service handler
+//
+	{
+	TInt res = KErrNone;
+
+	switch(aMessage.Function())
+		{
+		case EDebugServResumeThread:
+			res = ResumeThread(aMessage);
+			break;
+
+		case EDebugServSuspendThread:
+			res = SuspendThread(aMessage);
+			break;          
+
+//		case EDebugServReadProcessInfo:
+//			res = ReadProcessInfo(aMessage);
+//			break;        
+//
+//		case EDebugServReadThreadInfo:
+//			res = ReadThreadInfo(aMessage);
+//			break;
+
+		case EDebugServReadMemory:
+			res = ReadMemory(aMessage);
+			break;        
+
+		case EDebugServWriteMemory:
+			res = WriteMemory(aMessage);
+			break;        
+
+		default:
+			User::Leave(KErrNotSupported);
+			break;
+		}
+
+	aMessage.Complete(res);
+	}
+
+
+
+TInt CDebugServSession::SuspendThread(const RMessage2& aMessage)
+//
+// Session suspend thread
+//
+	{
+	TInt err;
+
+	err = iKernelDriver.SuspendThread(aMessage.Int0());
+
+	return err;
+	}
+
+TInt CDebugServSession::ResumeThread(const RMessage2& aMessage)
+//
+// Server resume thread
+//
+	{
+	TInt err;
+
+	err = iKernelDriver.ResumeThread(aMessage.Int0());
+
+	return err;
+	}
+
+//TInt CDebugServSession::ReadProcessInfo(const RMessage2& aMessage)
+////
+//// Server read process information
+////
+//	{
+//	TInt err;
+//	TProcessInfo procinfo;
+//	TMetroTrkTaskInfo processInfo(0);
+//
+//	err = iKernelDriver.GetProcessInfo(aMessage.Int0(), processInfo);
+//
+//	if (KErrNone == err)
+//		{
+//		procinfo.iProcessID = processInfo.iId;
+//		procinfo.iPriority = processInfo.iPriority;
+//		procinfo.iName.Copy(processInfo.iName);
+//
+//		TPckgBuf<TProcessInfo> p(procinfo);
+//		aMessage.WriteL(1,p);        
+//		}
+//
+//	return err;
+//	}
+//
+//TInt CDebugServSession::ReadThreadInfo(const RMessage2& aMessage)
+////
+//// Server read thread information
+////
+//	{
+//	TInt err;
+//	TThreadInfo thrdinfo;
+//	TMetroTrkTaskInfo threadInfo(aMessage.Int1()); // Sets OtherID to the second input parameter in aMessage
+//
+//	// aMessage.Int0 is the index into the thread list for the process
+//	err = iKernelDriver.GetThreadInfo(aMessage.Int0(), threadInfo);	   
+//
+//	if (KErrNone == err)
+//		{
+//		thrdinfo.iThreadID = threadInfo.iId;
+//		thrdinfo.iPriority = threadInfo.iPriority;
+//		thrdinfo.iName.Copy(threadInfo.iName);
+//		thrdinfo.iOwningProcessID = threadInfo.iOtherId;
+//
+//		TPckgBuf<TThreadInfo> p(thrdinfo);
+//
+//		// Write out the results to the third argument passed in (pointer to the threadinfo structure)
+//		aMessage.WriteL(2,p);           
+//		}
+//
+//	return err;
+//	}
+
+TInt CDebugServSession::ReadMemory(const RMessage2& aMessage)
+//
+// Server read process memory
+//
+	{   
+	TInt err;
+	TUint32 threadId = aMessage.Int0();
+	TPckgBuf<TMemoryInfo> pckg = *(TPckgBuf<TMemoryInfo> *)(aMessage.Ptr1());
+	TMemoryInfo* InputMemoryInfo = &pckg();
+
+	TPtr8 *ptrtst = InputMemoryInfo->iDataPtr;
+
+	err = iKernelDriver.ReadMemory(threadId, InputMemoryInfo->iAddress, InputMemoryInfo->iSize, *ptrtst);
+
+	return err;
+	}
+
+TInt CDebugServSession::WriteMemory(const RMessage2& aMessage)
+//
+// Server write process memory
+//
+	{
+	TInt err;
+	TUint32 threadId = aMessage.Int0();
+	TPckgBuf<TMemoryInfo> pckg = *(TPckgBuf<TMemoryInfo> *)(aMessage.Ptr1());
+	TMemoryInfo* InputMemoryInfo = &pckg();
+
+	TPtr8 *ptrtst = InputMemoryInfo->iDataPtr;
+
+	err = iKernelDriver.WriteMemory(threadId, InputMemoryInfo->iAddress, InputMemoryInfo->iSize, *ptrtst);
+
+	return err;
+	}
+
+
+GLDEF_C TInt CDebugServServer::ThreadFunction(TAny*)
+//
+// Server thread function, continues until active scheduler stops
+//
+	{
+	CTrapCleanup* cleanup=CTrapCleanup::New();
+	if (cleanup == NULL)
+		{
+		User::Leave(KErrNoMemory);
+		}
+
+	CActiveScheduler *pA=new CActiveScheduler;
+	CDebugServServer *pS=new CDebugServServer(EPriorityStandard);
+
+	CActiveScheduler::Install(pA);
+
+	TInt err = pS->Start(KDebugServerName);
+	if (err != KErrNone)
+		{
+		User::Leave(KErrNone);
+		}
+
+	RThread::Rendezvous(KErrNone);
+
+	CActiveScheduler::Start();
+
+	delete pS;
+	delete pA;
+	delete cleanup;
+
+	return (KErrNone);
+	}
+
+
+
+EXPORT_C TInt StartThread(RThread& aServerThread)
+//
+// Start the server thread
+//
+	{
+	TInt res=KErrNone;
+
+	TFindServer finddebugserver(KDebugServerName);
+	TFullName name;
+
+	if (finddebugserver.Next(name) != KErrNone)
+		{
+		res = aServerThread.Create( KDebugServerName,
+									CDebugServServer::ThreadFunction,
+									KDefaultStackSize,
+									KDefaultHeapSize,
+									KDefaultHeapSize,
+									NULL
+									);
+
+		if (res == KErrNone)
+			{
+			TRequestStatus rendezvousStatus;
+
+			aServerThread.SetPriority(EPriorityNormal);
+			aServerThread.Rendezvous(rendezvousStatus);
+			aServerThread.Resume();
+			User::WaitForRequest(rendezvousStatus);
+			}                                 
+		else
+			{
+			aServerThread.Close();
+			}
+		}
+
+	return res;
+	}
+
+
+
+RDebugServSession::RDebugServSession()
+//
+// Server session constructor
+//
+	{
+	}
+
+TInt RDebugServSession::Open()
+//
+// Session open
+//
+	{
+	TInt r = StartThread(iServerThread);
+	if (r == KErrNone)
+		{
+		r=CreateSession(KDebugServerName, Version(), KDefaultMessageSlots);
+		}
+
+	return r;
+	}
+
+
+TVersion RDebugServSession::Version(void) const
+//
+// Session version
+//
+	{
+	return (TVersion(KDebugServMajorVersionNumber, KDebugServMinorVersionNumber, KDebugServBuildVersionNumber));
+	}
+
+TInt RDebugServSession::SuspendThread(const TInt aThreadID)
+//
+// Session suspend thread request
+//
+	{
+	TIpcArgs args(aThreadID);
+	TInt res;
+	res = SendReceive(EDebugServSuspendThread, args);
+
+	return res;
+	}
+
+TInt RDebugServSession::ResumeThread(const TInt aThreadID)
+//
+// Session resume thread request
+//
+	{
+	TIpcArgs args(aThreadID);
+	TInt res;
+	res = SendReceive(EDebugServResumeThread, args);
+
+	return res;
+	}
+
+
+//TInt RDebugServSession::ReadProcessInfo(const TInt aIndex, TProcessInfo* aInfo)
+////
+//// Session read process information request
+////
+//	{
+//	TPckgBuf<TProcessInfo> pckg;
+//	pckg = *aInfo;
+//
+//	TIpcArgs args(aIndex, &pckg);
+//
+//	TInt res;
+//
+//	res = SendReceive(EDebugServReadProcessInfo, args);
+//
+//	*aInfo = pckg();
+//
+//	return res;
+//
+//	}
+//
+//TInt RDebugServSession::ReadThreadInfo(const TInt aIndex, const TInt aProc, TThreadInfo* aInfo)
+////
+//// Session read thread information request
+////
+//	{
+//	TPckgBuf<TThreadInfo> pckg;
+//	pckg = *aInfo;
+//
+//	TIpcArgs args(aIndex, aProc, &pckg);
+//
+//	TInt res;
+//
+//	res = SendReceive(EDebugServReadThreadInfo, args);
+//
+//	*aInfo = pckg();
+//
+//	return res;
+//
+//	}
+
+
+TInt RDebugServSession::ReadMemory(const TUint32 aThreadID, TMemoryInfo* aInfo)
+//
+// Session read thread memory request
+//
+	{
+	TPckgBuf<TMemoryInfo> pckg;
+	pckg = *aInfo;
+
+	TIpcArgs args(aThreadID, &pckg);
+
+	TInt res;
+
+	res = SendReceive(EDebugServReadMemory, args);
+
+	*aInfo = pckg();
+
+	return res;
+
+	}
+
+
+TInt RDebugServSession::WriteMemory(const TUint32 aThreadID, TMemoryInfo* aInfo)
+//
+// Session write thread memory request
+//
+	{
+	TPckgBuf<TMemoryInfo> pckg;
+	pckg = *aInfo;
+
+	TIpcArgs args(aThreadID, &pckg);
+
+	TInt res;
+
+	res = SendReceive(EDebugServWriteMemory, args);
+
+	return res;
+	}
+
+
+
+TInt RDebugServSession::Close()
+//
+// Session close the session and thread
+//
+	{
+	RSessionBase::Close();
+	iServerThread.Close();
+
+	return KErrNone;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/metro_trk/d_rmdebugserver.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,73 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// t_rmdebugserver.h
+// Definitions for the run mode debug agent server side session.
+// 
+//
+
+#ifndef RMDEBUGSVR_H
+#define RMDEBUGSVR_H
+
+// Server name
+_LIT(KDebugServerName,"DebugServer");
+_LIT(KDebugDriverName,"MetroTrk Driver");
+_LIT(KDebugDriverFileName,"trkdriver.ldd");
+
+// A version must be specifyed when creating a session with the server
+const TUint KDebugServMajorVersionNumber=0;
+const TUint KDebugServMinorVersionNumber=1;
+const TUint KDebugServBuildVersionNumber=1;
+const TUint KDefaultMessageSlots=4;
+const TUint KDefaultHeapSize=0x10000;
+
+class CDebugServSession;
+
+
+// Server
+class CDebugServServer : public CServer2
+	{
+	public:
+		CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const;
+	public:
+		static TInt ThreadFunction(TAny* aStarted);
+	protected:
+		CDebugServServer(CActive::TPriority aActiveObjectPriority);
+	};
+
+// Server side session
+class CDebugServSession : public CSession2
+	{
+	public:
+		CDebugServSession();
+		~CDebugServSession();
+		void ConstructL ( void );
+		void ServiceL(const RMessage2& aMessage);
+
+		TInt ReadMemory(const RMessage2& aMessage);
+		TInt WriteMemory(const RMessage2& aMessage);
+
+//		TInt ReadProcessInfo(const RMessage2& aMessage);
+//		TInt ReadThreadInfo(const RMessage2& aMessage);
+
+		TInt ResumeThread(const RMessage2& aMessage);
+		TInt SuspendThread(const RMessage2& aMessage);
+
+	public:
+		RMetroTrkDriver iKernelDriver;	
+
+	private:
+	};
+
+
+#endif // RMDEBUGSVR_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/metro_trk/t_rmdebug.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,347 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Tests the functionality of the run mode debug device driver.
+// 
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <e32test.h>
+#include <e32ldr.h>
+#include <f32dbg.h>
+#include "d_rmdebugclient.h"
+#include "d_rmdebugthread.h"
+#include "t_rmdebug.h"
+
+IMPORT_C TInt StartDebugThread(RThread& aServerThread);
+IMPORT_D extern TInt TestData;
+IMPORT_D extern TBuf8<SYMBIAN_RMDBG_MEMORYSIZE> gMemoryAccessBytes;
+
+LOCAL_D RTest test(_L("T_RMDEBUG"));
+
+CRunModeAgent::CRunModeAgent()
+//
+// CRunModeAgent constructor
+//
+	{
+	}
+
+CRunModeAgent* CRunModeAgent::NewL()
+//
+// CRunModeAgent::NewL
+//
+	{
+	CRunModeAgent* self = new(ELeave) CRunModeAgent();
+
+  	self->ConstructL();
+
+   if (self->iState != ERunModeAgentRunning)
+       {
+       delete self;
+       self = NULL;
+       }       
+	return self;
+	}
+
+CRunModeAgent::~CRunModeAgent()
+//
+// CRunModeAgent destructor
+//
+	{
+	iServSession.Close();
+	iDebugThread.Close();
+   iState = ERunModeAgentUnInit;
+	}
+
+void CRunModeAgent::ConstructL()
+//
+// CRunModeAgent::ConstructL
+//
+	{
+	TInt err;
+	err = StartDebugThread(iDebugThread);
+
+	if (err == KErrNone)
+		{
+		if (iServSession.Open() == KErrNone)
+           {
+           iState = ERunModeAgentRunning;
+           }
+       else
+           {
+           iState = ERunModeAgentUnInit;
+           }
+		}
+	else
+		{
+		User::Panic(_L("Can't start debug thread"), err);
+		}
+}
+
+
+
+CRunModeAgent *RunModeAgent;
+
+// Test process names
+_LIT(ProcessName1,"T_RMDEBUG");
+_LIT(ProcessName1a,"t_rmdebug");
+//_LIT(ProcessName2,"ekern");
+//_LIT(ProcessName3,"efile");
+_LIT(KWildCard,"*");
+
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-0185
+//! @SYMTestType 
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test reading process list
+//! @SYMTestActions Several calls to read the process list
+//! @SYMTestExpectedResults KErrNone and the owning process ID set
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestProcessList()
+	{
+	TInt    err=KErrNone;
+	TBool	found = FALSE;
+
+	test.Next(_L("TestProcessList - Read Process List\n"));
+
+	TFindProcess find(KWildCard);
+	TFullName name;
+	while(find.Next(name)==KErrNone)
+		{
+		RProcess process;
+		err = process.Open(find);
+		if (err == KErrNone)
+			{
+			if ((name.Find(ProcessName1) != KErrNotFound) ||
+				(name.Find(ProcessName1a) != KErrNotFound))
+				{				
+					iProcessID = process.Id();
+					found = TRUE;				
+				}
+			process.Close();				
+			}
+	   }   
+	test(found== TRUE);   
+	}
+
+// Test thread name
+_LIT(ThreadName1,"DebugThread");
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-0186
+//! @SYMTestType 
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test reading thread list
+//! @SYMTestActions Several calls to read the thread list
+//! @SYMTestExpectedResults KErrNone and the debug thread ID set
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestThreadList()
+	{
+	TInt        err=KErrNone;
+	TBool       found = FALSE;
+
+	test.Next(_L("TestThreadList - Read Thread List\n"));
+
+   	TFindThread find(KWildCard);
+	TFullName name;
+	while(find.Next(name)==KErrNone)
+		{
+		RThread thread;
+		err = thread.Open(find);
+       	if (err == KErrNone)
+			{
+			RProcess process;
+			thread.Process(process);
+			if (((TUint32)process.Id() == iProcessID) &&
+				(name.Find(ThreadName1) != KErrNotFound))
+				{
+				found = TRUE;           
+				iThreadID = thread.Id();
+				}
+			}
+			thread.Close();
+   		}   
+
+	test(found==TRUE);   
+	}
+
+   
+//---------------------------------------------
+//! @SYMTestCaseID KBase-0187
+//! @SYMTestType 
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test reading and writing thread memory
+//! @SYMTestActions Several call to read and write blocks of thread memory
+//! @SYMTestExpectedResults KErrNone
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestMemoryAccess()
+{
+	TInt err=KErrNone;
+	TMemoryInfo MemoryInfo;
+	TInt i;
+
+	test.Next(_L("TestMemoryAccess - Read Memory\n"));     
+
+	for (i = 0; i < SYMBIAN_RMDBG_MEMORYSIZE; i++)
+		{
+		gMemoryAccessBytes.Append(i);
+		}
+
+	MemoryInfo.iAddress = (TUint32)(&gMemoryAccessBytes[0]);
+	MemoryInfo.iSize = SYMBIAN_RMDBG_MEMORYSIZE;
+
+	HBufC8 *data = HBufC8::NewLC(SYMBIAN_RMDBG_MEMORYSIZE);
+	TPtr8 ptr_memread(data->Des());   
+	MemoryInfo.iDataPtr = &ptr_memread;
+
+//	test.Printf(_L("Read address = 0x%x Read size = 0x%x\n"),MemoryInfo.iAddress,MemoryInfo.iSize);
+
+	err = iServSession.ReadMemory(iThreadID, &MemoryInfo);
+
+	for (i = 0; i < MemoryInfo.iSize; i++)
+		{
+		if (ptr_memread.Ptr()[i] != gMemoryAccessBytes[i])
+			{
+			err = KErrCorrupt;       		
+			}
+		}
+
+
+	// Test out writing memory.   
+	test.Next(_L("TestMemoryAccess - Write Memory\n"));
+//	test.Printf(_L("Write address = 0x%x Write size = 0x%x\n"),MemoryInfo.iAddress,MemoryInfo.iSize);
+	if (err== KErrNone)
+		{
+		// Now reset the buffer
+		for (i = 0; i < SYMBIAN_RMDBG_MEMORYSIZE; i++)
+			{
+			gMemoryAccessBytes[i] = 0;
+			}      
+
+		// Write our data into the buffer
+		err = iServSession.WriteMemory(iThreadID, &MemoryInfo);
+
+		for (i = 0; i < MemoryInfo.iSize; i++)
+			{
+			if (ptr_memread.Ptr()[i] != gMemoryAccessBytes[i])
+				{
+				err = KErrCorrupt;       		
+				}
+			}
+
+		}
+
+	if (gMemoryAccessBytes[5] == 0)
+		{
+		err = KErrCorrupt;
+		}
+
+	CleanupStack::PopAndDestroy(data);       
+	test(err==KErrNone);   
+	}
+
+
+//---------------------------------------------
+//! @SYMTestCaseID KBase-0188
+//! @SYMTestType 
+//! @SYMPREQ PREQ1426
+//! @SYMTestCaseDesc Test suspending and resuming a task
+//! @SYMTestActions Suspends a thread checks the contents of a variable then waits and tests it hasnt changed
+//! @SYMTestExpectedResults KErrNone
+//! @SYMTestPriority High
+//! @SYMTestStatus Implemented
+//---------------------------------------------
+void CRunModeAgent::TestSuspendResume()
+	{
+	TInt err;
+
+	test.Next(_L("TestSuspendResume - Suspend\n"));
+	// Suspend the thread
+	err = iServSession.SuspendThread(iThreadID);
+	test(err==KErrNone);
+	TInt localtestdata;
+	localtestdata = TestData;
+
+	// Wait 3 seconds (suspends this thread) and hopefully resumes the
+	// thread we are controlling via the iServSession.SuspendThread request
+	User::After(3000000);
+
+	// Now check data hasnt changed
+	test(localtestdata==TestData);
+
+	// Resume the thread
+	test.Next(_L("TestSuspendResume - Resume\n"));
+	err = iServSession.ResumeThread(iThreadID);
+	test(err==KErrNone);
+
+	// Wait 3 seconds (suspends this thread) and hopefully resumes the
+	// thread we are controlling via the iServSession.SuspendThread request
+	User::After(3000000);
+
+	// Now check that the thread being controlled has resumed and is
+	// updating the variable
+	test(localtestdata!=TestData);
+	}
+   
+void CRunModeAgent::ClientAppL()
+//
+// Performs each test in turn
+//
+	{
+	test.Start(_L("ClientAppL"));
+
+	TestProcessList();
+	TestThreadList();
+	TestMemoryAccess();
+	TestSuspendResume();
+	test.End();   
+	}
+
+GLDEF_C TInt E32Main()
+//
+// Entry point for run mode debug driver test
+//
+	{
+   TInt ret = KErrNone;
+   
+	// client
+	CTrapCleanup* trap = CTrapCleanup::New();
+	if (!trap)
+		return KErrNoMemory;
+
+   RunModeAgent = CRunModeAgent::NewL();
+   if (RunModeAgent != NULL)
+       {
+   	test.Title();
+
+        __UHEAP_MARK;
+	    TRAPD(r,RunModeAgent->ClientAppL());
+       ret = r;
+	    __UHEAP_MARKEND;
+
+	    delete RunModeAgent;
+       }
+       
+	delete trap;
+
+	return ret;
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/metro_trk/t_rmdebug.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,61 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Definitions for the run mode debug tests
+// 
+//
+
+#ifndef RMDEBUG_H
+#define RMDEBUG_H
+
+// Function codes (opcodes) used in message passing between client and server
+enum TRunModeAgentState
+	{
+	ERunModeAgentUnInit,
+    ERunModeAgentRunning,
+	};
+
+
+//
+// class CRunModeAgent
+//
+// The basic run mode agent.
+//
+class CRunModeAgent : public CBase
+	{
+	public:
+		static CRunModeAgent* NewL();
+		~CRunModeAgent();
+		void ClientAppL();
+
+	private:
+		CRunModeAgent();
+		void ConstructL();
+
+		TInt TestStartup();
+		TInt TestShutdown();
+
+		void TestProcessList();
+		void TestThreadList();
+		void TestMemoryAccess();
+		void TestSuspendResume();
+
+	private:
+		RDebugServSession	iServSession;
+		RThread				iDebugThread;
+		TInt				iProcessID;
+		TInt				iThreadID;
+        TInt                iState;
+	};
+
+#endif // RMDEBUG_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/multi_agent_tests/t_agent_eventhandler.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,124 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Implements the handling of run mode events for a particular target executable
+// 
+
+#include <e32base.h>
+#include <e32property.h>
+#include <e32test.h>
+
+#include "t_rmdebug_app.h"
+#include "t_agent_eventhandler.h"
+#include "t_multi_agent.h"
+#include "t_debug_logging.h" 
+
+using namespace Debug;
+
+CAgentAsyncEvent::CAgentAsyncEvent(CMultiAgent& aDriver, const TDesC& aExeName, const TDesC& aExeConfig):
+	CActive(EPriorityStandard), iDriver(aDriver)
+	{
+	}
+
+CAgentAsyncEvent* CAgentAsyncEvent::NewLC(CMultiAgent& aDriver, const TDesC& aExeName, const TDesC& aExeConfig)
+	{
+	CAgentAsyncEvent* self = new(ELeave) CAgentAsyncEvent(aDriver, aExeName, aExeConfig);
+	CleanupStack::PushL(self);
+	self->ConstructL(aExeName, aExeConfig);
+	return self;
+	}
+
+CAgentAsyncEvent* CAgentAsyncEvent::NewL(CMultiAgent& aDriver, const TDesC& aExeName, const TDesC& aExeConfig)
+	{
+	CAgentAsyncEvent* self = CAgentAsyncEvent::NewLC(aDriver, aExeName, aExeConfig);
+	CleanupStack::Pop(); // self
+	return self;
+	}
+
+void CAgentAsyncEvent::ConstructL(const TDesC& aExeName, const TDesC& aExeConfig)
+	{
+	iExeName.CreateL(aExeName);
+	iExeConfig.CreateL(aExeConfig);
+	CActiveScheduler::Add(this);
+	}
+
+CAgentAsyncEvent::~CAgentAsyncEvent()
+	{
+	LOG_MSG2("~CAgentAsyncEvent(), this = 0x%08x", this);
+
+	iSEventInfo.iEventInfoBuf.Delete(0, sizeof(TEventInfo));
+	iExeName.Close();
+	iExeConfig.Close();
+	iProc.Close();
+	Cancel(); // Cancel any request, if outstanding
+	}
+
+/*
+ * Issue request to DSS and notify the active scheduler
+ */
+void CAgentAsyncEvent::Watch()
+	{
+	LOG_MSG2("ENTER: CAgentAsyncEvent::Watch, this = 0x%08x", this);
+	iDriver.DebugDriver().GetEvent(GetExecutable(), iStatus, iSEventInfo.iEventInfoBuf);
+
+	if (!IsActive())
+		{
+		LOG_MSG("CAgentAsyncEvent::Watch(): SetActive()");
+		SetActive();
+		}
+
+	LOG_MSG("EXIT: CAgentAsyncEvent::Watch");
+	}
+
+void CAgentAsyncEvent::RunL()
+	{
+	LOG_MSG4("ENTER: CAgentAsyncEvent::RunL iDebugType=%d, iStatus.Int() %d, this 0x%x08", 
+			 iSEventInfo.iEventInfo.iEventType, iStatus.Int(), this);
+	
+    LOG_MSG2("%S", &TPtr8((TUint8*)GetExecutable().Ptr(), 2*GetExecutable().Length(), 2*GetExecutable().Length()));	
+	iDriver.HandleEvent(iSEventInfo.iEventInfo);
+
+	LOG_MSG2("iDriver.GetNumApps() %d: ", iDriver.GetNumApps());
+	LOG_MSG2("iDriver.iLaunchCompleted  %d: ", iDriver.GetLaunchCompleted());
+
+	if (iDriver.GetLaunchCompleted() < iDriver.GetNumApps())
+		{
+		// Do not call Watch() if target has run to completion but test is still on going
+		if (iSEventInfo.iEventInfo.iEventType != EEventsRemoveProcess)
+			{
+			LOG_MSG("CAgentAsyncEvent::RunL Setting Watch()");
+			Watch();
+			}
+		}
+	else
+		{
+		// Stop event handling for all targets
+		LOG_MSG("CAgentAsyncEvent::RunL CActiveScheduler::Stop() & Cancel");
+		CActiveScheduler::Stop();
+		}
+
+	LOG_MSG2("EXIT: CAgentAsyncEvent::RunL", KNullDesC);
+	}
+
+void CAgentAsyncEvent::DoCancel()
+	{
+	LOG_MSG("CAgentAsyncEvent::DoCancel");
+	}
+
+TInt CAgentAsyncEvent::RunError(TInt aError)
+	{
+	LOG_MSG3(" RunL() has left with error %d, this 0x%08X", aError, this);
+	return aError; 
+	// Can we handle this error? Not at the moment!
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/multi_agent_tests/t_agent_eventhandler.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,90 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Definitions for event handling via the DSS and target specific information
+//
+//
+
+#ifndef RMDEBUG_AGENT_EVENTHANDLER_H
+#define RMDEBUG_AGENT_EVENTHANDLER_H
+
+#include "t_multi_agent.h"
+
+using namespace Debug;
+
+class CMultiAgent;
+
+/**
+ Class for gathering event data from the run-mode driver
+ */
+class TAgentEventInfo
+{
+public:
+	TAgentEventInfo() : 
+	iEventInfoBuf((TUint8*)&iEventInfo, sizeof(TEventInfo), sizeof(TEventInfo))
+	{ 	
+	}
+
+public:
+	// This is the underlying class for event interaction with the Run Mode debug API 
+	TEventInfo			iEventInfo;
+	
+	// A convenience handle for iEventInfo used across the Debug::GetEvent() method 
+	TPtr8				iEventInfoBuf;
+};
+
+/**
+  Active object class used to trap asynchronous events
+  Also, contains target specific parameters
+  */
+class CAgentAsyncEvent : public CActive
+	{
+public:
+	// Close buffers and Cancel and destroy
+	~CAgentAsyncEvent();	
+
+	// Two-phased constructor
+	static CAgentAsyncEvent* NewLC(CMultiAgent& aDriver, const TDesC& aExeName, const TDesC& aExeConfig);
+
+	// Two-phased constructor
+	static CAgentAsyncEvent* NewL(CMultiAgent& aDriver, const TDesC& aExeName, const TDesC& aExeConfig);
+
+	// set up ASP and issue another request	
+	void Watch();
+
+	TDesC& GetExecutable() { return iExeName; }
+ 	TDesC& GetExeConfig() { return iExeConfig; }
+	RProcess& GetProcHandle() { return iProc; }
+
+protected:
+	// from CActive
+	virtual void RunL();
+	virtual void DoCancel();
+	virtual TInt RunError(TInt aError);
+
+private:
+	CAgentAsyncEvent(CMultiAgent& aDriver, const TDesC& aExeName, const TDesC& aExeConfig);
+	void ConstructL(const TDesC& aExeName, const TDesC& aExeConfig);
+
+private:
+	RBuf iExeName;
+	RBuf iExeConfig;
+	RProcess iProc;
+
+	CMultiAgent& iDriver;
+	TAgentEventInfo iSEventInfo;
+	};
+
+#endif // RMDEBUG_AGENT_EVENTHANDLER_H
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/multi_agent_tests/t_debug_logging.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,52 @@
+// Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Logging macros for use in debug subsystem
+// 
+//
+
+#ifndef RMDEBUG_MULTI_AGENT_LOGGING_H
+#define RMDEBUG_MULTI_AGENT_LOGGING_H
+
+/* Debug messages
+ * 
+ * Debug messages are only generated for debug builds.
+ * 
+ * As user mode use RDebug::Printf(). 
+ * 
+ */
+
+// Uncomment if logging of multi agent test required
+// #define MULTI_AGENT_DEBUG_LOGGING 
+
+#ifdef MULTI_AGENT_DEBUG_LOGGING
+
+    #include <e32debug.h>
+
+    #define LOG_MSG( a )              RDebug::Printf( a )
+    #define LOG_MSG2( a, b )          RDebug::Printf( a, b )
+    #define LOG_MSG3( a, b, c )       RDebug::Printf( a, b, c )
+    #define LOG_MSG4( a, b, c, d )    RDebug::Printf( a, b, c, d )
+    #define LOG_MSG5( a, b, c, d, e )    RDebug::Printf( a, b, c, d, e )
+
+#else
+
+  #define LOG_MSG( a )
+  #define LOG_MSG2( a, b )
+  #define LOG_MSG3( a, b, c )
+  #define LOG_MSG4( a, b, c, d )
+  #define LOG_MSG5( a, b, c, d, e )
+
+#endif
+
+#endif //RMDEBUG_MULTI_AGENT_LOGGING_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/multi_agent_tests/t_multi_agent.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,432 @@
+// Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Tests the run mode debug device component by launching multiple targets 
+// on different CPUs. On a single core the targets run on the same CPU.  
+//
+
+#include <e32base.h>
+#include <e32property.h>
+#include <hal.h>
+#include <e32test.h>
+#include <e32def.h>
+
+#include "t_rmdebug_app.h"
+#include "t_multi_agent.h"
+#include "t_agent_eventhandler.h"
+#include "t_debug_logging.h"
+
+const TVersion securityServerVersion(0,1,1);
+
+/**
+ * First phase constructor
+ */
+CMultiAgent* CMultiAgent::NewL()
+	{
+	CMultiAgent* self = new(ELeave) CMultiAgent();
+	self->ConstructL();
+	return self;
+	}
+
+/**
+  * Destructor
+  */
+CMultiAgent::~CMultiAgent()
+	{
+	LOG_MSG("~CMultiTargetAgent\n");
+	iServSession.Close();
+	}
+
+/**
+ * Constructor
+ */
+CMultiAgent::CMultiAgent() 
+	{
+	}
+
+/**
+ * Second phase constructor
+ */
+void CMultiAgent::ConstructL()
+	{
+	}
+
+/**
+  Parse the command line, set agent cpu affinity and call main test function
+  */
+void CMultiAgent::ClientAppL()
+	{
+	LOG_MSG("ENTER: CMultiTargetAgent::ClientAppL"); 
+
+	iNumApps = KNumApps;
+	iAgentCpuNo = KAgentCpu;
+	iTargetNameOffset = KTargetOffset;
+
+	TInt argc = User::CommandLineLength();
+	HBufC* commandLine = NULL;
+	LOG_MSG2(">Launcher Process() argc=%d", argc);
+	
+	if(argc)
+		{
+		commandLine = HBufC::NewLC(argc);
+		TPtr commandLineBuffer = commandLine->Des();
+		User::CommandLine(commandLineBuffer);
+
+		RBuf printCommandLine;
+		CleanupClosePushL(printCommandLine);
+		printCommandLine.CreateL(commandLine->Des().Length());
+		printCommandLine.Copy(commandLine->Des());
+		printCommandLine.Collapse();
+		LOG_MSG2(">command line = %S", &printCommandLine );
+		CleanupStack::PopAndDestroy( &printCommandLine );
+
+		// create a lexer and read through the command line
+		TLex lex(*commandLine);
+	
+		while (!lex.Eos())
+		{
+			// only look for options with first character '-'
+			if (lex.Get() == '-')
+			{
+			TChar arg = lex.Get();
+			
+				switch ( arg )
+				{
+				case 'n':
+					lex.Val( iNumApps );
+					LOG_MSG2("parsed numApps as %d", iNumApps); 
+					break;
+		
+				case 'a':
+					lex.Val( iAgentCpuNo );
+					LOG_MSG2("parsed agentCpuNo as %d", iAgentCpuNo);                        
+					break;
+
+				case 'o':
+					lex.Val( iTargetNameOffset );
+					LOG_MSG2("parsed iTargetNameOffset as %d", iTargetNameOffset);        
+					break;
+
+				default:
+					LOG_MSG("Bad argument from user"); 
+					break;                 
+				}
+			}
+		}
+	}
+	// Create active scheduler (to run active objects)
+	CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
+	CleanupStack::PushL(scheduler);
+	CActiveScheduler::Install(scheduler);
+	
+	if (iAgentCpuNo)
+		{
+		LOG_MSG2("CMultiAgent::ClientAppL() - setting agent to cpu %d", iAgentCpuNo);
+		UserSvr::HalFunction(EHalGroupKernel, EKernelHalLockThreadToCpu, (TAny *)iAgentCpuNo, 0);
+		}
+
+	TInt err = iServSession.Connect(securityServerVersion);
+	
+	if (err != KErrNone)
+		{
+		User::Panic(_L("Can't open server session"), err);
+		}
+
+	StartTest();
+
+	// Note: below is a workaround to overcome an issue with RTest server crashing 
+	// when writing to the windows console from different agents (on different CPUs 
+	// at the same time). To overcome this we signal the launcher using a global 
+	// semaphore to indicate a RTest complete instead
+	RSemaphore launchSemaphore;
+	CleanupClosePushL(launchSemaphore);
+            
+	TFindSemaphore launchSemFinder(KLaunchSemaphoreSearchString);
+	TFullName semaphoreResult;
+	TInt ret = launchSemFinder.Next(semaphoreResult);
+	LOG_MSG3( "> Find Launch Semaphote.Next ret=%d, %lS", ret, &semaphoreResult);
+         
+	ret = launchSemaphore.OpenGlobal(semaphoreResult);
+	LOG_MSG2( ">OpenGlobal semaphore ret=%d", ret );         
+    
+	LOG_MSG( ">Signalling semaphore" );
+	launchSemaphore.Signal();
+	CleanupStack::PopAndDestroy(&launchSemaphore); // launchSemaphore
+
+	// Delete active scheduler
+	CleanupStack::PopAndDestroy(scheduler);
+
+	if (commandLine)
+	CleanupStack::PopAndDestroy(commandLine);
+	
+	LOG_MSG( "EXIT: CMultiTargetAgent::ClientAppL"); 
+	}
+
+/**
+  Launch a process
+  @param aProcess the RProcess object used to create the process
+  @param aFileName file name of the executable used to create the process
+  @return KErrNone on success, or one of the other system wide error codes
+  */
+TInt CMultiAgent::LaunchProcess(RProcess& aProcess, const TDesC& aExeName, const TDesC& aCommandLine)    
+	{
+	LOG_MSG( "ENTER: CMultiAgent::LaunchProcess");
+    LOG_MSG2("%S", &TPtr8((TUint8*)aExeName.Ptr(), 2*aExeName.Length(), 2*aExeName.Length()));	
+	
+	// wait for 0.5 seconds due to issue with creating several processes in smp quickly
+	User::After(500000);
+	
+	TInt err = aProcess.Create( aExeName, aCommandLine );
+	LOG_MSG2( "CMultiAgent::LaunchProcess, aProcess.Create err = %d", err); 
+
+	// check that there was no error raised
+	if (err != KErrNone)
+		return err;
+	
+	// rendezvous with process
+	TRequestStatus status = KRequestPending;
+	aProcess.Rendezvous(status);
+
+	if (KRequestPending != status.Int())
+		{
+		// startup failed so kill the process
+		LOG_MSG2( "> RProcess Rendezvous() failed with %d. Killing process", status.Int() );
+		aProcess.Kill(KErrNone);
+		LOG_MSG( "EXIT: CMultiAgent::LaunchProcess");
+		return status.Int();
+		}
+	else
+		{
+		// start the test target
+		aProcess.Resume();
+		User::WaitForRequest(status);
+	
+		LOG_MSG2( "> CMultiAgent::LaunchProcess: RProcess Resume() Rendezvous successful %d: ", status.Int() );
+
+		if(KErrNone != status.Int())
+			{
+			LOG_MSG2( "> RProcess Resume() failed with %d. Killing process", status.Int() );
+			aProcess.Kill(KErrNone);
+			}
+
+		LOG_MSG( "EXIT: CMultiAgent::LaunchProcess");
+		return status.Int();
+		}
+	}
+
+/**
+  Handle Event
+  @param aEventInfo object containing event information from the DSS 
+  */
+void CMultiAgent::HandleEvent(TEventInfo& aEventInfo)
+	{
+	LOG_MSG( "ENTER: CMultiAgent::HandleEvent" ); 
+	TInt ret = KErrNone;
+	const TInt idValid = 1;
+	
+	switch ( aEventInfo.iEventType )
+		{
+		case EEventsAddProcess:
+			{
+			LOG_MSG(">> EEventsAddProcess");                        
+			TPtrC8 exeNamePtr8(aEventInfo.iAddProcessInfo.iFileName, aEventInfo.iAddProcessInfo.iFileNameLength);
+	
+			RBuf8 exeName8;
+			CleanupClosePushL(exeName8);
+			exeName8.CreateL(exeNamePtr8);
+			LOG_MSG2("From event: exeName8=%S", &exeName8);
+			CleanupStack::PopAndDestroy(&exeName8);
+			LOG_MSG("Testing if event process id is valid");
+
+			LOG_MSG2("Got aEventInfo.iProcessId=%d", I64LOW( aEventInfo.iProcessId));
+			__ASSERT_ALWAYS((aEventInfo.iProcessIdValid==idValid), User::Panic(_L("ProcessId Invalid"), aEventInfo.iProcessIdValid));
+	
+			RProcess targetProc;
+			ret = targetProc.Open(TProcessId(aEventInfo.iProcessId));
+			LOG_MSG2("RProcess open ret=%d", ret);
+			targetProc.Close();
+
+			__ASSERT_ALWAYS((ret == KErrNone), User::Panic(_L("ProcessId Invalid"), aEventInfo.iProcessIdValid));
+			break;
+			}
+	
+		case EEventsStartThread:
+			{
+			LOG_MSG(">> EEventsStartThread");                
+			TPtrC8 exeNamePtr8(aEventInfo.iStartThreadInfo.iFileName, aEventInfo.iStartThreadInfo.iFileNameLength);
+			RBuf8 exe8Name;
+			CleanupClosePushL(exe8Name);
+			exe8Name.CreateL(exeNamePtr8);
+			LOG_MSG2("From event: exeName8=%S", &exe8Name);
+			CleanupStack::PopAndDestroy(&exe8Name);
+	
+			LOG_MSG("Testing if event process id is valid" );
+
+			__ASSERT_ALWAYS((aEventInfo.iProcessIdValid==idValid), User::Panic(_L("ProcessId Invalid"), aEventInfo.iProcessIdValid));
+
+			LOG_MSG2("Got aEventInfo.iProcessId=%d", I64LOW(aEventInfo.iProcessId));
+
+			LOG_MSG("Testing if event thread id is valid");
+
+			__ASSERT_ALWAYS((aEventInfo.iThreadIdValid==idValid), User::Panic(_L("ThreadId Invalid"), aEventInfo.iThreadIdValid));
+
+			LOG_MSG2("Got aEventInfo.iThreadId=%d", I64LOW(aEventInfo.iThreadId));
+			break;                    
+			}                       
+
+		case EEventsUserTrace:
+			{
+			LOG_MSG(">> EEventsUserTrace");  
+			break;
+			}
+
+		case EEventsRemoveProcess:
+			{
+			LOG_MSG( ">> EEventsRemoveProcess");                        
+			iLaunchCompleted++; 
+			break;
+			}
+	
+		default:   
+			{
+			LOG_MSG( ">> Unknown event - probably due to DSS busy?");
+			break;
+			}	
+		}
+ 	 
+	LOG_MSG("EXIT: CMultiAgent::HandleEvent"); 
+	}
+
+/**
+ * Main test function which launches several targets and stresses the DSS 
+ */
+TInt CMultiAgent::StartTest()
+	{
+	LOG_MSG("ENTER: CMultiTargetAgent::StartTest");
+
+	for( TInt i = 0; i < iNumApps; i++ )
+		{
+		RBuf targetName;
+		RBuf launcherOptions;
+
+		CleanupClosePushL(targetName); 
+		CleanupClosePushL(launcherOptions); 
+
+		targetName.CreateL( KTargetExe().Length() + 2 );
+		targetName.Format( KTargetExe(), i + iTargetNameOffset + 1 );
+
+		LOG_MSG2("App %d: ", i+1);
+		LOG_MSG2("%S", &TPtr8((TUint8*)targetName.Ptr(), 2*targetName.Length(), 2*targetName.Length()));	
+
+		launcherOptions.CreateL( KTargetOptions().Length() + 2 );
+		launcherOptions.Format( KTargetOptions(), (TUint)ENormalExit, (i+1) );
+
+		LOG_MSG( "AppOptions : ");
+		LOG_MSG2("%S", &TPtr8((TUint8*)launcherOptions.Ptr(), 2*launcherOptions.Length(), 2*launcherOptions.Length()));	
+		
+		// Add each test target to array
+		iTargetList.AppendL(CAgentAsyncEvent::NewL(*this, targetName, launcherOptions));
+		CleanupStack::PopAndDestroy(2, &targetName );
+		}
+	
+	iLaunchCompleted = 0;
+	TInt err = KErrNone;
+		
+	for (TInt i = 0; i < iNumApps; i++)
+		{
+		// Attach to process non-passively
+		LOG_MSG2( ">AttachExecutable app %d ", i + iTargetNameOffset + 1 );
+		LOG_MSG2("%S", &TPtr8((TUint8*)iTargetList[i]->GetExecutable().Ptr(), 2*iTargetList[i]->GetExecutable().Length(), 
+					2*iTargetList[i]->GetExecutable().Length()));
+
+		err = iServSession.AttachExecutable( iTargetList[i]->GetExecutable(), EFalse);
+		__ASSERT_ALWAYS((err == KErrNone), User::Panic(_L("DSS Attach failed"), err));
+
+		// Continue on interested event actions
+		LOG_MSG2( ">SetEventAction app %d,  EEventsStartThread EAcionContinue", i + iTargetNameOffset + 1);
+
+		err = iServSession.SetEventAction( iTargetList[i]->GetExecutable(), EEventsStartThread, EActionContinue);
+		__ASSERT_ALWAYS((err==KErrNone), User::Panic(_L("SetEventAction Error"), err));
+	
+		LOG_MSG2(">SetEventAction app %d,  EEventsAddProcess EActionContinue", i + iTargetNameOffset + 1);
+		err = iServSession.SetEventAction( iTargetList[i]->GetExecutable(), EEventsAddProcess, EActionContinue);
+		__ASSERT_ALWAYS((err==KErrNone), User::Panic(_L("SetEventAction Error"), err));
+
+		LOG_MSG2(">SetEventAction app %d,  EEventsUserTrace EActionContinue", i + iTargetNameOffset + 1);
+		err = iServSession.SetEventAction( iTargetList[i]->GetExecutable(), EEventsUserTrace, EActionContinue);
+		__ASSERT_ALWAYS((err==KErrNone), User::Panic(_L("SetEventAction Error"), err));
+	
+		LOG_MSG2(">SetEventAction app %d,  EEventsRemoveProcess EActionContinue", i + iTargetNameOffset + 1);
+		err = iServSession.SetEventAction( iTargetList[i]->GetExecutable(), EEventsRemoveProcess, EActionContinue);
+		__ASSERT_ALWAYS((err==KErrNone), User::Panic(_L("SetEventAction Error"), err));
+
+		// Add target object to active schedular
+		iTargetList[i]->Watch();
+		}
+
+	for (TInt i= 0; i< iNumApps; i++)
+		{
+		LOG_MSG( ">Calling LaunchProcess function");
+		err = LaunchProcess(iTargetList[i]->GetProcHandle(), iTargetList[i]->GetExecutable(), iTargetList[i]->GetExeConfig());
+		__ASSERT_ALWAYS((err==KErrNone), User::Panic(_L("LaunchProcess failed"), err));
+		}
+
+	LOG_MSG( ">CActiveScheduler::Start()");
+	CActiveScheduler::Start();
+
+	for (TInt i= 0; i < iNumApps; i++)
+		{
+		// Now detach again
+		LOG_MSG( "Before iServSession.DetachExecutable" );
+		err = iServSession.DetachExecutable(iTargetList[i]->GetExecutable());
+		__ASSERT_ALWAYS((err==KErrNone), User::Panic(_L("DetachExecutable failed"), err));
+		}
+	
+	// Free all the memory
+	iTargetList.ResetAndDestroy();
+	LOG_MSG( "EXIT: CMultiTargetAgent::StartTest" );
+
+	return KErrNone;
+	}
+
+/**
+  * Entry point for run mode debug driver test
+  */
+GLDEF_C TInt E32Main()
+	{
+	LOG_MSG( "ENTER: Multi_agent E32Main ");
+	__UHEAP_MARK;
+
+	TInt ret = KErrNone;
+	RProcess::Rendezvous(KErrNone);
+	
+	CTrapCleanup* trap = CTrapCleanup::New();
+		
+	if (!trap)
+		return KErrNoMemory;
+	
+	CMultiAgent *runModeAgent = CMultiAgent::NewL();
+
+	if (runModeAgent != NULL)
+		{
+		TRAP(ret,runModeAgent->ClientAppL());
+		LOG_MSG2( "ClientAppL returned %d", ret );
+		delete runModeAgent;
+		}
+
+	delete trap;
+	__UHEAP_MARKEND;
+	LOG_MSG( "EXIT: Multi_agent E32Main ");
+	return ret;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/multi_agent_tests/t_multi_agent.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,110 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Definitions for the run mode debug tests
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef RMDEBUG_MULTI_AGENT_H
+#define RMDEBUG_MULTI_AGENT_H
+
+#include <u32hal.h>
+#include <f32file.h>
+#include <rm_debug_api.h>
+
+using namespace Debug;
+
+_LIT(KLaunchSemaphoreName, "t_rmdebug_launch_semaphore");
+_LIT(KLaunchSemaphoreSearchString, "t_rmdebug_launch_semaphore*");
+
+// Currently the targets are instances of t_rmdebug_app.exe
+_LIT(KTargetExe,"z:\\sys\\bin\\t_rmdebug_app%d.exe");
+
+_LIT(KTargetOptions,"-f%d -a%d");
+
+// If changing this, make sure there are enough apps built/in the rom 
+const TInt KNumApps = 5;
+
+// Default CPU execution for Agent
+const TInt KAgentCpu = 0;
+
+// Workaround to ensure we have the same agent binary when running multiple agents
+const TInt KTargetOffset = 0;
+
+class CAgentAsyncEvent;
+
+/**
+  @Class CRunModeAgent
+  
+  The basic run mode agent
+  */
+class CMultiAgent : public CBase
+	{
+	public:
+	static CMultiAgent* NewL();
+	~CMultiAgent();
+	void ClientAppL();  
+	RSecuritySvrSession&  DebugDriver() { return iServSession; };	
+	void HandleEvent(TEventInfo& aSEventInfo);
+
+	public:
+	TInt GetLaunchCompleted() const { return iLaunchCompleted; }
+	TInt GetNumApps() const { return iNumApps; }
+	TInt GetTargetOffset() const { return iTargetNameOffset; }
+
+	private:
+	CMultiAgent();
+	void ConstructL();
+	TInt StartTest();
+	TInt LaunchProcess(RProcess& aProcess, const TDesC& aExeName, const TDesC& aCommandLine);
+	
+	private:
+
+	/**
+	 * CPU agent executes on; by default this is 0 
+	 */
+	TInt iAgentCpuNo;
+
+	/*
+	 * Offset for running multiple targets using the same agent
+	 */
+	TInt iTargetNameOffset;
+
+	/** 
+	 * Number of applications/targets per agent
+	 */
+	TInt iNumApps;
+
+	/**
+	 * Flag used for terminating the event handling for a target 
+	 */	
+	TInt iLaunchCompleted;
+
+	/*
+	 * Handle to DSS
+	 */
+	RSecuritySvrSession iServSession;
+	
+	/**
+	 * Array to target parameters required by the agent
+	 */	
+	RPointerArray<CAgentAsyncEvent> iTargetList;
+	};
+
+#endif // RMDEBUG_MULTI_AGENT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/multi_agent_tests/t_multi_agent_launcher.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,229 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Helper app to launch debug targets
+//
+//
+
+#include "t_multi_agent_launcher.h"
+
+#include "t_debug_logging.h"
+
+/**
+ * Launch a process
+ * @param aProcess the RProcess object used for creating the process
+ * @param aExeName the name of the executable to run 
+ * @param aCommandLine command line parameters to pass when creating the process 
+ * @return KErrNone on success, or one of the other system wide error codes
+ */
+TInt LaunchProcess(RProcess& aProcess, TDesC& aExeName, TDesC& aCommandLine )    
+	{
+	LOG_MSG("ENTER: t_multi_agent_launcher: launchProcess"); 
+
+	LOG_MSG2("aExeName %S ", &TPtr8((TUint8*)aExeName.Ptr(), 2*aExeName.Length(), 2*aExeName.Length()));
+	LOG_MSG2("aCommandLine %S", &TPtr8((TUint8*)aCommandLine.Ptr(), 2*aCommandLine.Length(), 2*aCommandLine.Length()));
+
+	TInt err = aProcess.Create( aExeName, aCommandLine );
+	LOG_MSG2("t_multi_agent_launcher launchProcess, aProcess.Create err = %d", err); 
+
+	// check that there was no error raised
+	if(err != KErrNone)
+		{
+		return err;
+		}
+
+	// rendezvous with process
+	TRequestStatus status = KRequestPending;
+	aProcess.Rendezvous(status);
+
+	if(KRequestPending != status.Int())
+		{
+		// startup failed so kill the process
+		LOG_MSG2("t_multi_agent_launcher: launchProcess: RProcess Rendezvous() failed with %d. Killing process", status.Int());
+		aProcess.Kill(KErrNone);
+		return status.Int();
+		}
+	else
+		{
+		aProcess.Resume();
+		User::WaitForRequest(status);
+
+		LOG_MSG2("t_multi_agent_launcher: launchProcess: RProcess Resume() Rendezvous successful %d: ", status.Int());
+
+		if(KErrNone != status.Int())
+			{
+			LOG_MSG2("t_multi_agent_launcher: RProcess Resume() failed with %d. Killing process", status.Int());
+			aProcess.Kill(KErrNone);
+			}
+
+		LOG_MSG("EXIT: t_multi_agent_launcher launchProcess");
+		return status.Int();
+		}
+	}
+
+/**
+ * Read command line parameters and control the launching of the agents. 
+ */
+void MainL()
+	{	
+	LOG_MSG( "ENTER: t_multi_agent_launcher MainL()");
+
+	TInt ret = KErrNone;
+	TInt numAgents = KNumAgents;
+	TInt numTargets = KNumTargets;
+	TInt numTestRuns = KNumTestRuns;
+
+	TInt argc = User::CommandLineLength();
+	HBufC* commandLine = NULL;
+	LOG_MSG2("t_multi_agent_launcher: MainL(): argc=%d", argc);
+    
+	if(argc)
+		{
+		commandLine = HBufC::NewLC(argc);
+		TPtr commandLineBuffer = commandLine->Des();
+		User::CommandLine(commandLineBuffer);
+
+		RBuf printCommandLine;
+		CleanupClosePushL( printCommandLine );
+		printCommandLine.CreateL( commandLine->Des().Length() );
+		printCommandLine.Copy( commandLine->Des() );
+		printCommandLine.Collapse();
+		LOG_MSG2("t_multi_agent_launcher: command line = %S", &printCommandLine);
+		CleanupStack::PopAndDestroy( &printCommandLine );
+ 
+		// create a lexer and read through the command line
+		TLex lex(*commandLine);
+		while (!lex.Eos())
+			{
+			// only look for options with first character '-'
+			if (lex.Get() == '-')
+				{
+					TChar arg = lex.Get();
+					switch ( arg )
+						{
+						case 'n':
+							lex.Val( numAgents );
+							LOG_MSG2("t_multi_agent_launcher: parsed numAgents as %d", numAgents);
+							break;
+						case 'm':
+							lex.Val( numTargets );
+							LOG_MSG2("t_multi_agent_launcher: parsed numTargets as %d", numTargets);                        
+							break;  
+						case 't':
+							lex.Val( numTestRuns );
+							LOG_MSG2("t_multi_agent_launcher: parsed numTestRuns as %d", numTestRuns);                        
+							break;                    
+						default:
+							LOG_MSG("t_multi_agent_launcher: unknown argument ignoring it");
+							break;                 
+						}
+				}
+			}
+		}
+
+	// Note: below is a workaround to overcome an issue with RTest server crashing 
+	// when writing to the windows console from different agents (on different CPUs 
+	// at the same time). To overcome this we get signaled by the agents when they have 
+	// completed their tests so that we can do a RTest complete
+	RSemaphore launchSemaphore;
+	CleanupClosePushL(launchSemaphore);
+	ret = launchSemaphore.CreateGlobal(KLaunchSemaphoreName, 0);
+	LOG_MSG2( ">Target Launcher : RSemaphore.CreateGlobal ret %d", ret);
+	User::LeaveIfError( ret );
+
+	ret = launchSemaphore.OpenGlobal(KLaunchSemaphoreName);
+	LOG_MSG2( ">Target Launcher : RSemaphore.OpenGlobal ret %d", ret);
+	User::LeaveIfError( ret );
+
+	//Now launch the requested number of apps for the requested number of test runs
+	for( TInt j = 0; j < numTestRuns; j++ )
+		{ 
+			for( TInt i = 0; i < numAgents; i++ )  
+				{
+					RBuf targetName;
+					targetName.CleanupClosePushL();
+					targetName.CreateL(KAgentExe());
+
+					RProcess aProc;
+					CleanupClosePushL(aProc); 
+					RBuf launcherOptions;
+					CleanupClosePushL(launcherOptions);
+				    const TInt additionalWords = 2;	
+					launcherOptions.CreateL( KAgentOptions().Length() + additionalWords );
+		
+					// Apply offset: launcherOptions.Format( .., .., i * numTargets, ..)
+					// workaround to ensure we have the same binary for multiple agents. 
+					// e.g. So if offset = 0, agent attaches to app1, app2, app3, app4, app5
+					// if offset = 5, agent attached to app6, app7, app8, app9, app10 etc.
+					// Note: apps need to be in rom otherwise the agent will fail on an assert 
+					// (with KErrNotFound)
+					launcherOptions.Format( KAgentOptions(), (TUint)numTargets, i * numTargets, 0);
+			
+					ret = LaunchProcess( aProc, targetName, launcherOptions );	
+					CleanupStack::PopAndDestroy(3,&targetName);
+					User::LeaveIfError(ret);
+				}
+		}
+
+	// Wait for all agents to do their testing before checking the semaphore
+	User::After(12000000);
+
+	LOG_MSG( ">Target Launcher:  Semaphore wait");
+
+	for (TInt i = 0; i < numAgents; i ++)
+		{
+		//We need this delay just in case an agent crashes and never signals the sem
+		ret = launchSemaphore.Wait(100000);
+		if( ret != KErrNone )
+			{
+			LOG_MSG3("launchSemaphore.Wait ret %d for agent %d", ret, i);
+			break;
+			}
+		}
+
+	LOG_MSG2( "testing for Semaphore ret %d", ret);
+
+	// We only want to have one RTest instance at any one time since otherwise RTest can panic
+	RTest test(_L("T_MULTI_AGENT_LAUNCHER"));
+	test.Start(_L("t_multi_agent_launcher Check for agents finishing correctly"));
+	test(ret == KErrNone);
+	test.End();
+	test.Close();
+
+	CleanupStack::PopAndDestroy(&launchSemaphore); // launchSemaphore
+
+	if( commandLine )
+	CleanupStack::PopAndDestroy(commandLine);
+	
+	LOG_MSG("EXIT: t_multi_agent_launcher MainL()");
+	}
+ 
+GLDEF_C TInt E32Main()
+	{
+	LOG_MSG("ENTER: Multi_agent_launcher E32Main()");
+	__UHEAP_MARK;
+
+	CTrapCleanup* trap = CTrapCleanup::New();
+	if (!trap)
+		return KErrNoMemory;
+
+	TRAPD(err, MainL());
+	LOG_MSG2("Multi_agent_launcher: returning from MainL(), err = %d", err);
+	
+	delete trap;
+	LOG_MSG("EXIT: Multi_agent_launcher E32Main()");
+	__UHEAP_MARKEND;
+
+	return err;
+	}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/multi_agent_tests/t_multi_agent_launcher.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,45 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Definitions for agent launcher
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef RMDEBUG_MULTI_AGENT_LAUNCHER_H
+#define RMDEBUG_MULTI_AGENT_LAUNCHER_H
+
+#include <e32test.h>
+
+// Default test runs
+const TInt KNumTestRuns = 1; 
+
+// Default number of targets per agent
+const TInt KNumTargets = 5;
+
+// Default number of agents, if changing this make sure there are enough apps being built 
+const TInt KNumAgents = 2; 
+
+_LIT(KAgentExe,"z:\\sys\\bin\\t_rmdebug_multi_agent.exe");
+_LIT(KAgentOptions,"-n%d -o%d -a%d");
+
+_LIT(KLaunchSemaphoreName, "t_rmdebug_launch_semaphore");
+_LIT(KLaunchSemaphoreSearchString, "t_rmdebug_launch_semaphore*");
+
+#endif // RMDEBUG_MULTI_AGENT_LAUNCHER_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/multi_target_tests/t_multi_target.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,402 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Test the ability of the debug system to handle events from several debug targets
+//
+//
+
+#include <e32base.h>
+#include <e32property.h>
+
+#include <hal.h>
+#include <e32test.h>
+
+#include "t_multi_target.h"
+#include "t_target_launcher.h"
+#include "t_rmdebug_app.h"
+
+#ifdef KERNEL_OOM_TESTING
+  #ifdef USER_OOM_TESTING
+    #error "Cannot define both KERNEL_OOM_TESTING and USER_OOM_TESTING"
+  #endif
+#endif
+
+
+using namespace Debug;
+
+const TVersion securityServerVersion(0,1,1);
+
+const TVersion testVersion(2,1,0);
+
+#ifdef SYMBIAN_STANDARDDEBUG
+LOCAL_D RTest test(_L("T_RMDEBUG_MULTI_TARGET"));
+#endif
+
+#ifdef SYMBIAN_OEMDEBUG
+LOCAL_D RTest test(_L("T_RMDEBUG_MULTI_TARGET_OEM"));
+#endif
+
+#ifdef SYMBIAN_OEM2DEBUG
+LOCAL_D RTest test(_L("T_RMDEBUG_MULTI_TARGET_OEM2"));
+#endif
+
+
+
+CMultiTargetAgent* CMultiTargetAgent::NewL()
+//
+// CMultiTargetAgent::NewL
+//
+  {
+  CMultiTargetAgent* self = new(ELeave) CMultiTargetAgent();
+
+  self->ConstructL();
+
+  return self;
+  }
+
+
+CMultiTargetAgent::~CMultiTargetAgent()
+//
+// CMultiTargetAgent destructor
+//
+    {
+    RDebug::Printf("~CMultiTargetAgent\n");
+    iServSession.Close();
+    }
+
+
+CMultiTargetAgent::CMultiTargetAgent() : 
+    iEventPtr( (TUint8*)&iEventInfo, sizeof(TEventInfo) )
+    {
+    }
+
+
+void CMultiTargetAgent::ConstructL()
+//
+// CMultiTargetAgent::ConstructL
+//
+  {
+  }
+
+/**
+ * Helper code for the stepping tests. Returns the number of nanokernel ticks in one second.
+ *
+ * @return Number of nanokernel ticks. 0 if unsuccesful.
+ */
+TInt CMultiTargetAgent::HelpTicksPerSecond(void)
+  {
+  TInt nanokernel_tick_period;
+  HAL::Get(HAL::ENanoTickPeriod, nanokernel_tick_period);
+
+  ASSERT(nanokernel_tick_period != 0);
+
+  static const TInt KOneMillion = 1000000;
+
+  return KOneMillion/nanokernel_tick_period;
+  }
+
+void CMultiTargetAgent::ClientAppL()
+//
+// Performs each test in turn
+//
+  {
+  TInt err = iServSession.Connect(securityServerVersion);
+  if (err != KErrNone)
+      {
+      User::Panic(_L("Can't open server session"), err);
+      }
+
+  LaunchTargetsInOrderL();
+  RDebug::Printf( "returning from CMultiTargetAgent::ClientAppL" );
+  }
+
+/**
+  Launch a process
+
+  @param aProcess The RProcess object to use to create the process
+  @param aExeName File name of the executable to create the process from
+  @param aCommandLine The command line to pass to the new process
+  @return KErrNone on success, or one of the other system wide error codes
+  */
+TInt CMultiTargetAgent::LaunchProcess(RProcess& aProcess, TDesC & aExeName, TDesC & aCommandLine )
+    {    
+    TInt err = aProcess.Create( aExeName, aCommandLine );    
+    if(err != KErrNone)
+        {
+        RDebug::Printf( "aProcess.Create ret %d", err);
+        return err;
+        }
+
+    TRequestStatus status = KRequestPending;
+    aProcess.Rendezvous(status);
+    if(KRequestPending != status.Int())
+        {
+        // startup failed so kill the process
+        aProcess.Kill(KErrNone);
+        return status.Int();
+        }
+    else
+        {
+        // start up succeeded so resume the process
+        aProcess.Resume();
+        // Give the process a chance to run
+        User::After( 500000 );
+        return KErrNone;
+        }
+    }
+
+void CMultiTargetAgent::SetupDebugServerL()
+    {
+    RDebug::Printf( "CMultiTargetAgent::SetupDebugServerL" );
+
+    iTargets.ReserveL( KNumApps );
+
+    RBuf targetName;
+    CleanupClosePushL( targetName );
+
+    for( TInt numApps = 0; numApps < KNumApps; numApps++ )
+        {
+        iTargets.AppendL( targetName );
+        RDebug::Printf( "Attach to DSS for app %d ", numApps );
+
+        iTargets[numApps].CreateL( KTargetExe().Length() + 2 );
+        iTargets[numApps].Format( KTargetExe(), numApps+1 );
+
+        TInt ret = iServSession.AttachExecutable( iTargets[numApps], EFalse );
+        test( ret == KErrNone );
+
+        RDebug::Printf( ">SetEventAction app %d,  EEventsStartThread EActionSuspend", numApps );
+        ret = iServSession.SetEventAction( iTargets[numApps], EEventsStartThread, EActionSuspend );
+        test( ret == KErrNone );
+
+        RDebug::Printf( ">SetEventAction app %d,  EEventsAddProcess EActionContinue", numApps );
+        ret = iServSession.SetEventAction( iTargets[numApps], EEventsAddProcess, EActionContinue );
+        test( ret == KErrNone );
+
+        RDebug::Printf( ">SetEventAction app %d,  EEventsRemoveProcess EActionContinue", numApps );
+        ret = iServSession.SetEventAction( iTargets[numApps], EEventsRemoveProcess, EActionContinue );
+        test( ret == KErrNone );
+        }
+
+    CleanupStack::PopAndDestroy( &targetName ); // targetName
+
+    }
+
+
+
+TInt CMultiTargetAgent::LaunchTargetsInOrderL()
+    {
+    RDebug::Printf( "CMultiTargetAgent::LaunchTargetsInOrderL" );
+    
+    RBuf launcher;
+    CleanupClosePushL( launcher );
+    launcher.CreateL( KLauncherExe() );
+    
+    RBuf launcherOptions;
+    CleanupClosePushL( launcherOptions ); 
+    launcherOptions.CreateL( KTargetOptions().Length() + 2 );
+    launcherOptions.Format( KTargetOptions(), (TUint)ENormalExit );
+
+    RDebug::Printf( ">LaunchProcess()" );
+    RProcess launcherProc; 
+    CleanupClosePushL( launcherProc );
+    
+    TInt ret = LaunchProcess( launcherProc, launcher, launcherOptions );
+    RDebug::Printf( "<LaunchProcess() ret %d", ret );
+    
+    CleanupStack::PopAndDestroy( &launcherProc ); // launcherProc
+    CleanupStack::PopAndDestroy( &launcherOptions ); // launcherOptions
+    CleanupStack::PopAndDestroy( &launcher ); //launcher 
+
+    test( ret == KErrNone );
+    
+    RSemaphore launchSemaphore;   
+    CleanupClosePushL( launchSemaphore );
+            
+    TFindSemaphore launchSemFinder( KLaunchMutexNameSearchString );
+    TFullName mutexResult;
+    ret = launchSemFinder.Next(mutexResult);
+    RDebug::Printf( ">  Find Launch Semaphote.Next ret=%d, %lS", ret, &mutexResult );
+    test( ret == KErrNone );   
+     
+    ret = launchSemaphore.OpenGlobal( mutexResult );
+    RDebug::Printf( "> OpenGlobal mutex ret=%d", ret );         
+    test( ret == KErrNone );    
+    
+    TBool thisLaunchCompleted; 
+
+    SetupDebugServerL();
+   
+    for( TInt numLaunches = KNumLaunches; numLaunches > 0; numLaunches-- )
+        {
+        for( TInt numApps = KNumApps; numApps > 0; numApps-- )
+            {
+            thisLaunchCompleted = EFalse;
+            // This will trigger the launcher app to launch the next target
+            RDebug::Printf( " >Mutex.Signal app=%d, launch=%d", numApps, numLaunches);
+            launchSemaphore.Signal();
+            
+            RBuf8 tgt8Name; 
+            CleanupClosePushL( tgt8Name );
+           
+            RBuf tgtCollapseName;
+            CleanupClosePushL( tgtCollapseName );
+                    
+            tgtCollapseName.CreateL( iTargets[numApps-1] );
+            tgt8Name.CreateL( tgtCollapseName.Collapse() );
+            
+
+            while( ! thisLaunchCompleted )
+                {
+                RDebug::Printf( ">GetEvent app %d for %S", numApps, &tgt8Name );
+                iServSession.GetEvent( iTargets[numApps-1], iStatus, iEventPtr );
+          
+                // Wait for the target to get started.
+                RDebug::Printf( " >Wait for event from target app=%d, launch=%d\n", numApps, numLaunches);
+                User::WaitForRequest( iStatus );
+                RDebug::Printf( " <Wait for request returned with status %d", iStatus.Int() );
+                test( iStatus==KErrNone );
+    
+                RDebug::Printf( " > Got iEventType =%d, app=%d", iEventInfo.iEventType, numApps );
+                switch( iEventInfo.iEventType )
+                    {
+                    case EEventsAddProcess:
+                        {
+                        RDebug::Printf( "Got EEventsAddProcess" );                        
+                        TPtrC8 exeNamePtr8( iEventInfo.iAddProcessInfo.iFileName, iEventInfo.iAddProcessInfo.iFileNameLength );
+                        
+                        RBuf8 exeName8;
+                        CleanupClosePushL( exeName8 );
+                        exeName8.CreateL( exeNamePtr8 );
+                        RDebug::Printf( " from event: exeName8=%S", &exeName8 );
+                        CleanupStack::PopAndDestroy( &exeName8 );
+                        
+                        RBuf8 compareName8;
+                        CleanupClosePushL( compareName8 );
+                        compareName8.CreateL( KTargetExeName().Length() + 10 );
+                        compareName8.Format( KTargetExeName(), numApps );
+                        RDebug::Printf( " comparing to: compareName8=%S", &compareName8 );
+                        
+                        test( compareName8.CompareC( exeNamePtr8 ) == 0 );
+                        CleanupStack::PopAndDestroy( &compareName8 );
+
+                        RDebug::Printf( "Testing if event process id is valid" );
+                        test( iEventInfo.iProcessIdValid );
+                        RDebug::Printf( "Got iEventInfo.iProcessId=%d", I64LOW( iEventInfo.iProcessId ) );
+                        
+                        RProcess targetProc;
+                        ret = targetProc.Open( TProcessId( iEventInfo.iProcessId ) );
+                        RDebug::Printf( "RProcess open ret=%d",ret );
+                        targetProc.Close();
+                        test( ret == KErrNone );
+                        
+                        break;
+                        }//EEventsAddProcess
+                        
+                    case EEventsStartThread:
+                        {
+                        RDebug::Printf( "Got EEventsStartThread" );
+                         
+                        TPtrC8 exeNamePtr8( iEventInfo.iStartThreadInfo.iFileName, iEventInfo.iStartThreadInfo.iFileNameLength );
+                        RBuf8 exe8Name;
+                        CleanupClosePushL( exe8Name );
+                        exe8Name.CreateL( exeNamePtr8 );
+                        RDebug::Printf( " from event: exeName8=%S", &exe8Name );
+                        CleanupStack::PopAndDestroy( &exe8Name );
+                        
+                        test( tgt8Name.CompareC( exeNamePtr8 ) == 0 );
+                        
+                        RDebug::Printf( "Testing if event process id is valid" );
+                        test( iEventInfo.iProcessIdValid );
+                        RDebug::Printf( "Got iEventInfo.iProcessId=%d", I64LOW( iEventInfo.iProcessId ) );
+                         
+                        RDebug::Printf( "Testing if event thread id is valid" );
+                        test( iEventInfo.iThreadIdValid );
+                        RDebug::Printf( "Got iEventInfo.iThreadId=%d", I64LOW( iEventInfo.iThreadId ) );
+                        
+                        RThread targetThread;
+                        CleanupClosePushL( targetThread );
+                        
+                        ret = targetThread.Open( TThreadId( iEventInfo.iThreadId ) );
+                        RDebug::Printf( "RThread open ret=%d", ret );
+                        test( ret == KErrNone ); 
+                         
+                        test( iEventInfo.iThreadId == targetThread.Id() );  
+
+                        RDebug::Printf( "Resuming thread for app=%d, id=%d", numApps, I64LOW( targetThread.Id() ));
+                        ret = iServSession.ResumeThread( iEventInfo.iThreadId );
+                        CleanupStack::PopAndDestroy( &targetThread );
+                        
+                        test( ret == KErrNone );
+                        
+                        ret = iServSession.ResumeThread( iEventInfo.iThreadId );
+                        break;                    
+                        }//case EEventsStartThread                        
+
+                    case ( EEventsRemoveProcess ):
+                        {
+                        RDebug::Printf( "*** Got EEventsRemoveProcess. app%d has exited. Moving on to next app", numApps );                        
+                        thisLaunchCompleted = ETrue;
+                        break;
+                        }
+                        
+                    default :   
+                        RDebug::Printf( "Got unknown event" );
+                        test( EFalse );
+                        break;
+                    }
+                }//while
+
+            CleanupStack::PopAndDestroy( &tgtCollapseName ); // tgtCollapseName
+            CleanupStack::PopAndDestroy( &tgt8Name ); // tgt8Name 
+            }
+        }    
+
+        CleanupStack::PopAndDestroy( &launchSemaphore ); // launchSemaphore
+      
+        for( TInt i = iTargets.Count()-1; i>=0; i-- )
+            {
+            RDebug::Printf( "Closing target %d", i );
+            iTargets[ i ].Close();
+            }
+
+        iTargets.Close();
+        
+        return KErrNone;
+    }
+
+
+GLDEF_C TInt E32Main()
+    {
+    TInt ret = KErrNone;
+   
+  
+    CTrapCleanup* trap = CTrapCleanup::New();
+    if (!trap)
+      return KErrNoMemory;
+    test.Title();
+   
+    CMultiTargetAgent *runModeAgent = CMultiTargetAgent::NewL();
+    if (runModeAgent != NULL)
+        {
+        __UHEAP_MARK;
+        TRAP(ret,runModeAgent->ClientAppL());
+        __UHEAP_MARKEND;
+        
+        RDebug::Printf( "ClientAppL returned %d", ret );
+        delete runModeAgent;
+        }
+
+    delete trap;
+    return ret;
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/multi_target_tests/t_multi_target.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,93 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Definitions for the run mode debug tests
+// 
+//
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#ifndef RMDEBUG_MULTI_TARGET_H
+#define RMDEBUG_MULTI_TARGET_H
+
+#include "t_rmdebug_app.h"
+
+#include <rm_debug_api.h>
+
+class CMultiTargetAgent;
+
+//
+// class CRunModeAgent
+//
+// The basic run mode agent.
+//
+class CMultiTargetAgent : public CBase
+	{
+public:
+	static CMultiTargetAgent* NewL();
+	~CMultiTargetAgent();
+	void ClientAppL();
+	
+    TInt LaunchProcess(RProcess& aProcess, TDesC & aExeName, TDesC & aCommandLine );
+    
+private:
+	CMultiTargetAgent();
+	void ConstructL();
+
+	void ReportPerformance(void);
+
+	TInt HelpTicksPerSecond(void);
+
+	enum TTestMode 
+		{
+		//run all the tests
+		EModeAll = 1<<0,
+		//run the specified tests in reverse order
+		EModeReverse = 1<<1,
+		//print out help
+		EModeHelp = 1<<2,
+		//print out help
+		EModeVersion = 1<<3
+		};
+	
+	TInt LaunchTargetsInOrderL();
+	void SetupDebugServerL();
+
+private:
+
+#if defined(KERNEL_OOM_TESTING)
+	RKernelLowMemorySecuritySvrSession iServSession;
+#elif defined (USER_OOM_TESTING)
+	RUserLowMemorySecuritySvrSession iServSession;
+#else
+	Debug::RSecuritySvrSession iServSession;
+#endif
+	RSemaphore iAddressGlobSem;
+
+	TUid iMySid;
+
+	// Timing information
+	TInt iStartTick;
+	TInt iStopTick;
+
+	RArray<RBuf> iTargets;
+  TRequestStatus iStatus;
+  Debug::TEventInfo iEventInfo;
+  TPtr8 iEventPtr;
+	};
+
+#endif // RMDEBUG_MULTI_TARGET_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/trk_blocking/t_trkdummyapp.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,532 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Ensure that old insecure Trk debug agent cannot be installed
+// as it should be blocked from SWInstall'ing by a trkdummyapp.exe contained within
+// the base OS with the same SID as the insecure Trk.
+// 
+//
+
+#include <e32base.h>
+#include <e32base_private.h>
+#include <e32cons.h>
+#include <e32test.h>
+#include <e32ldr.h>
+#include <e32cmn.h>
+#include <e32cmn_private.h>
+#include <f32dbg.h>
+#include <f32file.h>
+#include "t_trkdummyapp.h"
+
+LOCAL_D RTest test(_L("T_TRKDUMMYAPP"));
+
+CTrkDummyAppTest::CTrkDummyAppTest()
+//
+// CTrkDummyAppTest constructor
+//
+	{
+	// nothing to do
+	}
+
+CTrkDummyAppTest* CTrkDummyAppTest::NewL()
+//
+// CRunModeAgent::NewL
+//
+	{
+	CTrkDummyAppTest* self = new(ELeave) CTrkDummyAppTest();
+
+  	self->ConstructL();
+
+	return self;
+	}
+
+CTrkDummyAppTest::~CTrkDummyAppTest()
+//
+// CTrkDummyAppTest destructor
+//
+	{
+	// Nothing to do
+	}
+
+void CTrkDummyAppTest::ConstructL()
+//
+// CTrkDummyAppTest::ConstructL
+//
+	{
+	// nothing to do here
+	}
+
+
+CTrkDummyAppTest *TrkDummyTest;
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-TRKDUMMYAPP-0792
+//! @SYMTestType        
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests that a known insecure debug agent trkapp.sis cannot be installed
+//!                     by ensuring the existence of a Symbian OS common app called trkdummyapp.exe
+//!                     already exists with the same Secure ID as the insecure app.
+//! @SYMTestActions     
+//!    
+//!     1.              Calls RProcess.Create() on z:\sys\bin\trkdummyapp.exe. Fail if unsuccessful.
+//!     
+//!     2.              Obtain the Secure ID of the process derived from z:\sys\bin\trkdummyapp.exe.
+//!
+//!     3.              Close the process derived from z:\sys\bin\trkdummyapp.exe.
+//!
+//! @SYMTestExpectedResults 
+//!
+//!     1.              Fails if unable to create a process from z:\sys\bin\trkdummyapp.exe.
+//!
+//!     2.              The Secure ID of trkdummyapp.exe has the Secure ID 0x101F7159. Fail otherwise.
+//! 
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+// Names of some test programs used for testing security
+_LIT(KRMDebugSecurityTrkDummyApp,"z:\\sys\\bin\\trkdummyapp.exe");
+
+void CTrkDummyAppTest::TestSecurityCheckPreventInsecureTrkDebugAgent(void)
+	{
+
+	test.Next(_L("TestSecurityCheckPreventInsecureTrkDebugAgent, SID 0x101F7159\n"));
+
+	RProcess process;
+	TInt err = process.Create(KRMDebugSecurityTrkDummyApp, KNullDesC, EOwnerProcess);
+	test (err == KErrNone);
+
+	// rendezvous with process
+	TRequestStatus status;
+	process.Rendezvous(status);
+
+	// obtain the secure ID for the process
+	TSecurityInfo secInfo(process);
+
+	static const TSecureId KTrkDummyAppSID = 0x101F7159;
+
+	test(secInfo.iSecureId.iId == KTrkDummyAppSID);
+
+	// Kill the process, as we don't need it anymore
+	process.Kill(KErrNone);
+
+	process.Close();
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-TRKDUMMYAPP-0793
+//! @SYMTestType        
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests that a known insecure debug agent trkapp.sis cannot be installed
+//!                     by ensuring the existence of a Symbian OS common app called trkdummyapp.exe
+//!                     already exists with the same Secure ID as the insecure app.
+//! @SYMTestActions     
+//!    
+//!     1.              Calls RProcess.Create() on z:\sys\bin\trkdummyapp2.exe. Fail if unsuccessful.
+//!     
+//!     2.              Obtain the Secure ID of the process derived from z:\sys\bin\trkdummyapp2.exe.
+//!
+//!     3.              Close the process derived from z:\sys\bin\trkdummyapp2.exe.
+//!
+//! @SYMTestExpectedResults 
+//!
+//!     1.              Fails if unable to create a process from z:\sys\bin\trkdummyapp2.exe.
+//!
+//!     2.              The Secure ID of trkdummyapp.exe has the Secure ID 0x2000a7dd. Fail otherwise.
+//! 
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+// Names of some test programs used for testing security
+_LIT(KRMDebugSecurityTrkDummyApp2,"z:\\sys\\bin\\trkdummyapp2.exe");
+
+void CTrkDummyAppTest::TestSecurityCheckPreventInsecureTrkDebugAgent2(void)
+	{
+
+	test.Next(_L("TestSecurityCheckPreventInsecureTrkDebugAgent2, SID 0x2000a7dd\n"));
+
+	RProcess process;
+	TInt err = process.Create(KRMDebugSecurityTrkDummyApp2, KNullDesC, EOwnerProcess);
+	test (err == KErrNone);
+
+	// rendezvous with process
+	TRequestStatus status;
+	process.Rendezvous(status);
+
+	// obtain the secure ID for the process
+	TSecurityInfo secInfo(process);
+
+	static const TSecureId KTrkDummyAppSID2 = 0x2000a7dd;
+
+	test(secInfo.iSecureId.iId == KTrkDummyAppSID2);
+
+	// Kill the process, as we don't need it anymore
+	process.Kill(KErrNone);
+
+	process.Close();
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-TRKDUMMYAPP-2396
+//! @SYMTestType        
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests that a known insecure debug agent trkapp.sis cannot be installed
+//!                     by ensuring the existence of a Symbian OS common app called trkdummyapp200159D8.exe
+//!                     already exists with the same Secure ID as the insecure app.
+//! @SYMTestActions     
+//!    
+//!     1.              Calls RProcess.Create() on z:\sys\bin\trkdummyapp200159D8.exe. Fail if unsuccessful.
+//!     
+//!     2.              Obtain the Secure ID of the process derived from z:\sys\bin\trkdummyapp200159D8.exe.
+//!
+//!     3.              Close the process derived from z:\sys\bin\trkdummyapp200159D8.exe.
+//!
+//! @SYMTestExpectedResults 
+//!
+//!     1.              Fails if unable to create a process from z:\sys\bin\trkdummyapp200159D8.exe.
+//!
+//!     2.              The Secure ID of trkdummyapp200159D8.exe has the Secure ID 0x200159D8. Fail otherwise.
+//! 
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+// Names of some test programs used for testing security
+_LIT(KRMDebugSecurityTrkDummyApp200159D8,"z:\\sys\\bin\\trkdummyapp200159D8.exe");
+
+void CTrkDummyAppTest::TestSecurityCheckPreventInsecureTrkDebugAgent200159D8(void)
+	{
+	test.Next(_L("TestSecurityCheckPreventInsecureTrkDebugAgent, SID 0x200159D8\n"));
+
+	RProcess process;
+	TInt err = process.Create(KRMDebugSecurityTrkDummyApp200159D8, KNullDesC, EOwnerProcess);
+	test (err == KErrNone);
+
+	// rendezvous with process
+	TRequestStatus status;
+	process.Rendezvous(status);
+
+	// obtain the secure ID for the process
+	TSecurityInfo secInfo(process);
+
+	static const TSecureId KTrkDummyAppSID2 = 0x200159D8;
+
+	test(secInfo.iSecureId.iId == KTrkDummyAppSID2);
+
+	// Kill the process, as we don't need it anymore
+	process.Kill(KErrNone);
+
+	process.Close();
+	}
+
+//----------------------------------------------------------------------------------------------
+//! @SYMTestCaseID      KBase-T-TRKDUMMYAPP-2397
+//! @SYMTestType        
+//! @SYMPREQ            PREQ1426
+//! @SYMTestCaseDesc    Tests that a known insecure debug agent trkapp.sis cannot be installed
+//!                     by ensuring the existence of a Symbian OS common app called trkdummyapp200170BC.exe
+//!                     already exists with the same Secure ID as the insecure app.
+//! @SYMTestActions     
+//!    
+//!     1.              Calls RProcess.Create() on z:\sys\bin\trkdummyapp200170BC.exe. Fail if unsuccessful.
+//!     
+//!     2.              Obtain the Secure ID of the process derived from z:\sys\bin\trkdummyapp200170BC.exe.
+//!
+//!     3.              Close the process derived from z:\sys\bin\trkdummyapp200170BC.exe.
+//!
+//! @SYMTestExpectedResults 
+//!
+//!     1.              Fails if unable to create a process from z:\sys\bin\trkdummyapp200170BC.exe.
+//!
+//!     2.              The Secure ID of trkdummyapp.exe has the Secure ID 0x200170BC. Fail otherwise.
+//! 
+//! @SYMTestPriority        High
+//! @SYMTestStatus          Implemented
+//----------------------------------------------------------------------------------------------
+
+// Names of some test programs used for testing security
+_LIT(KRMDebugSecurityTrkDummyApp200170BC,"z:\\sys\\bin\\trkdummyapp200170BC.exe");
+
+void CTrkDummyAppTest::TestSecurityCheckPreventInsecureTrkDebugAgent200170BC(void)
+	{
+
+	test.Next(_L("TestSecurityCheckPreventInsecureTrkDebugAgent, SID 0x200170BC\n"));
+
+	RProcess process;
+	TInt err = process.Create(KRMDebugSecurityTrkDummyApp200170BC, KNullDesC, EOwnerProcess);
+	test (err == KErrNone);
+
+	// rendezvous with process
+	TRequestStatus status;
+	process.Rendezvous(status);
+
+	// obtain the secure ID for the process
+	TSecurityInfo secInfo(process);
+
+	static const TSecureId KTrkDummyAppSID2 = 0x200170BC;
+
+	test(secInfo.iSecureId.iId == KTrkDummyAppSID2);
+
+	// Kill the process, as we don't need it anymore
+	process.Kill(KErrNone);
+
+	process.Close();
+	}
+
+void CTrkDummyAppTest::ClientAppL()
+//
+// Performs each test in turn
+//
+	{
+	test.Start(_L("ClientAppL"));
+
+	TestSecurityCheckPreventInsecureTrkDebugAgent();
+
+	TestSecurityCheckPreventInsecureTrkDebugAgent2();
+
+	TestSecurityCheckPreventInsecureTrkDebugAgent200159D8();
+
+	TestSecurityCheckPreventInsecureTrkDebugAgent200170BC();
+
+	test.End();
+	}
+
+
+
+GLDEF_C TInt E32Main()
+//
+// Entry point for run mode debug driver test
+//
+	{
+   TInt ret = KErrNone;
+
+	// client
+	CTrapCleanup* trap = CTrapCleanup::New();
+	if (!trap)
+		return KErrNoMemory;
+
+   	test.Title();
+   TrkDummyTest = CTrkDummyAppTest::NewL();
+   if (TrkDummyTest != NULL)
+       {
+        __UHEAP_MARK;
+	    TRAP(ret,TrkDummyTest->ClientAppL());
+	    __UHEAP_MARKEND;
+
+	    delete TrkDummyTest;
+       }
+       
+	delete trap;
+
+	return ret;
+	}
+
+// End of file - t_trkdummyapp.cpp
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/rm_debug/trk_blocking/t_trkdummyapp.h	Mon Mar 15 12:45:50 2010 +0200
@@ -0,0 +1,59 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "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:
+// Ensure that old insecure Trk debug agent cannot be installed
+// as it should be blocked from SWInstall'ing by a trkdummyapp.exe contained within
+// the base OS with the same SID as the insecure Trk.
+// 
+//
+
+/**
+@file
+@internalTechnology
+@released
+*/
+
+#ifndef T_TRKDUMMYAPP_H
+#define T_TRKDUMMYAPP_H
+
+class CTrkDummyAppTest;
+
+//
+// class CTrkDummyAppTest
+//
+// Basic test of the existence of the TrkDummyApp.
+//
+class CTrkDummyAppTest : public CBase
+	{
+public:
+	static CTrkDummyAppTest* NewL();
+	~CTrkDummyAppTest();
+	void ClientAppL();
+
+	void TestSecurityCheckPreventInsecureTrkDebugAgent(void);
+
+	void TestSecurityCheckPreventInsecureTrkDebugAgent2(void);
+
+	void TestSecurityCheckPreventInsecureTrkDebugAgent200159D8(void);
+
+	void TestSecurityCheckPreventInsecureTrkDebugAgent200170BC(void);
+
+private:
+	CTrkDummyAppTest();
+	void ConstructL();
+
+	void TestTrkDummyAppExists();
+
+	};
+
+#endif // T_TRKDUMMYAPP_H
--- a/kerneltest/f32test/filesystem/fat/b_fat32.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/filesystem/fat/b_fat32.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -63,15 +63,16 @@
 
 const TInt KMaxFatEntries  = 2048;
 const TInt KMaxFatSize     = KMaxFatEntries * 4;
-const TInt KDirAttrReadOnly  = 0x01;
-const TInt KDirAttrHidden    = 0x02;
-const TInt KDirAttrSystem    = 0x04;
-const TInt KDirAttrVolumeId  = 0x08;
-const TInt KDirAttrDirectory = 0x10;
-const TInt KDirAttrArchive   = 0x20;
-const TInt KDirAttrLongName  = KDirAttrReadOnly | KDirAttrHidden | KDirAttrSystem | KDirAttrVolumeId;
-const TInt KDirAttrLongMask  = KDirAttrLongName | KDirAttrDirectory | KDirAttrArchive;
-const TInt KDirLastLongEntry = 0x40;
+
+const TUint KDirAttrReadOnly  = 0x01;
+const TUint KDirAttrHidden    = 0x02;
+const TUint KDirAttrSystem    = 0x04;
+const TUint KDirAttrVolumeId  = 0x08;
+const TUint KDirAttrDirectory = 0x10;
+const TUint KDirAttrArchive   = 0x20;
+const TUint KDirAttrLongName  = KDirAttrReadOnly | KDirAttrHidden | KDirAttrSystem | KDirAttrVolumeId;
+const TUint KDirAttrLongMask  = KDirAttrLongName | KDirAttrDirectory | KDirAttrArchive;
+const TUint KDirLastLongEntry = 0x40;
 
 void CreateFatEntry(const TDesC& aDir, TBool aVFatEntry, TDes *apFileName=NULL);
 
@@ -1495,7 +1496,7 @@
     }
 
 
-static  void TestMakeDir(const TDesC& aName,TInt aNewClust,TInt aParentClust)
+static  void TestMakeDir(const TDesC& aName, TUint aNewClust, TUint aParentClust)
 //
 // Test make dir
 //
@@ -1526,7 +1527,7 @@
     pE++;
     if (pE->Name()[0]!='.' || pE->Name()[1]!='.')
         Error(_L("Second entry is not '..'"),KErrNone);
-    if (pE->StartCluster() != ((aParentClust==gRootCluster)?0:aParentClust))
+    if (pE->StartCluster() != ((aParentClust==(TUint)gRootCluster)?0:aParentClust))
         Error(_L("Start cluster of .. is not parent directory"),KErrNone);
     }
 
--- a/kerneltest/f32test/filesystem/fat/t_compat32.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/filesystem/fat/t_compat32.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -156,7 +156,7 @@
 // Replace a 8.3 filename with upper and lower case letters which is, actually out of FAT specs.
 // I.e. VFAT entries are valid, but DOS entry has a lower case symbol, which is wrong.
 //
-LOCAL_C void Test1(TNameCase aCase)
+static void Test1(TNameCase aCase)
 	{
 	test.Next(_L("Replace a file with a wrong DOS entry"));
 	QuickFormat();
@@ -190,7 +190,7 @@
 // Renaming a 8.3 filename with upper and lower case letters which is, actually out of FAT specs.
 // I.e. VFAT entries are valid, but DOS entry has a lower case symbol, which is wrong.
 //
-LOCAL_C void Test2(TNameCase aCase)
+static void Test2(TNameCase aCase)
 	{
 	test.Next(_L("Rename a file with a wrong DOS entry"));
 	QuickFormat();
@@ -520,11 +520,89 @@
 
 }
 
+//---------------------------------------------
+/**
+    Test that the created VFAT entryset corresponds to what Windows creates in the 
+    same situation
+*/
+void TestVFatEntryInterop()
+{
+    test.Next(_L("Testind VFAT entries interoperability\n"));
+    QuickFormat();
 
-GLDEF_C void CallTestsL()
-//
-// Call tests that may leave
-//
+    TInt nRes;
+    _LIT(KFName, "\\longfilename12345678");
+    
+    //-- 1. create a file with long FN that isn't multiple of 13 (max unicode characters in VFAT entry)
+    const TUint KFileSize = 24;
+    nRes = CreateEmptyFile(TheFs, KFName, KFileSize);
+    test(nRes == KErrNone);
+
+    //-- 2. verify that the dir. entries are the same what Windows creates.
+	nRes = TheDisk.Open(TheFs,CurrentDrive());
+	test(nRes == KErrNone);
+
+    //-- read 1st dir. entry from the root dir and check it.
+    //-- this is the rest of the LFN 
+    TInt64 posEntry = gBootSector.RootDirStartSector() << KDefaultSectorLog2; //-- dir entry1 position
+
+    TFatDirEntry fatEntry;
+	TPtr8 ptrEntry((TUint8*)&fatEntry, KSizeOfFatDirEntry);
+
+    nRes = TheDisk.Read(posEntry, ptrEntry);
+    test(nRes == KErrNone);
+
+    //-- the expected entry #1 contents (what Windows places there). 
+    const TUint8 KEntry1[KSizeOfFatDirEntry] = {0x42, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x0F, 0x00, 0xF7, 0x37, 0x00,
+                                                0x38, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
+
+    nRes = Mem::Compare(fatEntry.iData, KSizeOfFatDirEntry, KEntry1, KSizeOfFatDirEntry);
+    test(nRes == KErrNone);
+
+    //-- read 2nd dir. entry from the root dir and check it.
+    //-- this is the beginning of the LFN 
+
+    posEntry += KSizeOfFatDirEntry;
+    nRes = TheDisk.Read(posEntry, ptrEntry);
+    test(nRes == KErrNone);
+
+    //-- the expected entry #2 contents (what Windows places there). 
+    const TUint8 KEntry2[KSizeOfFatDirEntry] = { 0x01, 0x6C, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x66, 0x00, 0x0F, 0x00, 0xF7, 0x69, 0x00,
+                                                 0x6C, 0x00, 0x65, 0x00, 0x6E, 0x00, 0x61, 0x00, 0x6D, 0x00, 0x00, 0x00, 0x65, 0x00, 0x31, 0x00 };
+
+    nRes = Mem::Compare(fatEntry.iData, KSizeOfFatDirEntry, KEntry2, KSizeOfFatDirEntry);
+    test(nRes == KErrNone);
+
+    //-- read the last, 3rd entry from the root dir and check it.
+    //-- this is the DOS entry
+
+    posEntry += KSizeOfFatDirEntry;
+    nRes = TheDisk.Read(posEntry, ptrEntry);
+    test(nRes == KErrNone);
+
+    //-- first 13 bytes of DOS entry SFN, attributes and DIR_NTRes field
+    const TUint8 KEntry3[13] = {'L','O','N','G','F','I','~','1',' ',' ',' ', 0x20, 0x00 };
+    nRes = Mem::Compare(fatEntry.iData, 13, KEntry3, 13);
+    test(nRes == KErrNone);
+
+    //-- skip file time stamps, they are not consistent
+
+    //-- test file size and start cluster of the file
+    test(fatEntry.StartCluster() != gBootSector.RootClusterNum() && fatEntry.StartCluster() != 0);
+    test(fatEntry.Size() == KFileSize);
+
+    //-- goto the next entry, this must be the end of directory
+    posEntry += KSizeOfFatDirEntry;
+    nRes = TheDisk.Read(posEntry, ptrEntry);
+    test(nRes == KErrNone);
+    test(fatEntry.IsEndOfDirectory());
+
+    TheDisk.Close();
+
+}
+
+
+void CallTestsL()
 	{
 
 	TInt drvNum;
@@ -546,6 +624,8 @@
 
 	GetBootInfo();
 
+    TestVFatEntryInterop();
+
 	Test1(EUpper); // Test directory entries with 8.3 uppercase (no VFAT entries expected)
 	Test1(ELower); // Test directory entries with 8.3 lowercase (   VFAT entries expected)
 	Test1(EMixed); // Test directory entries with 8.3 mixed     (   VFAT entries expected)
@@ -559,7 +639,6 @@
 	TestPDEF116912();
 
     TestReplaceByShortName();
-
 	}
 
 
--- a/kerneltest/f32test/filesystem/fat/t_scn32dr1.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/filesystem/fat/t_scn32dr1.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -597,7 +597,7 @@
             RDebug::Print(_L("%5d: ------------- end of directory"), aNum);
         return EFalse;
         }
-    else if ((d->Attributes() & KDirAttrLongMask) == KDirAttrLongName)
+    else if (((TInt)d->Attributes() & KDirAttrLongMask) == KDirAttrLongName)
         {
         TBuf16<15> name;
         ExtractNameString(name, aEntry);
@@ -795,7 +795,7 @@
     TheRawDisk.Close();
     RDebug::Print(_L("Cluster %d @ 0x%08X:"), aCluster, ClusterToByte(aCluster));
     TFatDirEntry* d = (TFatDirEntry*)ptr.Ptr() + aEntry;
-    while ((d->Attributes() & KDirAttrLongMask) == KDirAttrLongName && aEntry < gEntriesPerCluster)
+    while (((TInt)d->Attributes() & KDirAttrLongMask) == KDirAttrLongName && aEntry < gEntriesPerCluster)
         {
         if (d->IsErased() || d->IsEndOfDirectory())
             break;
@@ -807,7 +807,7 @@
         start = -1;
     else if (d->IsEndOfDirectory())
         start = -1;
-    else if ((d->Attributes() & KDirAttrLongMask) == KDirAttrLongName)
+    else if (((TInt)d->Attributes() & KDirAttrLongMask) == KDirAttrLongName)
         start = -1;
     else if (!IsValidDirEntry(d))
         start = -1;
--- a/kerneltest/f32test/filesystem/fat/t_tscan32.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/filesystem/fat/t_tscan32.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -563,7 +563,7 @@
 		}
 	else if (d->IsEndOfDirectory())
 		return EFalse;
-	else if ((d->Attributes() & KDirAttrLongMask) == KDirAttrLongName)
+	else if (((TInt)d->Attributes() & KDirAttrLongMask) == KDirAttrLongName)
 		{
 		TBuf16<15> name;
 		ExtractNameString(name, aEntry);
--- a/kerneltest/f32test/fileutils/inc/fat_utils.h	Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/fileutils/inc/fat_utils.h	Mon Mar 15 12:45:50 2010 +0200
@@ -77,22 +77,22 @@
 
 
 //-----------------------------------------------------------------------------
-const TInt KFatFirstSearchCluser    =2;     ///< FAT usable clusters start from 2; FAT[0] and FAT[1] are reserved
+const TUint KFatFirstSearchCluser   =2;     ///< FAT usable clusters start from 2; FAT[0] and FAT[1] are reserved
 const TInt KFatDirNameSize			=11;    ///< Dos directory/File name length
-const TInt KFatDirReserved1Size		=8;     ///< Size of reserved area one in a directory enrty
+const TUint KFatDirReserved1Size	=8;     ///< Size of reserved area one in a directory enrty
 const TInt KVolumeLabelSize			=11;    ///< Volume lable size
 const TInt KFileSysTypeSize			=8;     ///< File system type parameter size
 const TInt KVendorIdSize			=8;     ///< Vendor ID parameter size
-const TInt KVFatEntryAttribute		=0x0F;  ///< VFat entry attribute setting
-const TInt KBootSectorSignature		=0xAA55;///< File system Boot sector signiture
+const TUint KVFatEntryAttribute		=0x0F;  ///< VFat entry attribute setting
+const TUint KBootSectorSignature	=0xAA55;///< File system Boot sector signiture
 const TUint8 KDotEntryByte			=0x2e;  ///< Dot value for self and parent pointer directory entries
 const TUint8 KBlankSpace			=0x20;  ///< Blank space in a directory entry
-const TInt KSizeOfFatDirEntry		=32;    ///< Size in bytes of a Fat directry entry 
-const TInt KSizeOfFatDirEntryLog2	=5;     ///< Log2 of size in bytes of a Fat directry entry 
-const TInt KFat16VolumeLabelPos 	=43;    ///< Position of volume lable in BPB for Fat12/16
-const TInt KFat32VolumeLabelPos		=71;    ///< Position of volume lable in BPB for Fat32
-const TInt KReservedIdOldEntry		=1;	    ///< used for TFatDirEntry::SetReserved2(..)
-const TInt KReservedIdNewEntry		=0;
+const TUint  KSizeOfFatDirEntry		=32;    ///< Size in bytes of a Fat directry entry 
+const TUint  KSizeOfFatDirEntryLog2	=5;     ///< Log2 of size in bytes of a Fat directry entry 
+const TUint  KFat16VolumeLabelPos 	=43;    ///< Position of volume lable in BPB for Fat12/16
+const TUint  KFat32VolumeLabelPos	=71;    ///< Position of volume lable in BPB for Fat32
+const TUint  KReservedIdOldEntry	=1;	    ///< used for TFatDirEntry::SetReserved2(..)
+const TUint  KReservedIdNewEntry	=0;
 const TInt KSizeOfFatBootSector     =90;    ///< Size in bytes of Boot sector parameter block (BPB) 
 
 const TUint32 KBootSectorNum        =0;     ///< Main Boot Sector number (always 0)
@@ -325,9 +325,9 @@
     void InitZ();
 
     const TPtrC8 Name() const;
-    TInt Attributes() const;
+    TUint Attributes() const;
     TTime Time() const;
-    TInt StartCluster() const;
+    TUint32 StartCluster() const;
     TUint32 Size() const;
     TBool IsErased() const;
     TBool IsCurrentDirectory() const;
@@ -335,10 +335,10 @@
     TBool IsEndOfDirectory() const;
     TBool IsGarbage() const;
     void SetName(const TDesC8& aDes);
-    void SetAttributes(TInt anAtt);
+    void SetAttributes(TUint anAtt);
     void SetTime(TTime aTime);
     void SetCreateTime(TTime aTime);
-    void SetStartCluster(TInt aStartCluster);
+    void SetStartCluster(TUint32 aStartCluster);
     void SetSize(TUint32 aFilesize);
     void SetErased();
     void SetCurrentDirectory();
--- a/kerneltest/f32test/fileutils/src/fat_utils.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/fileutils/src/fat_utils.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -1149,7 +1149,7 @@
 	{return TPtrC8((TUint8*)&(pDir->iName),KFatDirNameSize);}
 
 /** @return The attributes for the Directory entry */
-TInt TFatDirEntry::Attributes() const
+TUint TFatDirEntry::Attributes() const
 	{return pDir->iAttributes;}
 
 /** @return Time of file creation */
@@ -1157,7 +1157,7 @@
 	{return DosTimeToTTime(pDir->iTime,pDir->iDate);}
 
 /** @return The Start cluster for the file or directory for this entry  */
-TInt TFatDirEntry::StartCluster() const		
+TUint32 TFatDirEntry::StartCluster() const		
 	{
     const TUint16 KStClustMaskHi = 0x0FFF;	
     return ((pDir->iStartClusterHi&KStClustMaskHi)<<16) | pDir->iStartClusterLo;
@@ -1198,7 +1198,7 @@
 Set the file or directory attributes for this entry 
 @param anAtts The file or directory attributes
 */
-void TFatDirEntry::SetAttributes(TInt anAtts)
+void TFatDirEntry::SetAttributes(TUint anAtts)
 	{
 	ASSERT(!(anAtts&~KMaxTUint8));
 	pDir->iAttributes=(TUint8)anAtts;
@@ -1224,7 +1224,7 @@
 Set the start cluster number of the file or directory refered to by the entry
 @param aStartCluster The start cluster number
 */
-void TFatDirEntry::SetStartCluster(TInt aStartCluster)
+void TFatDirEntry::SetStartCluster(TUint32 aStartCluster)
 	{
 	const TUint32 KHalfWordMask	= 0x0000FFFF;
     pDir->iStartClusterLo=(TUint16)(aStartCluster & KHalfWordMask);
--- a/kerneltest/f32test/server/t_main.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/server/t_main.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -680,10 +680,8 @@
 	r = controlIo(TheFs,theDrive, KControlIoCacheCount, orgValues);
 	test_KErrNone(r);
 
-	test.Printf(_L("Requests on close queue at start=%d\n"),orgValues.iCloseCount);
-	test.Printf(_L("Requests on free queue at start=%d\n"),orgValues.iFreeCount);
-	test.Printf(_L("Requests dynamically allocated at start=%d\n"),orgValues.iAllocated);
-	test.Printf(_L("Requests in total at start=%d\n"),orgValues.iTotalCount);
+	test.Printf(_L("Requests at start: CloseQ %d FreeQ %d total %d peak %d\n"), 
+		orgValues.iCloseCount, orgValues.iFreeCount, orgValues.iTotalCount, orgValues.iRequestCountPeak);
 
 	// File cache
 
@@ -793,10 +791,10 @@
 	r = controlIo(TheFs,theDrive, KControlIoCacheCount, values);
 	test_KErrNone(r);
 	
-	test.Printf(_L("Requests on close queue at end=%d\n"),values.iCloseCount);
-	test.Printf(_L("Requests on free queue at end=%d\n"),values.iFreeCount);
-	test.Printf(_L("Requests dynamically allocated at end=%d\n"),values.iAllocated);
-	test.Printf(_L("Requests in total at end=%d\n"),values.iTotalCount);
+	test.Printf(_L("Requests at end: CloseQ %d FreeQ %d total %d peak %d\n"), 
+		values.iCloseCount, values.iFreeCount, values.iTotalCount, values.iRequestCountPeak);
+	test.Printf(_L("Operations at end: FreeQ %d total %d peak=%d\n"),
+		values.iOpFreeCount, values.iOpRequestCount, values.iOpRequestCountPeak);
 	
 	test(orgValues.iCloseCount==values.iCloseCount);
 	test(orgValues.iAllocated == values.iAllocated);
--- a/kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/cmassstoragemountcb.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/cmassstoragemountcb.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -220,280 +220,6 @@
 	delete hDes;
 	}
 
-/**
-Make sure that the file system is fat.
-*/
-TBool CMassStorageMountCB::ValidateBootSector()
-	{
-	__FNLOG("CMassStorageMountCB::ValidateBootSector");
-
-	TFatBootSector bootSector;
-	TInt r=ReadBootSector(bootSector);
-	__PRINT1(_L("CMassStorageMountCB::MountL - ReadBootSector returned %d"),r);
-	if (r != KErrNone)
-		{
-		return EFalse;
-		}
-
-	__PRINT(_L("\nBootSector info"));
-	__PRINT8BIT1(_L("FAT type = %S"),bootSector.FileSysType());
-	__PRINT8BIT1(_L("Vendor ID = %S"),bootSector.VendorId());
-	__PRINT1(_L("BytesPerSector %d"),bootSector.BytesPerSector());
-	__PRINT1(_L("SectorsPerCluster %d"),bootSector.SectorsPerCluster());
-	__PRINT1(_L("ReservedSectors %d"),bootSector.ReservedSectors());
-	__PRINT1(_L("NumberOfFats %d"),bootSector.NumberOfFats());
-	__PRINT1(_L("RootDirEntries %d"),bootSector.RootDirEntries());
-	__PRINT1(_L("Total Sectors = %d"),bootSector.TotalSectors());
-	__PRINT1(_L("MediaDescriptor = 0x%x"),bootSector.MediaDescriptor());
-	__PRINT1(_L("FatSectors %d"),bootSector.FatSectors());
-	__PRINT1(_L("SectorsPerTrack %d"),bootSector.SectorsPerTrack());
-	__PRINT1(_L("NumberOfHeads %d"),bootSector.NumberOfHeads());
-	__PRINT1(_L("HugeSectors %d"),bootSector.HugeSectors());
-	__PRINT1(_L("Fat32 Sectors %d"),bootSector.FatSectors32());
-	__PRINT1(_L("Fat32 Flags %d"),bootSector.FATFlags());
-	__PRINT1(_L("Fat32 Version Number %d"),bootSector.VersionNumber());
-	__PRINT1(_L("Root Cluster Number %d"),bootSector.RootClusterNum());
-	__PRINT1(_L("FSInfo Sector Number %d"),bootSector.FSInfoSectorNum());
-	__PRINT1(_L("Backup Boot Rec Sector Number %d"),bootSector.BkBootRecSector());
-	__PRINT1(_L("PhysicalDriveNumber %d"),bootSector.PhysicalDriveNumber());
-	__PRINT1(_L("ExtendedBootSignature %d"),bootSector.ExtendedBootSignature());
-	__PRINT1(_L("UniqueID %d"),bootSector.UniqueID());
-	__PRINT8BIT1(_L("VolumeLabel %S"),bootSector.VolumeLabel());
-	__PRINT8BIT1(_L("FileSysType %S\n"),bootSector.FileSysType());
-
-    iUniqueID=bootSector.UniqueID();
-	iIs16BitFat=bootSector.Is16BitFat();
-
-	iIs32BitFat=bootSector.Is32BitFat();
-	switch (DetermineFatType(bootSector))
-		{
-		case 12:
-			iIs16BitFat = EFalse;
-			iIs32BitFat = EFalse;
-			break;
-		case 16:
-			iIs16BitFat = ETrue;
-			iIs32BitFat = EFalse;
-			break;
-		case 32:
-			iIs16BitFat = EFalse;
-			iIs32BitFat = ETrue;
-			break;
-		default:
-			return EFalse;
-		}
-
-	TInt sectorsPerCluster=bootSector.SectorsPerCluster();
-	if (!IsPowerOfTwo(sectorsPerCluster))
-		return EFalse;
-
-	TInt sectorSizeLog2=Log2(bootSector.BytesPerSector());
-	if (sectorSizeLog2<0 || !IsPowerOfTwo(bootSector.BytesPerSector()))
-		return EFalse;
-
-	TInt firstFatSector=bootSector.ReservedSectors();
-	if (firstFatSector<1)
-		return EFalse;
-
-	TInt fatSizeInBytes;
-	if(iIs32BitFat)
-		{
-		fatSizeInBytes=bootSector.FatSectors32()*bootSector.BytesPerSector();
-		if (fatSizeInBytes<bootSector.BytesPerSector())
-			return EFalse;
-		}
-	else
-		{
-		fatSizeInBytes=bootSector.FatSectors()*bootSector.BytesPerSector();
-		if (fatSizeInBytes<bootSector.BytesPerSector())
-			return EFalse;
-
-		TInt rootDirectorySector=firstFatSector+bootSector.FatSectors()*bootSector.NumberOfFats();
-		if (rootDirectorySector<3)
-			return EFalse;
-
-		TInt rootDirSizeInBytes=bootSector.RootDirEntries()*KSizeOfFatDirEntry;
-		TInt numOfRootDirSectors=(rootDirSizeInBytes+(1<<sectorSizeLog2)-1)>>sectorSizeLog2;
-		TInt rootDirEnd=(rootDirectorySector+numOfRootDirSectors)<<sectorSizeLog2;
-		if (rootDirEnd<(4<<sectorSizeLog2))
-			return EFalse;
-		}
-
-
-	TInt totalSectors=bootSector.TotalSectors();
-	if (totalSectors==0)
-		totalSectors=bootSector.HugeSectors();
-	if (totalSectors<5)
-		return EFalse;
-
-	TInt numberOfFats=bootSector.NumberOfFats();
-	if (numberOfFats<1)
-		return EFalse;
-
-	return ETrue;
-	}
-
-/**
-Read non aligned boot data from media into TFatBootSector structure
-
-@param aBootSector refrence to TFatBootSector populate
-@return Media read error code
-*/
-TInt CMassStorageMountCB::ReadBootSector(TFatBootSector& aBootSector)
-	{
-	__FNLOG("CMassStorageMountCB::ReadBootSector");
-	TInt pos=0;
-	TUint8 data[KSizeOfFatBootSector];
-    TPtr8 buf(&data[0],KSizeOfFatBootSector);
-    TInt r=LocalDrive()->Read(0,KSizeOfFatBootSector,buf);
-	if (r!=KErrNone)
-		{
-		__PRINT1(_L("LocalDrive::Read() failed - %d"),r);
-		return(r);
-		}
-//	0	TUint8 iJumpInstruction[3]
-	Mem::Copy(&aBootSector.iJumpInstruction,&data[pos],3);
-	pos+=3;
-// 3	TUint8 iVendorId[KVendorIdSize]
-	Mem::Copy(&aBootSector.iVendorId,&data[pos],KVendorIdSize);
-	pos+=KVendorIdSize;
-// 11	TUint16 iBytesPerSector
-	Mem::Copy(&aBootSector.iBytesPerSector,&data[pos],2);
-	pos+=2;
-// 13	TUint8 sectorsPerCluster
-	Mem::Copy(&aBootSector.iSectorsPerCluster,&data[pos],1);
-	pos+=1;
-// 14	TUint16 iReservedSectors
-	Mem::Copy(&aBootSector.iReservedSectors,&data[pos],2);
-	pos+=2;
-// 16	TUint8 numberOfFats
-	Mem::Copy(&aBootSector.iNumberOfFats,&data[pos],1);
-	pos+=1;
-// 17	TUint16 iRootDirEntries
-	Mem::Copy(&aBootSector.iRootDirEntries,&data[pos],2);
-	pos+=2;
-// 19	TUint16 totalSectors
-	Mem::Copy(&aBootSector.iTotalSectors,&data[pos],2);
-	pos+=2;
-// 21	TUint8 iMediaDescriptor
-	Mem::Copy(&aBootSector.iMediaDescriptor,&data[pos],1);
-	pos+=1;
-// 22	TUint16 iFatSectors
-	Mem::Copy(&aBootSector.iFatSectors,&data[pos],2);
-	pos+=2;
-// 24	TUint16 iSectorsPerTrack
-	Mem::Copy(&aBootSector.iSectorsPerTrack,&data[pos],2);
-	pos+=2;
-// 26	TUint16 iNumberOfHeads
-	Mem::Copy(&aBootSector.iNumberOfHeads,&data[pos],2);
-	pos+=2;
-// 28	TUint32 iHiddenSectors
-	Mem::Copy(&aBootSector.iHiddenSectors,&data[pos],4);
-	pos+=4;
-// 32	TUint32 iHugeSectors
-	Mem::Copy(&aBootSector.iHugeSectors,&data[pos],4);
-	pos+=4;
-
-	if(aBootSector.iRootDirEntries == 0)	//indicates we have FAT32 volume
-		{
-		__PRINT(_L("\nFile system thinks Fat32"));
-
-		//36 TUint32 iFatSectors32
-		Mem::Copy(&aBootSector.iFatSectors32, &data[pos],4);
-		pos+=4;
-		//40 TUint16 iFATFlags
-		Mem::Copy(&aBootSector.iFATFlags, &data[pos],2);
-		pos+=2;
-		//42 TUint16 iVersionNumber
-		Mem::Copy(&aBootSector.iVersionNumber, &data[pos],2);
-		pos+=2;
-		//44 TUint32 iRootClusterNum
-		Mem::Copy(&aBootSector.iRootClusterNum, &data[pos],4);
-		pos+=4;
-		//48 TUint16 iFSInfoSectorNum
-		Mem::Copy(&aBootSector.iFSInfoSectorNum, &data[pos],2);
-		pos+=2;
-		//50 TUint16 iBkBootRecSector
-		Mem::Copy(&aBootSector.iBkBootRecSector, &data[pos],2);
-		pos+=(2+12);//extra 12 for the reserved bytes
-		}
-
-// 36|64	TUint8 iPhysicalDriveNumber
-	Mem::Copy(&aBootSector.iPhysicalDriveNumber,&data[pos],1);
-	pos+=1;
-// 37|65	TUint8 iReserved
-	Mem::Copy(&aBootSector.iReserved,&data[pos],1);
-	pos+=1;
-// 38|66	TUint8 iExtendedBootSignature
-	Mem::Copy(&aBootSector.iExtendedBootSignature,&data[pos],1);
-	pos+=1;
-// 39|67	TUint32 iUniqueID
-	Mem::Copy(&aBootSector.iUniqueID,&data[pos],4);
-	pos+=4;
-// 43|71	TUint8 iVolumeLabel[KVolumeLabelSize]
-	Mem::Copy(&aBootSector.iVolumeLabel,&data[pos],KVolumeLabelSize);
-	pos+=KVolumeLabelSize;
-// 54|82	TUint8 iFileSysType[KFileSysTypeSize]
-	Mem::Copy(&aBootSector.iFileSysType,&data[pos],KFileSysTypeSize);
-// 62|90
-
-	return(KErrNone);
-	}
-
-/**
-Work out if we have a FAT12|16|32 volume.
-Returns 12, 16 or 32 as appropriate.
-Returns 0 if can't be calculated (invalid values)
-*/
-TInt CMassStorageMountCB::DetermineFatType(TFatBootSector& aBootSector)
-	{
-	TUint32 ressectors = aBootSector.ReservedSectors();
-
-	if (aBootSector.SectorsPerCluster() < 1)
-		return 0;
-
-	if (aBootSector.RootDirEntries() != 0)
-		{
-		TUint32 rootdirbytes;
-		rootdirbytes = aBootSector.RootDirEntries() * 32 + aBootSector.BytesPerSector() - 1;
-		ressectors += rootdirbytes / aBootSector.BytesPerSector();
-		}
-
-	if (aBootSector.FatSectors() != 0)
-		ressectors += aBootSector.NumberOfFats() * aBootSector.FatSectors();
-	else
-		ressectors += aBootSector.NumberOfFats() * aBootSector.FatSectors32();
-
-	TUint32 totalsectors;
-	if (aBootSector.TotalSectors() != 0)
-		totalsectors = aBootSector.TotalSectors();
-	else
-		totalsectors = aBootSector.HugeSectors();
-
-	if (ressectors < 1 || totalsectors < 1)
-		return 0;
-
-	TUint32 datasec;
-	datasec = totalsectors - ressectors;
-
-	TUint32 countofclusters;
-	countofclusters = datasec / aBootSector.SectorsPerCluster();
-
-	__PRINT1(_L("CFatMountCB: Count of clusters = %d\n"), countofclusters);
-
-	if (countofclusters < 4085)
-		{
-		return 12;
-		}
-	else if (countofclusters < 65525)
-		{
-		return 16;
-		}
-	else
-		{
-		return 32;
-		}
-	}
 
 TInt CMassStorageMountCB::ReMount()
 	{
--- a/kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/inc/cmassstoragefilesystem.h	Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/inc/cmassstoragefilesystem.h	Mon Mar 15 12:45:50 2010 +0200
@@ -35,7 +35,6 @@
     };
 
 
-
 /**
 Mass Storage Filesystem class.
 Only supports creating a new mount. Calling NewFileL, NewDirL and NewFormatL
@@ -82,8 +81,6 @@
 	CUsbMassStorageController* iMassStorageController;
 	TBool iRunning;
     TLunToDriveMap iDriveMap;
-
-
 	};
 
 #endif // __CMASSSTORAGEFILESYSTEM_H__
--- a/kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/inc/cmassstoragemountcb.h	Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/shostmassstorage/testclient/usbtestmsclient/inc/cmassstoragemountcb.h	Mon Mar 15 12:45:50 2010 +0200
@@ -25,7 +25,6 @@
 #ifndef __CMASSSTORAGEMOUNTCB_H__
 #define __CMASSSTORAGEMOUNTCB_H__
 
-#include <f32fsys.h>
 
 /**
 Mass Storage Mount.
@@ -34,7 +33,6 @@
 ControlIO is also supported for debug builds and returns KErrNotSupported for Release builds.
 @internalTechnology
 */
-class TFatBootSector;
 class CMassStorageMountCB : public CLocDrvMountCB
 	{
 public:
@@ -65,208 +63,14 @@
 	CMassStorageMountCB(const TLunToDriveMap& aDriveMapping);
 	void WritePasswordData();
 	TInt DriveNumberToLun(TInt aDriveNumber);
-	TBool ValidateBootSector();
-	TInt ReadBootSector(TFatBootSector& aBootSector);
-	TInt DetermineFatType(TFatBootSector& aBootSector);
 	TInt CheckDriveNumberL();
 
     TBool IsPowerOfTwo(TInt aNum);
     TInt Log2(TInt aNum);
 
 private:
-	TBool iIs16BitFat;
-	TBool iIs32BitFat;
 	const TLunToDriveMap& iDriveMapping;
 	};
 
-const TInt KSizeOfFatBootSector	= 90;
-const TInt KVendorIdSize = 8;
-const TInt KVolumeLabelSize = 11;
-const TInt KFileSysTypeSize = 8;
-const TInt KBootSectorSignature = 0xAA55;
-const TInt KSizeOfFatDirEntry = 32;
-
-/**
-Boot sector parameter block, enables access to all file system parameters.
-Data is populated at mount time from the BPB sector
-@internalTechnology
-*/
-class TFatBootSector
-	{
-public:
-	inline const TPtrC8 VendorId() const;
-	inline TUint16 BytesPerSector() const;
-	inline TInt SectorsPerCluster() const;
-	inline TInt ReservedSectors() const;
-	inline TInt NumberOfFats() const;
-	inline TInt RootDirEntries() const;
-	inline TInt TotalSectors() const;
-	inline TUint8 MediaDescriptor() const;
-	inline TInt FatSectors() const;
-	inline TInt SectorsPerTrack() const;
-	inline TInt NumberOfHeads() const;
-	inline TInt HiddenSectors() const;
-	inline TInt HugeSectors() const;
-	inline TInt PhysicalDriveNumber() const;
-	inline TInt ExtendedBootSignature() const;
-	inline TUint32 UniqueID() const;
-	inline const TPtrC8 VolumeLabel() const;
-	inline const TPtrC8 FileSysType() const;
-	inline TInt BootSectorSignature() const;
-	inline void SetJumpInstruction();
-	inline void SetVendorID(const TDesC8& aDes);
-	inline void SetBytesPerSector(TInt aBytesPerSector);
-	inline void SetSectorsPerCluster(TInt aSectorsPerCluster);
-	inline void SetReservedSectors(TInt aReservedSectors);
-	inline void SetNumberOfFats(TInt aNumberOfFats);
-	inline void SetRootDirEntries(TInt aRootDirEntries);
-	inline void SetTotalSectors(TInt aTotalSectors);
-	inline void SetMediaDescriptor(TUint8 aMediaDescriptor);
-	inline void SetFatSectors(TInt aFatSectors);
-	inline void SetSectorsPerTrack(TInt aSectorsPerTrack);
-	inline void SetNumberOfHeads(TInt aNumberOfHeads);
-	inline void SetHiddenSectors(TUint32 aHiddenSectors);
-	inline void SetHugeSectors(TUint32 aTotalSectors);
-	inline void SetPhysicalDriveNumber(TInt aPhysicalDriveNumber);
-	inline void SetReservedByte(TUint8 aReservedByte);
-	inline void SetExtendedBootSignature(TInt anExtendedBootSignature);
-	inline void SetUniqueID(TUint32 anUniqueID);
-	inline void SetVolumeLabel(const TDesC8& aDes);
-	inline void SetFileSysType(const TDesC8& aDes);
-
-	inline void SetFatSectors32(TUint32	aFatSectors32);
-	inline void SetFATFlags(TUint16 aFATFlags);
-	inline void SetVersionNumber(TUint16	aVersionNumber);
-	inline void SetRootClusterNum(TUint32 aRootCusterNum);
-	inline void SetFSInfoSectorNum(TUint16 aFSInfoSectorNum);
-	inline void SetBkBootRecSector(TUint16 aBkBootRecSector);
-	inline TUint32 FatSectors32() const;
-	inline TUint16 FATFlags() const;
-	inline TUint16 VersionNumber() const;
-	inline TUint32 RootClusterNum() const;
-	inline TUint16 FSInfoSectorNum() const;
-	inline TUint16 BkBootRecSector() const;
-public:
-	inline TBool Is16BitFat();
-	inline TBool Is32BitFat();
-	inline TInt FirstFatSectorPos();
-	inline TInt RootDirStartSector();
-	inline TInt FirstFreeSector();
-public:
-	/**
-	Jump instruction used for bootable volumes
-	*/
-    TUint8 iJumpInstruction[3];
-	/**
-	Vendor ID of the file system that formatted the volume
-	*/
-    TUint8 iVendorId[KVendorIdSize];
-	/**
-	Bytes per sector
-	*/
-    TUint16 iBytesPerSector;
-	/**
-	Sectors per cluster ratio
-	*/
-    TUint8 iSectorsPerCluster;
-	/**
-	Number of reserved sectors on the volume
-	*/
-    TUint16 iReservedSectors;
-	/**
-	Number of Fats on the volume
-	*/
-    TUint8 iNumberOfFats;
-	/**
-	Number of entries allowed in the root directory, specific to Fat12/16, zero for FAT32
-	*/
-    TUint16 iRootDirEntries;
-	/**
-	Total sectors on the volume, zero for FAT32
-	*/
-    TUint16 iTotalSectors;
-	/**
-	Media descriptor
-	*/
-    TUint8 iMediaDescriptor;
-	/**
-	Sectors used for the Fat table, zero for FAT32
-	*/
-    TUint16 iFatSectors;
-	/**
-	Sectors per track
-	*/
-    TUint16 iSectorsPerTrack;
-	/**
-	Number of heads
-	*/
-    TUint16 iNumberOfHeads;
-	/**
-	Number of hidden sectors in the volume
-	*/
-    TUint32 iHiddenSectors;
-	/**
-	Total sectors in the volume, Used if totalSectors > 65535
-	*/
-    TUint32 iHugeSectors;
-
-	/**
-	Start of additional elements @ offset 36 for FAT32
-	Sectors in Fat table for 32 bit volume
-	*/
-	TUint32	iFatSectors32;
-	/**
-	Fat flags
-	*/
-	TUint16 iFATFlags;
-	/**
-	Version number of the file system
-	*/
-	TUint16	iVersionNumber;
-	/**
-	Cluster number of the root directory
-	*/
-	TUint32 iRootClusterNum;
-	/**
-	Sector number containing the FSIInfo structure
-	*/
-	TUint16 iFSInfoSectorNum;
-	/**
-	Backup boot sector
-	*/
-	TUint16 iBkBootRecSector;
-	/**
-	Reserved space
-	End of Fat32 Only parameters section
-	*/
-	TUint8	iReserved2[12];
-
-	/**
-	Physical drive number, not used in Symbian OS
-	*/
-	TUint8 iPhysicalDriveNumber;
-	/**
-	Reserved byte
-	*/
-    TUint8 iReserved;
-	/**
-	Extended boot signiture
-	*/
-    TUint8 iExtendedBootSignature;
-	/**
-	Unique volume ID
-	*/
-    TUint32 iUniqueID;
-	/**
-	The volume's label
-	*/
-    TUint8 iVolumeLabel[KVolumeLabelSize];
-	/**
-	File system type
-	*/
-	TUint8 iFileSysType[KFileSysTypeSize];
-	};
-
-#include "tfatbootsector.inl"
 
 #endif //__CMASSSTORAGEMOUNTCB_H__
--- a/kerneltest/f32test/smassstorage/src/t_ms_fsunit.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/kerneltest/f32test/smassstorage/src/t_ms_fsunit.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -21,11 +21,8 @@
 */
 
 #include <f32file.h>
+#include <f32fsys.h>
 #include <e32test.h>
-#include <e32std.h>
-#include <e32std_private.h>
-#include <e32svr.h>
-#include <hal.h>
 #include "t_ms_main.h"
 #include "t_ms_common.h"
 #include "cmassstoragefilesystem.h"
@@ -268,7 +265,6 @@
 EXPORT_C CLocDrvMountCB::~CLocDrvMountCB()
 
 	{
-	__PRINT1(_L("CLocDrvMountCB::~CLocDrvMountCB() 0x%x"),this);
 	if(iProxyDrive)
 		delete(iProxyDrive);
 	}
--- a/userlibandfileserver/fileserver/group/release.txt	Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/group/release.txt	Mon Mar 15 12:45:50 2010 +0200
@@ -1,3 +1,30 @@
+Version 2.00.2039
+=================
+(Made by vfebvre 23/02/2010)
+
+1.	niccox
+	1.	DEF144323 remove redundant bootsector code from smassstorage
+
+
+Version 2.00.2038
+=================
+(Made by vfebvre 18/02/2010)
+
+1.	famustaf
+	1.	PDEF144438 Optimise TParseBase::AddDir() to not use TFileName
+
+2.	migubarr
+	1.	DEF144407: File Server request cache is not big enough for S60
+
+
+Version 2.00.2037
+=================
+(Made by vfebvre 11/02/2010)
+
+1.	dlyokhin
+	1.	DEF144356 VFAT interoperability: LFN entries padding is wrong
+
+
 Version 2.00.2036
 =================
 (Made by vfebvre 09/02/2010)
--- a/userlibandfileserver/fileserver/inc/f32dbg.h	Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/inc/f32dbg.h	Mon Mar 15 12:45:50 2010 +0200
@@ -194,10 +194,17 @@
 class TIOCacheValues
 	{ 
 public:
-	TInt iFreeCount;	// number of requests on free queue
-	TInt iCloseCount;	// number of requests on close queue
-	TInt iAllocated;	// number of dynamically allocated requests
-	TInt iTotalCount;	// number of permanently & dynamically allocated requests
+	TInt iFreeCount;	// current number of requests on free queue
+	TInt iCloseCount;	// current number of requests on close queue
+	TInt iAllocated;	// no longer used
+	TInt iTotalCount;	// current number of requests
+	TInt iRequestCountPeak;	// peak number of requests, i.e. peak value reached by iTotalCount
+
+
+	// the same again but for the OperationAllocator
+	TInt iOpFreeCount;
+	TInt iOpRequestCount;
+	TInt iOpRequestCountPeak;
 	};
 
 class TFileCacheStats
--- a/userlibandfileserver/fileserver/inc/f32ver.h	Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/inc/f32ver.h	Mon Mar 15 12:45:50 2010 +0200
@@ -58,6 +58,6 @@
 
 @see TVersion
 */
-const TInt KF32BuildVersionNumber=2036;
+const TInt KF32BuildVersionNumber=2039;
 //
 #endif
--- a/userlibandfileserver/fileserver/sfile/sf_debug.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/sfile/sf_debug.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -450,8 +450,15 @@
 			TIOCacheValues cacheValues;
 			cacheValues.iCloseCount= RequestAllocator::CloseCount();
 			cacheValues.iFreeCount= RequestAllocator::FreeCount();
-			cacheValues.iAllocated=	RequestAllocator::AllocatedCount();
-			cacheValues.iTotalCount= RequestAllocator::TotalCount();
+			cacheValues.iAllocated=	0;	// no longer used
+			cacheValues.iTotalCount= RequestAllocator::RequestCount();
+			cacheValues.iRequestCountPeak = RequestAllocator::RequestCountPeak();
+
+			cacheValues.iOpFreeCount= OperationAllocator::FreeCount();
+			cacheValues.iOpRequestCount= OperationAllocator::RequestCount();
+			cacheValues.iOpRequestCountPeak = OperationAllocator::RequestCountPeak();
+
+
 			TPckgBuf<TIOCacheValues> pkgBuf(cacheValues);
 
 			// ensure we only write what the client buffer can hold -
--- a/userlibandfileserver/fileserver/sfile/sf_lepoc.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/sfile/sf_lepoc.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -202,14 +202,33 @@
 #ifdef _DEBUG
 	__IF_DEBUG(Printf("processed reloc table (size=%d,pageCount=%d)", iCodeRelocTableSize, pageCount));
 
-	// dump the import fixup table if loader tracing enabled
-	const TUint16* table16 = (const TUint16*)table;
-	const TInt halfWordsInTable = iCodeRelocTableSize / 2;
-	for(i = 0; i < halfWordsInTable; i += 4)
+	// Dump the processed reloc table if loader tracing enabled. The dump is in
+	// two parts; first, the page indexes (1 word per page), then the entries
+	// describing the items to be relocated on each of these pages, formatted
+	// with up to 8 entries per line but starting a new line for each page.
+	// Each of these entries has the relocation type in the first nibble, and
+	// the offset within the page in the remaining 3 nibbles.
+	const TUint32* table32 = (const TUint32*)table;
+	for (i = 0; i <= pageCount; ++i)
+		__IF_DEBUG(Printf("%04x: %08x", i*4, table32[i]));
+
+	for (i = 0; i < pageCount; ++i)
 		{
-		__IF_DEBUG(Printf(
-			"reloc %04x: %04x %04x %04x %04x",
-			i * 2, table16[i+0], table16[i+1], table16[i+2], table16[i+3]));
+		TUint start = table32[i];
+		TInt nbytes = table32[i+1] - start;
+		while (nbytes)
+			{
+			TBuf8<0x100> buf;
+			buf.Format(_L8("%04x:"), start);
+
+			const TUint16* p = (const TUint16*)(table+start);
+			TInt n = nbytes <= 16 ? nbytes : 16;
+			for (nbytes -= n, start += n; n > 0; n -= 2)
+				buf.AppendFormat(_L8(" %04x"), *p++);
+
+			buf.AppendFormat(_L8("\r\n"));
+			__IF_DEBUG(RawPrint(buf));
+			}
 		}
 #endif
 	return KErrNone;
@@ -268,6 +287,18 @@
 		}
 	}
 
+// A version that will work in user or supervisor mode
+void MyPrintf(const char* aFmt, ...)
+	{
+	VA_LIST list;
+	VA_START(list, aFmt);
+	TPtrC8 fmt((const TText8*)aFmt);
+	TBuf8<0x100> buf;
+	buf.AppendFormatList(fmt, list);
+	buf.AppendFormat(_L8("\r\n"));
+	RDebug::RawPrint(buf);
+	VA_END(list);
+	}
 
 /**
 Arguments for svRelocateSection.
@@ -340,29 +371,80 @@
 
 /**
 Fix up the export directory
-Only performed on PE images.  ELF image's exports are marked
-as relocatable and therefore relocated by svRelocateSection when the 
-text section is relocated up
+Only performed on PE images.  ELF image's exports are marked as relocatable
+and therefore relocated by svRelocateSection along with the text section
 */
 TInt svRelocateExports(TAny* aPtr)
 	{
-	E32Image* pI=(E32Image*)aPtr;
-	TUint32* destExport=(TUint32*)pI->iExportDirLoad;
-	TInt i=pI->iExportDirCount;
-	TUint32 codeBase=pI->iCodeRunAddress;
-	while (i-->0)
-		*destExport+++=codeBase;
+	E32Image& exporter = *(E32Image*)aPtr;
+
+	// Dump everything potentially useful that we know about the exporter ...
+	__LDRTRACE(MyPrintf("RelocateExports: paged? %d, iRomImageHeader@%08x, iHeader@%08x",
+						exporter.iUseCodePaging, exporter.iRomImageHeader, exporter.iHeader));
+	__LDRTRACE(MyPrintf("  iCodeLoadAddress %08x, iCodeRunAddress %08x, iCodeSize %x iTextSize %x",
+						exporter.iCodeLoadAddress, exporter.iCodeRunAddress,
+						exporter.iCodeSize, exporter.iTextSize))
+	__LDRTRACE(MyPrintf("  iDataLoadAddress %08x, iDataRunAddress %08x, iDataSize %x iBssSize %x iTotalDataSize %x",
+						exporter.iDataLoadAddress, exporter.iDataRunAddress,
+						exporter.iDataSize, exporter.iBssSize, exporter.iTotalDataSize));
+	__LDRTRACE(MyPrintf("  iCodeDelta, %x iDataDelta %x, iExportDirEntryDelta %x",
+						exporter.iCodeDelta, exporter.iDataDelta, exporter.iExportDirEntryDelta));
+
+	// It turns out that very little of the exporter info is useful! For
+	// example, the required code and data deltas are NOT those provided
+	// by the exporter, nor are the load addresses relevant ... :(
+	//
+	// In the case of a PE-derived image, the entries in the export table
+	// are expressed in terms of offsets into the image file, rather than
+	// locations in memory. Each therefore needs to be relocated by the
+	// difference between its file offset and its run address.
+	//
+	// It is assumed that the code segment appears before the data segment
+	// in the file; therefore, export table entries with values between 0
+	// and (exporter.iCodeSize) refer to the text segment, while higher
+	// values represent references to data addresses. Since the run addresses
+	// of code and data segments may be different, each type of export must
+	// be relocated with respect to the correct section.
+	//
+	// The following express the start and finish of each section in terms of
+	// file offsets and then derive the required adjustments to the entries
+	// in the export table ...
+	TUint32 codeStart = 0;							// compiler whinges if this is 'const' :(
+	const TUint32 codeFinish = codeStart + exporter.iCodeSize;
+	const TUint32 dataStart = codeFinish;
+	const TUint32 dataFinish = dataStart + exporter.iTotalDataSize;
+	const TUint32 codeDelta = exporter.iCodeRunAddress - codeStart;
+	const TUint32 dataDelta = exporter.iDataRunAddress - dataStart;
+
+	TUint32* destExport = (TUint32*)exporter.iExportDirLoad;
+	for (TInt i = exporter.iExportDirCount; --i >= 0; )
+		{
+		TUint32 relocAddr = *destExport;
+		TUint32 newValue;
+		if (relocAddr >= codeStart && relocAddr < codeFinish)
+			newValue = relocAddr + codeDelta;		// points to text/rdata section
+		else if (relocAddr >= dataStart && relocAddr < dataFinish)
+			newValue = relocAddr + dataDelta;		// points to data/bss section
+		else
+			newValue = relocAddr;					// unknown - just leave it alone
+		*destExport++ = newValue;
+
+		__LDRTRACE(MyPrintf("RelocateExports: export %d %08x => %08x %c",
+							exporter.iExportDirCount-i, relocAddr, newValue,
+							(relocAddr >= codeStart && relocAddr < codeFinish) ? 'C' :
+							(relocAddr >= dataStart && relocAddr < dataFinish) ? 'D' : 'X'));
+		}
+
 	return 0;
 	}
 
 
 struct SFixupImportAddressesInfo
 	{
-	TUint32* iIat;
-	TUint32* iExportDir;
-	TUint32 iExportDirEntryDelta;
-	TInt iNumImports;
-	E32Image* iExporter;
+	TUint32* iIat;					// Next part of IAT to be fixed up
+	E32Image* iExporter;			// Module from which we're importing
+	TInt iNumImports;				// Number of imports from this exporter
+
 	/**
 	For demand paging, this points to the buffer which is populated
 	so each page can be fixed up as it is loaded in.
@@ -378,52 +460,104 @@
 Fix up the import address table, used for 'PE derived' executables.
 @param aPtr Pointer to function arguments (SFixupImportAddressesInfo structure).
 			SFixupImportAddressesInfo::iIat is updated by this function.
+
+For a given importer, this function will be called once for each image from which
+objects are imported, and each time it will update the relevant portion of the
+importer's IAT, until all imports from all exporters have been processed.
 */
 TInt svFixupImportAddresses(TAny* aPtr)
 	{
 	SFixupImportAddressesInfo& info = *(SFixupImportAddressesInfo*)aPtr;
-
-	TUint32 maxOrdinal = (TUint32)info.iExporter->iExportDirCount;
-	TUint32 absentOrdinal = (TUint32)info.iExporter->iFileEntryPoint;
-
-	TUint32* exp_dir = info.iExportDir - KOrdinalBase; // address of 0th ordinal
-	TUint32 exp_delta = info.iExportDirEntryDelta;
+	E32Image& exporter = *info.iExporter;
+
+#ifdef _DEBUG
+	__LDRTRACE(MyPrintf(">svFixupImportAddresses %d imports, code@%08x, fixup@%08x exporter@%08x",
+						info.iNumImports, info.iCodeLoadAddress, info.iFixup64, info.iExporter));
+
+	// Dump everything potentially useful that we know about the exporter ...
+	__LDRTRACE(MyPrintf("%S: paged? %d, iRomImageHeader@%08x, iHeader@%08x",
+						&exporter.iFileName, exporter.iUseCodePaging,
+						exporter.iRomImageHeader, exporter.iHeader));
+	__LDRTRACE(MyPrintf("iCodeLoadAddress %08x, iCodeRunAddress %08x, iCodeSize %x iTextSize %x",
+						exporter.iCodeLoadAddress, exporter.iCodeRunAddress,
+						exporter.iCodeSize, exporter.iTextSize))
+	__LDRTRACE(MyPrintf("iDataLoadAddress %08x, iDataRunAddress %08x, iDataSize %x iBssSize %x iTotalDataSize %x",
+						exporter.iDataLoadAddress, exporter.iDataRunAddress,
+						exporter.iDataSize, exporter.iBssSize, exporter.iTotalDataSize));
+	__LDRTRACE(MyPrintf("iCodeDelta, %x iDataDelta %x, iExportDirEntryDelta %x",
+						exporter.iCodeDelta, exporter.iDataDelta, exporter.iExportDirEntryDelta));
+
+	if (exporter.iRomImageHeader)
+		{
+		const TRomImageHeader& rh = *exporter.iRomImageHeader;
+		__LDRTRACE(MyPrintf("ROM: iCodeAddress %08x, iCodeSize %x, iTextSize %x",
+							rh.iCodeAddress, rh.iCodeSize, rh.iTextSize));
+		__LDRTRACE(MyPrintf("ROM: iDataAddress %08x, iDataSize %x, iBssSize %x",
+							rh.iDataAddress, rh.iDataSize, rh.iBssSize));
+		__LDRTRACE(MyPrintf("ROM: iDataBssLinearBase %08x, iTotalDataSize %x",
+							rh.iDataBssLinearBase, rh.iTotalDataSize));
+		}
+
+	if (exporter.iHeader)
+		{
+		const E32ImageHeader& ih = *exporter.iHeader;
+		__LDRTRACE(MyPrintf("HEAD: iCodeBase %08x, iCodeSize %x, iTextSize %x",
+							ih.iCodeBase, ih.iCodeSize, ih.iTextSize));
+		__LDRTRACE(MyPrintf("HEAD: iDataBase %08x, iDataSize %x, iBssSize %x",
+							ih.iDataBase, ih.iDataSize, ih.iBssSize));
+		}
+#endif // _DEBUG
+
+	// 'exportDir' points to the address of the 0th ordinal (symbol name data);
+	// ordinary exports start from ordinal 1
+	const TUint32* const exportDir = (TUint32*)exporter.iExportDirLoad - KOrdinalBase;
+	const TUint32 maxOrdinal = (TUint32)exporter.iExportDirCount;
+	const TUint32 absentOrdinal = (TUint32)exporter.iFileEntryPoint;
 
 	TUint32* iat = info.iIat;
-	TUint32* iatE = iat+info.iNumImports;
-	for(; iat<iatE; ++iat)
+	TUint32* const iatEnd = iat + info.iNumImports;
+	for (; iat < iatEnd; ++iat)
 		{
-		TUint32 imp = *iat;
-		if(imp>maxOrdinal)
+		// Each IAT slot contains the ordinal number of the export to be imported from
+		// the exporter. We use that index to locate the address of the export itself.
+		TUint32 ordinal = *iat;
+		if (ordinal > maxOrdinal)
 			return KErrNotSupported;
 
-		TUint32 writeValue;
-		if(imp==0 && !(info.iExporter->iAttr&ECodeSegAttNmdExpData))
-			{
-			// attempt to import ordinal zero (symbol name data) from an executable
-			// which doesn't export this information, use NULL for imported value in this case...
-			writeValue = NULL;
-			}
-		else
+		// If the import number is 0 (symbol name data), and the exporter doesn't provide
+		// this, we don't regard it as an error; we just skip this block, leaving the
+		// address set to 0. For all other valid cases, we index the export directory to
+		// find the exported object's address (which has already been relocated) ...
+		TUint32 newValue = 0;
+		if (ordinal > 0 || (exporter.iAttr & ECodeSegAttNmdExpData))
 			{
-			// get imported value from exporter...
-			TUint32 exp_addr = exp_dir[imp];
-			if(exp_addr==0 || exp_addr==absentOrdinal)
+			TUint32 expAddr = exportDir[ordinal];
+			if (expAddr == 0 || expAddr == absentOrdinal)
 				return KErrNotSupported;
-			writeValue = exp_addr + exp_delta;
+			// The new value is just the address of the export, no adjustment needed
+			newValue = expAddr;
 			}
 
-		// if not code paging then directly fix up the import...
-		if (info.iFixup64 == 0)
-			*iat = writeValue;
+		__LDRTRACE(MyPrintf("svFixupImportAddresses: import[%d]@%08x is export[%d] == %08x",
+							iat - info.iIat, iat, ordinal, newValue));
+
+		// In non-paged code, we can simply replace the ordinals in the IAT with the
+		// object addresses to which they refer once and for all. However, in a code
+		// paging system, the IAT may be thrown away and later reloaded from the code
+		// image; therefore, we need to save the updates in the buffer pointed to by
+		// 'iFixup64' so that they can be reapplied each time the code page(s)
+		// containing (parts of the) IAT are reloaded. The fixup entries are in the
+		// form of 64-bit words, with the 32-bit address-to-be-fixed-up in the upper
+		// half and the value-to-be-stored-there in the lower half -- the multiple
+		// casts are needed to stop some compilers whinging about converting a
+		// pointer to a 64-bit integral type :(
+		if (!info.iFixup64)
+			*iat = newValue;
 		else
-		// ...otherwise defer until the page is fixed up
-			{
-			TUint64 iat64 = reinterpret_cast<TUint64>(iat);
-			*info.iFixup64++ = (iat64 << 32) | writeValue;
-			}
+			*info.iFixup64++ = ((TUint64)(TUintPtr)iat << 32) | newValue;
 		}
 
+	// Finally, update 'info.iIat' to show which imports have been processed
 	info.iIat = iat;
 	return KErrNone;
 	}
@@ -436,50 +570,155 @@
 TInt svElfDerivedFixupImportAddresses(TAny* aPtr)
 	{
 	SFixupImportAddressesInfo& info = *(SFixupImportAddressesInfo*)aPtr;
-	TUint32 maxOrdinal = (TUint32)info.iExporter->iExportDirCount;
-	TUint32 absentOrdinal = (TUint32)info.iExporter->iFileEntryPoint;
-
-	TUint32* exp_dir = info.iExportDir - KOrdinalBase; // address of 0th ordinal
-	TUint32 exp_delta = info.iExportDirEntryDelta;
-	TUint32 code = info.iCodeLoadAddress;
+	E32Image& exporter = *info.iExporter;
+
+#ifdef _DEBUG
+	__LDRTRACE(MyPrintf(">svElfDerivedFixupImportAddresses %d imports, code@%08x, fixup@%08x exporter@%08x",
+						info.iNumImports, info.iCodeLoadAddress, info.iFixup64, info.iExporter));
+
+	// Dump everything potentially useful that we know about the exporter ...
+	__LDRTRACE(MyPrintf("%S: paged? %d, iRomImageHeader@%08x, iHeader@%08x",
+						&exporter.iFileName, exporter.iUseCodePaging,
+						exporter.iRomImageHeader, exporter.iHeader));
+	__LDRTRACE(MyPrintf("iCodeLoadAddress %08x, iCodeRunAddress %08x, iCodeSize %x iTextSize %x",
+						exporter.iCodeLoadAddress, exporter.iCodeRunAddress,
+						exporter.iCodeSize, exporter.iTextSize))
+	__LDRTRACE(MyPrintf("iDataLoadAddress %08x, iDataRunAddress %08x, iDataSize %x iBssSize %x iTotalDataSize %x",
+						exporter.iDataLoadAddress, exporter.iDataRunAddress,
+						exporter.iDataSize, exporter.iBssSize, exporter.iTotalDataSize));
+	__LDRTRACE(MyPrintf("iCodeDelta, %x iDataDelta %x, iExportDirEntryDelta %x",
+						exporter.iCodeDelta, exporter.iDataDelta, exporter.iExportDirEntryDelta));
+
+	if (exporter.iRomImageHeader)
+		{
+		const TRomImageHeader& rh = *exporter.iRomImageHeader;
+		__LDRTRACE(MyPrintf("ROM: iCodeAddress %08x, iCodeSize %x, iTextSize %x",
+							rh.iCodeAddress, rh.iCodeSize, rh.iTextSize));
+		__LDRTRACE(MyPrintf("ROM: iDataAddress %08x, iDataSize %x, iBssSize %x",
+							rh.iDataAddress, rh.iDataSize, rh.iBssSize));
+		__LDRTRACE(MyPrintf("ROM: iDataBssLinearBase %08x, iTotalDataSize %x",
+							rh.iDataBssLinearBase, rh.iTotalDataSize));
+		}
+
+	if (exporter.iHeader)
+		{
+		const E32ImageHeader& ih = *exporter.iHeader;
+		__LDRTRACE(MyPrintf("HEAD: iCodeBase %08x, iCodeSize %x, iTextSize %x",
+							ih.iCodeBase, ih.iCodeSize, ih.iTextSize));
+		__LDRTRACE(MyPrintf("HEAD: iDataBase %08x, iDataSize %x, iBssSize %x",
+							ih.iDataBase, ih.iDataSize, ih.iBssSize));
+		}
+#endif // _DEBUG
+
+	// Here we calculate the bounds of each section of the exporter, as
+	// code and data exports may have to be offset by different amounts.
+	// Unfortunately, the required information seems to be in several
+	// different places, depending on whether the code is ROM or RAM, etc
+	TUint32 codeStart = exporter.iCodeRunAddress;
+	TUint32 codeEnd = codeStart + exporter.iCodeSize;
+	TUint32 dataStart = exporter.iDataRunAddress;
+	TUint32 dataEnd = dataStart + exporter.iTotalDataSize;
+
+	if (exporter.iRomImageHeader)
+		{
+		const TRomImageHeader& rh = *exporter.iRomImageHeader;
+		codeStart = rh.iCodeAddress;
+		codeEnd = codeStart + rh.iCodeSize;
+		dataStart = rh.iDataBssLinearBase;
+		dataEnd = dataStart + rh.iTotalDataSize;
+		}
+
+	if (exporter.iHeader)
+		{
+		const E32ImageHeader& ih = *exporter.iHeader;
+		codeStart = ih.iCodeBase;
+		codeEnd = codeStart + ih.iCodeSize;
+		dataStart = ih.iDataBase;
+		dataEnd = dataStart + ih.iDataSize + ih.iBssSize;
+		}
+
+	// 'exportDir' points to the address of the 0th ordinal (symbol name data);
+	// ordinary exports start from ordinal 1
+	const TUint32* const exportDir = (TUint32*)exporter.iExportDirLoad - KOrdinalBase;
+	const TUint32 maxOrdinal = (TUint32)exporter.iExportDirCount;
+	const TUint32 absentOrdinal = (TUint32)exporter.iFileEntryPoint;
+
+	const TUint32 codeDelta = exporter.iCodeDelta;
+	const TUint32 dataDelta = exporter.iDataDelta;
+	const TUint32 dirDelta = exporter.iExportDirEntryDelta;
+	TUint8* const codeBase = (TUint8*)info.iCodeLoadAddress;
 
 	TUint32* iol = info.iImportOffsetList;
-	TUint32* iolE = iol+info.iNumImports;
-	for(; iol<iolE; ++iol)
+	TUint32* const iolEnd = iol + info.iNumImports;
+	for(; iol < iolEnd; ++iol)
 		{
-		TUint32* impPtr = (TUint32*)(code+*iol);
-		TUint32 impd = *impPtr;
-		TUint32 imp = impd & 0xffff;
-		TUint32 offset = impd >> 16;
-		if(imp>maxOrdinal)
+		// Whereas the PE format's IAT contains ordinals to be imported, the ELF IOL
+		// (Import Offset List) is a list of offsets (within the importer's code) of
+		// the locations that contain references to imported objects.
+		//
+		// At the start of this process, each such location contains a composite value,
+		// of which the low 16 bits indicate the ordinal to be imported from the
+		// exporter's directory, and the upper 16 provide an optional adjustment to
+		// be added to the imported value.
+		//
+		// This composite value has to be replaced by the actual address of the
+		// object being imported (plus the adjustment factor, if any).
+		TUint32 codeOffset = *iol;
+		TUint32* codePtr = (TUint32*)(codeBase+codeOffset);
+		TUint32 importInfo = *codePtr;
+		TUint32 ordinal = importInfo & 0xffff;
+		TUint32 adjustment = importInfo >> 16;
+		if(ordinal > maxOrdinal)
 			return KErrNotSupported;
 
-		TUint32 writeValue;
-		if(imp==0 && !(info.iExporter->iAttr&ECodeSegAttNmdExpData))
+		// If the import number is 0 (symbol name data), and the exporter doesn't provide
+		// this, we don't regard it as an error; we just skip this block, leaving the
+		// address set to 0. For all other valid cases, we index the export directory to find
+		// the exported object's address (which may OR MAY NOT have already been relocated)
+		TUint32 expAddr = 0;
+		TUint32 newValue = 0;
+		if (ordinal > 0 || (exporter.iAttr & ECodeSegAttNmdExpData))
 			{
-			// attempt to import ordinal zero (symbol name data) from an executable
-			// which doesn't export this information, use NULL for imported value in this case...
-			writeValue = NULL;
+			expAddr = exportDir[ordinal];
+			if(expAddr == 0 || expAddr == absentOrdinal)
+				return KErrNotSupported;
+
+			// If the exporter does not use code paging, then the entries in the export
+			// table will already have been relocated along with its text section. In
+			// the paged case, however, the relocation will have been deferred until the
+			// relevant pages are (re)loaded; therefore, we have to deduce here whether
+			// each export is code or data so that we can apply the correct delta ...
+			TUint32 sectionDelta;
+			if (!exporter.iUseCodePaging)
+				sectionDelta = dirDelta;
+			else if (expAddr >= codeStart && expAddr < codeEnd)
+				sectionDelta = codeDelta;			// points to text/rdata section
+			else if (expAddr >= dataStart && expAddr < dataEnd)
+				sectionDelta = dataDelta;			// points to data/bss section
+			else
+				sectionDelta = dirDelta;			// unknown - assume nonpaged?
+			newValue = expAddr + sectionDelta + adjustment;
 			}
+
+		__LDRTRACE(MyPrintf("svElfDerivedFixupImportAddresses: import[%d] (%08x:%08x) is export[%d] %08x+%08x => %08x",
+							iol - info.iImportOffsetList, codePtr, importInfo, ordinal, expAddr, adjustment, newValue));
+
+		// In non-paged code, we can simply replace the ordinals in the IAT with the
+		// object addresses to which they refer once and for all. However, in a code
+		// paging system, the IAT may be thrown away and later reloaded from the code
+		// image; therefore, we need to save the updates in the buffer pointed to by
+		// 'iFixup64' so that they can be reapplied each time the code page(s)
+		// containing (parts of the) IAT are reloaded. The fixup entries are in the
+		// form of 64-bit words, with the 32-bit address-to-be-fixed-up in the upper
+		// half and the value-to-be-stored-there in the lower half -- the multiple
+		// casts are needed to stop some compilers whinging about converting a
+		// pointer to a 64-bit integral type :(
+		if (!info.iFixup64)
+			*codePtr = newValue;
 		else
-			{
-			// get imported value from exporter...
-			TUint32 exp_addr = exp_dir[imp];
-			if(exp_addr==0 || exp_addr==absentOrdinal)
-				return KErrNotSupported;
-			writeValue = exp_addr + exp_delta + offset;
-			}
-
-		// if not code paging then directly fix up the import...
-		if (info.iFixup64 == 0)
-			*impPtr = writeValue;
-		// ...otherwise defer until the page is fixed up
-		else
-			{
-			TUint64 impPtr64 = reinterpret_cast<TUint64>(impPtr);
-			*info.iFixup64++ = (impPtr64 << 32) | writeValue;
-			}
+			*info.iFixup64++ = ((TUint64)(TUintPtr)codePtr << 32) | newValue;
 		}
+
 	return KErrNone;
 	}
 
@@ -2834,8 +3073,9 @@
 			//	on "new" dlls
 			if (e->iDepCount && !e->iAlreadyLoaded && e->iIsDll)
 				{
-				__IF_DEBUG(Printf("****Go recursive****"));
+				__IF_DEBUG(Printf("****Going recursive****"));
 				r = e->LoadDlls(aArray);
+				__IF_DEBUG(Printf("****Returned from recursion****"));
 				if (r!=KErrNone)
 					{
 					return r;
@@ -2956,8 +3196,6 @@
 			r = exp->ReadExportDirLoad();
 			if (r != KErrNone)
 				return r;
-			info.iExportDir = (TUint32*)exp->iExportDirLoad;
-			info.iExportDirEntryDelta = exp->iExportDirEntryDelta;
 			info.iNumImports = block->iNumberOfImports;
 			info.iExporter = exp;
 
@@ -2976,10 +3214,14 @@
 			if (impfmt == KImageImpFmt_ELF)
 				{
 				info.iImportOffsetList = (TUint32*)(block+1);
+				__IF_DEBUG(Printf("Import format ELF (%08x); info@%08x", impfmt, &info));
 				r = ExecuteInSupervisorMode(&svElfDerivedFixupImportAddresses, &info);
 				}
 			else
+				{
+				__IF_DEBUG(Printf("Import format PE (%08x); info@%08x", impfmt, &info));
 				r = ExecuteInSupervisorMode(&svFixupImportAddresses, &info);
+				}
 
 			if (r != KErrNone)
 				{
@@ -3058,7 +3300,18 @@
 */
 TInt E32Image::BuildImportFixupTable()
 	{
-	__IF_DEBUG(Printf(">BuildImportFixupTable,0x%08x,%d", iFixups, iFixupCount));
+	__IF_DEBUG(Printf(">BuildImportFixupTable,%d@%08x,%08x", iFixupCount, iFixups, iCodeLoadAddress));
+
+#ifdef _DEBUG
+	// Dump the incoming fixup table if loader tracing enabled. Each item is an
+	// (address, value) pair, where the address and the value are 32 bits each.
+	TInt i;
+	for (i = 0; i < iFixupCount; ++i)
+		{
+		TUint64 x = iFixups[i];
+		__IF_DEBUG(Printf("%04x: %08x %08x", i*sizeof(TUint64), I64HIGH(x), I64LOW(x)));
+		}
+#endif	// DEBUG
 
 	// sort the array in address order, to organize by page
 	RArray<TUint64> fixup64ToSort(sizeof(TUint64), iFixups, iFixupCount);
@@ -3070,7 +3323,7 @@
 	// to the word at offset XXX.  (See PREQ1110 Design Sketch v1.0 S3.1.1.2.3.2.)
 
 	TUint32 pageCount = SizeToPageCount(iCodeSize);
-	iImportFixupTableSize = (pageCount+1) * sizeof(TUint32) + iFixupCount * 3 * sizeof(TUint16);
+	iImportFixupTableSize = (pageCount+1)*sizeof(TUint32) + 3*iFixupCount*sizeof(TUint16);
 	iImportFixupTable = (TUint32*) User::Alloc(iImportFixupTableSize);
 	__IF_DEBUG(Printf("iImportFixupTable=0x%08x", iImportFixupTable));
 	if (iImportFixupTable == 0)
@@ -3121,18 +3374,20 @@
 	while (++lastPage <= pageCount)
 		iImportFixupTable[lastPage] = iImportFixupTableSize;
 
-	__IF_DEBUG(Printf("processed table (size=%d,pageCount=%d)", iImportFixupTableSize, pageCount));
-
 #ifdef _DEBUG
-	// dump the import fixup table if loader tracing enabled
+	__IF_DEBUG(Printf("processed fixup table (size=%d,pageCount=%d)", iImportFixupTableSize, pageCount));
+
+	// Dump the processed fixup table if loader tracing enabled. The dump is in two
+	// parts; first, the page indexes (1 word per page), then the entries describing
+	// the items to be relocated, each of which is a 16-bit offset-within-page and a
+	// 32-bit value to be stored there.
+	for (i = 0; i <= (TInt)pageCount; ++i)
+		__IF_DEBUG(Printf("%04x: %08x", i*4, iImportFixupTable[i]));
+
 	const TUint16* table16 = (const TUint16*)iImportFixupTable;
 	const TInt halfWordsInTable = iImportFixupTableSize / 2;
-	for (TInt i = 0; i < halfWordsInTable; i += 4)
-		{
-		__IF_DEBUG(Printf(
-			"%04x: %04x %04x %04x %04x",
-			i * 2, table16[i+0], table16[i+1], table16[i+2], table16[i+3]));
-		}
+	for (i *= 2; i < halfWordsInTable; i += 3)
+		__IF_DEBUG(Printf("%04x: %04x %04x%04x", i*2, table16[i+0], table16[i+2], table16[i+1]));
 #endif
 
 	User::Free(iFixups);
--- a/userlibandfileserver/fileserver/sfile/sf_main.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/sfile/sf_main.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -474,7 +474,9 @@
 	KernHeapAllocFailCount=-1;
 #endif
 	
-	TInt r= RequestAllocator::iCacheLock.CreateLocal();
+	TInt r = RequestAllocator::Initialise();
+	__ASSERT_ALWAYS(r==KErrNone,Fault(EFsCacheLockFailure));
+	r = OperationAllocator::Initialise();
 	__ASSERT_ALWAYS(r==KErrNone,Fault(EFsCacheLockFailure));
 	
 	// initialise the TParse pool lock object
@@ -492,7 +494,6 @@
 	r=FsThreadManager::CreateDisconnectThread();
 	__ASSERT_ALWAYS(r==KErrNone,Fault(EMainDisconnectThread));
 
-	RequestAllocator::Initialise();
 
 	//
 	// Install a trap handler
--- a/userlibandfileserver/fileserver/sfile/sf_request.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/sfile/sf_request.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -27,81 +27,25 @@
 
 CFsClientMessageRequest* RequestAllocator::iFreeHead;				
 CFsClientMessageRequest* RequestAllocator::iCloseHead;
-TInt RequestAllocator::iAllocNum;
-TInt RequestAllocator::iAllocNumOperation;
-TMsgOperation* RequestAllocator::iFreeHeadSupOp;
-
-#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
-TInt RequestAllocator::iAllocated;
-#endif
+TInt RequestAllocator::iRequestCount;
+TInt RequestAllocator::iFreeCount;
+TInt RequestAllocator::iRequestCountPeak;
 RFastLock RequestAllocator::iCacheLock;
 
-void RequestAllocator::Initialise()
-	{	
-	iFreeHead=NULL;  
-	iCloseHead=NULL; 
-	iAllocNum=0; 
-#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
-	iAllocated=0;
-#endif
-	iAllocNumOperation=0;
-	iFreeHeadSupOp=NULL;
-	}
+TMsgOperation* OperationAllocator::iFreeHead;				
+TInt OperationAllocator::iRequestCount;
+TInt OperationAllocator::iFreeCount;
+TInt OperationAllocator::iRequestCountPeak;
+RFastLock OperationAllocator::iCacheLock;
 
-TInt RequestAllocator::AllocRequest(TInt aNum)
-//
-//	Allocates a group of request objects
-//
-	{
-    TInt i;
-	if(iAllocNum < KMaxRequestAllocated)
-		{
-		__CACHE_PRINT(_L("RequestAllocator::AllocRequest() Not reached the limit"));
-		CFsClientMessageRequest* list;
-		CFsClientMessageRequest* start;
-		list = new CFsClientMessageRequest[KAllocReqBlock];
-		start = list;
-		if(!list)
-			return KErrNoMemory;
-		
-		// Make sure the constructors are called for every element in the array
-		// - some compilers don't do this
-		for(TInt j=0; j<KAllocReqBlock; j++)
-			{
-			CFsClientMessageRequest* request = &list[j];
-			new(request) CFsClientMessageRequest();
-			}
-
-		iAllocNum += KAllocReqBlock;
-		CFsClientMessageRequest* last;
-		for(i=1;i<KAllocReqBlock;i++)
-			{
-			last = list;
-			list++;
-			last->iNext = list;
-			}
-		list->iNext = iFreeHead;
-		iFreeHead = start;
-		return KErrNone;
-		}
-	else
-		{
-		__CACHE_PRINT1(_L("RequestAllocator::AllocRequest() Limit exceeded Count = %d"),aNum);
-		CFsClientMessageRequest* request;
-		for(i=0;i<aNum;i++)
-			{
-			request=new CFsClientMessageRequest;
-			if(!request)
-				return KErrNoMemory;
-#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
-			iAllocated++;
-#endif
-			request->SetAllocated();
-			request->iNext=iFreeHead;
-			iFreeHead=request;
-			}
-		return KErrNone;
-		}
+TInt RequestAllocator::Initialise()
+	{	
+	iFreeHead = NULL;  
+	iCloseHead = NULL; 
+	iRequestCount = 0; 
+	iFreeCount = 0;
+	iRequestCountPeak = 0;
+	return iCacheLock.CreateLocal();
 	}
 
 void RequestAllocator::FreeRequest(CFsClientMessageRequest* aRequest)
@@ -109,28 +53,28 @@
 //free request 
 //
 	{
-	__CACHE_PRINT1(_L("PLUGIN: RequestAllocator::FreeRequest for %x"), aRequest);
-	if(aRequest->IsAllocated())
+	__CACHE_PRINT1(_L("RequestAllocator::FreeRequest for %x"), aRequest);
+	ASSERT(aRequest != NULL);
+	iCacheLock.Wait();
+	if (iFreeCount >= KFreeCountMax)
 		{
-		__CACHE_PRINT(_L("RequestAllocator::FreeRequest() Allocated request"));
-		delete(aRequest);
-#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
-		iAllocated--;
-#endif
-		return;
+		delete aRequest;
+		ASSERT(iRequestCount > 0);
+		iRequestCount--;
 		}
-	
-	__CACHE_PRINT(_L("RequestAllocator::FreeRequest() returning to free list"));
-	iCacheLock.Wait();
-	aRequest->iNext = iFreeHead;
-	iFreeHead=aRequest;
-	aRequest->SetSubstedDrive(NULL);
+	else
+		{
+		aRequest->SetSubstedDrive(NULL);
+		aRequest->iNext = iFreeHead;
+		iFreeHead=aRequest;
+		iFreeCount++;
+		}
 	iCacheLock.Signal();
 	}
 
 void RequestAllocator::OpenSubFailed(CSessionFs* aSession)
 //
-//	Move requst from closed list to free list
+//	Move request from closed list to free list
 //
 	{
 	__ASSERT_DEBUG(iCloseHead!=NULL,Fault(ERequestAllocatorOpenSubFailed)); // On arriving here Close Queue is supposed to be empty
@@ -142,34 +86,39 @@
 	iCacheLock.Wait();
 	CFsClientMessageRequest* rp = iCloseHead;
 	iCloseHead = rp->iNext;
+	iCacheLock.Signal();
 	
 	// dec the number of closed requests owned by this session
 	aSession->CloseRequestCountDec();
 
-	rp->iNext = NULL;
-	if(rp->IsAllocated())
+	__CACHE_PRINT1(_L("RequestAllocator::OpenSubFailed() IsAllocated %d"), rp->IsAllocated());
+	FreeRequest(rp);
+	}
+
+CFsClientMessageRequest* RequestAllocator::GetRequest()
+//
+// Get request from the free queue
+//
+	{
+	CFsClientMessageRequest* request;
+	if (iFreeHead == NULL)
 		{
-		__CACHE_PRINT(_L("RequestAllocator::OpenSubFailed() Allocated request"));
-		delete(rp);
-#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
-		iAllocated--;
-#endif
+		request = new CFsClientMessageRequest;
+		if (request)
+			{
+			iRequestCount++;
+			iRequestCountPeak = Max(iRequestCountPeak, iRequestCount);
+			}
 		}
 	else
 		{
-		__CACHE_PRINT(_L("RequestAllocator::OpenSubFailed()"));
-		if(iFreeHead)
-			{
-			rp->iNext = iFreeHead;
-			}
-		else
-			{
-			rp->iNext = NULL;
-			}
-
-		iFreeHead = rp;		
+		request = iFreeHead;
+		iFreeHead = iFreeHead->iNext;
+		request->iNext = NULL;
+		iFreeCount--;
+		ASSERT(iFreeCount >= 0);
 		}
-	iCacheLock.Signal();
+	return request;
 	}
 
 TInt RequestAllocator::GetMessageRequest(const TOperation& aOperation,const RMessage2& aMessage,CFsClientMessageRequest* &aRequest)
@@ -181,27 +130,20 @@
 		{
 		__CACHE_PRINT(_L("++RequestAllocator::GetMessageRequest() Open sub-sess"));
 		iCacheLock.Wait();
-		if(iFreeHead == NULL || iFreeHead->iNext == NULL)
-			{
-			if(AllocRequest(2)!= KErrNone)
-				{
-				iCacheLock.Signal();
-				return KErrNoMemory;
-				}
-			}
-		aRequest= iFreeHead;						//get our request from free head
-		iFreeHead = iFreeHead->iNext->iNext;	//set next but one as new free head read for next
 
-		aRequest->iNext->iNext = NULL;				//seperate our request and close from free list
-		CFsClientMessageRequest* CRp = aRequest->iNext;
-		aRequest->iNext = NULL;
-		if(iCloseHead)
+		aRequest = GetRequest();
+		CFsClientMessageRequest* closeRequest = GetRequest();
+		
+		if (aRequest == NULL || closeRequest == NULL)
 			{
-			CRp->iNext = iCloseHead;		//set second one as a reserved (tail) close request
-			iCloseHead = CRp;
+			delete aRequest;
+			delete closeRequest;
+			iCacheLock.Signal();
+			return KErrNoMemory;
 			}
-		else
-			iCloseHead = CRp;
+
+		closeRequest->iNext = iCloseHead;		//set second one as a reserved (tail) close request
+		iCloseHead = closeRequest;
 		
 		((CSessionFs*) aMessage.Session())->CloseRequestCountInc();
 		}
@@ -272,6 +214,7 @@
 			}
 
 		iCacheLock.Wait();
+		ASSERT(iCloseHead);
 		aRequest = iCloseHead;
 		iCloseHead = aRequest->iNext;
 		((CSessionFs*) aMessage.Session())->CloseRequestCountDec();
@@ -289,17 +232,12 @@
 		{
 		__CACHE_PRINT(_L("++RequestAllocator::GetMessageRequest() "));
 		iCacheLock.Wait();
-		if(!iFreeHead)
+		aRequest = GetRequest();
+		if (aRequest == NULL)
 			{
-			if(AllocRequest(1) != KErrNone)
-				{
-				iCacheLock.Signal();
-				return KErrNoMemory; 
-				}
+			iCacheLock.Signal();
+			return KErrNoMemory; 
 			}
-		aRequest = iFreeHead;						
-		iFreeHead = aRequest->iNext;
-		aRequest->iNext= NULL;
 		}
 
 	aRequest->Init();
@@ -322,126 +260,103 @@
 #if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
 TInt RequestAllocator::CloseCount()
 	{TInt count=0;
+	iCacheLock.Wait();
+
 	CFsClientMessageRequest* list=iCloseHead;
 	while(list!=NULL)
 		{
 		count++;
 		list=list->iNext;
 		}
+
+	iCacheLock.Signal();
 	return(count);
 	} 
 TInt RequestAllocator::FreeCount()
 	{
 	TInt count=0;
+	iCacheLock.Wait();
 	CFsClientMessageRequest* list=iFreeHead;
 	while(list!=NULL)
 		{
 		count++;
 		list=list->iNext;
 		}
-	return(count);}
+	ASSERT(count == iFreeCount);
+	iCacheLock.Signal();
+	return(count);
+	}
 #endif
 
-TInt RequestAllocator::AllocOperation()
-//
-//	Allocates a group of TMsgOperation objects
+TInt OperationAllocator::Initialise()
+	{	
+	iFreeHead = NULL;  
+	iRequestCount = 0; 
+	iFreeCount = 0;
+	return iCacheLock.CreateLocal();
+	}
+
+void OperationAllocator::FreeOperation(TMsgOperation* aOperation)
 //
-// Must be called with iCacheLock held
+// free Operation
+//
 	{
-    TInt i;
-	if(iAllocNumOperation < KMaxOperationAllocated)
+	__CACHE_PRINT1(_L("RequestAllocator::FreeOperation() returning %x to free list"), aOperation);
+	ASSERT(aOperation != NULL);
+	iCacheLock.Wait();
+	if (iFreeCount >= KFreeCountMax)
 		{
-		__CACHE_PRINT(_L("RequestAllocator::AllocOperation() Not reached the limit"));
-		TMsgOperation* list;
-		TMsgOperation* start;
-		list = new TMsgOperation[KAllocReqBlock];
-		start = list;
-		if(!list)
-			return KErrNoMemory;
-		
-		for(TInt j=0; j<KAllocReqBlock; j++)
-			{
-			TMsgOperation* request = &list[j];
-			request->iIsAllocated = EFalse;
-			}
-
-		iAllocNumOperation += KAllocReqBlock;
-		TMsgOperation* last;
-		for(i=1;i<KAllocReqBlock;i++)
-			{
-			last = list;
-			list++;
-			last->iNext = list;
-			}
-		list->iNext = iFreeHeadSupOp;
-		iFreeHeadSupOp = start;
-		return KErrNone;
+		delete aOperation;
+		ASSERT(iRequestCount > 0);
+		iRequestCount--;
 		}
 	else
 		{
-		__CACHE_PRINT(_L("RequestAllocator::AllocOperation() Limit exceeded"));
-		TMsgOperation* request;
+		aOperation->iNext = iFreeHead;
+		iFreeHead = aOperation;
+		iFreeCount++;
+		}
 
-		request=new TMsgOperation;
-		if(!request)
-			return KErrNoMemory;
-#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
-		iAllocated++;
-#endif
-		request->iIsAllocated = ETrue;
-		request->iNext=iFreeHeadSupOp;
-		iFreeHeadSupOp=request;
+	iCacheLock.Signal();
+	}
 
-		return KErrNone;
-		}
-	}
-TInt RequestAllocator::GetOperation(TMsgOperation* &aOperation)
+TInt OperationAllocator::GetOperation(TMsgOperation* &aOperation)
 //
 //	tries to get a pre allocated subop from the cache. Failing that allocates one individualy 
 //	
 	{
 
 	__CACHE_PRINT(_L("RequestAllocator::GetOperation() "));
+
 	iCacheLock.Wait();
-	if(!iFreeHeadSupOp)
+
+	TInt r = KErrNone;
+	if (iFreeHead == NULL)
 		{
-		if(AllocOperation() != KErrNone)
+		aOperation = new TMsgOperation;
+		if (aOperation == NULL)
+			r = KErrNoMemory; 
+		else
 			{
-			iCacheLock.Signal();
-			return KErrNoMemory; 
+			iRequestCount++;
+			iRequestCountPeak = Max(iRequestCountPeak, iRequestCount);
 			}
 		}
-	aOperation = iFreeHeadSupOp;						
-	iFreeHeadSupOp = aOperation->iNext;
-	aOperation->iNext = aOperation->iPrev = NULL;
+	else
+		{
+		aOperation = iFreeHead;
+		iFreeHead = iFreeHead->iNext;
+		iFreeCount--;
+		ASSERT(iFreeCount >= 0);
+		}
+
+	if (aOperation)
+		aOperation->iNext = aOperation->iPrev = NULL;
 
 	iCacheLock.Signal();
-	return KErrNone;
+	return r;
 	}	
 
-void RequestAllocator::FreeOperation(TMsgOperation* aOperation)
-//
-// free Operation
-//
-	{
-	if(aOperation->iIsAllocated)
-		{
-		__CACHE_PRINT(_L("RequestAllocator::FreeOperation() Allocated subop"));
-		delete(aOperation);
-#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
-		iAllocated--;
-#endif
-		return;
-		}
-	
-	__CACHE_PRINT(_L("RequestAllocator::FreeOperation() returning to free list"));
-	iCacheLock.Wait();
-	aOperation->iNext = iFreeHeadSupOp;	// NB backward link only used when request in in use
-	iFreeHeadSupOp = aOperation;
-
-	iCacheLock.Signal();
-	}
-
 
 CFsRequest::CFsRequest()
 //
@@ -1821,7 +1736,7 @@
 TInt CFsMessageRequest::PushOperation(TFsRequestFunc aCallback, TInt aNextState, TInt aFunction)
 	{
 	TMsgOperation* nextOperation;
-	TInt r = RequestAllocator::GetOperation(nextOperation);
+	TInt r = OperationAllocator::GetOperation(nextOperation);
 	if (r != KErrNone)
 		return r;
 
@@ -1949,7 +1864,7 @@
 			SetOperationFunc(iCurrentOperation->iFunction);
 		}
 
-	RequestAllocator::FreeOperation(currentOperation);
+	OperationAllocator::FreeOperation(currentOperation);
 	}
 
 TMsgOperation& CFsMessageRequest::CurrentOperation()
--- a/userlibandfileserver/fileserver/sfile/sf_std.h	Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/sfile/sf_std.h	Mon Mar 15 12:45:50 2010 +0200
@@ -1398,9 +1398,10 @@
 	TRequestStatus iStatus;
 	TBool iIsAllocated;
 	};
-const TInt KMaxRequestAllocated		= 45;
-const TInt KMaxOperationAllocated	= KMaxRequestAllocated * 2;
-const TInt KAllocReqBlock=15;
+
+// If the number of requests on the free queue reaches this value then completed requests 
+// are returned to the heap rather than being added to thefree queue
+const TInt KFreeCountMax = 64;
 
 class TParseCon
 	{
@@ -1413,34 +1414,53 @@
 class RequestAllocator
 	{
 public:
+	static TInt Initialise();
+
 	static TInt GetMessageRequest(const TOperation& aOperation,const RMessage2& aMessage,CFsClientMessageRequest* &aRequest);
-	static void FreeRequest(CFsClientMessageRequest* aRequest); // Use the one from cache
+	static void FreeRequest(CFsClientMessageRequest* aRequest);
 	static void OpenSubFailed(CSessionFs* aSession); 
-	static TInt AllocRequest(TInt aNum);
+
+#if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
+	inline static TInt RequestCount();
+	inline static TInt RequestCountPeak();
+	static TInt CloseCount();
+	static TInt FreeCount();
+#endif
+
+private:
+	static CFsClientMessageRequest* GetRequest();
 
-	static TInt AllocOperation();
+private:
+	static RFastLock iCacheLock;
+	static CFsClientMessageRequest* iFreeHead;				
+	static CFsClientMessageRequest* iCloseHead;
+
+	static TInt iRequestCount;			// current number of requests
+	static TInt iFreeCount;				// current number of requests on free queue
+	static TInt iRequestCountPeak;				// maximum value of requests reached
+	};
+
+class OperationAllocator
+	{
+public:
+	static TInt Initialise();
+
 	static TInt GetOperation(TMsgOperation* &aOperation);
 	static void FreeOperation(TMsgOperation* aOperation);
 
-
-	static void Initialise();
 #if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
-	inline static TInt TotalCount();
-	static TInt CloseCount();
-	static TInt FreeCount();
-	inline static TInt AllocatedCount();
-private:
-	static TInt iAllocated;
+	inline static TInt RequestCount();
+	inline static TInt RequestCountPeak();
+	inline static TInt FreeCount();
 #endif
-public:
-	static RFastLock iCacheLock;
+
 private:
-	static TInt iAllocNum;
-	static CFsClientMessageRequest* iFreeHead;				
-	static CFsClientMessageRequest* iCloseHead;
+	static RFastLock iCacheLock;
+	static TMsgOperation* iFreeHead;
 
-	static TInt iAllocNumOperation;
-	static TMsgOperation* iFreeHeadSupOp;
+	static TInt iRequestCount;			// current number of requests
+	static TInt iFreeCount;				// current number of requests on free queue
+	static TInt iRequestCountPeak;				// maximum value of requests reached
 	};
 
 
--- a/userlibandfileserver/fileserver/sfile/sf_std.inl	Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/sfile/sf_std.inl	Mon Mar 15 12:45:50 2010 +0200
@@ -310,12 +310,19 @@
 
 #if defined(_USE_CONTROLIO) || defined(_DEBUG) || defined(_DEBUG_RELEASE)
 // Class RequestAllocator
-/** returns number of dynamically allocated requests  */
-TInt RequestAllocator::AllocatedCount()
-{ return iAllocated;}
 /** returns number of permanently & dynamically allocated requests  */
-TInt RequestAllocator::TotalCount()
-{ return iAllocated + iAllocNum;}
+TInt RequestAllocator::RequestCount()
+	{ return iRequestCount;}
+TInt RequestAllocator::RequestCountPeak()
+	{ return iRequestCountPeak;}
+
+TInt OperationAllocator::FreeCount()
+	{ return iFreeCount;}
+TInt OperationAllocator::RequestCount()
+	{ return iRequestCount;}
+TInt OperationAllocator::RequestCountPeak()
+	{ return iRequestCountPeak;}
+
 #endif
 
 //---------------------------------------------------------------------------------------------------------------------
--- a/userlibandfileserver/fileserver/sfsrv/cl_parse.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/sfsrv/cl_parse.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -302,9 +302,9 @@
 	TInt pos=aName.Locate(KPathDelimiter);
 	if (pos!=KErrNotFound)
 		return(KErrBadName);
-	TFileName n=aName;
-	n.Append(KPathDelimiter);
-	NameBuf().Insert(iField[EName].pos,n);
+	
+	NameBuf().Insert(iField[EName].pos,aName);
+	NameBuf().Insert(iField[EName].pos + aName.Length(),TPtrC16((const TUint16*)(&KPathDelimiter),1));
 	iField[EPath].len=(TUint8)(iField[EPath].len+len);
 	iField[EName].pos=(TUint8)(iField[EName].pos+len);
 	iField[EExt].pos=(TUint8)(len+iField[EExt].pos);
--- a/userlibandfileserver/fileserver/smassstorage/cmassstoragefilesystem.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/smassstorage/cmassstoragefilesystem.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -21,6 +21,8 @@
 */
 
 #include <f32file.h>
+#include <f32ver.h>
+#include "cusbmassstoragecontroller.h"
 #include "cmassstoragefilesystem.h"
 #include "cmassstoragemountcb.h"
 #include "massstoragedebug.h"
--- a/userlibandfileserver/fileserver/smassstorage/cmassstoragemountcb.cpp	Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/smassstorage/cmassstoragemountcb.cpp	Mon Mar 15 12:45:50 2010 +0200
@@ -23,10 +23,9 @@
 #include <f32fsys.h>
 #include <f32file.h>
 #include "cmassstoragemountcb.h"
+#include "cusbmassstoragecontroller.h"
 #include "cmassstoragefilesystem.h"
-#include "drivemanager.h"
 #include "massstoragedebug.h"
-#include "massstorageutil.h"
 
 CMassStorageMountCB::CMassStorageMountCB(const RArray<TInt>& aDriveMapping)
     : iDriveMapping(aDriveMapping)
@@ -214,281 +213,6 @@
 	delete hDes;
 	}
 
-/**
-Make sure that the file system is fat.
-*/
-TBool CMassStorageMountCB::ValidateBootSector()
-	{
-	__FNLOG("CMassStorageMountCB::ValidateBootSector");
-
-	TFatBootSector bootSector;
-	TInt r=ReadBootSector(bootSector);
-	__PRINT1(_L("CMassStorageMountCB::MountL - ReadBootSector returned %d"),r);
-	if (r != KErrNone)
-		{
-		return EFalse;
-		}
-
-	__PRINT(_L("\nBootSector info"));
-	__PRINT8BIT1(_L("FAT type = %S"),bootSector.FileSysType());
-	__PRINT8BIT1(_L("Vendor ID = %S"),bootSector.VendorId());
-	__PRINT1(_L("BytesPerSector %d"),bootSector.BytesPerSector());
-	__PRINT1(_L("SectorsPerCluster %d"),bootSector.SectorsPerCluster());
-	__PRINT1(_L("ReservedSectors %d"),bootSector.ReservedSectors());
-	__PRINT1(_L("NumberOfFats %d"),bootSector.NumberOfFats());
-	__PRINT1(_L("RootDirEntries %d"),bootSector.RootDirEntries());
-	__PRINT1(_L("Total Sectors = %d"),bootSector.TotalSectors());
-	__PRINT1(_L("MediaDescriptor = 0x%x"),bootSector.MediaDescriptor());
-	__PRINT1(_L("FatSectors %d"),bootSector.FatSectors());
-	__PRINT1(_L("SectorsPerTrack %d"),bootSector.SectorsPerTrack());
-	__PRINT1(_L("NumberOfHeads %d"),bootSector.NumberOfHeads());
-	__PRINT1(_L("HugeSectors %d"),bootSector.HugeSectors());
-	__PRINT1(_L("Fat32 Sectors %d"),bootSector.FatSectors32());
-	__PRINT1(_L("Fat32 Flags %d"),bootSector.FATFlags());
-	__PRINT1(_L("Fat32 Version Number %d"),bootSector.VersionNumber());
-	__PRINT1(_L("Root Cluster Number %d"),bootSector.RootClusterNum());
-	__PRINT1(_L("FSInfo Sector Number %d"),bootSector.FSInfoSectorNum());
-	__PRINT1(_L("Backup Boot Rec Sector Number %d"),bootSector.BkBootRecSector());
-	__PRINT1(_L("PhysicalDriveNumber %d"),bootSector.PhysicalDriveNumber());
-	__PRINT1(_L("ExtendedBootSignature %d"),bootSector.ExtendedBootSignature());
-	__PRINT1(_L("UniqueID %d"),bootSector.UniqueID());
-	__PRINT8BIT1(_L("VolumeLabel %S"),bootSector.VolumeLabel());
-	__PRINT8BIT1(_L("FileSysType %S\n"),bootSector.FileSysType());
-
-    iUniqueID=bootSector.UniqueID();
-	iIs16BitFat=bootSector.Is16BitFat();
-
-	iIs32BitFat=bootSector.Is32BitFat();
-	switch (DetermineFatType(bootSector))
-		{
-		case 12:
-			iIs16BitFat = EFalse;
-			iIs32BitFat = EFalse;
-			break;
-		case 16:
-			iIs16BitFat = ETrue;
-			iIs32BitFat = EFalse;
-			break;
-		case 32:
-			iIs16BitFat = EFalse;
-			iIs32BitFat = ETrue;
-			break;
-		default:
-			return EFalse;
-		}
-
-	TInt sectorsPerCluster=bootSector.SectorsPerCluster();
-	if (!IsPowerOfTwo(sectorsPerCluster))
-		return EFalse;
-
-	TInt sectorSizeLog2=Log2(bootSector.BytesPerSector());
-	if (sectorSizeLog2<0 || !IsPowerOfTwo(bootSector.BytesPerSector()))
-		return EFalse;
-
-	TInt firstFatSector=bootSector.ReservedSectors();
-	if (firstFatSector<1)
-		return EFalse;
-
-	TInt fatSizeInBytes;
-	if(iIs32BitFat)
-		{
-		fatSizeInBytes=bootSector.FatSectors32()*bootSector.BytesPerSector();
-		if (fatSizeInBytes<bootSector.BytesPerSector())
-			return EFalse;
-		}
-	else
-		{
-		fatSizeInBytes=bootSector.FatSectors()*bootSector.BytesPerSector();
-		if (fatSizeInBytes<bootSector.BytesPerSector())
-			return EFalse;
-
-		TInt rootDirectorySector=firstFatSector+bootSector.FatSectors()*bootSector.NumberOfFats();
-		if (rootDirectorySector<3)
-			return EFalse;
-
-		TInt rootDirSizeInBytes=bootSector.RootDirEntries()*KSizeOfFatDirEntry;
-		TInt numOfRootDirSectors=(rootDirSizeInBytes+(1<<sectorSizeLog2)-1)>>sectorSizeLog2;
-		TInt rootDirEnd=(rootDirectorySector+numOfRootDirSectors)<<sectorSizeLog2;
-		if (rootDirEnd<(4<<sectorSizeLog2))
-			return EFalse;
-		}
-
-
-	TInt totalSectors=bootSector.TotalSectors();
-	if (totalSectors==0)
-		totalSectors=bootSector.HugeSectors();
-	if (totalSectors<5)
-		return EFalse;
-
-	TInt numberOfFats=bootSector.NumberOfFats();
-	if (numberOfFats<1)
-		return EFalse;
-
-	return ETrue;
-	}
-
-/**
-Read non aligned boot data from media into TFatBootSector structure
-
-@param aBootSector refrence to TFatBootSector populate
-@return Media read error code
-*/
-TInt CMassStorageMountCB::ReadBootSector(TFatBootSector& aBootSector)
-	{
-	__FNLOG("CMassStorageMountCB::ReadBootSector");
-	TInt pos=0;
-	TUint8 data[KSizeOfFatBootSector];
-    TPtr8 buf(&data[0],KSizeOfFatBootSector);
-    TInt r=LocalDrive()->Read(0,KSizeOfFatBootSector,buf);
-	if (r!=KErrNone)
-		{
-		__PRINT1(_L("LocalDrive::Read() failed - %d"),r);
-		return(r);
-		}
-//	0	TUint8 iJumpInstruction[3]
-	Mem::Copy(&aBootSector.iJumpInstruction,&data[pos],3);
-	pos+=3;
-// 3	TUint8 iVendorId[KVendorIdSize]
-	Mem::Copy(&aBootSector.iVendorId,&data[pos],KVendorIdSize);
-	pos+=KVendorIdSize;
-// 11	TUint16 iBytesPerSector
-	Mem::Copy(&aBootSector.iBytesPerSector,&data[pos],2);
-	pos+=2;
-// 13	TUint8 sectorsPerCluster
-	Mem::Copy(&aBootSector.iSectorsPerCluster,&data[pos],1);
-	pos+=1;
-// 14	TUint16 iReservedSectors
-	Mem::Copy(&aBootSector.iReservedSectors,&data[pos],2);
-	pos+=2;
-// 16	TUint8 numberOfFats
-	Mem::Copy(&aBootSector.iNumberOfFats,&data[pos],1);
-	pos+=1;
-// 17	TUint16 iRootDirEntries
-	Mem::Copy(&aBootSector.iRootDirEntries,&data[pos],2);
-	pos+=2;
-// 19	TUint16 totalSectors
-	Mem::Copy(&aBootSector.iTotalSectors,&data[pos],2);
-	pos+=2;
-// 21	TUint8 iMediaDescriptor
-	Mem::Copy(&aBootSector.iMediaDescriptor,&data[pos],1);
-	pos+=1;
-// 22	TUint16 iFatSectors
-	Mem::Copy(&aBootSector.iFatSectors,&data[pos],2);
-	pos+=2;
-// 24	TUint16 iSectorsPerTrack
-	Mem::Copy(&aBootSector.iSectorsPerTrack,&data[pos],2);
-	pos+=2;
-// 26	TUint16 iNumberOfHeads
-	Mem::Copy(&aBootSector.iNumberOfHeads,&data[pos],2);
-	pos+=2;
-// 28	TUint32 iHiddenSectors
-	Mem::Copy(&aBootSector.iHiddenSectors,&data[pos],4);
-	pos+=4;
-// 32	TUint32 iHugeSectors
-	Mem::Copy(&aBootSector.iHugeSectors,&data[pos],4);
-	pos+=4;
-
-	if(aBootSector.iRootDirEntries == 0)	//indicates we have FAT32 volume
-		{
-		__PRINT(_L("\nFile system thinks Fat32"));
-
-		//36 TUint32 iFatSectors32
-		Mem::Copy(&aBootSector.iFatSectors32, &data[pos],4);
-		pos+=4;
-		//40 TUint16 iFATFlags
-		Mem::Copy(&aBootSector.iFATFlags, &data[pos],2);
-		pos+=2;
-		//42 TUint16 iVersionNumber
-		Mem::Copy(&aBootSector.iVersionNumber, &data[pos],2);
-		pos+=2;
-		//44 TUint32 iRootClusterNum
-		Mem::Copy(&aBootSector.iRootClusterNum, &data[pos],4);
-		pos+=4;
-		//48 TUint16 iFSInfoSectorNum
-		Mem::Copy(&aBootSector.iFSInfoSectorNum, &data[pos],2);
-		pos+=2;
-		//50 TUint16 iBkBootRecSector
-		Mem::Copy(&aBootSector.iBkBootRecSector, &data[pos],2);
-		pos+=(2+12);//extra 12 for the reserved bytes
-		}
-
-// 36|64	TUint8 iPhysicalDriveNumber
-	Mem::Copy(&aBootSector.iPhysicalDriveNumber,&data[pos],1);
-	pos+=1;
-// 37|65	TUint8 iReserved
-	Mem::Copy(&aBootSector.iReserved,&data[pos],1);
-	pos+=1;
-// 38|66	TUint8 iExtendedBootSignature
-	Mem::Copy(&aBootSector.iExtendedBootSignature,&data[pos],1);
-	pos+=1;
-// 39|67	TUint32 iUniqueID
-	Mem::Copy(&aBootSector.iUniqueID,&data[pos],4);
-	pos+=4;
-// 43|71	TUint8 iVolumeLabel[KVolumeLabelSize]
-	Mem::Copy(&aBootSector.iVolumeLabel,&data[pos],KVolumeLabelSize);
-	pos+=KVolumeLabelSize;
-// 54|82	TUint8 iFileSysType[KFileSysTypeSize]
-	Mem::Copy(&aBootSector.iFileSysType,&data[pos],KFileSysTypeSize);
-// 62|90
-
-	return(KErrNone);
-	}
-
-/**
-Work out if we have a FAT12|16|32 volume.
-Returns 12, 16 or 32 as appropriate.
-Returns 0 if can't be calculated (invalid values)
-*/
-TInt CMassStorageMountCB::DetermineFatType(TFatBootSector& aBootSector)
-	{
-	TUint32 ressectors = aBootSector.ReservedSectors();
-
-	if (aBootSector.SectorsPerCluster() < 1)
-		return 0;
-
-	if (aBootSector.RootDirEntries() != 0)
-		{
-		TUint32 rootdirbytes;
-		rootdirbytes = aBootSector.RootDirEntries() * 32 + aBootSector.BytesPerSector() - 1;
-		ressectors += rootdirbytes / aBootSector.BytesPerSector();
-		}
-
-	if (aBootSector.FatSectors() != 0)
-		ressectors += aBootSector.NumberOfFats() * aBootSector.FatSectors();
-	else
-		ressectors += aBootSector.NumberOfFats() * aBootSector.FatSectors32();
-
-	TUint32 totalsectors;
-	if (aBootSector.TotalSectors() != 0)
-		totalsectors = aBootSector.TotalSectors();
-	else
-		totalsectors = aBootSector.HugeSectors();
-
-	if (ressectors < 1 || totalsectors < 1)
-		return 0;
-
-	TUint32 datasec;
-	datasec = totalsectors - ressectors;
-
-	TUint32 countofclusters;
-	countofclusters = datasec / aBootSector.SectorsPerCluster();
-
-	__PRINT1(_L("CFatMountCB: Count of clusters = %d\n"), countofclusters);
-
-	if (countofclusters < 4085)
-		{
-		return 12;
-		}
-	else if (countofclusters < 65525)
-		{
-		return 16;
-		}
-	else
-		{
-		return 32;
-		}
-	}
-
 TInt CMassStorageMountCB::ReMount()
 	{
 	return KErrNotReady;
--- a/userlibandfileserver/fileserver/smassstorage/inc/cmassstoragefilesystem.h	Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/smassstorage/inc/cmassstoragefilesystem.h	Mon Mar 15 12:45:50 2010 +0200
@@ -23,11 +23,9 @@
 #ifndef __CMASSSTORAGEFILESYSTEM_H__
 #define __CMASSSTORAGEFILESYSTEM_H__
 
-#include <f32fsys.h>
-#include <f32ver.h>
-#include <f32file.h>
-#include "cusbmassstoragecontroller.h"
 
+//Forward Declaration
+class CUsbMassStorageController;
 
 /**
 Mass Storage Filesystem class.
@@ -75,8 +73,6 @@
 	CUsbMassStorageController* iMassStorageController;
 	TBool iRunning;
 	RArray<TInt> iMsDrives;
-	
-			
 	};
 
 #endif // __CMASSSTORAGEFILESYSTEM_H__
--- a/userlibandfileserver/fileserver/smassstorage/inc/cmassstoragemountcb.h	Fri Mar 12 15:50:11 2010 +0200
+++ b/userlibandfileserver/fileserver/smassstorage/inc/cmassstoragemountcb.h	Mon Mar 15 12:45:50 2010 +0200
@@ -23,7 +23,6 @@
 #ifndef __CMASSSTORAGEMOUNTCB_H__
 #define __CMASSSTORAGEMOUNTCB_H__
 
-#include <f32fsys.h>
 
 /**
 Mass Storage Mount.
@@ -32,7 +31,6 @@
 ControlIO is also supported for debug builds and returns KErrNotSupported for Release builds.
 @internalTechnology
 */
-class TFatBootSector;
 class CMassStorageMountCB : public CLocDrvMountCB
 	{
 	public:
@@ -63,205 +61,11 @@
 	CMassStorageMountCB(const RArray<TInt>& aDriveMapping);
 	void WritePasswordData();
 	TInt DriveNumberToLun(TInt aDriveNumber);
-	TBool ValidateBootSector();
-	TInt ReadBootSector(TFatBootSector& aBootSector);
-	TInt DetermineFatType(TFatBootSector& aBootSector);
 	TInt CheckDriveNumberL();
 
 	private:
-	TBool iIs16BitFat;
-	TBool iIs32BitFat;
 	const RArray<TInt>& iDriveMapping;
 	};
 
-const TInt KSizeOfFatBootSector	= 90;
-const TInt KVendorIdSize = 8;
-const TInt KVolumeLabelSize = 11;
-const TInt KFileSysTypeSize = 8;
-const TInt KBootSectorSignature = 0xAA55;
-const TInt KSizeOfFatDirEntry = 32;
-
-/**
-Boot sector parameter block, enables access to all file system parameters.
-Data is populated at mount time from the BPB sector
-@internalTechnology
-*/
-class TFatBootSector
-	{
-public:
-	inline const TPtrC8 VendorId() const;
-	inline TUint16 BytesPerSector() const;
-	inline TInt SectorsPerCluster() const;
-	inline TInt ReservedSectors() const;
-	inline TInt NumberOfFats() const;
-	inline TInt RootDirEntries() const;
-	inline TInt TotalSectors() const;
-	inline TUint8 MediaDescriptor() const;
-	inline TInt FatSectors() const;
-	inline TInt SectorsPerTrack() const;
-	inline TInt NumberOfHeads() const;
-	inline TInt HiddenSectors() const;
-	inline TInt HugeSectors() const;
-	inline TInt PhysicalDriveNumber() const;
-	inline TInt ExtendedBootSignature() const;
-	inline TUint32 UniqueID() const;
-	inline const TPtrC8 VolumeLabel() const;
-	inline const TPtrC8 FileSysType() const;
-	inline TInt BootSectorSignature() const;
-	inline void SetJumpInstruction();
-	inline void SetVendorID(const TDesC8& aDes);
-	inline void SetBytesPerSector(TInt aBytesPerSector);
-	inline void SetSectorsPerCluster(TInt aSectorsPerCluster);
-	inline void SetReservedSectors(TInt aReservedSectors);
-	inline void SetNumberOfFats(TInt aNumberOfFats);
-	inline void SetRootDirEntries(TInt aRootDirEntries);
-	inline void SetTotalSectors(TInt aTotalSectors);
-	inline void SetMediaDescriptor(TUint8 aMediaDescriptor);
-	inline void SetFatSectors(TInt aFatSectors);
-	inline void SetSectorsPerTrack(TInt aSectorsPerTrack);
-	inline void SetNumberOfHeads(TInt aNumberOfHeads);
-	inline void SetHiddenSectors(TUint32 aHiddenSectors);
-	inline void SetHugeSectors(TUint32 aTotalSectors);
-	inline void SetPhysicalDriveNumber(TInt aPhysicalDriveNumber);
-	inline void SetReservedByte(TUint8 aReservedByte);
-	inline void SetExtendedBootSignature(TInt anExtendedBootSignature);
-	inline void SetUniqueID(TUint32 anUniqueID);
-	inline void SetVolumeLabel(const TDesC8& aDes);
-	inline void SetFileSysType(const TDesC8& aDes);
-
-	inline void SetFatSectors32(TUint32	aFatSectors32);
-	inline void SetFATFlags(TUint16 aFATFlags);
-	inline void SetVersionNumber(TUint16	aVersionNumber);
-	inline void SetRootClusterNum(TUint32 aRootCusterNum);
-	inline void SetFSInfoSectorNum(TUint16 aFSInfoSectorNum);
-	inline void SetBkBootRecSector(TUint16 aBkBootRecSector);
-	inline TUint32 FatSectors32() const;
-	inline TUint16 FATFlags() const;
-	inline TUint16 VersionNumber() const;
-	inline TUint32 RootClusterNum() const;
-	inline TUint16 FSInfoSectorNum() const;
-	inline TUint16 BkBootRecSector() const;
-public:
-	inline TBool Is16BitFat();
-	inline TBool Is32BitFat();
-	inline TInt FirstFatSectorPos();
-	inline TInt RootDirStartSector();
-	inline TInt FirstFreeSector();
-public:
-	/**
-	Jump instruction used for bootable volumes
-	*/
-    TUint8 iJumpInstruction[3];
-	/**
-	Vendor ID of the file system that formatted the volume
-	*/
-    TUint8 iVendorId[KVendorIdSize];
-	/**
-	Bytes per sector
-	*/
-    TUint16 iBytesPerSector;
-	/**
-	Sectors per cluster ratio
-	*/
-    TUint8 iSectorsPerCluster;
-	/**
-	Number of reserved sectors on the volume
-	*/
-    TUint16 iReservedSectors;
-	/**
-	Number of Fats on the volume
-	*/
-    TUint8 iNumberOfFats;
-	/**
-	Number of entries allowed in the root directory, specific to Fat12/16, zero for FAT32
-	*/
-    TUint16 iRootDirEntries;
-	/**
-	Total sectors on the volume, zero for FAT32
-	*/
-    TUint16 iTotalSectors;
-	/**
-	Media descriptor
-	*/
-    TUint8 iMediaDescriptor;
-	/**
-	Sectors used for the Fat table, zero for FAT32
-	*/
-    TUint16 iFatSectors;
-	/**
-	Sectors per track
-	*/
-    TUint16 iSectorsPerTrack;
-	/**
-	Number of heads
-	*/
-    TUint16 iNumberOfHeads;
-	/**
-	Number of hidden sectors in the volume
-	*/
-    TUint32 iHiddenSectors;
-	/**
-	Total sectors in the volume, Used if totalSectors > 65535
-	*/
-    TUint32 iHugeSectors;
-
-	/**
-	Start of additional elements @ offset 36 for FAT32
-	Sectors in Fat table for 32 bit volume
-	*/
-	TUint32	iFatSectors32;
-	/**
-	Fat flags
-	*/
-	TUint16 iFATFlags;
-	/**
-	Version number of the file system
-	*/
-	TUint16	iVersionNumber;
-	/**
-	Cluster number of the root directory
-	*/
-	TUint32 iRootClusterNum;
-	/**
-	Sector number containing the FSIInfo structure
-	*/
-	TUint16 iFSInfoSectorNum;
-	/**
-	Backup boot sector
-	*/
-	TUint16 iBkBootRecSector;
-	/**
-	Reserved space
-	End of Fat32 Only parameters section
-	*/
-	TUint8	iReserved2[12];
-
-	/**
-	Physical drive number, not used in Symbian OS
-	*/
-	TUint8 iPhysicalDriveNumber;
-	/**
-	Reserved byte
-	*/
-    TUint8 iReserved;
-	/**
-	Extended boot signiture
-	*/
-    TUint8 iExtendedBootSignature;
-	/**
-	Unique volume ID
-	*/
-    TUint32 iUniqueID;
-	/**
-	The volume's label
-	*/
-    TUint8 iVolumeLabel[KVolumeLabelSize];
-	/**
-	File system type
-	*/
-	TUint8 iFileSysType[KFileSysTypeSize];
-	};
-
-#include "tfatbootsector.inl"
 
 #endif //__CMASSSTORAGEMOUNTCB_H__