libraries/memoryaccess/MemoryAccess.cpp
changeset 0 7f656887cf89
child 7 184a1eb85cf2
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // MemoryAccess.cpp
       
     2 // 
       
     3 // Copyright (c) 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "Eclipse Public License v1.0"
       
     6 // which accompanies this distribution, and is available
       
     7 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 // 
       
     9 // Initial Contributors:
       
    10 // Accenture - Initial contribution
       
    11 //
       
    12 
       
    13 //#include <m32std.h>
       
    14 #include <nkern.h>
       
    15 #include <kernel.h>
       
    16 #include <kern_priv.h>
       
    17 
       
    18 #include <fshell/common.mmh>
       
    19 
       
    20 #ifdef FSHELL_DOBJECTIX_SUPPORT
       
    21 #include "dobject.h" // To pick up my defn of DObjectIx/DObjectIxNinePointOneHack
       
    22 #endif
       
    23 
       
    24 #include <e32cmn.h>
       
    25 #include "memoryaccess.h"
       
    26 #include "PropertyAccess.h"
       
    27 #include "fdebuggerkernel.h"
       
    28 #include "DynamicDfcSupport.h"
       
    29 
       
    30 //define this to get log output
       
    31 /*#define DO_LOGGING
       
    32 
       
    33 #ifdef DO_LOGGING
       
    34 	#define DO_LOG(X) X
       
    35 #else
       
    36 	#define DO_LOG(X)
       
    37 #endif */
       
    38 
       
    39 const TInt KLocalBufferSize=4096;
       
    40 
       
    41 const TInt KMajorVersionNumber=1;
       
    42 const TInt KMinorVersionNumber=0;
       
    43 const TInt KBuildVersionNumber=0;
       
    44 _LIT(KMemAccessPanicCategory,"MemAccess");
       
    45 enum TMemAccessPanic
       
    46 	{
       
    47 	EMemAccessPanicBadContainerType,
       
    48 	EMemAccessMutexAlreadyHeld,
       
    49 	EMemAccessMutexNotHeld
       
    50 	};
       
    51 
       
    52 class DMemoryAccess;
       
    53 
       
    54 // DMemoryAccessFactory
       
    55 //
       
    56 NONSHARABLE_CLASS(DMemoryAccessFactory) : public DLogicalDevice
       
    57     {
       
    58 public:
       
    59     DMemoryAccessFactory();
       
    60 	~DMemoryAccessFactory();
       
    61 
       
    62 	TInt GetEventHandler(DDebuggerEventHandler*& aResult);
       
    63 	TInt GetDfcQue(TDfcQue*& aResult);
       
    64 	
       
    65 private:
       
    66     TInt Install();                     //overriding pure virtual
       
    67     void GetCaps(TDes8& aDes) const;    //overriding pure virtual
       
    68     TInt Create(DLogicalChannelBase*& aChannel);         //overriding pure virtual
       
    69 	void Lock();
       
    70 	void Unlock();
       
    71 
       
    72 private:
       
    73 	DDebuggerEventHandler* iSharedEventHandler;
       
    74 	TDynDfcQueWrapper* iDfcQueWrapper;
       
    75 	NFastMutex iLock;
       
    76     };
       
    77 
       
    78 
       
    79 // DECLARE_STANDARD_LDD
       
    80 //  Standard Extension Framework export
       
    81 DECLARE_STANDARD_EXTENSION()
       
    82 	{
       
    83 	return KErrNone;
       
    84 	}
       
    85 
       
    86 DECLARE_EXTENSION_LDD()
       
    87 	{
       
    88 	return new DMemoryAccessFactory();
       
    89 	}
       
    90 
       
    91 class DThreadChangeHandler;
       
    92 class DMsgQueue;
       
    93 
       
    94 // DMemoryAccess
       
    95 //
       
    96 NONSHARABLE_CLASS(DMemoryAccess) : public DLogicalChannel, public MDebuggerEventClient
       
    97     {
       
    98 public:
       
    99     DMemoryAccess();
       
   100     ~DMemoryAccess();
       
   101 private:
       
   102 //Framework
       
   103     TInt DoCreate(TInt aUnit,const TDesC* anInfo,const TVersion& aVer);
       
   104 	void HandleMsg(TMessageBase* aMsg);
       
   105     void DoCancel(TInt aReqNo);
       
   106     TInt DoRequest(TInt aReqNo,TRequestStatus aStatus,TAny* a1,TAny* a2);
       
   107     TInt DoControl(TInt aFunction,TAny *a1,TAny *a2);
       
   108 //API
       
   109     TInt GetThreadMem(TAny* aParams, TAny* aBuf);
       
   110     TInt GetAllocatorAddress(TUint aId, TUint8*& aAddr, TBool aGetCurrentAllocator=EFalse); //TOMSCI If false, get the created allocator. If true, get the current one
       
   111 	TInt GetContainerCount(const TObjectType aObjectType, TUint& aCount);
       
   112 	TInt AcquireContainerMutex(const TObjectType aObjectType);
       
   113 	TInt ReleaseContainerMutex(const TObjectType aObjectType);
       
   114 	TInt GetObjectType(TUint8* aObjectPtr, TObjectType& aType);
       
   115 	TInt GetObjectInfo(TObjectType aObjectType, TInt aObjectIndexInContainer, TDes8* aKernelInfoBuf);
       
   116 	TInt GetObjectInfoByPtr(TObjectType aObjectType, TUint8* aObjectPtr, TDes8* aKernelInfoBuf);
       
   117 	TInt GetObjectInfoByName(TObjectType aObjectType, const TDesC8& aObjectName, TDes8* aKernelInfoBuf);
       
   118 	TInt GetObjectInfoByHandle(TObjectType aObjectType, TInt aThreadId, TInt aObjectHandle, TDes8* aKernelInfoBuf);
       
   119 	TInt GetObjectAddresses(TObjectType aObjectType, const TDesC8& aOwningProcess, TDes8* aKernelInfoBuf);
       
   120 	TInt GetChunkAddresses(TUint aControllingProcessId, TDes8* aKernelInfoBuf);
       
   121 	TInt AcquireCodeSegMutex();
       
   122 	TInt ReleaseCodeSegMutex();
       
   123 	TInt GetNextCodeSegInfo(TDes8* aCodeSegInfoBuf);
       
   124 	TInt ObjectDie(TObjectKillParamsBuf& aObjectKillParamsBuf);
       
   125 	TInt FindPtrInCodeSegments(TAny* aDllNamePtr, TAny* aPtr);
       
   126 	TInt GetHandleOwners(TAny* aObj, TAny* aOwnersBuf);
       
   127 	TInt GetThreadHandles(TInt aThreadId, TAny* aHandlesBuf);
       
   128 	TInt GetProcessHandles(TInt aProcessId, TAny* aHandlesBuf);
       
   129 	TInt SetThreadPriority(TInt aThreadHandle, TInt aPriority);
       
   130 	void NotifyThreadCreation(TRequestStatus* aStatus);
       
   131 	void CancelNotifyThreadCreation();
       
   132 	TInt SetPriorityOverride(TInt aPriority, TAny* aMatchString);
       
   133 	TInt SetCriticalFlags(TInt aThreadHandle, TUint aFlags);
       
   134 	TInt OpenThread(TUint aTid);
       
   135 //Helpers
       
   136 	void GetObjectInfo(DObject* aObject, TObjectKernelInfo& aInfo);
       
   137 	TInt GetObjectPositionInContainer(TUint8* aObjectPtr, DObjectCon& aContainer, TInt& aPosInContainer);
       
   138 	TInt GetThreadInfo(DThread* aThread, TDes8* aThreadInfoBuf);
       
   139 	TInt GetProcessInfo(DProcess* aProcess, TDes8* aProcessInfoBuf);
       
   140 	TInt GetChunkInfo(DChunk* aChunk, TDes8* aChunkInfoBuf);
       
   141 	TInt GetLibraryInfo(DLibrary* aLibrary, TDes8* aLibraryInfoBuf);
       
   142 	TInt GetSemaphoreInfo(DSemaphore* aSemaphore, TDes8* aLibraryInfoBuf);
       
   143 	TInt GetMutexInfo(DMutex* aMutex, TDes8* aLibraryInfoBuf);
       
   144 	TInt GetTimerInfo(DTimer* aTimer, TDes8* aTimerInfoBuf);
       
   145 	TInt GetServerInfo(DServer* aServer, TDes8* aServerInfoBuf);
       
   146 	TInt GetSessionInfo(DSession* aSession, TDes8* aSessionInfoBuf);
       
   147 	TInt GetLogicalDeviceInfo(DLogicalDevice* aLogicalDevice, TDes8* aLogicalDeviceInfoBuf);
       
   148 	TInt GetPhysicalDeviceInfo(DPhysicalDevice* aPhysicalDevice, TDes8* aPhysicalDeviceInfoBuf);
       
   149 	TInt GetLogicalChannelInfo(DLogicalChannel* aLogicalChannel, TDes8* aLogicalChannelInfoBuf);
       
   150 	TInt GetChangeNotifierInfo(DChangeNotifier* aChangeNotifier, TDes8* aChangeNotifierInfoBuf);
       
   151 	TInt GetUndertakerInfo(DUndertaker* aUndertaker, TDes8* aUndertakerInfoBuf);
       
   152 	TInt GetMsgQueueInfo(DMsgQueue* aMsgQueue, TDes8* aMsgQueueInfoBuf);
       
   153 //	TInt GetPropertyRefInfo(DPropertyRef* aPropertyRef, TDes8* aPropertyRefInfoBuf);
       
   154 	TInt GetCondVarInfo(DCondVar* aCondVar, TDes8* aCondVarInfoBuf);
       
   155 	TInt InPlaceObjectRename(TAny* aParamsBuf, TAny* aNewNamePtr);
       
   156 	TInt InPlaceSetProcessFileName(TAny* aParamsBuf, TAny* aNewNamePtr);
       
   157 	TLinAddr DoGetAllocatorAddress(DThread* aThread, TBool aGetCurrent);
       
   158 	TInt EnableHeapTracing(TUint aThreadId, TBool aEnable);
       
   159 	TInt DefragRam(TInt aPriority);
       
   160 	TInt EmptyRamZone(TInt aPriority, TUint aZone);
       
   161 	TInt GetRamZoneInfo(TUint aZone, TAny* aInfoPkg);
       
   162 	TInt SetProcessProperties(TInt aProcessHandle, TAny* aProperties);
       
   163 	TInt WriteShadowMemory(TLinAddr aAddress, TAny* aNewContents);
       
   164 	TInt FreeShadowMemory(TLinAddr aAddress, TInt aLength);
       
   165 	TInt DebuggerFn(TInt aFn, TAny* a1, TAny* a2);
       
   166 	TInt GetRegisters(TAny* a1, TAny* /*a2*/);
       
   167 	DThread* ThreadFromHandle(TInt aHandle);
       
   168 
       
   169 
       
   170 private: // From MDebuggerEventClient
       
   171 	void BreakpointHit(TDes& aPkg);
       
   172 
       
   173 private:
       
   174 	DThread* iClient;
       
   175 	TBool iLocks[ENumObjectTypes];
       
   176 	TBool iCodeSegLock;
       
   177 	DCodeSeg* iCurrentCodeSeg;
       
   178 	DThreadChangeHandler* iEventHandler;
       
   179 	DPropertyAccess* iPropertyAccess;
       
   180 	TAny* iClientBreakpointNotifyPkg;
       
   181 	TRequestStatus* iClientBreakpointNotifyStatus;
       
   182 	};
       
   183 
       
   184 
       
   185 NONSHARABLE_CLASS(DThreadChangeHandler) : public DKernelEventHandler
       
   186 	{
       
   187 public:
       
   188 	DThreadChangeHandler(DThread* aClientThread);
       
   189 	~DThreadChangeHandler();
       
   190 	static TUint Event(TKernelEvent aEvent, TAny* a1, TAny* a2, TAny* aPrivateData);
       
   191 	TUint DoEvent(TKernelEvent aEvent, TAny* a1, TAny* a2);
       
   192 	void SetStatus(TRequestStatus* aStatus);
       
   193 
       
   194 private:
       
   195 	DThread* iThread;
       
   196 	TRequestStatus* iStatus;
       
   197 public:
       
   198 	TBuf8<256> iMatch;
       
   199 	TInt iPriorityToSet;
       
   200 	};
       
   201 
       
   202 // class DMemoryAccessFactory Implementation
       
   203 
       
   204 //
       
   205 //
       
   206 DMemoryAccessFactory::DMemoryAccessFactory()
       
   207 	{
       
   208     iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
       
   209 	}
       
   210 
       
   211 // DMemoryAccessFactory::Create
       
   212 //
       
   213 TInt DMemoryAccessFactory::Create(DLogicalChannelBase*& aChannel)
       
   214     {
       
   215     aChannel=new DMemoryAccess();
       
   216 	if (aChannel==NULL)
       
   217 		return KErrNoMemory;
       
   218 	else
       
   219 		return KErrNone;
       
   220     }
       
   221 
       
   222 // DMemoryAccessFactory::Install
       
   223 //
       
   224 TInt DMemoryAccessFactory::Install()
       
   225     {
       
   226     TInt err = SetName(&KMemoryAccessName);
       
   227 	if (err == KErrNone)
       
   228 		{
       
   229 		DDebuggerEventHandler* dontCare;
       
   230 		err = GetEventHandler(dontCare); // We call this to make sure the event handler is always running, so we can track creator info asap
       
   231 		}
       
   232 	return err;
       
   233     }
       
   234 
       
   235 // DMemoryAccessFactory::GetCaps
       
   236 //
       
   237 void DMemoryAccessFactory::GetCaps(TDes8& /*aDes*/) const
       
   238     {
       
   239 /*    TCapsMemoryAccessV01 b;
       
   240     b.iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
       
   241     aDes.FillZ(aDes.MaxLength());
       
   242     aDes.Copy((TUint8*)&b,Min(aDes.MaxLength(),sizeof(b)));
       
   243 */    } 
       
   244 
       
   245 
       
   246 // class DMemoryAccess Implementation
       
   247 
       
   248 // Ctor
       
   249 //
       
   250 DMemoryAccess::DMemoryAccess()
       
   251     : DLogicalChannel()
       
   252     {
       
   253     //SetBehaviour(-1); //JR
       
   254     }
       
   255 
       
   256 
       
   257 const TInt KMemAccessDfcThreadPriority = 27;
       
   258 
       
   259 // DMemoryAccess::DoCreate
       
   260 //  Check capabilities & version & start listening for events
       
   261 TInt DMemoryAccess::DoCreate(TInt /*aUnit*/,const TDesC* /*anInfo*/,const TVersion& aVer)
       
   262     {
       
   263 	TInt ret=KErrNone;
       
   264 	
       
   265 	//Require Power Management to use this driver
       
   266 	//Not ideal, but better than nothing
       
   267 	//if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by MEMORYACCESS.LDD (Memory Access for Task Managers)")))
       
   268 	//    return KErrPermissionDenied;
       
   269     
       
   270     if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer))
       
   271     	{
       
   272     	return KErrNotSupported;
       
   273     	}
       
   274     iClient=&Kern::CurrentThread();
       
   275 	iClient->Open();
       
   276 
       
   277 	TDfcQue* q = NULL;
       
   278 	ret = ((DMemoryAccessFactory*)iDevice)->GetDfcQue(q);
       
   279 
       
   280 	if (ret == KErrNone)
       
   281 		{
       
   282     	SetDfcQ(q);
       
   283     	iMsgQ.Receive();		
       
   284 		}
       
   285 
       
   286     return ret;
       
   287     }
       
   288 
       
   289 TInt DMemoryAccessFactory::GetDfcQue(TDfcQue*& aQue)
       
   290 	{
       
   291 	Lock();
       
   292 	if (iDfcQueWrapper)
       
   293 		{
       
   294 		aQue = iDfcQueWrapper->Que();
       
   295 		Unlock();
       
   296 		return KErrNone;
       
   297 		}
       
   298 	Unlock(); // Can't hold a fast mutex around DFC q creation
       
   299 
       
   300 	TDynDfcQueWrapper* wrapper = NULL;
       
   301 	_LIT(KDfcThreadName, "MemoryAccess-fshell");
       
   302 	TInt ret = TDynDfcQueWrapper::Create(wrapper, KMemAccessDfcThreadPriority, KDfcThreadName);
       
   303 	
       
   304 	if (ret == KErrNone)
       
   305 		{
       
   306 		Lock();
       
   307 		if (iDfcQueWrapper)
       
   308 			{
       
   309 			// Someone beat us to it while we weren't holding the lock
       
   310 			aQue = iDfcQueWrapper->Que();
       
   311 			Unlock();
       
   312 			wrapper->Destroy();
       
   313 			}
       
   314 		else
       
   315 			{
       
   316 			iDfcQueWrapper = wrapper;
       
   317 			aQue = iDfcQueWrapper->Que();
       
   318 			Unlock();
       
   319 			}
       
   320 		}
       
   321 	return ret;
       
   322 	}
       
   323 
       
   324 
       
   325 // dtor
       
   326 //
       
   327 DMemoryAccess::~DMemoryAccess()
       
   328     {
       
   329     //Clean up any mutexes that have been left open
       
   330 	DObjectCon* const * cons = Kern::Containers();
       
   331     for (TInt ii=0;ii<ENumObjectTypes;++ii)
       
   332     	{
       
   333     	if (iLocks[ii])
       
   334     		{
       
   335 			DObjectCon* container = cons[ii];
       
   336 			container->Signal();
       
   337     		}
       
   338     	}
       
   339 
       
   340 	DMutex* const codeSegLock = Kern::CodeSegLock();
       
   341 
       
   342     if (iCodeSegLock && codeSegLock)
       
   343 		{
       
   344 		Kern::MutexSignal(*codeSegLock);
       
   345 		}
       
   346 
       
   347 	if (iClientBreakpointNotifyStatus)
       
   348 		{
       
   349 		// Hmm I'm sure there are some threading subtleties here that I'm missing
       
   350 		DDebuggerEventHandler* handler = NULL;
       
   351 		TInt err = ((DMemoryAccessFactory*)iDevice)->GetEventHandler(handler);
       
   352 		if (!err) handler->UnregisterForBreakpointNotification(this);
       
   353 		Kern::RequestComplete(iClient, iClientBreakpointNotifyStatus, KErrCancel);
       
   354 		}
       
   355 
       
   356 	if (iEventHandler)
       
   357 		{
       
   358 		NKern::ThreadEnterCS();
       
   359 		iEventHandler->Close();
       
   360 		NKern::ThreadLeaveCS();
       
   361 		}
       
   362 
       
   363 	delete iPropertyAccess;
       
   364 	if (iClient)
       
   365 		{
       
   366 		iClient->Close(NULL);
       
   367 		}
       
   368 	}
       
   369    
       
   370 // DMemoryAccess::HandleMsg
       
   371 //  Called when user side sends us something
       
   372 void DMemoryAccess::HandleMsg(TMessageBase* aMsg)
       
   373 	{
       
   374     TThreadMessage& m=*(TThreadMessage*)aMsg;
       
   375 
       
   376     // Get message type
       
   377     TInt id=m.iValue;
       
   378 
       
   379     // Decode the message type and dispatch it to the relevent handler function...
       
   380     
       
   381     // A logical channel can be closed either explicitly by its user-side client,
       
   382     // or implicitly if the client thread dies. In the latter case, the channel
       
   383     // is closed in the context of the kernel supervisor thread. 
       
   384 
       
   385     if (id==(TInt)ECloseMsg)
       
   386         {
       
   387         // Channel Close
       
   388 		// We don't actually have any async requests
       
   389         //DoCancel(RMemoryAccess::EAllRequests); //JR
       
   390         m.Complete(KErrNone, EFalse);
       
   391         return;
       
   392         }
       
   393 
       
   394     // For all other message types, we check that the message is from the thread
       
   395     // that created us.
       
   396     if(m.Client()!=iClient)
       
   397         {
       
   398         Kern::ThreadKill(m.Client(),EExitPanic,ERequestFromWrongThread,KMemAccessPanicCategory);
       
   399         m.Complete(KErrNone,ETrue);
       
   400         return;
       
   401         }
       
   402     if (id==KMaxTInt)
       
   403         {
       
   404         // DoCancel
       
   405         DoCancel(m.Int0());
       
   406         m.Complete(KErrNone,ETrue);
       
   407         return;
       
   408         }
       
   409     if (id<0)
       
   410         {
       
   411         // DoRequest
       
   412         TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
       
   413         TInt r=DoRequest(~id, *pS, m.Ptr1(), m.Ptr2());
       
   414         if (r!=KErrNone)
       
   415             Kern::RequestComplete(iClient,pS,r);
       
   416         m.Complete(KErrNone,ETrue);
       
   417         }
       
   418     else
       
   419         {
       
   420         // DoControl
       
   421         TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
       
   422         m.Complete(r,ETrue);
       
   423         }	
       
   424 	}
       
   425 
       
   426 // DMemoryAccess::DoRequest
       
   427 //  Handles async messages, called from HandleMsg
       
   428 TInt DMemoryAccess::DoRequest(TInt /*aReqNo*/, TRequestStatus /*aStatus*/, TAny* /*a1*/, TAny* /*a2*/)
       
   429     {
       
   430     return KErrNone;
       
   431     }
       
   432 
       
   433 // DMemoryAccess::DoCancel
       
   434 //  Cancels async messages, called from HandleMsg
       
   435 void DMemoryAccess::DoCancel(TInt /*aReqNo*/)
       
   436     {
       
   437     }
       
   438 
       
   439 // DMemoryAccess::DoControl
       
   440 //  Handles sync messages, called from HandleMsg
       
   441 TInt DMemoryAccess::DoControl(TInt aFunction, TAny* a1, TAny* a2)
       
   442     {
       
   443 	// Kern::Printf("[DMemoryAccess] ::DoControl; Function: %d", aFunction);
       
   444     switch (aFunction)
       
   445         {
       
   446     case RMemoryAccess::EControlGetThreadMem:
       
   447         return GetThreadMem(a1, a2);
       
   448     case RMemoryAccess::EControlGetAllocatorAddress:
       
   449         return GetAllocatorAddress((TUint)a1, *(TUint8**)a2);
       
   450     case RMemoryAccess::EControlGetCurrentAllocatorAddress:
       
   451         return GetAllocatorAddress((TUint)a1, *(TUint8**)a2, ETrue);
       
   452     case RMemoryAccess::EControlFindPtrInCodeSegments:
       
   453 		return FindPtrInCodeSegments(a1, a2);
       
   454     case RMemoryAccess::EControlGetHandleOwners:
       
   455 		return GetHandleOwners(a1, a2);
       
   456     case RMemoryAccess::EControlGetThreadHandles:
       
   457 		return GetThreadHandles((TUint)a1, a2);
       
   458     case RMemoryAccess::EControlGetProcessHandles:
       
   459 		return GetProcessHandles((TUint)a1, a2);
       
   460 	case RMemoryAccess::EControlForceCrash:
       
   461 		Kern::Fault("ForceCrash-QR3", 0);
       
   462 		return KErrNone;
       
   463 	case RMemoryAccess::EControlReboot:
       
   464 		Kern::Restart((TInt)a1);
       
   465 		return KErrNone;
       
   466 	case RMemoryAccess::EControlGetPropertyInt:
       
   467 	case RMemoryAccess::EControlGetPropertyDesc:
       
   468 	case RMemoryAccess::EControlSetPropertyInt:
       
   469 	case RMemoryAccess::EControlSetPropertyDesc:
       
   470 	case RMemoryAccess::EControlDeleteProperty:
       
   471 	case RMemoryAccess::EControlPropertyNotify:
       
   472 	case RMemoryAccess::EControlPropertyNotifyCancel:
       
   473 	case RMemoryAccess::EControlSubscribeToProperty:
       
   474 		if (!iPropertyAccess)
       
   475 			{
       
   476 			iPropertyAccess = new DPropertyAccess(iClient);
       
   477 			}
       
   478 		if (!iPropertyAccess) return KErrNoMemory;
       
   479 		return iPropertyAccess->HandleProperty(aFunction, a1, a2);
       
   480 	case RMemoryAccess::EControlSetThreadPriority:
       
   481 		return SetThreadPriority((TInt)a1, (TInt)a2);
       
   482 	case RMemoryAccess::EControlNotifyThreadCreation:
       
   483 		NotifyThreadCreation((TRequestStatus*)a1);
       
   484 		return KErrNone;
       
   485 	case RMemoryAccess::EControlCancelNotifyThreadCreation:
       
   486 		CancelNotifyThreadCreation();
       
   487 		return KErrNone;
       
   488 	case RMemoryAccess::EControlSetPriorityOverride:
       
   489 		return SetPriorityOverride((TInt)a1, a2);
       
   490 	case RMemoryAccess::EControlSetCriticalFlags:
       
   491 		return SetCriticalFlags((TInt)a1, (TUint)a2);
       
   492 	case RMemoryAccess::EControlInPlaceThreadRename:
       
   493 		{
       
   494 		DThread* thread = ThreadFromHandle((TInt)a1);
       
   495 		if (!thread) return 0;
       
   496 		TBuf<64> buf;
       
   497 		TInt err = Kern::ThreadDesRead(iClient, a2, buf, 0);
       
   498 		if (err)
       
   499 			{
       
   500 			thread->Close(NULL);
       
   501 			return err;
       
   502 			}
       
   503 		thread->iName->Copy(buf);
       
   504 		TLinAddr addr = (TLinAddr)thread->iName;
       
   505 		thread->Close(NULL);
       
   506 		return addr;
       
   507 		}
       
   508 	case RMemoryAccess::EControlInPlaceObjectRename:
       
   509 		return InPlaceObjectRename(a1, a2);
       
   510 	case RMemoryAccess::EControlInPlaceSetProcessFileName:
       
   511 		return InPlaceSetProcessFileName(a1, a2);
       
   512 	case RMemoryAccess::EControlOpenThread:
       
   513 		return OpenThread((TUint)a1);
       
   514     case RMemoryAccess::EControlResetTimer:
       
   515         return KErrNone;
       
   516 	case RMemoryAccess::EControlGetContainerCount:
       
   517 		return GetContainerCount(*(TObjectType*)&a1, *(TUint*)a2);
       
   518 	case RMemoryAccess::EControlAcquireContainerMutex:
       
   519 		return AcquireContainerMutex(*(TObjectType*)&a1);
       
   520 	case RMemoryAccess::EControlReleaseContainerMutex:
       
   521 		return ReleaseContainerMutex(*(TObjectType*)&a1);
       
   522     case RMemoryAccess::EControlGetObjectType:
       
   523     	return GetObjectType((TUint8*)a1, *(TObjectType*)a2);
       
   524     case RMemoryAccess::EControlGetObjectInfo:
       
   525 		{
       
   526 		TObjectInfoByIndexParamsBuf params;
       
   527 		TInt err = Kern::ThreadDesRead(iClient,a1,params,0);
       
   528 		if (err == KErrNone)
       
   529 			{
       
   530 			err = GetObjectInfo(params().iObjectType, params().iObjectIndex, (TDes8*)a2);
       
   531 			}
       
   532 		return err;
       
   533 		}
       
   534     case RMemoryAccess::EControlGetObjectInfoByPtr:
       
   535 		{
       
   536 		TObjectInfoByPtrParamsBuf params;
       
   537 		TInt err = Kern::ThreadDesRead(iClient,a1,params,0);
       
   538 		if (err == KErrNone)
       
   539 			{
       
   540 			err = GetObjectInfoByPtr(params().iObjectType, params().iObjectPtr, (TDes8*)a2);
       
   541 			}
       
   542 		return err;
       
   543 		}
       
   544     case RMemoryAccess::EControlGetObjectInfoByName:
       
   545 		{
       
   546 		TObjectInfoByNameParamsBuf params;
       
   547 		TInt err = Kern::ThreadDesRead(iClient,a1,params,0);
       
   548 		if (err == KErrNone)
       
   549 			{
       
   550 			err = GetObjectInfoByName(params().iObjectType, params().iObjectName, (TDes8*)a2);
       
   551 			}
       
   552 		return err;
       
   553 		}
       
   554     case RMemoryAccess::EControlGetObjectInfoByHandle:
       
   555     	{
       
   556 		TObjectInfoByHandleParamsBuf params;
       
   557 		TInt err = Kern::ThreadDesRead(iClient,a1,params,0);
       
   558 		if (err == KErrNone)
       
   559 			{
       
   560 			err = GetObjectInfoByHandle(params().iObjectType, params().iThreadId, params().iObjectHandle, (TDes8*)a2);
       
   561 			}
       
   562 		return err;
       
   563 		}
       
   564     case RMemoryAccess::EControlAcquireCodeSegMutex:
       
   565     	return AcquireCodeSegMutex();
       
   566     case RMemoryAccess::EControlReleaseCodeSegMutex:
       
   567     	return ReleaseCodeSegMutex();
       
   568     case RMemoryAccess::EControlGetNextCodeSegInfo:
       
   569     	return GetNextCodeSegInfo((TDes8*)a1);
       
   570     case RMemoryAccess::EControlObjectDie:
       
   571     	{
       
   572 		TObjectKillParamsBuf params;
       
   573 		TInt err = Kern::ThreadDesRead(iClient,a1,params,0);
       
   574 		if (err == KErrNone)
       
   575 			{
       
   576 			err = ObjectDie(params);
       
   577 			}
       
   578 		return err;
       
   579     	}
       
   580     case RMemoryAccess::EControlGetObjectAddresses:
       
   581 		{
       
   582 		TGetObjectAddressesParamsBuf params;
       
   583 		TInt err = Kern::ThreadDesRead(iClient,a1,params,0);
       
   584 		if (err == KErrNone)
       
   585 			{
       
   586 			err = GetObjectAddresses(params().iObjectType,params().iOwningProcess,(TDes8*)a2);
       
   587 			}
       
   588 		return err;
       
   589 		}
       
   590     case RMemoryAccess::EControlGetChunkAddresses:
       
   591 		{
       
   592 		TGetChunkAddressesParamsBuf params;
       
   593 		TInt err = Kern::ThreadDesRead(iClient,a1,params,0);
       
   594 		if (err == KErrNone)
       
   595 			{
       
   596 			err = GetChunkAddresses(params().iControllingProcessId,(TDes8*)a2);
       
   597 			}
       
   598 		return err;
       
   599 		}
       
   600 	case RMemoryAccess::EControlEnableHeapTracing:
       
   601 		return EnableHeapTracing((TUint)a1, (TBool)a2);
       
   602 	case RMemoryAccess::EControlDefragRam:
       
   603 		return DefragRam((TInt)a1);
       
   604 	case RMemoryAccess::EControlEmptyRamZone:
       
   605 		return EmptyRamZone((TInt)a1, (TUint)a2);
       
   606 	case RMemoryAccess::EControlGetRamZoneInfo:
       
   607 		return GetRamZoneInfo((TUint)a1, a2);
       
   608 	case RMemoryAccess::EControlSetProcessProperties:
       
   609 		return SetProcessProperties((TInt)a1, a2);
       
   610 	case RMemoryAccess::EControlWriteShadowMemory:
       
   611 		return WriteShadowMemory((TLinAddr)a1, a2);
       
   612 	case RMemoryAccess::EControlFreeShadowMemory:
       
   613 		return FreeShadowMemory((TLinAddr)a1, (TInt)a2);
       
   614 	case RMemoryAccess::EControlGetZombieDebugMode:
       
   615 	case RMemoryAccess::EControlSetZombieDebugMode:
       
   616 	case RMemoryAccess::EControlGetZombies:
       
   617 	case RMemoryAccess::EControlReleaseZombie:
       
   618 	case RMemoryAccess::EControlSuspendThread:
       
   619 	case RMemoryAccess::EControlNotifyBreakpoint:
       
   620 	case RMemoryAccess::EControlSetBreakpoint:
       
   621 	case RMemoryAccess::EControlSetBreakpointEnabled:
       
   622 	case RMemoryAccess::EControlClearBreakpoint:
       
   623 	case RMemoryAccess::EControlContinueFromBreakpoint:
       
   624 	case RMemoryAccess::EControlGetBreakpoints:
       
   625 	case RMemoryAccess::EControlCancelNotifyBreakpoint:
       
   626 	case RMemoryAccess::EControlRegisterPersistantBreakpoint:
       
   627 	case RMemoryAccess::EControlSetSymbolicBreakpoint:
       
   628 		return DebuggerFn(aFunction, a1, a2);
       
   629 	case RMemoryAccess::EControlWriteMem:
       
   630 		{
       
   631 		TAny* args[3];
       
   632 		TInt err = Kern::ThreadRawRead(iClient, a1, &args, 3*sizeof(TAny*));
       
   633 		if (err) return err;
       
   634 		TUint targetId = (TUint)args[0];
       
   635 		TAny* srcAddr = args[1];
       
   636 		TAny* destAddr = args[2];
       
   637 		Kern::Containers()[EThread]->Wait();
       
   638 		DThread* target = Kern::ThreadFromId(targetId);
       
   639 		if (target) target->Open();
       
   640 		Kern::Containers()[EThread]->Signal();
       
   641 		if (!target) return KErrNotFound;
       
   642 		TInt dataLen = Kern::ThreadGetDesLength(iClient, srcAddr);
       
   643 		if (dataLen <= 0) err = dataLen;
       
   644 		TAny* mem = NULL;
       
   645 		if (!err) mem = Kern::Alloc(dataLen);
       
   646 		if (!mem) err = KErrNoMemory;
       
   647 		TPtr8 bah((TUint8*)mem, 0, dataLen);
       
   648 		if (!err) err = Kern::ThreadDesRead(iClient, srcAddr, bah, dataLen);
       
   649 		if (!err) err = Kern::ThreadRawWrite(target, destAddr, mem, dataLen);
       
   650 		Kern::Free(mem);
       
   651 		target->Close(NULL);
       
   652 		return err;
       
   653 		}
       
   654 #ifdef FSHELL_BTRACE_SUPPORT // SetTextTraceMode went in at the same time as btrace, afaik
       
   655 	case RMemoryAccess::EControlSetTextTraceMode:
       
   656 		{
       
   657 		TUint traceMode = 0;
       
   658 		TInt err = Kern::ThreadRawRead(iClient, a1, &traceMode, sizeof(TUint));
       
   659 		if (!err)
       
   660 			{
       
   661 			TUint origMode = Kern::SetTextTraceMode(traceMode, (TUint)a2);
       
   662 			err = Kern::ThreadRawWrite(iClient, a1, &origMode, sizeof(TUint));
       
   663 			}
       
   664 		return err;
       
   665 		}
       
   666 #endif
       
   667 	case RMemoryAccess::EControlGetRegisters:
       
   668 		return GetRegisters(a1, a2);
       
   669 	case RMemoryAccess::EControlSetDebugPort:
       
   670 		Kern::SuperPage().iDebugPort = (TInt)a1;
       
   671 		return KErrNone;
       
   672 	case RMemoryAccess::EControlGetCreatorThread:
       
   673 		{
       
   674 		DDebuggerEventHandler* handler = NULL;
       
   675 		TInt err = ((DMemoryAccessFactory*)iDevice)->GetEventHandler(handler);
       
   676 		if (err) return err;
       
   677 		TUint creator = handler->GetCreatorThread((TUint)a1);
       
   678 		if (creator == 0)
       
   679 			{
       
   680 			err = KErrNotFound;
       
   681 			}
       
   682 		else
       
   683 			{
       
   684 			err = Kern::ThreadRawWrite(iClient, a2, &creator, sizeof(TUint));
       
   685 			}
       
   686 		return err;
       
   687 		}
       
   688     default:
       
   689         return KErrNotSupported;
       
   690         }
       
   691     }
       
   692     
       
   693 // DMemoryAccess::GetThreadMem
       
   694 //  Gets a buffer of memory from a thread
       
   695 TInt DMemoryAccess::GetThreadMem(TAny* aParams, TAny* aBuf)
       
   696 	{
       
   697     TThreadMemoryAccessParams params;
       
   698 	TPckg<TThreadMemoryAccessParams> paramsBuf(params);
       
   699 	TInt err = Kern::ThreadDesRead(iClient, aParams, paramsBuf, 0);
       
   700 	if (err) return err;
       
   701 
       
   702 	// Copy the memory in page-sized chunks, so we don't have to allocate a huge buffer kernel-side
       
   703 	TInt localBufSize = Min(params.iSize, KLocalBufferSize);
       
   704 	HBuf8* localBuf = HBuf8::New(localBufSize);
       
   705 	if (!localBuf) return KErrNoMemory;
       
   706 
       
   707 	Kern::Containers()[EThread]->Wait();
       
   708 	DThread* thread = Kern::ThreadFromId(params.iId);
       
   709 	if (thread) thread->Open();
       
   710 	Kern::Containers()[EThread]->Signal();
       
   711 	if (!thread)
       
   712 		{
       
   713 		delete localBuf;
       
   714 		return KErrNotFound;
       
   715 		}
       
   716 	
       
   717 	TInt bytesCopied = 0;
       
   718 	TUint8* localPtr = (TUint8*)localBuf->Ptr();
       
   719 	while (!err && bytesCopied < params.iSize)
       
   720 		{
       
   721 		TInt toCopy = Min(params.iSize - bytesCopied, localBufSize);
       
   722 		localBuf->SetLength(toCopy);
       
   723 		err = Kern::ThreadRawRead(thread, params.iAddr + bytesCopied, localPtr, toCopy);
       
   724 		if (err) break;
       
   725 		err = Kern::ThreadDesWrite(iClient, aBuf, *localBuf, bytesCopied, 0, NULL);
       
   726 		bytesCopied += toCopy;
       
   727 		}
       
   728 	delete localBuf;
       
   729 	thread->Close(NULL);
       
   730 	return err;
       
   731 	}
       
   732 
       
   733 // DMemoryAccess::GetHeapBase
       
   734 //  Gets the base addess of a thread's heap
       
   735 TInt DMemoryAccess::GetAllocatorAddress(TUint aId, TUint8*& aAddr, TBool aGetCurrent)
       
   736     {
       
   737     TInt err = KErrNone;
       
   738    
       
   739  	//Acquire the threads container mutex
       
   740 	DObjectCon* const * cons = Kern::Containers();
       
   741 	DObjectCon* threads = cons[EThread];
       
   742 	threads->Wait();
       
   743 
       
   744 	NKern::ThreadEnterCS();
       
   745 	DThread* thread = Kern::ThreadFromId(aId);
       
   746 	if (thread) thread->Open();
       
   747     NKern::ThreadLeaveCS();
       
   748 
       
   749     threads->Signal();
       
   750 
       
   751     if (!thread)
       
   752         err = KErrNotFound;
       
   753 
       
   754 	if (!err)
       
   755 		{
       
   756 		TLinAddr allocator = DoGetAllocatorAddress(thread, aGetCurrent);
       
   757 		thread->Close(NULL);
       
   758 		err = Kern::ThreadRawWrite(iClient, &aAddr, (TUint8*)&allocator, sizeof(TUint8*));
       
   759     	}
       
   760 	return err;
       
   761 	}
       
   762     
       
   763 TLinAddr DMemoryAccess::DoGetAllocatorAddress(DThread* aThread, TBool aGetCurrent)
       
   764 	{
       
   765 	RAllocator* allocator = NULL;
       
   766 
       
   767 	allocator = aGetCurrent ? aThread->iAllocator : aThread->iCreatedAllocator;
       
   768 	if (!allocator)
       
   769 		{
       
   770 		// Check if it's a kernel thread
       
   771 		Kern::Containers()[EProcess]->Wait();
       
   772 		DProcess* kernProc = Kern::ProcessFromId(1);
       
   773 		Kern::Containers()[EProcess]->Signal();
       
   774 		if (aThread->iOwningProcess == kernProc)
       
   775 			{
       
   776 			// GeorgeN's cunning approach - the kern DProcess is one of the first things allocated to the kern heap and the heap is page aligned, so rounding down the dprocess pointer will give you the RHeapK addresss
       
   777 			allocator = (RAllocator*)(Kern::RoundToPageSize((TLinAddr)kernProc) - Kern::RoundToPageSize(1));
       
   778 			}
       
   779 		}
       
   780 
       
   781 	return (TLinAddr)allocator;
       
   782     }
       
   783 
       
   784 // DMemoryAccess::GetContainerCount
       
   785 //  Gets the object count of a kernel container specified by aObjectType
       
   786 TInt DMemoryAccess::GetContainerCount(const TObjectType aObjectType, TUint& aCount)
       
   787 	{
       
   788 	// Kern::Printf("[DMemoryAccess] ::GetContainerCount");
       
   789 	TInt err=KErrNone;
       
   790 	if (aObjectType<0 || aObjectType>= ENumObjectTypes)
       
   791 		{
       
   792 		Kern::ThreadKill(iClient,EExitPanic,EMemAccessPanicBadContainerType,KMemAccessPanicCategory);
       
   793 		}
       
   794 	
       
   795 	DObjectCon* const * cons = Kern::Containers();
       
   796 	DObjectCon* container = cons[aObjectType];
       
   797 	container->Wait();
       
   798 	
       
   799     TUint count=container->Count();
       
   800     err = Kern::ThreadRawWrite(iClient, &aCount, (TUint8*)&count, sizeof(TUint));
       
   801     
       
   802     container->Signal();
       
   803 	// Kern::Printf("[DMemoryAccess] ::GetContainerCount returning %d; count %d",err,count);
       
   804 	return err;    	
       
   805 	}
       
   806 	
       
   807 // DMemoryAccess::AcquireContainerMutex
       
   808 //  Acquire a mutex on the specified kernel container
       
   809 //  Must be called before attempting to retrieve any info from the container
       
   810 //  Must only be called once per container
       
   811 TInt DMemoryAccess::AcquireContainerMutex(const TObjectType aObjectType)
       
   812 	{
       
   813 	// Kern::Printf("[DMemoryAccess] ::AcquireContainerMutex, object type %d", aObjectType);
       
   814 	TInt err=KErrNone;
       
   815 	if (aObjectType<0 || aObjectType>= ENumObjectTypes)
       
   816 		{ //Check this is a valid container type
       
   817 		Kern::ThreadKill(iClient,EExitPanic,EMemAccessPanicBadContainerType,KMemAccessPanicCategory);
       
   818 		err=KErrArgument;
       
   819 		}
       
   820 	else
       
   821 		{
       
   822 		//Make sure none of the containers are already locked
       
   823 		for (TInt ii=0; ii<ENumObjectTypes;ii++)
       
   824 			{
       
   825 			if (iLocks[ii])
       
   826 				{ //Check the lock on this container is not currently held
       
   827 				Kern::ThreadKill(iClient,EExitPanic,EMemAccessMutexAlreadyHeld,KMemAccessPanicCategory);
       
   828 				}		
       
   829 			}
       
   830 		
       
   831 		DObjectCon* const * cons = Kern::Containers();
       
   832 		DObjectCon* container = cons[aObjectType];
       
   833 		container->Wait();
       
   834 		
       
   835 		iLocks[aObjectType]=ETrue;
       
   836 		}
       
   837 	// Kern::Printf("[DMemoryAccess] ::AcquireContainerMutex returning %d", err);
       
   838 	return err;    	
       
   839 	}
       
   840 	
       
   841 // DMemoryAccess::ReleaseContainerMutex
       
   842 //  Releases a mutex on the specified kernel container
       
   843 //  Must only be called when the mutex on the container is already held
       
   844 TInt DMemoryAccess::ReleaseContainerMutex(const TObjectType aObjectType)
       
   845 	{
       
   846 	// Kern::Printf("[DMemoryAccess] ::ReleaseContainerMutex, object type %d", aObjectType);
       
   847 	TInt err=KErrNone;
       
   848 	if (aObjectType<0 || aObjectType>= ENumObjectTypes)
       
   849 		{ //Check this is a valid container type
       
   850 		Kern::ThreadKill(iClient,EExitPanic,EMemAccessPanicBadContainerType,KMemAccessPanicCategory);
       
   851 		err=KErrArgument;
       
   852 		}
       
   853 	if (!iLocks[aObjectType])
       
   854 		{ //Check the lock on this container is currently held
       
   855 		Kern::ThreadKill(iClient,EExitPanic,EMemAccessMutexNotHeld,KMemAccessPanicCategory);
       
   856 		err=KErrGeneral;
       
   857 		}
       
   858 
       
   859 	if (err==KErrNone)
       
   860 		{
       
   861 		DObjectCon* const * cons = Kern::Containers();
       
   862 		DObjectCon* container = cons[aObjectType];
       
   863 		__ASSERT_MUTEX(container->Lock());
       
   864 
       
   865 	    container->Signal();
       
   866 		iLocks[aObjectType]=EFalse;
       
   867 		}
       
   868 	// Kern::Printf("[DMemoryAccess] ::ReleaseContainerMutex returning %d", err);
       
   869 	return err;    	
       
   870 	}
       
   871 
       
   872 // DMemoryAccess::GetObjectInfo
       
   873 //  Utility function to extract generic info from a DObject
       
   874 void DMemoryAccess::GetObjectInfo(DObject* aObject, TObjectKernelInfo& aInfo)
       
   875 	{
       
   876 	//Kern::Printf("[DMemoryAccess] ::GetObjectInfo");
       
   877 	if (aObject)
       
   878 		{
       
   879 		aInfo.iAddressOfKernelObject=(TUint8*)aObject;
       
   880 		aObject->FullName(aInfo.iFullName);
       
   881 		aObject->Name(aInfo.iName);
       
   882 		aInfo.iAccessCount=aObject->AccessCount();
       
   883 		aInfo.iUniqueID=aObject->UniqueID();
       
   884 		aInfo.iProtection=aObject->Protection();
       
   885 		aInfo.iAddressOfKernelOwner=(TUint8*)aObject->Owner();			
       
   886 		}
       
   887 	//Kern::Printf("[DMemoryAccess] ::GetObjectInfo returning");
       
   888 	}
       
   889 
       
   890 // DMemoryAccess::GetObjectType
       
   891 //  Finds the type of a kernel side DObject pointer by iterating the kernel containers
       
   892 //  Requires that none of the kernel containers are already locked
       
   893 //  returns KErrNotFound if the object does not exist in any of the kernel's containers
       
   894 TInt DMemoryAccess::GetObjectType(TUint8* aObjectPtr, TObjectType& aType)
       
   895 	{
       
   896 	// Kern::Printf("[DMemoryAccess] ::GetObjectType");
       
   897 	TInt err=KErrNotFound;
       
   898 	//Make sure none of the containers are already locked
       
   899 	for (TInt ii=0; ii<ENumObjectTypes;ii++)
       
   900 		{
       
   901 		if (iLocks[ii])
       
   902 			{ //Check the lock on this container is not currently held
       
   903 			Kern::ThreadKill(iClient,EExitPanic,EMemAccessMutexAlreadyHeld,KMemAccessPanicCategory);
       
   904 			err=KErrGeneral;
       
   905 			}		
       
   906 		}
       
   907 
       
   908 	if (err==KErrNone || err==KErrNotFound)
       
   909 		{
       
   910 		// Kern::Printf("[DMemoryAccess] Looking for object 0x%08X",aObjectPtr);
       
   911 		for (TInt ii=EThread; ii<ENumObjectTypes; ii++)
       
   912 			{
       
   913 			TInt posInContainer=KErrNotFound;
       
   914 			DObjectCon* const * cons = Kern::Containers();
       
   915 			DObjectCon& container = *cons[ii];
       
   916 			container.Wait();
       
   917 			if (GetObjectPositionInContainer(aObjectPtr, container, posInContainer)==KErrNone)
       
   918 				{
       
   919 				// Kern::Printf("[DMemoryAccess] ::GetObjectType found type %d",ii);
       
   920 				err = Kern::ThreadRawWrite(iClient, &aType, (TUint8*)&ii, sizeof(TObjectType));
       
   921 				ii=ENumObjectTypes; //prevent further loop iterations
       
   922 				}
       
   923 			container.Signal();
       
   924 			}
       
   925 		}
       
   926 	// Kern::Printf("[DMemoryAccess] ::GetObjectType returning %d",err);
       
   927 	return err;
       
   928 	}
       
   929 
       
   930 // DMemoryAccess::ObjectPositionInContainer
       
   931 //  Finds the position in the aContainer of the aObjectPtr kernel object
       
   932 //  Returns KErrNone if found, KErrNotFound if not
       
   933 //  Position in container will be returned in aPosInContainer
       
   934 //  The container mutex corresponding to the specified container must be already locked
       
   935 TInt DMemoryAccess::GetObjectPositionInContainer(TUint8* aObjectPtr, DObjectCon& aContainer, TInt& aPosInContainer)
       
   936 	{
       
   937 	// Kern::Printf("[DMemoryAccess] ::GetObjectPositionInContainer");
       
   938 	TInt err=KErrNotFound;
       
   939 	aPosInContainer=KErrNotFound;
       
   940 	
       
   941 	for (TInt jj=0; jj<aContainer.Count();jj++)
       
   942 		{
       
   943 		DObject* obj = (DObject*)aContainer[jj];
       
   944 		if ((TUint8*)obj == aObjectPtr)
       
   945 			{
       
   946 			aPosInContainer=jj;
       
   947 			err=KErrNone;
       
   948 			continue;
       
   949 			}
       
   950 		}
       
   951 	// Kern::Printf("[DMemoryAccess] ::GetObjectPositionInContainer returning %d; position %d",err,aPosInContainer);
       
   952 	return err;
       
   953 	}
       
   954 
       
   955 // DMemoryAccess::GetObjectInfo
       
   956 //  Provides data about a kernel object
       
   957 //  aObjectType specifies the type of object
       
   958 //  aObjectIndexInContainer specifies the index of the required object in the respective kernel container
       
   959 //  aKernelInfoBuf provides a buffer to populate with info.  Should be a derived class of TObjectKernelInfo corresponding to the object type
       
   960 //  The appropriate kernel container must already be locked
       
   961 TInt DMemoryAccess::GetObjectInfo(TObjectType aObjectType, TInt aObjectIndexInContainer, TDes8* aKernelInfoBuf)
       
   962 	{
       
   963 	//Kern::Printf("[DMemoryAccess] ::GetObjectInfo");
       
   964 	TInt err=KErrNone;
       
   965 
       
   966 	TBool alreadyHeld = iLocks[aObjectType];
       
   967 	if (!alreadyHeld)
       
   968 		{
       
   969 		// Automatically grab the lock
       
   970 		DObjectCon* const * cons = Kern::Containers();
       
   971 		DObjectCon& container = *cons[aObjectType];
       
   972 		container.Wait();
       
   973 		iLocks[aObjectType] = ETrue;
       
   974 		}
       
   975 
       
   976 	if (!iLocks[aObjectType])
       
   977 		{ //Check the lock on this container is currently held
       
   978 		Kern::ThreadKill(iClient,EExitPanic,EMemAccessMutexNotHeld,KMemAccessPanicCategory);
       
   979 		//Kern::Printf("[DMemoryAccess] ::GetObjectInfo: No Lock!");
       
   980 		err=KErrGeneral;
       
   981 		}
       
   982 	else
       
   983 		{
       
   984 		DObjectCon* const * cons = Kern::Containers();
       
   985 		DObjectCon& container = *cons[aObjectType];
       
   986 		//Kern::Printf("[DMemoryAccess] ::GetObjectInfo: Asserting lock...");
       
   987 		__ASSERT_MUTEX(container.Lock());
       
   988 		//Kern::Printf("[DMemoryAccess] ::GetObjectInfo: Lock OK");
       
   989 
       
   990 		// Bounds check index: because we acquire and release the locks more, we risk the container changing size after the client has got the size
       
   991 		if (aObjectIndexInContainer >= container.Count())
       
   992 			{
       
   993 			err = KErrOverflow;
       
   994 			goto returnAndReleaseLock; // Not elegant, and in fact the first goto I've used in over 5 years
       
   995 			}
       
   996 
       
   997 		DObject* object = (DObject*)container[aObjectIndexInContainer];
       
   998 
       
   999 		//Get the object info according to its type
       
  1000 		//Kern::Printf("[DMemoryAccess] ::GetObjectInfo: Calling specific function");
       
  1001 		switch (aObjectType)
       
  1002 			{
       
  1003 		case EThread:
       
  1004 			err=GetThreadInfo((DThread*)object, aKernelInfoBuf);
       
  1005 			break;
       
  1006 		case EProcess:
       
  1007 			err=GetProcessInfo((DProcess*)object, aKernelInfoBuf);
       
  1008 			break;
       
  1009 		case EChunk:
       
  1010 			err=GetChunkInfo((DChunk*)object, aKernelInfoBuf);
       
  1011 			break;
       
  1012 		case ELibrary:
       
  1013 			err=GetLibraryInfo((DLibrary*)object, aKernelInfoBuf);
       
  1014 			break;
       
  1015 		case ESemaphore:
       
  1016 			err=GetSemaphoreInfo((DSemaphore*)object, aKernelInfoBuf);
       
  1017 			break;
       
  1018 		case EMutex:
       
  1019 			err=GetMutexInfo((DMutex*)object, aKernelInfoBuf);
       
  1020 			break;
       
  1021 		case ETimer:
       
  1022 			err=GetTimerInfo((DTimer*)object, aKernelInfoBuf);
       
  1023 			break;
       
  1024 		case EServer:
       
  1025 			err=GetServerInfo((DServer*)object, aKernelInfoBuf);
       
  1026 			break;
       
  1027 		case ESession:
       
  1028 			err=GetSessionInfo((DSession*)object, aKernelInfoBuf);
       
  1029 			break;
       
  1030 		case ELogicalDevice:
       
  1031 			err=GetLogicalDeviceInfo((DLogicalDevice*)object, aKernelInfoBuf);
       
  1032 			break;
       
  1033 		case EPhysicalDevice:
       
  1034 			err=GetPhysicalDeviceInfo((DPhysicalDevice*)object, aKernelInfoBuf);
       
  1035 			break;
       
  1036 		case ELogicalChannel:
       
  1037 			err=GetLogicalChannelInfo((DLogicalChannel*)object, aKernelInfoBuf);
       
  1038 			break;
       
  1039 		case EChangeNotifier:
       
  1040 			err=GetChangeNotifierInfo((DChangeNotifier*)object, aKernelInfoBuf);
       
  1041 			break;
       
  1042 		case EUndertaker:
       
  1043 			err=GetUndertakerInfo((DUndertaker*)object, aKernelInfoBuf);
       
  1044 			break;
       
  1045 		case EMsgQueue:	
       
  1046 			err=GetMsgQueueInfo((DMsgQueue*)object, aKernelInfoBuf);
       
  1047 			break;
       
  1048 		case EPropertyRef:
       
  1049 //			err=GetPropertyRefInfo((DPropertyRef*)object, aKernelInfoBuf);
       
  1050 			break;
       
  1051 		case ECondVar:
       
  1052 			err=GetCondVarInfo((DCondVar*)object, aKernelInfoBuf);
       
  1053 			break;
       
  1054 		default:
       
  1055 			err=KErrNotFound;
       
  1056 			}
       
  1057 		}
       
  1058 returnAndReleaseLock:
       
  1059 	if (!alreadyHeld)
       
  1060 		{
       
  1061 		// Release the lock if we grabbed it automatically
       
  1062 		DObjectCon* const * cons = Kern::Containers();
       
  1063 		DObjectCon& container = *cons[aObjectType];
       
  1064 		container.Signal();
       
  1065 		iLocks[aObjectType] = alreadyHeld;
       
  1066 		}
       
  1067 	//Kern::Printf("[DMemoryAccess] ::GetObjectInfo returning %d",err);
       
  1068 	return err;    				
       
  1069 	}
       
  1070 	
       
  1071 // DMemoryAccess::GetObjectInfoByPtr
       
  1072 //  Provides data about a kernel object
       
  1073 //  aObjectType specifies the type of object
       
  1074 //  aObjectPtr specifies address of the required DObject in the kernel
       
  1075 //  aKernelInfoBuf provides a buffer to populate with info.  Should be a derived class of TObjectKernelInfo corresponding to the object type
       
  1076 //  No kernel container locks other than the one selected should be held
       
  1077 TInt DMemoryAccess::GetObjectInfoByPtr(TObjectType aObjectType, TUint8* aObjectPtr, TDes8* aKernelInfoBuf)
       
  1078 	{
       
  1079 	// Kern::Printf("[DMemoryAccess] ::GetObjectInfoByPtr");
       
  1080 	TInt posInContainer=KErrNotFound;
       
  1081 	DObjectCon* const * cons = Kern::Containers();
       
  1082 	DObjectCon& container = *cons[aObjectType];
       
  1083 	container.Wait();
       
  1084 	TBool alreadyHeld = iLocks[aObjectType];
       
  1085 	iLocks[aObjectType] = ETrue;
       
  1086 	
       
  1087 	TInt err=GetObjectPositionInContainer(aObjectPtr,container,posInContainer);
       
  1088 
       
  1089 	if (err==KErrNone)
       
  1090 		err=GetObjectInfo(aObjectType, posInContainer, aKernelInfoBuf);
       
  1091 	
       
  1092 	container.Signal();
       
  1093 	iLocks[aObjectType] = alreadyHeld;
       
  1094 	return err;
       
  1095 	}
       
  1096 
       
  1097 // DMemoryAccess::GetObjectInfoByName
       
  1098 //  Provides data about a kernel object
       
  1099 //  aObjectType specifies the type of object
       
  1100 //  aObjectName specifies name of the required DObject in the kernel
       
  1101 //  aKernelInfoBuf provides a buffer to populate with info.  Should be a derived class of TObjectKernelInfo corresponding to the object type
       
  1102 //  No kernel container locks other than the one selected should be held
       
  1103 TInt DMemoryAccess::GetObjectInfoByName(TObjectType aObjectType, const TDesC8& aObjectName, TDes8* aKernelInfoBuf)
       
  1104 	{
       
  1105 	DObjectCon* const * cons = Kern::Containers();
       
  1106 	DObjectCon& container = *cons[aObjectType];
       
  1107 	container.Wait();
       
  1108 	TBool alreadyHeld = iLocks[aObjectType];
       
  1109 	iLocks[aObjectType] = ETrue;
       
  1110 
       
  1111 	TInt err = KErrNotFound;
       
  1112 	for (TInt jj=0; jj<container.Count();jj++)
       
  1113 		{
       
  1114 		DObject* obj = (DObject*)container[jj];
       
  1115 		TBuf8<KMaxFullName> fullName;
       
  1116 		obj->FullName(fullName);
       
  1117 		if (fullName == aObjectName)
       
  1118 			{
       
  1119 			err=GetObjectInfo(aObjectType, jj, aKernelInfoBuf);
       
  1120 			break;
       
  1121 			}
       
  1122 		}
       
  1123 	
       
  1124 	container.Signal();
       
  1125 	iLocks[aObjectType] = alreadyHeld;
       
  1126 	return err;
       
  1127 	}
       
  1128 
       
  1129 // DMemoryAccess::GetObjectInfoByHandle
       
  1130 //  Provides data about a kernel object
       
  1131 //  aObjectType specifies the type of object
       
  1132 //  aThreadHandle specifies the user side handle of the thread in which context to find the required object
       
  1133 //  aObjectHandle specifies the user side handle of the required object
       
  1134 //  aKernelInfoBuf provides a buffer to populate with info.  Should be a derived class of TObjectKernelInfo corresponding to the object type
       
  1135 //  No kernel container locks other than the one selected should be held
       
  1136 TInt DMemoryAccess::GetObjectInfoByHandle(TObjectType aObjectType, TInt aThreadId, TInt aObjectHandle, TDes8* aKernelInfoBuf)
       
  1137 	{
       
  1138 	// Kern::Printf("[DMemoryAccess] ::GetObjectInfoByHandle");
       
  1139 	TInt err=KErrNone;	
       
  1140 
       
  1141 	DObjectCon* const * cons = Kern::Containers();
       
  1142 	DObjectCon& container = *cons[EThread];
       
  1143 	container.Wait();
       
  1144 	NKern::ThreadEnterCS();
       
  1145 	DThread* thread = Kern::ThreadFromId(aThreadId);
       
  1146     NKern::ThreadLeaveCS();
       
  1147 	container.Signal();
       
  1148 
       
  1149 	if (!thread)
       
  1150 		{
       
  1151 		err=KErrNotFound;
       
  1152 		}
       
  1153 	else
       
  1154 		{
       
  1155 		DObject* object;
       
  1156 
       
  1157 		if (aObjectHandle == (KCurrentThreadHandle&~KHandleNoClose))
       
  1158 			object = thread;
       
  1159 		else if (aObjectHandle == (KCurrentProcessHandle&~KHandleNoClose))
       
  1160 			object = thread->iOwningProcess;
       
  1161 		else
       
  1162 			{
       
  1163 			NKern::ThreadEnterCS();
       
  1164 			NKern::LockSystem();
       
  1165 			object = thread->ObjectFromHandle(aObjectHandle,aObjectType);
       
  1166 			NKern::UnlockSystem();
       
  1167 			NKern::ThreadLeaveCS();
       
  1168 			}
       
  1169 
       
  1170 		if (!object)
       
  1171 			{
       
  1172 			err=KErrNotFound;
       
  1173 			}
       
  1174 		else
       
  1175 			{
       
  1176 			err=GetObjectInfoByPtr(aObjectType, (TUint8*)object, aKernelInfoBuf);
       
  1177 			}
       
  1178 		}
       
  1179 
       
  1180 	return err;
       
  1181 	}
       
  1182 
       
  1183 
       
  1184 // DMemoryAccess::AcquireCodeSegMutex
       
  1185 //  Acquires the code segment mutex
       
  1186 TInt DMemoryAccess::AcquireCodeSegMutex()
       
  1187 	{
       
  1188 	// Kern::Printf("[DMemoryAccess] ::AcquireCodeSegMutex");
       
  1189 	TInt err=KErrNone;
       
  1190 
       
  1191 	if (iCodeSegLock)
       
  1192 		{ //Check the lock on code segs is not currently held
       
  1193 		Kern::ThreadKill(iClient, EExitPanic, EMemAccessMutexAlreadyHeld, KMemAccessPanicCategory);
       
  1194 		err = KErrAbort;
       
  1195 		}
       
  1196 
       
  1197 	DMutex* const codeSegLock = Kern::CodeSegLock();
       
  1198 
       
  1199 	if (!err)
       
  1200 		{
       
  1201 		if (codeSegLock)
       
  1202 			{
       
  1203 			Kern::MutexWait(*codeSegLock);
       
  1204 			iCodeSegLock = ETrue;
       
  1205 			}
       
  1206 		else
       
  1207 			{
       
  1208 			err = KErrNotFound;
       
  1209 			}
       
  1210 		}
       
  1211 	// Kern::Printf("[DMemoryAccess] ::AcquireCodeSegMutex returning %d", err);
       
  1212 	return err;    	
       
  1213 	}
       
  1214 
       
  1215 TInt DMemoryAccess::GetObjectAddresses(TObjectType aObjectType, const TDesC8& aOwningProcess, TDes8* aKernelInfoBuf)
       
  1216 	{
       
  1217 	DObjectCon* const * cons = Kern::Containers();
       
  1218 	DObjectCon& container = *cons[aObjectType];
       
  1219 	container.Wait();
       
  1220 	TBool alreadyHeld = iLocks[aObjectType];
       
  1221 	iLocks[aObjectType] = ETrue;
       
  1222 
       
  1223 	TInt maxLength = Kern::ThreadGetDesMaxLength(iClient, aKernelInfoBuf);
       
  1224 	TInt err = KErrNone;
       
  1225 	TInt offset = 0;
       
  1226 
       
  1227 	for (TInt jj=0;jj<container.Count();jj++)
       
  1228 		{
       
  1229 		if (offset >= maxLength)
       
  1230 			{
       
  1231 			err = KErrOverflow;
       
  1232 			break;
       
  1233 			}
       
  1234 
       
  1235 		TBool doAppend(EFalse);
       
  1236 		DObject* obj = (DObject*)container[jj];
       
  1237 		if (aOwningProcess.Length() > 0)
       
  1238 			{
       
  1239 			if (obj->Owner())
       
  1240 				{
       
  1241 				TBuf8<KMaxFullName> fullName;
       
  1242 				obj->Owner()->FullName(fullName);
       
  1243 				if (fullName.MatchF(aOwningProcess) == 0)
       
  1244 					{
       
  1245 					doAppend = ETrue;
       
  1246 					}
       
  1247 				}
       
  1248 			}
       
  1249 		else
       
  1250 			{
       
  1251 			doAppend = ETrue;
       
  1252 			}
       
  1253 
       
  1254 
       
  1255 		if (doAppend)
       
  1256 			{
       
  1257 			err = Kern::ThreadDesWrite(iClient, aKernelInfoBuf, TPtrC8((TUint8*)&obj, sizeof(TAny*)), offset, KChunkShiftBy0, iClient);
       
  1258 			if (err)
       
  1259 				{
       
  1260 				break;
       
  1261 				}
       
  1262 			else
       
  1263 				{
       
  1264 				offset += sizeof(TAny*);
       
  1265 				}
       
  1266 			}
       
  1267 		}
       
  1268 	
       
  1269 	container.Signal();
       
  1270 	iLocks[aObjectType] = alreadyHeld;
       
  1271 	return err;
       
  1272 	}
       
  1273 
       
  1274 TInt DMemoryAccess::GetChunkAddresses(TUint aControllingProcessId, TDes8* aKernelInfoBuf)
       
  1275 	{
       
  1276 	DObjectCon* const * cons = Kern::Containers();
       
  1277 	DObjectCon& container = *cons[EChunk];
       
  1278 	container.Wait();
       
  1279 	TBool alreadyHeld = iLocks[EChunk];
       
  1280 	iLocks[EChunk] = ETrue;
       
  1281 
       
  1282 	TInt maxLength = Kern::ThreadGetDesMaxLength(iClient, aKernelInfoBuf);
       
  1283 	const TInt maxPtrs = maxLength / sizeof (TUint32*);
       
  1284 	TInt err = KErrNone;
       
  1285 
       
  1286 	if (maxPtrs == 0)
       
  1287 		{
       
  1288 		err = KErrOverflow;
       
  1289 		}
       
  1290 	else
       
  1291 		{
       
  1292 		TInt offset = 0;
       
  1293 
       
  1294 		for (TInt jj=0;jj<container.Count();jj++)
       
  1295 			{
       
  1296 			DChunk* chunk = (DChunk*)container[jj];
       
  1297 			if ((aControllingProcessId == KNullProcessId) || (chunk->iControllingOwner == aControllingProcessId))
       
  1298 				{
       
  1299 				err = Kern::ThreadDesWrite(iClient, aKernelInfoBuf, TPtrC8((TUint8*)&chunk, sizeof(TAny*)), offset, KChunkShiftBy0, iClient);
       
  1300 				if (err)
       
  1301 					{
       
  1302 					break;
       
  1303 					}
       
  1304 				else
       
  1305 					{
       
  1306 					offset += sizeof(TAny*);
       
  1307 					if (offset >= maxPtrs)
       
  1308 						{
       
  1309 						err = KErrOverflow;
       
  1310 						break;
       
  1311 						}
       
  1312 					}
       
  1313 				}
       
  1314 			}
       
  1315 		}
       
  1316 	
       
  1317 	container.Signal();
       
  1318 	iLocks[EChunk] = alreadyHeld;
       
  1319 	return err;
       
  1320 	}
       
  1321 
       
  1322 
       
  1323 // DMemoryAccess::ReleaseCodeSegMutex
       
  1324 //  Releases the code segment mutex
       
  1325 TInt DMemoryAccess::ReleaseCodeSegMutex()
       
  1326 	{
       
  1327 	// Kern::Printf("[DMemoryAccess] ::ReleaseCodeSegMutex");
       
  1328 	TInt err=KErrNone;
       
  1329 
       
  1330 	if (!iCodeSegLock)
       
  1331 		{ //Check the lock on code segs is not currently held
       
  1332 		Kern::ThreadKill(iClient, EExitPanic, EMemAccessMutexNotHeld, KMemAccessPanicCategory);
       
  1333 		err = KErrAbort;
       
  1334 		}
       
  1335 
       
  1336 	DMutex* const codeSegLock = Kern::CodeSegLock();
       
  1337 
       
  1338 	if (!err)
       
  1339 		{
       
  1340 		if (codeSegLock)
       
  1341 			{
       
  1342 			Kern::MutexSignal(*codeSegLock);
       
  1343 			iCodeSegLock = EFalse;
       
  1344 			}
       
  1345 		else
       
  1346 			{
       
  1347 			err = KErrNotFound;
       
  1348 			}
       
  1349 		}
       
  1350 	// Kern::Printf("[DMemoryAccess] ::ReleaseCodeSegMutex returning %d", err);
       
  1351 	return err;    	
       
  1352 	}
       
  1353 
       
  1354 
       
  1355 TInt DMemoryAccess::GetNextCodeSegInfo(TDes8* aCodeSegInfoBuf)
       
  1356 	{
       
  1357 	// Kern::Printf("[DMemoryAccess] ::GetNextCodeSegInfo");
       
  1358 	TInt err = KErrNone;
       
  1359 	
       
  1360 	SDblQue* p = Kern::CodeSegList();
       
  1361 	SDblQueLink* anchor=&p->iA;
       
  1362 
       
  1363 	if (!iCurrentCodeSeg)
       
  1364 		{
       
  1365 		iCurrentCodeSeg = _LOFF(anchor->iNext, DCodeSeg, iLink);
       
  1366 		}
       
  1367 
       
  1368 	if (iCurrentCodeSeg->iLink.iNext != anchor)
       
  1369 		{
       
  1370 		iCurrentCodeSeg = _LOFF(iCurrentCodeSeg->iLink.iNext, DCodeSeg, iLink);
       
  1371 		}
       
  1372 	else
       
  1373 		{
       
  1374 		iCurrentCodeSeg = NULL;
       
  1375 		err = KErrNotFound;
       
  1376 		}
       
  1377 		
       
  1378 	if (!err)
       
  1379 		{
       
  1380 		//TCodeSegKernelInfoBuf* localInfoBuf = new TCodeSegKernelInfoBuf;
       
  1381 		TPckgBuf<TTomsciCodeSegKernelInfo>* localInfoBuf = new TPckgBuf<TTomsciCodeSegKernelInfo>;
       
  1382 		if (!localInfoBuf)
       
  1383 			{
       
  1384 			err = KErrNoMemory;
       
  1385 			}
       
  1386 		else
       
  1387 			{	
       
  1388 			//Get the code seg info
       
  1389 			(*localInfoBuf)().iRunAddress = iCurrentCodeSeg->iRunAddress;
       
  1390 			(*localInfoBuf)().iSize = iCurrentCodeSeg->iSize;
       
  1391 			(*localInfoBuf)().iFileName = iCurrentCodeSeg->iFileName->Right((*localInfoBuf)().iFileName.MaxLength());
       
  1392 			(*localInfoBuf)().iAccessCount = iCurrentCodeSeg->iAccessCount;
       
  1393 			(*localInfoBuf)().iAddressOfKernelObject = (TUint8*)iCurrentCodeSeg;
       
  1394 			(*localInfoBuf)().iName = iCurrentCodeSeg->iRootName;
       
  1395 			(*localInfoBuf)().iDepCount = iCurrentCodeSeg->iDepCount;
       
  1396 
       
  1397 			//Copy the local info buffer into the client's address space
       
  1398 		    err = Kern::ThreadDesWrite(iClient, aCodeSegInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL);
       
  1399 			delete localInfoBuf;
       
  1400 			}
       
  1401 		}
       
  1402 
       
  1403 	// Kern::Printf("[DMemoryAccess] ::GetNextCodeSegInfo returning %d", err);
       
  1404 	return err;
       
  1405 	}
       
  1406 
       
  1407 TInt DMemoryAccess::ObjectDie(TObjectKillParamsBuf& aObjectKillParamsBuf)
       
  1408 	{
       
  1409 	TInt err=KErrNone;
       
  1410 	DObjectCon* const * cons = Kern::Containers();
       
  1411 
       
  1412 	switch(aObjectKillParamsBuf().iObjectType)
       
  1413 		{
       
  1414 	case EThread:
       
  1415 		{
       
  1416 		//Use the address of the kernel object ...
       
  1417 		DThread* thread = (DThread*)aObjectKillParamsBuf().iObjectPtr;
       
  1418 		//... unless the client has supplied an object ID
       
  1419 		if (aObjectKillParamsBuf().iObjectId!=0)
       
  1420 			{
       
  1421 			DObjectCon& container = *cons[EThread];
       
  1422 			container.Wait();
       
  1423 			NKern::ThreadEnterCS();
       
  1424 			thread = Kern::ThreadFromId(aObjectKillParamsBuf().iObjectId);
       
  1425 		    NKern::ThreadLeaveCS();
       
  1426 			container.Signal();
       
  1427 			}
       
  1428 		if (thread==NULL)
       
  1429 			err=KErrNotFound;
       
  1430 		else
       
  1431 			Kern::ThreadKill(thread, aObjectKillParamsBuf().iType, aObjectKillParamsBuf().iReason, aObjectKillParamsBuf().iCategory);
       
  1432 		break;
       
  1433 		}
       
  1434 	case EProcess:
       
  1435 		{
       
  1436 		//Use the address of the kernel object ...
       
  1437 		DProcess* process = (DProcess*)aObjectKillParamsBuf().iObjectPtr;
       
  1438 		//... unless the client has supplied an object ID
       
  1439 		if (aObjectKillParamsBuf().iObjectId!=0)
       
  1440 			{
       
  1441 			DObjectCon& container = *cons[EProcess];
       
  1442 			container.Wait();
       
  1443 			NKern::ThreadEnterCS();
       
  1444 			process = Kern::ProcessFromId(aObjectKillParamsBuf().iObjectId);
       
  1445 		    NKern::ThreadLeaveCS();
       
  1446 			container.Signal();
       
  1447 			}
       
  1448 		if (process==NULL)
       
  1449 			err=KErrNotFound;
       
  1450 		else
       
  1451 			{
       
  1452 			Kern::ThreadKill(process->FirstThread(), aObjectKillParamsBuf().iType, aObjectKillParamsBuf().iReason, aObjectKillParamsBuf().iCategory);
       
  1453 			}
       
  1454 		break;
       
  1455 		}
       
  1456 	default:
       
  1457 		err=KErrNotSupported;
       
  1458 		break;
       
  1459 		}
       
  1460 	return err;
       
  1461 	}
       
  1462 	
       
  1463 	
       
  1464 TInt DMemoryAccess::GetThreadInfo(DThread* aThread, TDes8* aThreadInfoBuf)
       
  1465 	{
       
  1466 	// Kern::Printf("[DMemoryAccess] ::GetThreadInfo");
       
  1467 	TInt err=KErrNone;
       
  1468 	//construct local info buffer to populate
       
  1469 	TThreadKernelInfoBuf* localInfoBuf = new TThreadKernelInfoBuf;	
       
  1470 	if (!localInfoBuf)
       
  1471 		{
       
  1472 		err=KErrNoMemory;
       
  1473 		}
       
  1474 	else
       
  1475 		{
       
  1476 		//Get the standard DObject info
       
  1477 		TThreadKernelInfo& localInfo = (*localInfoBuf)();
       
  1478 		GetObjectInfo(aThread, localInfo);
       
  1479 		//Get the thread specific info
       
  1480 		localInfo.iThreadId=aThread->iId;
       
  1481 		localInfo.iAddressOfOwningProcess=(TUint8*)aThread->iOwningProcess;
       
  1482 		localInfo.iThreadPriority = aThread->iDefaultPriority; // iDefaultPriority is more useful to know than iThreadPriority
       
  1483 		localInfo.iUserStackSize = aThread->iUserStackSize;
       
  1484 		localInfo.iFlags = aThread->iFlags;
       
  1485 		localInfo.iSupervisorStack = (TLinAddr)aThread->iSupervisorStack;
       
  1486 		localInfo.iSupervisorStackSize = aThread->iSupervisorStackSize;
       
  1487 		localInfo.iUserStackLimit = aThread->iUserStackRunAddress;
       
  1488 		localInfo.iNThreadSuspendCount = aThread->iNThread.iSuspendCount;
       
  1489 		//Copy the local info buffer into the client's address space
       
  1490 	    err = Kern::ThreadDesWrite(iClient, aThreadInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL);	
       
  1491 	    delete localInfoBuf;
       
  1492 		}
       
  1493 	return err;    		
       
  1494 	}
       
  1495 
       
  1496 TInt DMemoryAccess::GetProcessInfo(DProcess* aProcess, TDes8* aProcessInfoBuf)
       
  1497 	{
       
  1498 	//Kern::Printf("[DMemoryAccess] ::GetProcessInfo");
       
  1499 	TInt err=KErrNone;
       
  1500 
       
  1501 	//construct local info buffer to populate
       
  1502 	TProcessKernelInfoBuf* localInfoBuf = new TProcessKernelInfoBuf;
       
  1503 	if (!localInfoBuf)
       
  1504 		{
       
  1505 		err=KErrNoMemory;
       
  1506 		}
       
  1507 	else
       
  1508 		{
       
  1509 		//Get the standard DObject info
       
  1510 		// Kern::Printf("DMemoryAccess::GetProcessInfo getting object info");
       
  1511 		TProcessKernelInfo& localInfo = (*localInfoBuf)();
       
  1512 		GetObjectInfo (aProcess, localInfo);
       
  1513 		//Get the process specific info
       
  1514 		localInfo.iProcessId = aProcess->iId;
       
  1515 		localInfo.iPriority = aProcess->iPriority;
       
  1516 		localInfo.iAddressOfOwningProcess = (TUint8*)aProcess->iOwningProcess;
       
  1517 		localInfo.iCreatorId = aProcess->iCreatorId;
       
  1518 		localInfo.iSecurityZone = aProcess->iSecurityZone;
       
  1519 		localInfo.iUids = aProcess->iUids;
       
  1520 		localInfo.iAttributes = aProcess->iAttributes;
       
  1521 		localInfo.iFlags = aProcess->iFlags;
       
  1522 		localInfo.iAddressOfDataBssStackChunk = (TUint8*)aProcess->iDataBssStackChunk;
       
  1523 		TInt ii=0;
       
  1524 	    SDblQueLink* pLink=aProcess->iThreadQ.First();
       
  1525 		while ((pLink!=&aProcess->iThreadQ.iA) && (ii<KQueBufferLength))
       
  1526 			 {
       
  1527 			 DThread* pT=_LOFF(pLink,DThread,iProcessLink);
       
  1528 			 localInfo.iThreadQ.iBuffer[ii]=(TUint8*)pT;
       
  1529 			 pLink=pLink->iNext;
       
  1530 			 ii++;
       
  1531 			 }
       
  1532 		localInfo.iThreadQ.iStartFrom=0;
       
  1533 		localInfo.iThreadQ.iCount=ii;
       
  1534 		localInfo.iProcessSecurityInfo=aProcess->iS;
       
  1535 		localInfo.iProcessCreatorSecurityInfo=aProcess->iCreatorInfo;
       
  1536 		HBuf* commandLine = aProcess->iCommandLine;
       
  1537 		if (commandLine)
       
  1538 			{
       
  1539 			localInfo.iCommandLine = commandLine->Left(localInfo.iCommandLine.MaxLength());
       
  1540 			}
       
  1541 		memcpy(localInfo.iEnvironmentData, aProcess->iEnvironmentData, sizeof(TInt)*KNumEnvironmentSlots);
       
  1542 		localInfo.iFirstThreadId = 0;
       
  1543 		if (aProcess->FirstThread()) localInfo.iFirstThreadId = aProcess->FirstThread()->iId;
       
  1544 
       
  1545 		//Copy the local info buffer into the client's address space
       
  1546 		// Kern::Printf("DMemoryAccess::GetProcessInfo writing back");
       
  1547 	    err = Kern::ThreadDesWrite(iClient, aProcessInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL);	
       
  1548 		delete localInfoBuf;
       
  1549 		}
       
  1550 	return err;
       
  1551 	}
       
  1552 
       
  1553 	
       
  1554 TInt DMemoryAccess::GetChunkInfo(DChunk* aChunk, TDes8* aChunkInfoBuf)
       
  1555 	{
       
  1556 	// Kern::Printf("[DMemoryAccess] ::GetChunkInfo");
       
  1557 	TInt err=KErrNone;
       
  1558 	//construct local info buffer to populate
       
  1559 	TChunkKernelInfoBuf* localInfoBuf = new TChunkKernelInfoBuf;	
       
  1560 	if (!localInfoBuf)
       
  1561 		{
       
  1562 		err=KErrNoMemory;
       
  1563 		}
       
  1564 	else
       
  1565 		{
       
  1566 		TChunkKernelInfo& localInfo = (*localInfoBuf)();
       
  1567 		//Get the standard DObject info
       
  1568 		GetObjectInfo (aChunk, localInfo);
       
  1569 		//Get the chunk specific info
       
  1570 		localInfo.iSize = aChunk->Size();
       
  1571 		localInfo.iMaxSize = aChunk->MaxSize();
       
  1572 		localInfo.iBase = aChunk->Base();
       
  1573 		localInfo.iBottom = aChunk->Bottom();
       
  1574 		localInfo.iTop = aChunk->Top();
       
  1575 		localInfo.iAttributes = aChunk->iAttributes;
       
  1576 		localInfo.iStartPos = aChunk->iStartPos;
       
  1577 		localInfo.iControllingOwnerProcessId = aChunk->iControllingOwner;
       
  1578 		localInfo.iRestrictions = aChunk->iRestrictions;
       
  1579 		localInfo.iMapAttr = aChunk->iMapAttr;
       
  1580 		localInfo.iChunkType = aChunk->iChunkType;
       
  1581 		localInfo.iAddressOfOwningProcess = (TUint8*)aChunk->iOwningProcess;
       
  1582 #ifdef FSHELL_FLEXIBLEMM_AWARE
       
  1583 		if (localInfo.iBase == 0)
       
  1584 			{
       
  1585 			_LIT8(KKern, "ekern");
       
  1586 			DProcess* proc = aChunk->iOwningProcess;
       
  1587 			if (localInfo.iFullName.Left(KKern().Length()) != KKern && proc && proc->Open() == KErrNone)
       
  1588 				{
       
  1589 				// Probably shouldn't call ChunkUserBase for a non-user-owned chunk
       
  1590 				localInfo.iBase = Kern::ChunkUserBase(aChunk, proc->FirstThread());
       
  1591 				proc->Close(NULL);
       
  1592 				}
       
  1593 			}
       
  1594 #endif
       
  1595 		//Copy the local info buffer into the client's address space
       
  1596 	    err = Kern::ThreadDesWrite(iClient, aChunkInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL);	
       
  1597 		delete localInfoBuf;
       
  1598 		}
       
  1599 	return err;    		
       
  1600 	}
       
  1601 	
       
  1602 TInt DMemoryAccess::GetLibraryInfo(DLibrary* aLibrary, TDes8* aLibraryInfoBuf)
       
  1603 	{
       
  1604 	// Kern::Printf("[DMemoryAccess] ::GetLibraryInfo");
       
  1605 	TInt err=KErrNone;
       
  1606 	//construct local info buffer to populate
       
  1607 	TLibraryKernelInfoBuf* localInfoBuf = new TLibraryKernelInfoBuf;	
       
  1608 	if (!localInfoBuf)
       
  1609 		{
       
  1610 		err=KErrNoMemory;
       
  1611 		}
       
  1612 	else
       
  1613 		{
       
  1614 		//Get the standard DObject info
       
  1615 		GetObjectInfo (aLibrary, (*localInfoBuf)());
       
  1616 		//Get the library specific info
       
  1617 		(*localInfoBuf)().iMapCount = aLibrary->iMapCount;
       
  1618 		(*localInfoBuf)().iState = aLibrary->iState;
       
  1619 		(*localInfoBuf)().iAddressOfCodeSeg = (TUint8*)aLibrary->iCodeSeg;
       
  1620 
       
  1621 		//Copy the local info buffer into the client's address space
       
  1622 	    err = Kern::ThreadDesWrite(iClient, aLibraryInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL);	
       
  1623 		delete localInfoBuf;
       
  1624 		}
       
  1625 	return err;    		
       
  1626 	}
       
  1627 
       
  1628 TInt DMemoryAccess::GetSemaphoreInfo(DSemaphore* aSemaphore, TDes8* aSemaphoreInfoBuf)
       
  1629 	{
       
  1630 	// Kern::Printf("[DMemoryAccess] ::GetSemaphoreInfo");
       
  1631 	TInt err=KErrNone;
       
  1632 	//construct local info buffer to populate
       
  1633 	TSemaphoreKernelInfoBuf* localInfoBuf = new TSemaphoreKernelInfoBuf;	
       
  1634 	if (!localInfoBuf)
       
  1635 		{
       
  1636 		err=KErrNoMemory;
       
  1637 		}
       
  1638 	else
       
  1639 		{
       
  1640 		//Get the standard DObject info
       
  1641 		GetObjectInfo (aSemaphore, (*localInfoBuf)());
       
  1642 		//Get the Semaphore specific info
       
  1643 		(*localInfoBuf)().iCount = aSemaphore->iCount;
       
  1644 		(*localInfoBuf)().iResetting = aSemaphore->iResetting;
       
  1645 		TInt ii=0;
       
  1646 	    SDblQueLink* pLink=aSemaphore->iSuspendedQ.First();
       
  1647 		while ((pLink!=&aSemaphore->iSuspendedQ.iA) && (ii<KQueBufferLength))
       
  1648 			 {
       
  1649 			 DThread* pT=_LOFF(pLink,DThread,iWaitLink);
       
  1650 			 (*localInfoBuf)().iSuspendedQ.iBuffer[ii]=(TUint8*)pT;
       
  1651 			 pLink=pLink->iNext;
       
  1652 			 ii++;
       
  1653 			 }
       
  1654 		(*localInfoBuf)().iSuspendedQ.iStartFrom=0;
       
  1655 		(*localInfoBuf)().iSuspendedQ.iCount=ii;
       
  1656 
       
  1657 		//Copy the local info buffer into the client's address space
       
  1658 	    err = Kern::ThreadDesWrite(iClient, aSemaphoreInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL);	
       
  1659 		delete localInfoBuf;
       
  1660 		}
       
  1661 	return err;    		
       
  1662 	}
       
  1663 
       
  1664 TInt DMemoryAccess::GetMutexInfo(DMutex* aMutex, TDes8* aMutexInfoBuf)
       
  1665 	{
       
  1666 	// Kern::Printf("[DMemoryAccess] ::GetMutexInfo");
       
  1667 	TInt err=KErrNone;
       
  1668 	//construct local info buffer to populate
       
  1669 	TMutexKernelInfoBuf* localInfoBuf = new TMutexKernelInfoBuf;	
       
  1670 	if (!localInfoBuf)
       
  1671 		{
       
  1672 		err=KErrNoMemory;
       
  1673 		}
       
  1674 	else
       
  1675 		{
       
  1676 		//Get the standard DObject info
       
  1677 		GetObjectInfo (aMutex, (*localInfoBuf)());
       
  1678 		//Get the Mutex specific info
       
  1679 		(*localInfoBuf)().iHoldCount = aMutex->iHoldCount;
       
  1680 		(*localInfoBuf)().iWaitCount = aMutex->iWaitCount;
       
  1681 		(*localInfoBuf)().iResetting = aMutex->iResetting;
       
  1682 		(*localInfoBuf)().iOrder = aMutex->iOrder;
       
  1683 		TInt ii=0;
       
  1684 	    SDblQueLink* pLink=aMutex->iSuspendedQ.First();
       
  1685 		while ((pLink!=&aMutex->iSuspendedQ.iA) && (ii<KQueBufferLength))
       
  1686 			 {
       
  1687 			 DThread* pT=_LOFF(pLink,DThread,iWaitLink);
       
  1688 			 (*localInfoBuf)().iSuspendedQ.iBuffer[ii]=(TUint8*)pT;
       
  1689 			 pLink=pLink->iNext;
       
  1690 			 ii++;
       
  1691 			 }
       
  1692 		(*localInfoBuf)().iSuspendedQ.iStartFrom=0;
       
  1693 		(*localInfoBuf)().iSuspendedQ.iCount=ii;
       
  1694 		ii=0;
       
  1695 	    pLink=aMutex->iPendingQ.First();
       
  1696 		while ((pLink!=&aMutex->iPendingQ.iA) && (ii<KQueBufferLength))
       
  1697 			 {
       
  1698 			 DThread* pT=_LOFF(pLink,DThread,iWaitLink);
       
  1699 			 (*localInfoBuf)().iPendingQ.iBuffer[ii]=(TUint8*)pT;
       
  1700 			 pLink=pLink->iNext;
       
  1701 			 ii++;
       
  1702 			 }
       
  1703 		(*localInfoBuf)().iPendingQ.iStartFrom=0;
       
  1704 		(*localInfoBuf)().iPendingQ.iCount=ii;
       
  1705 
       
  1706 		//Copy the local info buffer into the client's address space
       
  1707 	    err = Kern::ThreadDesWrite(iClient, aMutexInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL);	
       
  1708 		delete localInfoBuf;
       
  1709 		}
       
  1710 	return err;    		
       
  1711 	}
       
  1712 
       
  1713 TInt DMemoryAccess::GetTimerInfo(DTimer* aTimer, TDes8* aTimerInfoBuf)
       
  1714 	{
       
  1715 	// Kern::Printf("[DMemoryAccess] ::GetTimerInfo");
       
  1716 	TInt err=KErrNone;
       
  1717 	//construct local info buffer to populate
       
  1718 	TTimerKernelInfoBuf* localInfoBuf = new TTimerKernelInfoBuf;	
       
  1719 	if (!localInfoBuf)
       
  1720 		{
       
  1721 		err=KErrNoMemory;
       
  1722 		}
       
  1723 	else
       
  1724 		{
       
  1725 		//Get the standard DObject info
       
  1726 		GetObjectInfo (aTimer, (*localInfoBuf)());
       
  1727 		//Get the timer specific info
       
  1728 		(*localInfoBuf)().iState = aTimer->iTimer.iState;
       
  1729 		(*localInfoBuf)().iType = aTimer->iTimer.iType;
       
  1730 #if FSHELL_PLATFORM_SYMTB >= 92 || FSHELL_PLATFORM_FOUNDATION >= 3
       
  1731 		(*localInfoBuf)().iClientStatus = NULL; //TOMSCI TEMP
       
  1732 #else
       
  1733 		(*localInfoBuf)().iClientStatus = (TLinAddr)aTimer->iTimer.iStatus;
       
  1734 #endif
       
  1735 
       
  1736 		//Copy the local info buffer into the client's address space
       
  1737 	    err = Kern::ThreadDesWrite(iClient, aTimerInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL);	
       
  1738 		delete localInfoBuf;
       
  1739 		}
       
  1740 	return err;    		
       
  1741 	}
       
  1742 
       
  1743 TInt DMemoryAccess::GetServerInfo(DServer* aServer, TDes8* aServerInfoBuf)
       
  1744 	{
       
  1745 	// Kern::Printf("[DMemoryAccess] ::GetServerInfo");
       
  1746 	TInt err=KErrNone;
       
  1747 	//construct local info buffer to populate
       
  1748 	TServerKernelInfoBuf* localInfoBuf = new TServerKernelInfoBuf;
       
  1749 	if (!localInfoBuf)
       
  1750 		{
       
  1751 		err=KErrNoMemory;
       
  1752 		}
       
  1753 	else
       
  1754 		{
       
  1755 		//Get the standard DObject info
       
  1756 		GetObjectInfo (aServer, (*localInfoBuf)());
       
  1757 		//Get the server specific info
       
  1758 		(*localInfoBuf)().iAddressOfOwningThread = (TUint8*)aServer->iOwningThread;
       
  1759 		(*localInfoBuf)().iOwningThreadId = aServer->iOwningThread->iId;
       
  1760 		(*localInfoBuf)().iSessionType = aServer->iSessionType;
       
  1761 		TInt ii=0;
       
  1762 	    SDblQueLink* pLink=aServer->iSessionQ.First();
       
  1763 		while ((pLink!=&aServer->iSessionQ.iA) && (ii<KQueBufferLength))
       
  1764 			 {
       
  1765 			 DSession* pT=_LOFF(pLink,DSession,iServerLink);
       
  1766 			 (*localInfoBuf)().iSessionQ.iBuffer[ii]=(TUint8*)pT;
       
  1767 			 pLink=pLink->iNext;
       
  1768 			 ii++;
       
  1769 			 }
       
  1770 		(*localInfoBuf)().iSessionQ.iStartFrom=0;
       
  1771 		(*localInfoBuf)().iSessionQ.iCount=ii;
       
  1772 
       
  1773 		//Copy the local info buffer into the client's address space
       
  1774 	    err = Kern::ThreadDesWrite(iClient, aServerInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL);	
       
  1775 		delete localInfoBuf;
       
  1776 		}
       
  1777 	return err;    		
       
  1778 	}
       
  1779 
       
  1780 TInt DMemoryAccess::GetSessionInfo(DSession* aSession, TDes8* aSessionInfoBuf)
       
  1781 	{
       
  1782 	// Kern::Printf("[DMemoryAccess] ::GetSessionInfo");
       
  1783 	TInt err=KErrNone;
       
  1784 	//construct local info buffer to populate
       
  1785 	TSessionKernelInfoBuf* localInfoBuf = new TSessionKernelInfoBuf;
       
  1786 	if (!localInfoBuf)
       
  1787 		{
       
  1788 		err=KErrNoMemory;
       
  1789 		}
       
  1790 	else
       
  1791 		{
       
  1792 		//Get the standard DObject info
       
  1793 		GetObjectInfo (aSession, (*localInfoBuf)());
       
  1794 		//Get the session specific info
       
  1795 		(*localInfoBuf)().iServer = (TUint8*)aSession->iServer;
       
  1796 #if defined(FSHELL_PLATFORM_FOUNDATION) || defined(FSHELL_PLATFORM_SYMTB)
       
  1797 		(*localInfoBuf)().iSessionPtr = (TAny*)aSession->iSessionCookie;
       
  1798 #else
       
  1799 		(*localInfoBuf)().iSessionPtr = (TAny*)aSession->iSessionPtr;
       
  1800 #endif
       
  1801 		(*localInfoBuf)().iTotalAccessCount = aSession->iTotalAccessCount;
       
  1802 		(*localInfoBuf)().iSessionType = aSession->iSessionType;
       
  1803 		(*localInfoBuf)().iSvrSessionType = aSession->iSvrSessionType;
       
  1804 		(*localInfoBuf)().iMsgCount = aSession->iMsgCount;
       
  1805 		(*localInfoBuf)().iMsgLimit = aSession->iMsgLimit;
       
  1806 
       
  1807 		//Copy the local info buffer into the client's address space
       
  1808 	    err = Kern::ThreadDesWrite(iClient, aSessionInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL);	
       
  1809 		delete localInfoBuf;
       
  1810 		}
       
  1811 	return err;    		
       
  1812 	}
       
  1813 
       
  1814 TInt DMemoryAccess::GetLogicalDeviceInfo(DLogicalDevice* aLogicalDevice, TDes8* aLogicalDeviceInfoBuf)
       
  1815 	{
       
  1816 	// Kern::Printf("[DMemoryAccess] ::GetLogicalDeviceInfo");
       
  1817 	TInt err=KErrNone;
       
  1818 	//construct local info buffer to populate
       
  1819 	TLogicalDeviceKernelInfoBuf* localInfoBuf = new TLogicalDeviceKernelInfoBuf;
       
  1820 	if (!localInfoBuf)
       
  1821 		{
       
  1822 		err=KErrNoMemory;
       
  1823 		}
       
  1824 	else
       
  1825 		{	
       
  1826 		//Get the standard DObject info
       
  1827 		GetObjectInfo (aLogicalDevice, (*localInfoBuf)());
       
  1828 		//Get the logical device specific info
       
  1829 		(*localInfoBuf)().iVersion = aLogicalDevice->iVersion;
       
  1830 		(*localInfoBuf)().iParseMask = aLogicalDevice->iParseMask;
       
  1831 		(*localInfoBuf)().iUnitsMask = aLogicalDevice->iUnitsMask;
       
  1832 		(*localInfoBuf)().iOpenChannels = aLogicalDevice->iOpenChannels;
       
  1833 
       
  1834 		//Copy the local info buffer into the client's address space
       
  1835 	    err = Kern::ThreadDesWrite(iClient, aLogicalDeviceInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL);	
       
  1836 		delete localInfoBuf;
       
  1837 		}
       
  1838 	return err;    		
       
  1839 	}
       
  1840 
       
  1841 TInt DMemoryAccess::GetPhysicalDeviceInfo(DPhysicalDevice* aPhysicalDevice, TDes8* aPhysicalDeviceInfoBuf)
       
  1842 	{
       
  1843 	// Kern::Printf("[DMemoryAccess] ::GetPhysicalDeviceInfo");
       
  1844 	TInt err=KErrNone;
       
  1845 	//construct local info buffer to populate
       
  1846 	TPhysicalDeviceKernelInfoBuf* localInfoBuf = new TPhysicalDeviceKernelInfoBuf;
       
  1847 	if (!localInfoBuf)
       
  1848 		{
       
  1849 		err=KErrNoMemory;
       
  1850 		}
       
  1851 	else
       
  1852 		{
       
  1853 		//Get the standard DObject info
       
  1854 		GetObjectInfo (aPhysicalDevice, (*localInfoBuf)());
       
  1855 		//Get the physical device specific info
       
  1856 		(*localInfoBuf)().iVersion = aPhysicalDevice->iVersion;
       
  1857 		(*localInfoBuf)().iUnitsMask = aPhysicalDevice->iUnitsMask;
       
  1858 		(*localInfoBuf)().iAddressOfCodeSeg = (TUint8*)aPhysicalDevice->iCodeSeg;
       
  1859 
       
  1860 		//Copy the local info buffer into the client's address space
       
  1861 	    err = Kern::ThreadDesWrite(iClient, aPhysicalDeviceInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL);	
       
  1862 		delete localInfoBuf;
       
  1863 		}
       
  1864 	return err;    		
       
  1865 	}
       
  1866 
       
  1867 TInt DMemoryAccess::GetLogicalChannelInfo(DLogicalChannel* aLogicalChannel, TDes8* aLogicalChannelInfoBuf)
       
  1868 	{
       
  1869 	// Kern::Printf("[DMemoryAccess] ::GetLogicalChannelInfo");
       
  1870 	TInt err=KErrNone;
       
  1871 	//construct local info buffer to populate
       
  1872 	TLogicalChannelKernelInfoBuf* localInfoBuf = new TLogicalChannelKernelInfoBuf;
       
  1873 	if (!localInfoBuf)
       
  1874 		{
       
  1875 		err=KErrNoMemory;
       
  1876 		}
       
  1877 	else
       
  1878 		{	
       
  1879 		//Get the standard DObject info
       
  1880 		GetObjectInfo (aLogicalChannel, (*localInfoBuf)());
       
  1881 		//Get the logical channel info
       
  1882 		
       
  1883 		//Copy the local info buffer into the client's address space
       
  1884 	    err = Kern::ThreadDesWrite(iClient, aLogicalChannelInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL);	
       
  1885 		delete localInfoBuf;
       
  1886 		}
       
  1887 	return err;    		
       
  1888 	}
       
  1889 
       
  1890 TInt DMemoryAccess::GetChangeNotifierInfo(DChangeNotifier* aChangeNotifier, TDes8* aChangeNotifierInfoBuf)
       
  1891 	{
       
  1892 	// Kern::Printf("[DMemoryAccess] ::GetChangeNotifierInfo");
       
  1893 	TInt err=KErrNone;
       
  1894 	//construct local info buffer to populate
       
  1895 	TChangeNotifierKernelInfoBuf* localInfoBuf = new TChangeNotifierKernelInfoBuf;
       
  1896 	if (!localInfoBuf)
       
  1897 		{
       
  1898 		err=KErrNoMemory;
       
  1899 		}
       
  1900 	else
       
  1901 		{
       
  1902 		//Get the standard DObject info
       
  1903 		GetObjectInfo (aChangeNotifier, (*localInfoBuf)());
       
  1904 		//Get the change notifier specific info
       
  1905 		(*localInfoBuf)().iChanges = aChangeNotifier->iChanges;
       
  1906 		(*localInfoBuf)().iAddressOfThread = (TUint8*)aChangeNotifier->iThread;
       
  1907 		
       
  1908 		//Copy the local info buffer into the client's address space
       
  1909 	    err = Kern::ThreadDesWrite(iClient, aChangeNotifierInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL);	
       
  1910 		delete localInfoBuf;
       
  1911 		}
       
  1912 	return err;    		
       
  1913 	}
       
  1914 
       
  1915 TInt DMemoryAccess::GetMsgQueueInfo(DMsgQueue* aMsgQueue, TDes8* aMsgQueueInfoBuf)
       
  1916 	{
       
  1917 	// Kern::Printf("[DMemoryAccess] ::GetUndertakerInfo");
       
  1918 	TInt err=KErrNone;
       
  1919 	//construct local info buffer to populate
       
  1920 	TMsgQueueKernelInfoBuf* localInfoBuf = new TMsgQueueKernelInfoBuf;	
       
  1921 	if (!localInfoBuf)
       
  1922 		{
       
  1923 		err=KErrNoMemory;
       
  1924 		}
       
  1925 	else
       
  1926 		{
       
  1927 		//Get the standard DObject info
       
  1928 		GetObjectInfo((DObject*)aMsgQueue, (*localInfoBuf)());
       
  1929 		//Get the specific info - highly fragile this!
       
  1930 		const TInt KSizeOffset = sizeof(DObject)+(8*4);
       
  1931 		(*localInfoBuf)().iMaxMsgLength = *(TUint16*)((TLinAddr)aMsgQueue + KSizeOffset);
       
  1932 		
       
  1933 		//Copy the local info buffer into the client's address space
       
  1934 	    err = Kern::ThreadDesWrite(iClient, aMsgQueueInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL);	
       
  1935 		delete localInfoBuf;
       
  1936 		}
       
  1937 	return err;    		
       
  1938 	}
       
  1939 
       
  1940 TInt DMemoryAccess::GetUndertakerInfo(DUndertaker* aUndertaker, TDes8* aUndertakerInfoBuf)
       
  1941 	{
       
  1942 	// Kern::Printf("[DMemoryAccess] ::GetUndertakerInfo");
       
  1943 	TInt err=KErrNone;
       
  1944 	//construct local info buffer to populate
       
  1945 	TUndertakerKernelInfoBuf* localInfoBuf = new TUndertakerKernelInfoBuf;	
       
  1946 	if (!localInfoBuf)
       
  1947 		{
       
  1948 		err=KErrNoMemory;
       
  1949 		}
       
  1950 	else
       
  1951 		{
       
  1952 		//Get the standard DObject info
       
  1953 		GetObjectInfo (aUndertaker, (*localInfoBuf)());
       
  1954 		//Get the thread specific info
       
  1955 		(*localInfoBuf)().iOwningThread = (TUint8*)aUndertaker->iOwningThread;
       
  1956 		
       
  1957 		//Copy the local info buffer into the client's address space
       
  1958 	    err = Kern::ThreadDesWrite(iClient, aUndertakerInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL);	
       
  1959 		delete localInfoBuf;
       
  1960 		}
       
  1961 	return err;    		
       
  1962 	}
       
  1963 
       
  1964 TInt DMemoryAccess::GetCondVarInfo(DCondVar* aCondVar, TDes8* aCondVarInfoBuf)
       
  1965 	{
       
  1966 	// Kern::Printf("[DMemoryAccess] ::GetCondVarInfo");
       
  1967 	TInt err=KErrNone;
       
  1968 	//construct local info buffer to populate
       
  1969 	TCondVarKernelInfoBuf* localInfoBuf = new TCondVarKernelInfoBuf;
       
  1970 	if (!localInfoBuf)
       
  1971 		{
       
  1972 		err=KErrNoMemory;
       
  1973 		}
       
  1974 	else
       
  1975 		{	
       
  1976 		//Get the standard DObject info
       
  1977 		GetObjectInfo (aCondVar, (*localInfoBuf)());
       
  1978 		//Get the cond var specific info
       
  1979 		(*localInfoBuf)().iResetting = aCondVar->iResetting;
       
  1980 		(*localInfoBuf)().iAddressOfMutex = (TUint8*)aCondVar->iMutex;
       
  1981 		(*localInfoBuf)().iWaitCount = aCondVar->iWaitCount;
       
  1982 		TInt ii=0;
       
  1983 		SDblQueLink* pLink=aCondVar->iSuspendedQ.First();
       
  1984 		while ((pLink!=&aCondVar->iSuspendedQ.iA) && (ii<KQueBufferLength))
       
  1985 			 {
       
  1986 			 DThread* pT=_LOFF(pLink,DThread,iWaitLink);
       
  1987 			 (*localInfoBuf)().iSuspendedQ.iBuffer[ii]=(TUint8*)pT;
       
  1988 			 pLink=pLink->iNext;
       
  1989 			 ii++;
       
  1990 			 }
       
  1991 		(*localInfoBuf)().iSuspendedQ.iStartFrom=0;
       
  1992 		(*localInfoBuf)().iSuspendedQ.iCount=ii;
       
  1993 
       
  1994 		//Copy the local info buffer into the client's address space
       
  1995 		err = Kern::ThreadDesWrite(iClient, aCondVarInfoBuf, *localInfoBuf, 0, KTruncateToMaxLength, NULL);	
       
  1996 		delete localInfoBuf;
       
  1997 		}
       
  1998 	return err;    		
       
  1999 	}
       
  2000 
       
  2001 TInt DMemoryAccess::FindPtrInCodeSegments(TAny* aDllNamePtr, TAny* aPtr)
       
  2002 	{
       
  2003 	/*
       
  2004 	// Iterate the code segments
       
  2005 	TInt err = AcquireCodeSegMutex();
       
  2006 	if (err) return err;
       
  2007 	DCodeSeg* currentCodeSeg = NULL;
       
  2008 
       
  2009 	//BEGIN copied from GetNextCodeSegInfo
       
  2010 	SDblQue* p = Kern::CodeSegList();
       
  2011 	SDblQueLink* anchor=&p->iA;
       
  2012 
       
  2013 	currentCodeSeg = _LOFF(anchor->iNext, DCodeSeg, iLink);
       
  2014 
       
  2015 	while (currentCodeSeg)
       
  2016 		{
       
  2017 		if (currentCodeSeg->iLink.iNext != anchor)
       
  2018 			{
       
  2019 			currentCodeSeg = _LOFF(currentCodeSeg->iLink.iNext, DCodeSeg, iLink);
       
  2020 			if ((TUint)aPtr >= currentCodeSeg->iRunAddress && (TUint)aPtr < currentCodeSeg->iRunAddress + currentCodeSeg->iSize)
       
  2021 				{
       
  2022 				// Found it
       
  2023 				break;
       
  2024 				}
       
  2025 			}
       
  2026 		else
       
  2027 			{
       
  2028 			// Not found any code seg matching
       
  2029 			currentCodeSeg = NULL;
       
  2030 			err = KErrNotFound;
       
  2031 			}
       
  2032 		}
       
  2033 	//END copied from GetNextCodeSegInfo
       
  2034 	ReleaseCodeSegMutex();
       
  2035 	// End iterate
       
  2036 	*/
       
  2037 
       
  2038 	Kern::MutexWait(*Kern::CodeSegLock());
       
  2039 	DCodeSeg* currentCodeSeg = Kern::CodeSegFromAddress((TLinAddr)aPtr, iClient->iOwningProcess);
       
  2040 	TInt err = KErrNone;
       
  2041 	TInt offset = 0;
       
  2042 	TBuf8<256> dllName;
       
  2043 	if (currentCodeSeg)
       
  2044 		{
       
  2045 		dllName.Copy(*currentCodeSeg->iFileName);
       
  2046 		offset = (TUint)aPtr - currentCodeSeg->iRunAddress; // This won't work on flexible memory model!
       
  2047 		}
       
  2048 	else
       
  2049 		{
       
  2050 		err = KErrNotFound;
       
  2051 		}
       
  2052 	Kern::MutexSignal(*Kern::CodeSegLock());
       
  2053 
       
  2054 	if (!err)
       
  2055 		{
       
  2056 		err = Kern::ThreadDesWrite(iClient, aDllNamePtr, dllName, 0, KTruncateToMaxLength, NULL);
       
  2057 		}
       
  2058 	return err ? err : offset;
       
  2059 	}
       
  2060 
       
  2061 TInt DMemoryAccess::GetHandleOwners(TAny* aObj, TAny* aOwnersBuf)
       
  2062 	{
       
  2063 #ifdef FSHELL_DOBJECTIX_SUPPORT
       
  2064 	TBuf8<256> buf;
       
  2065 	
       
  2066 	// Code adapted from ExecHandler::HandleInfo
       
  2067 	DObject* pO=(DObject*)aObj;
       
  2068 	TInt r = KErrNone;
       
  2069 	/*
       
  2070 	DThread& t = *iClient;
       
  2071 	//TInt r=K::OpenObjectFromHandle(aHandle,pO);
       
  2072 	//BEGIN this bit copied from K::OpenObjectFromHandle
       
  2073 	TInt r=KErrBadHandle;
       
  2074 	NKern::ThreadEnterCS();
       
  2075 	NKern::LockSystem();
       
  2076 	pO=t.ObjectFromHandle(aHandle);
       
  2077 	if (pO)
       
  2078 		r=pO->Open();
       
  2079 	NKern::UnlockSystem();
       
  2080 	if (r!=KErrNone)
       
  2081 		{
       
  2082 		pO=NULL;
       
  2083 		NKern::ThreadLeaveCS();
       
  2084 		}
       
  2085 	//END
       
  2086 	*/
       
  2087 
       
  2088 	if (r==KErrNone)
       
  2089 		{
       
  2090 		//DObjectIx::Wait(); //TOMSCI I can't call this frmo a device driver, why did the code I copied do it but none of the DMemoryAccess stuff that uses containers do it??
       
  2091 		//DProcess* pCurrentProcess=TheCurrentThread->iOwningProcess;
       
  2092 		//hinfo.iNumOpenInThread=TheCurrentThread->iHandles->Count(pO);
       
  2093 		//hinfo.iNumOpenInProcess=pCurrentProcess->iHandles->Count(pO);
       
  2094 
       
  2095 		DObjectCon* const * cons=Kern::Containers();
       
  2096 		DObjectCon& threads = *cons[EThread];
       
  2097 		threads.Wait();
       
  2098 		TInt c=threads.Count();
       
  2099 		TInt i=0;
       
  2100 		for (;i<c;i++)
       
  2101 			{
       
  2102 			DThread *pT=(DThread *)threads[i];
       
  2103 			DObjectIx* handles = pT->iHandles;
       
  2104 			if (handles) // maybe a nearly dead one hanging around
       
  2105 				{
       
  2106 				TInt rr=((DObjectIxNinePointTwoHack*)handles)->At(pO);
       
  2107 				if (rr!=KErrNotFound)
       
  2108 					{
       
  2109 					TPckgBuf<TUint> idBuf(pT->iId);
       
  2110 					if (buf.Length() + idBuf.Length() >= buf.MaxLength())
       
  2111 						{
       
  2112 						r = KErrOverflow;
       
  2113 						break;
       
  2114 						}
       
  2115 					else
       
  2116 						{
       
  2117 						buf.Append(idBuf);
       
  2118 						}
       
  2119 					//++hinfo.iNumThreads;
       
  2120 					//if (pT->iOwningProcess==pCurrentProcess)
       
  2121 					//	++hinfo.iNumOpenInProcess;
       
  2122 					}
       
  2123 				}
       
  2124 			}
       
  2125 		threads.Signal();
       
  2126 
       
  2127 		DObjectCon& processes = *cons[EProcess];
       
  2128 		processes.Wait();
       
  2129 		c=processes.Count();
       
  2130 		for (i=0;i<c;i++)
       
  2131 			{
       
  2132 			DProcess *pP=(DProcess *)processes[i];
       
  2133 			DObjectIx* handles = pP->iHandles;
       
  2134 			if (handles) // maybe a nearly dead one hanging around
       
  2135 				{
       
  2136 				TInt rr=((DObjectIxNinePointTwoHack*)handles)->At(pO);
       
  2137 				if (rr!=KErrNotFound)
       
  2138 					{
       
  2139 					//++hinfo.iNumProcesses;
       
  2140 					TPckgBuf<TUint> idBuf(pP->iId);
       
  2141 					if (buf.Length() + idBuf.Length() >= buf.MaxLength())
       
  2142 						{
       
  2143 						r = KErrOverflow;
       
  2144 						break;
       
  2145 						}
       
  2146 					else
       
  2147 						{
       
  2148 						buf.Append(idBuf);
       
  2149 						}
       
  2150 					}
       
  2151 				}
       
  2152 			}
       
  2153 		processes.Signal();
       
  2154 		//DObjectIx::Signal();
       
  2155 
       
  2156 
       
  2157 		//DObjectIx::Signal();
       
  2158 		//pO->Close(NULL);
       
  2159 		//NKern::ThreadLeaveCS();
       
  2160 		}
       
  2161 	
       
  2162 	TInt clientLen = Kern::ThreadGetDesMaxLength(iClient, aOwnersBuf);
       
  2163 	if (clientLen < 0) return clientLen;
       
  2164 	TInt writeErr = Kern::ThreadDesWrite(iClient, aOwnersBuf, buf, 0, KTruncateToMaxLength, NULL);
       
  2165 	if (writeErr) return writeErr;
       
  2166 	return (clientLen < buf.Length()) ? KErrOverflow : r;
       
  2167 #else
       
  2168 	return KErrNotSupported;
       
  2169 #endif
       
  2170 	}
       
  2171 
       
  2172 TInt DMemoryAccess::GetThreadHandles(TInt aThreadId, TAny* aHandlesBuf)
       
  2173 	{
       
  2174 #ifdef FSHELL_DOBJECTIX_SUPPORT
       
  2175 	TInt maxLength = Kern::ThreadGetDesMaxLength(iClient, aHandlesBuf);
       
  2176 	TInt err = KErrNone;
       
  2177 
       
  2178 	DObjectCon* const * cons = Kern::Containers();
       
  2179 	DObjectCon& container = *cons[EThread];
       
  2180 	container.Wait();
       
  2181 	NKern::ThreadEnterCS();
       
  2182 	DThread* thread = Kern::ThreadFromId(aThreadId);
       
  2183 	//TOMSCI FIXME we don't increment thread's ref count
       
  2184 	NKern::ThreadLeaveCS();
       
  2185 	container.Signal();
       
  2186 	if (thread == NULL) 
       
  2187 		{
       
  2188 		return KErrNotFound;
       
  2189 		}
       
  2190 
       
  2191 	// Note, this code is inherently dodgy because it doesn't claim DObjectIx::HandleMutex.
       
  2192 	DObjectIxNinePointTwoHack* handles = (DObjectIxNinePointTwoHack*)thread->iHandles;
       
  2193 	if (handles)
       
  2194 		{
       
  2195 		TInt offset = 0;
       
  2196 
       
  2197 		for (TInt i = 0; i < handles->Count(); ++i)
       
  2198 			{
       
  2199 			if (offset >= maxLength)
       
  2200 				{
       
  2201 				err = KErrOverflow;
       
  2202 				break;
       
  2203 				}
       
  2204 			NKern::LockSystem();
       
  2205 			DObject* obj = (*handles)[i];
       
  2206 			NKern::UnlockSystem();
       
  2207 			if (obj != NULL)
       
  2208 				{
       
  2209 				err = Kern::ThreadDesWrite(iClient, aHandlesBuf, TPtrC8((TUint8*)&obj, sizeof(TAny*)), offset, KChunkShiftBy0, iClient);
       
  2210 				if (err)
       
  2211 					{
       
  2212 					break;
       
  2213 					}
       
  2214 				else
       
  2215 					{
       
  2216 					offset += sizeof(TAny*);
       
  2217 					}
       
  2218 				}
       
  2219 			}
       
  2220 		}
       
  2221 
       
  2222 	//TOMSCI What is this unlock doing here? TODO FIXME!!!
       
  2223 	NKern::UnlockSystem();
       
  2224 	return err;
       
  2225 #else
       
  2226 	return KErrNotSupported;
       
  2227 #endif
       
  2228 	}
       
  2229 
       
  2230 TInt DMemoryAccess::GetProcessHandles(TInt aProcessId, TAny* aHandlesBuf)
       
  2231 	{
       
  2232 #ifdef FSHELL_DOBJECTIX_SUPPORT
       
  2233 	TInt maxLength = Kern::ThreadGetDesMaxLength(iClient, aHandlesBuf);
       
  2234 	TInt err = KErrNone;
       
  2235 
       
  2236 	DObjectCon* const * cons = Kern::Containers();
       
  2237 	DObjectCon& container = *cons[EProcess];
       
  2238 	container.Wait();
       
  2239 	NKern::ThreadEnterCS();
       
  2240 	DProcess* process = Kern::ProcessFromId(aProcessId);
       
  2241 	NKern::ThreadLeaveCS();
       
  2242 	container.Signal();
       
  2243 	if (process == NULL) 
       
  2244 		{
       
  2245 		return KErrNotFound;
       
  2246 		}
       
  2247 
       
  2248 	// Note, this code is inherently dodgy because it doesn't claim DObjectIx::HandleMutex.
       
  2249 	DObjectIxNinePointTwoHack* handles = (DObjectIxNinePointTwoHack*)process->iHandles;
       
  2250 	if (handles)
       
  2251 		{
       
  2252 		TInt offset = 0;
       
  2253 
       
  2254 		for (TInt i = 0; i < handles->Count(); ++i)
       
  2255 			{
       
  2256 			if (offset >= maxLength)
       
  2257 				{
       
  2258 				err = KErrOverflow;
       
  2259 				break;
       
  2260 				}
       
  2261 			NKern::LockSystem();
       
  2262 			DObject* obj = (*handles)[i];
       
  2263 			NKern::UnlockSystem();
       
  2264 			if (obj != NULL)
       
  2265 				{
       
  2266 				err = Kern::ThreadDesWrite(iClient, aHandlesBuf, TPtrC8((TUint8*)&obj, sizeof(TAny*)), offset, KChunkShiftBy0, iClient);
       
  2267 				if (err)
       
  2268 					{
       
  2269 					break;
       
  2270 					}
       
  2271 				else
       
  2272 					{
       
  2273 					offset += sizeof(TAny*);
       
  2274 					}
       
  2275 				}
       
  2276 			}
       
  2277 		}
       
  2278 
       
  2279 	return err;
       
  2280 #else
       
  2281 	return KErrNotSupported;
       
  2282 #endif
       
  2283 	}
       
  2284 
       
  2285 TInt DMemoryAccess::SetCriticalFlags(TInt aThreadHandle, TUint aFlags)
       
  2286 	{
       
  2287 	NKern::LockSystem();
       
  2288 	DThread* thread = (DThread*)Kern::ObjectFromHandle(iClient, aThreadHandle, EThread);
       
  2289 	if (!thread) 
       
  2290 		{
       
  2291 		NKern::UnlockSystem();
       
  2292 		return KErrNotFound;
       
  2293 		}
       
  2294 
       
  2295 	const TUint32 clear =	KThreadFlagSystemPermanent | KThreadFlagSystemCritical |
       
  2296 							KThreadFlagProcessPermanent | KThreadFlagProcessCritical;
       
  2297 
       
  2298 	TUint newFlags = (thread->iFlags&~clear) | aFlags;
       
  2299 	thread->iFlags = newFlags;
       
  2300 
       
  2301 	NKern::UnlockSystem();
       
  2302 	return KErrNone;
       
  2303 	}
       
  2304 
       
  2305 // Enter and exit with system lock held
       
  2306 TInt SetPri(DThread* aThread, TInt aPriority)
       
  2307 	{
       
  2308 	//Kern::SetThreadPriority(aPriority, aThread);
       
  2309 
       
  2310 	// Bypass limitation of Kern::SetThreadPriority on specifying relative priorities
       
  2311 	if (aPriority<EThrdPriorityIdle || aPriority==-1 || aPriority==0 || aPriority>=KNumPriorities)
       
  2312 		return KErrArgument;
       
  2313 	aThread->SetThreadPriority(aPriority);
       
  2314 	return KErrNone;
       
  2315 	}
       
  2316 
       
  2317 TInt DMemoryAccess::SetThreadPriority(TInt aThreadHandle, TInt aPriority)
       
  2318 	{
       
  2319 	NKern::LockSystem();
       
  2320 	DThread* thread = (DThread*)Kern::ObjectFromHandle(iClient, aThreadHandle, EThread);
       
  2321 	if (!thread) 
       
  2322 		{
       
  2323 		NKern::UnlockSystem();
       
  2324 		return KErrNotFound;
       
  2325 		}
       
  2326 
       
  2327 	TInt err = SetPri(thread, aPriority);
       
  2328 	NKern::UnlockSystem();
       
  2329 	return err;
       
  2330 	}
       
  2331 
       
  2332 void DMemoryAccess::NotifyThreadCreation(TRequestStatus* aStatus)
       
  2333 	{
       
  2334 	// TODO: Have this migrate to the shared event handler
       
  2335 	TInt err = KErrNone;
       
  2336 	TBool supported = DKernelEventHandler::DebugSupportEnabled();
       
  2337 	if (!supported) err = KErrNotSupported;
       
  2338 	if (!err && !iEventHandler)
       
  2339 		{
       
  2340 		iEventHandler = new DThreadChangeHandler(iClient);
       
  2341 		if (iEventHandler)
       
  2342 			{
       
  2343 			iEventHandler->Add(DKernelEventHandler::EAppend);
       
  2344 			}
       
  2345 		else
       
  2346 			{
       
  2347 			err = KErrNoMemory;
       
  2348 			}
       
  2349 		}
       
  2350 
       
  2351 	if (err)
       
  2352 		{
       
  2353 		Kern::RequestComplete(iClient, aStatus, err);
       
  2354 		}
       
  2355 	else
       
  2356 		{
       
  2357 		iEventHandler->SetStatus(aStatus);
       
  2358 		}
       
  2359 	}
       
  2360 
       
  2361 void DMemoryAccess::CancelNotifyThreadCreation()
       
  2362 	{
       
  2363 	if (iEventHandler)
       
  2364 		{
       
  2365 		iEventHandler->SetStatus(NULL);
       
  2366 		}
       
  2367 	}
       
  2368 
       
  2369 TInt DMemoryAccess::SetPriorityOverride(TInt aPriority, TAny* aMatchString)
       
  2370 	{
       
  2371 	// TODO: Have this migrate to the shared event handler
       
  2372 	// Or... just remove it. It's really odd code that could probably achieve its end goals in a much more sensible way.
       
  2373 	TInt err = KErrNone;
       
  2374 	if (!iEventHandler)
       
  2375 		{
       
  2376 		iEventHandler = new DThreadChangeHandler(iClient);
       
  2377 		if (iEventHandler)
       
  2378 			{
       
  2379 			iEventHandler->Add(DKernelEventHandler::EAppend);
       
  2380 			}
       
  2381 		else
       
  2382 			{
       
  2383 			err = KErrNoMemory;
       
  2384 			}
       
  2385 		}
       
  2386 	
       
  2387 	// TODO: this isn't thread safe, as iEventHandler is already added... meh.
       
  2388 	
       
  2389 	if (!err)
       
  2390 		{
       
  2391 		iEventHandler->iPriorityToSet = aPriority;
       
  2392 		err = Kern::ThreadDesRead(iClient, aMatchString, iEventHandler->iMatch,	0);
       
  2393 		}
       
  2394 	return err;
       
  2395 	}
       
  2396 
       
  2397 TInt DMemoryAccess::OpenThread(TUint aThreadId)
       
  2398 	{
       
  2399 	NKern::ThreadEnterCS();
       
  2400 	DObjectCon* threads = Kern::Containers()[EThread];
       
  2401 	threads->Wait();
       
  2402 	DThread* thread = Kern::ThreadFromId(aThreadId);
       
  2403 	if (thread && thread->Open() != KErrNone)
       
  2404 		{
       
  2405 		// Failed to open
       
  2406 		thread = NULL;
       
  2407 		}
       
  2408 	threads->Signal();
       
  2409 
       
  2410 	if (thread)
       
  2411 		{
       
  2412 		TInt res = Kern::MakeHandleAndOpen(iClient, thread);
       
  2413 		thread->Close(NULL);
       
  2414 		NKern::ThreadLeaveCS();
       
  2415 		return res;
       
  2416 		}
       
  2417 	else
       
  2418 		{
       
  2419 		NKern::ThreadLeaveCS();
       
  2420 		return KErrNotFound;
       
  2421 		}
       
  2422 	}
       
  2423 
       
  2424 DThreadChangeHandler::DThreadChangeHandler(DThread* aClientThread)
       
  2425 	: DKernelEventHandler(&Event, this), iThread(aClientThread)
       
  2426 	{
       
  2427 	}
       
  2428 
       
  2429 DThreadChangeHandler::~DThreadChangeHandler()
       
  2430 	{
       
  2431 	}
       
  2432 
       
  2433 /*static*/ TUint DThreadChangeHandler::Event(TKernelEvent aEvent, TAny* a1, TAny* a2, TAny* aPrivateData)
       
  2434 	{
       
  2435 	DThreadChangeHandler* self = static_cast<DThreadChangeHandler*>(aPrivateData);
       
  2436 	return self->DoEvent(aEvent, a1, a2);
       
  2437 	}
       
  2438 
       
  2439 TUint DThreadChangeHandler::DoEvent(TKernelEvent aEvent, TAny* a1, TAny* /*a2*/)
       
  2440 	{
       
  2441 	if (aEvent == EEventAddThread)
       
  2442 		{
       
  2443 		TRequestStatus* nullstat = NULL;
       
  2444 		TRequestStatus* stat = (TRequestStatus*)NKern::SafeSwap(nullstat, (TAny*&)iStatus);
       
  2445 		DThread* thread = static_cast<DThread*>(a1);
       
  2446 		TBool notify = ETrue;
       
  2447 
       
  2448 		if (iPriorityToSet && iMatch.Length())
       
  2449 			{
       
  2450 			TBuf8<256> name;
       
  2451 			thread->AppendFullName(name);
       
  2452 			if (name.MatchF(iMatch) >= 0)
       
  2453 				{
       
  2454 				//Kern::Printf("Matched %O", thread);
       
  2455 				NKern::LockSystem();
       
  2456 				SetPri(thread, iPriorityToSet);
       
  2457 				NKern::UnlockSystem();
       
  2458 				}
       
  2459 			else
       
  2460 				{
       
  2461 				// Not a thread we're interested in
       
  2462 				notify = EFalse;
       
  2463 				}
       
  2464 			}
       
  2465 		if (stat && notify)
       
  2466 			{
       
  2467 			TInt res = Kern::MakeHandleAndOpen(iThread, thread);
       
  2468 			Kern::RequestComplete(iThread, stat, res);
       
  2469 			}
       
  2470 		}
       
  2471 	return ERunNext;
       
  2472 	}
       
  2473 
       
  2474 void DThreadChangeHandler::SetStatus(TRequestStatus* aStatus)
       
  2475 	{
       
  2476 	TRequestStatus* oldStat = (TRequestStatus*)NKern::SafeSwap(aStatus, (TAny*&)iStatus);
       
  2477 	if (oldStat)
       
  2478 		{
       
  2479 		Kern::RequestComplete(iThread, oldStat, KErrCancel);
       
  2480 		}
       
  2481 	}
       
  2482 
       
  2483 TInt DMemoryAccess::InPlaceObjectRename(TAny* aParamsBuf, TAny* aNewNamePtr)
       
  2484 	{
       
  2485 	TObjectInfoByPtrParams params;
       
  2486 	TPckg<TObjectInfoByPtrParams> paramsPkg(params);
       
  2487 	TInt err = Kern::ThreadDesRead(iClient, aParamsBuf, paramsPkg, 0);
       
  2488 	if (err) return err;
       
  2489 
       
  2490 	TKName newName;
       
  2491 	err = Kern::ThreadDesRead(iClient, aNewNamePtr, newName, 0);
       
  2492 	if (err) return err;
       
  2493 
       
  2494 	TInt posInContainer = KErrNotFound;
       
  2495 	DObjectCon* const * cons = Kern::Containers();
       
  2496 	DObjectCon& container = *cons[params.iObjectType];
       
  2497 	container.Wait();
       
  2498 	TBool alreadyHeld = iLocks[params.iObjectType];
       
  2499 	iLocks[params.iObjectType] = ETrue;
       
  2500 	
       
  2501 	err = GetObjectPositionInContainer(params.iObjectPtr, container, posInContainer);
       
  2502 
       
  2503 	if (err == KErrNone)
       
  2504 		{
       
  2505 		DObject* obj = container[posInContainer];
       
  2506 		obj->iName->Copy(newName);
       
  2507 		}
       
  2508 	container.Signal();
       
  2509 	iLocks[params.iObjectType] = alreadyHeld;
       
  2510 	return err;
       
  2511 	}
       
  2512 
       
  2513 TInt DMemoryAccess::InPlaceSetProcessFileName(TAny* a1, TAny* aNewNamePtr)
       
  2514 	{
       
  2515 	NKern::LockSystem();
       
  2516 	DProcess* process = (DProcess*)Kern::ObjectFromHandle(iClient, (TUint)a1, EProcess);
       
  2517 	NKern::UnlockSystem();
       
  2518 	if (!process) 
       
  2519 		{
       
  2520 		return KErrNotFound;
       
  2521 		}
       
  2522 	TBuf<256> filename;
       
  2523 	TInt err = Kern::ThreadDesRead(iClient, aNewNamePtr, filename, 0);
       
  2524 	if (err) return err;
       
  2525 	//thread->iName->Copy(buf);
       
  2526 #ifdef __WINS__
       
  2527 	// Wins does 'optimisations' on the file name meaning an in-place copy will never work
       
  2528 	HBuf* newName = HBuf8::New(filename);
       
  2529 	if (!newName) return KErrNoMemory;
       
  2530 	HBuf* oldName = (HBuf*)NKern::SafeSwap(newName, (TAny*&)process->iCodeSeg->iFileName);
       
  2531 	delete oldName;
       
  2532 #else
       
  2533 	process->iCodeSeg->iFileName->Copy(filename);
       
  2534 #endif
       
  2535 	return KErrNone;
       
  2536 	}
       
  2537 
       
  2538 class RHackAllocator : public RAllocator
       
  2539 	{
       
  2540 public:
       
  2541 	using RAllocator::iFlags;
       
  2542 	};
       
  2543 
       
  2544 TInt DMemoryAccess::EnableHeapTracing(TUint aThreadId, TBool aEnable)
       
  2545 	{
       
  2546 #ifndef FSHELL_BTRACE_SUPPORT
       
  2547 	// If the kernel doesn't have btrace, the heap won't have instrumentation
       
  2548 	(void)aThreadId;
       
  2549 	(void)aEnable;
       
  2550 	return KErrNotSupported;
       
  2551 #else
       
  2552 
       
  2553 	DObjectCon* threads = Kern::Containers()[EThread];
       
  2554 	NKern::ThreadEnterCS();
       
  2555 	threads->Wait();
       
  2556 	DThread* thread = Kern::ThreadFromId(aThreadId);
       
  2557 	if (thread) thread->Open();
       
  2558     threads->Signal();
       
  2559     NKern::ThreadLeaveCS();
       
  2560 
       
  2561 	if (!thread) return KErrNotFound;
       
  2562 	TLinAddr allocatorAddr = DoGetAllocatorAddress(thread, EFalse);
       
  2563 	if (!allocatorAddr) 
       
  2564 		{
       
  2565 		thread->Close(NULL);
       
  2566 		return KErrNotFound;
       
  2567 		}
       
  2568 
       
  2569 	TLinAddr flagsAddr = allocatorAddr + _FOFF(RHackAllocator, iFlags);
       
  2570 	TUint flags = 0;
       
  2571 	TInt err = Kern::ThreadRawRead(thread, (void*)flagsAddr, &flags, sizeof(TUint));
       
  2572 	if (!err)
       
  2573 		{
       
  2574 		if (aEnable) flags |= RAllocator::ETraceAllocs;
       
  2575 		else flags &= ~(RAllocator::ETraceAllocs);
       
  2576 		err = Kern::ThreadRawWrite(thread, (void*)flagsAddr, &flags, sizeof(TUint));
       
  2577 		}
       
  2578 	NKern::ThreadEnterCS();
       
  2579 	thread->Close(NULL);
       
  2580     NKern::ThreadLeaveCS();
       
  2581 	return err;
       
  2582 #endif
       
  2583 	}
       
  2584 
       
  2585 #if defined(FSHELL_RAMDEFRAG_SUPPORT) && !defined(__WINS__) // emulator platform.h doesn't have the ram defrag APIs
       
  2586 
       
  2587 TInt DMemoryAccess::DefragRam(TInt aPriority)
       
  2588 	{
       
  2589 	TInt priority = aPriority;
       
  2590 	if (priority == -1) priority = TRamDefragRequest::KInheritPriority; // I know KInheritPriority is actually -1 anyway but better to be correctly typed
       
  2591 	TRamDefragRequest request;
       
  2592 	return request.DefragRam(priority);
       
  2593 	}
       
  2594 
       
  2595 TInt DMemoryAccess::EmptyRamZone(TInt aPriority, TUint aZone)
       
  2596 	{
       
  2597 	TInt priority = aPriority;
       
  2598 	if (priority == -1) priority = TRamDefragRequest::KInheritPriority; // I know KInheritPriority is actually -1 anyway but better to be correctly typed
       
  2599 	TRamDefragRequest request;
       
  2600 	return request.EmptyRamZone(aZone, priority);
       
  2601 	}
       
  2602 
       
  2603 TInt DMemoryAccess::GetRamZoneInfo(TUint aZone, TAny* aInfoPkg)
       
  2604 	{
       
  2605 	SRamZonePageCount info;
       
  2606 	TInt err = Epoc::GetRamZonePageCount(aZone, info);
       
  2607 	if (err) return err;
       
  2608 
       
  2609 	TRamZoneInfo clientInf;
       
  2610 	clientInf.iFreePages = info.iFreePages;
       
  2611 	clientInf.iUnknownPages = info.iUnknownPages;
       
  2612 	clientInf.iFixedPages = info.iFixedPages;
       
  2613 	clientInf.iMovablePages = info.iMovablePages;
       
  2614 	clientInf.iDiscardablePages = info.iDiscardablePages;
       
  2615 	TPckg<TRamZoneInfo> clientPkg(clientInf);
       
  2616 	err = Kern::ThreadDesWrite(iClient, aInfoPkg, clientPkg, 0, KTruncateToMaxLength, NULL);
       
  2617 	return err;
       
  2618 	}
       
  2619 
       
  2620 #else
       
  2621 
       
  2622 TInt DMemoryAccess::DefragRam(TInt /*aPriority*/)
       
  2623 	{
       
  2624 	return KErrNotSupported;
       
  2625 	}
       
  2626 
       
  2627 TInt DMemoryAccess::EmptyRamZone(TInt /*aPriority*/, TUint /*aZone*/)
       
  2628 	{
       
  2629 	return KErrNotSupported;
       
  2630 	}
       
  2631 
       
  2632 TInt DMemoryAccess::GetRamZoneInfo(TUint /*aZone*/, TAny* /*aInfoPkg*/)
       
  2633 	{
       
  2634 	return KErrNotSupported;
       
  2635 	}
       
  2636 
       
  2637 #endif
       
  2638 
       
  2639 TCapabilitySet StoT(const SCapabilitySet& aCaps)
       
  2640 	{
       
  2641 	TCapabilitySet result;
       
  2642 	result.SetEmpty();
       
  2643 	memcpy(&result, &aCaps, sizeof(SCapabilitySet));
       
  2644 	return result;
       
  2645 	}
       
  2646 	
       
  2647 SCapabilitySet TtoS(const TCapabilitySet& aCaps)
       
  2648 	{
       
  2649 	SCapabilitySet result;
       
  2650 	memcpy(&result, &aCaps, sizeof(SCapabilitySet));
       
  2651 	return result;
       
  2652 	}
       
  2653 
       
  2654 // Copied from DProcess::ConvertPriority
       
  2655 TInt DProcessConvertPriority(TProcessPriority aPriority)
       
  2656 	{
       
  2657 	TInt p=-1;
       
  2658 	switch(aPriority)
       
  2659 		{
       
  2660 		case EPriorityLow: p=EProcPriorityLow; break;
       
  2661 		case EPriorityBackground: p=EProcPriorityBackground; break;
       
  2662 		case EPriorityForeground: p=EProcPriorityForeground; break;
       
  2663 		case EPriorityHigh: p=EProcPriorityHigh; break;
       
  2664 		case EPriorityWindowServer: p=EProcPrioritySystemServer1; break;
       
  2665 		case EPriorityFileServer: p=EProcPrioritySystemServer2; break;
       
  2666 		case EPriorityRealTimeServer: p=EProcPriorityRealTimeServer; break;
       
  2667 		case EPrioritySupervisor: p=EProcPrioritySystemServer3; break;
       
  2668 		}
       
  2669 	return p;
       
  2670 	}
       
  2671 
       
  2672 TInt DMemoryAccess::SetProcessProperties(TInt aProcessHandle, TAny* aProperties)
       
  2673 	{
       
  2674 	TProcessProperties properties;
       
  2675 	TPckg<TProcessProperties> pkg(properties);
       
  2676 	TInt err = Kern::ThreadDesRead(iClient, aProperties, pkg, 0);
       
  2677 	if (err) return err;
       
  2678 
       
  2679 	NKern::LockSystem();
       
  2680 	DProcess* proc = (DProcess*)Kern::ObjectFromHandle(iClient, aProcessHandle, EProcess);
       
  2681 	if (!proc) return KErrBadHandle;
       
  2682 	proc->Open();
       
  2683 	NKern::UnlockSystem();
       
  2684 
       
  2685 	if (properties.iSid != 0xFFFFFFFFu) proc->iS.iSecureId = properties.iSid;
       
  2686 	if (properties.iVid != 0xFFFFFFFFu) proc->iS.iVendorId = properties.iVid;
       
  2687 
       
  2688 	// Why is there no way of converting from an SCapabilitySet to a TCapabilitySet?
       
  2689 	TCapabilitySet caps = StoT(proc->iS.iCaps);
       
  2690 	caps.Union(properties.iCapsToAdd);
       
  2691 	caps.Remove(properties.iCapsToRemove);
       
  2692 	SCapabilitySet newSet = TtoS(caps);
       
  2693 	memcpy(&proc->iS.iCaps, &newSet, sizeof(SCapabilitySet));
       
  2694 
       
  2695 	if (properties.iProcessPriority)
       
  2696 		{
       
  2697 		TInt priority = DProcessConvertPriority((TProcessPriority)properties.iProcessPriority);
       
  2698 		if (priority < 0) err = KErrArgument;
       
  2699 		else proc->iPriority = priority; // Note this won't recalculate thread priorities
       
  2700 		}
       
  2701 
       
  2702 	proc->Close(NULL);
       
  2703 	return err;
       
  2704 	}
       
  2705 
       
  2706 #ifndef FSHELL_COPYTOSHADOWMEMORY_SUPPORT
       
  2707 // Not sure exactly when it was introduced. Somewhere between 9.1 and 9.3 or anywhere that used ARM7
       
  2708 // If CopyToShadowMemory is available it MUST be used, on ARM7 or later, otherwise you'll get an exception
       
  2709 #define NO_COPYTOSHADOWMEMORY
       
  2710 #endif
       
  2711 
       
  2712 TInt DMemoryAccess::WriteShadowMemory(TLinAddr aAddress, TAny* aNewContents)
       
  2713 	{
       
  2714 #ifdef __WINS__
       
  2715 	(void)aAddress;
       
  2716 	(void)aNewContents;
       
  2717 	return KErrNotSupported; // Shadowing not supported on emulator
       
  2718 #else
       
  2719 	TBuf8<32> newMem;
       
  2720 	TInt len = Kern::ThreadGetDesLength(iClient, aNewContents);
       
  2721 	if (len < 0) return len;
       
  2722 	if (len > 32) return KErrTooBig; // API for CopyToShadowMemory says max 32 bytes, who are we to argue with hard-coded magic numbers (that aren't actually enforced afaics)
       
  2723 
       
  2724 	TInt err = Kern::ThreadDesRead(iClient, aNewContents, newMem, 0);
       
  2725 	if (err) return err;
       
  2726 
       
  2727 #ifdef NO_COPYTOSHADOWMEMORY
       
  2728 	// Can't check if the page is already shadowed, just error and go straight to trying to call AllocShadowPage
       
  2729 	err = KErrArgument;
       
  2730 #else
       
  2731 	err = Epoc::CopyToShadowMemory(aAddress, (TLinAddr)newMem.Ptr(), newMem.Size());
       
  2732 #endif
       
  2733 	if (err == KErrArgument || err == KErrNotFound)
       
  2734 		{
       
  2735 		// The documentation *says* it will always be KErrArgument but Flexible memory model actually returns KErrNotFound
       
  2736 		// Page (or pages) hasn't been shadowed yet
       
  2737 		TLinAddr pageForStart = aAddress & ~(Kern::RoundToPageSize(1)-1);
       
  2738 		TLinAddr pageForEnd = (aAddress + newMem.Size()) & ~(Kern::RoundToPageSize(1)-1);
       
  2739 		err = Epoc::AllocShadowPage(pageForStart);
       
  2740 		if ((err == KErrNone || err == KErrAlreadyExists) && pageForEnd != pageForStart)
       
  2741 			{
       
  2742 			// Maybe the area spans a page boundary and that was why the copy failed, so try allocing the end bit too
       
  2743 			err = Epoc::AllocShadowPage(pageForEnd);
       
  2744 			}
       
  2745 
       
  2746 		if (err == KErrNone || err == KErrAlreadyExists)
       
  2747 			{
       
  2748 			// Retry the copy
       
  2749 #ifdef NO_COPYTOSHADOWMEMORY
       
  2750 			memcpy((TAny*)aAddress, newMem.Ptr(), newMem.Size());
       
  2751 			err = KErrNone;
       
  2752 #else
       
  2753 			err = Epoc::CopyToShadowMemory(aAddress, (TLinAddr)newMem.Ptr(), newMem.Size());
       
  2754 #endif
       
  2755 			}
       
  2756 		}
       
  2757 	return err;
       
  2758 #endif // __WINS__
       
  2759 	}
       
  2760 
       
  2761 TInt DMemoryAccess::FreeShadowMemory(TLinAddr aAddress, TInt aLength)
       
  2762 	{
       
  2763 #ifdef __WINS__
       
  2764 	(void)aAddress;
       
  2765 	(void)aLength;
       
  2766 	return KErrNotSupported; // Shadowing not supported on emulator
       
  2767 #else
       
  2768 	const TInt pageSize = Kern::RoundToPageSize(1);
       
  2769 	TLinAddr end = aAddress + aLength;
       
  2770 	TLinAddr page = aAddress & ~(pageSize -1);
       
  2771 	while (page < end)
       
  2772 		{
       
  2773 		Epoc::FreeShadowPage(page);
       
  2774 		page += pageSize;
       
  2775 		}
       
  2776 	return KErrNone; // There aren't any errors that it's important or sensible to pass to the client
       
  2777 #endif // __WINS__
       
  2778 	}
       
  2779 
       
  2780 TInt DMemoryAccessFactory::GetEventHandler(DDebuggerEventHandler*& aResult)
       
  2781 	{
       
  2782 	if (!DKernelEventHandler::DebugSupportEnabled()) return KErrNotSupported;
       
  2783 	
       
  2784 	Lock();
       
  2785 	if (iSharedEventHandler)
       
  2786 		{
       
  2787 		aResult = iSharedEventHandler;
       
  2788 		Unlock();
       
  2789 		return KErrNone;
       
  2790 		}
       
  2791 	Unlock(); // Can't hold fast mutex around allocs
       
  2792 
       
  2793 	TDfcQue* q = NULL;
       
  2794 	TInt err = GetDfcQue(q);
       
  2795 	if (err) return err;
       
  2796 
       
  2797 	DDebuggerEventHandler* handler = DDebuggerEventHandler::New(q);
       
  2798 	if (!handler) return KErrNoMemory;
       
  2799 	// We must NOT call anything that could fail from this point on - otherwise it is impossible to safely close the DDebuggerEventHandler (looks like a bug in constructing a DKernelEventHandler from DLogicalDevice::Install())
       
  2800 	if (err != KErrNone)
       
  2801 		{
       
  2802 		handler->Close();
       
  2803 		return err;
       
  2804 		}
       
  2805 	Lock();
       
  2806 	if (iSharedEventHandler)
       
  2807 		{
       
  2808 		// Someone beat us to it
       
  2809 		Unlock();
       
  2810 		handler->Close();
       
  2811 		}
       
  2812 	else
       
  2813 		{
       
  2814 		iSharedEventHandler = handler;
       
  2815 		Unlock();
       
  2816 		}
       
  2817 	aResult = iSharedEventHandler;
       
  2818 
       
  2819 	return KErrNone;
       
  2820 	}
       
  2821 
       
  2822 void DMemoryAccessFactory::Lock()
       
  2823 	{
       
  2824 	NKern::FMWait(&iLock);
       
  2825 	}
       
  2826 
       
  2827 void DMemoryAccessFactory::Unlock()
       
  2828 	{
       
  2829 	NKern::FMSignal(&iLock);
       
  2830 	}
       
  2831 
       
  2832 TInt DMemoryAccess::DebuggerFn(TInt aFn, TAny* a1, TAny* a2)
       
  2833 	{
       
  2834 	DDebuggerEventHandler* handler = NULL;
       
  2835 	TInt err = ((DMemoryAccessFactory*)iDevice)->GetEventHandler(handler);
       
  2836 	if (err) return err;
       
  2837 	
       
  2838 	switch (aFn)
       
  2839 		{
       
  2840 		case RMemoryAccess::EControlGetZombieDebugMode:
       
  2841 			return handler->GetZombieMode();
       
  2842 		case RMemoryAccess::EControlSetZombieDebugMode:
       
  2843 			{
       
  2844 			TInt newmode = (TInt)a1;
       
  2845 			TInt oldmode = handler->GetZombieMode();
       
  2846 			if (newmode && !oldmode) iDevice->Open(); // Stops us getting unloaded
       
  2847 			else if (!newmode && oldmode) iDevice->Close(NULL);
       
  2848 			err = handler->SetZombieMode(newmode);
       
  2849 			break;
       
  2850 			}
       
  2851 		case RMemoryAccess::EControlGetZombies:
       
  2852 			{
       
  2853 			HBuf* zoms = handler->GetZombieThreadIds();
       
  2854 			if (zoms)
       
  2855 				{
       
  2856 				err = Kern::ThreadDesWrite(iClient, a1, *zoms, 0, KTruncateToMaxLength, NULL);
       
  2857 				if (err == KErrNone || err == KErrOverflow) err = zoms->Length();
       
  2858 				delete zoms;
       
  2859 				}
       
  2860 			else
       
  2861 				{
       
  2862 				err = KErrNoMemory;
       
  2863 				}
       
  2864 			break;
       
  2865 			}
       
  2866 		case RMemoryAccess::EControlReleaseZombie:
       
  2867 			{
       
  2868 			DThread* thread = ThreadFromHandle((TInt)a1);
       
  2869 			if (!thread) return KErrBadHandle;
       
  2870 			err = handler->ReleaseZombie(thread);
       
  2871 			thread->Close(NULL);
       
  2872 			break;
       
  2873 			}
       
  2874 		case RMemoryAccess::EControlSuspendThread:
       
  2875 			{
       
  2876 			DThread* thread = ThreadFromHandle((TInt)a1);
       
  2877 			if (!thread) return KErrBadHandle;
       
  2878 			err = handler->SuspendThread(thread);
       
  2879 			thread->Close(NULL);
       
  2880 			break;
       
  2881 			}
       
  2882 		case RMemoryAccess::EControlNotifyBreakpoint:
       
  2883 			{
       
  2884 			if (iClientBreakpointNotifyStatus) return KErrAlreadyExists;
       
  2885 			iClientBreakpointNotifyPkg = a1;
       
  2886 			iClientBreakpointNotifyStatus = (TRequestStatus*)a2;
       
  2887 			err = handler->RegisterForBreakpointNotification(this);
       
  2888 			if (err)
       
  2889 				{
       
  2890 				iClientBreakpointNotifyPkg = NULL;
       
  2891 				iClientBreakpointNotifyStatus = NULL;
       
  2892 				}
       
  2893 			break;
       
  2894 			}
       
  2895 		case RMemoryAccess::EControlCancelNotifyBreakpoint:
       
  2896 			{
       
  2897 			iClientBreakpointNotifyPkg = NULL;
       
  2898 			if (iClientBreakpointNotifyStatus)
       
  2899 				{
       
  2900 				handler->UnregisterForBreakpointNotification(this);
       
  2901 				Kern::RequestComplete(iClient, iClientBreakpointNotifyStatus, KErrCancel);
       
  2902 				}
       
  2903 			break;
       
  2904 			}
       
  2905 		case RMemoryAccess::EControlSetBreakpoint:
       
  2906 			{
       
  2907 			DThread* thread = ThreadFromHandle((TInt)a1);
       
  2908 			if (!thread) return KErrBadHandle;
       
  2909 			TUint32 args[2];
       
  2910 			RMemoryAccess::TPredicate cond;
       
  2911 			err = Kern::ThreadRawRead(iClient, a2, args, sizeof(args));
       
  2912 			if (!err && args[1]) err = Kern::ThreadRawRead(iClient, (TAny*)args[1], &cond, sizeof(RMemoryAccess::TPredicate));
       
  2913 			if (!err) err = handler->SetBreakpoint(thread, args[0], cond);
       
  2914 			thread->Close(NULL);
       
  2915 			break;
       
  2916 			}
       
  2917 		case RMemoryAccess::EControlSetSymbolicBreakpoint:
       
  2918 			{
       
  2919 			TUint32 args[3];
       
  2920 			err = Kern::ThreadRawRead(iClient, a1, args, sizeof(args));
       
  2921 			if (err) return err;
       
  2922 			DThread* thread = ThreadFromHandle(args[0]);
       
  2923 			if (!thread) return KErrBadHandle;
       
  2924 	
       
  2925 			RMemoryAccess::TPredicate cond;
       
  2926 			if (args[2] != 0) err = Kern::ThreadRawRead(iClient, (TAny*)args[2], &cond, sizeof(RMemoryAccess::TPredicate));
       
  2927 			if (err)
       
  2928 				{
       
  2929 				thread->Close(NULL);
       
  2930 				return err;
       
  2931 				}
       
  2932 			
       
  2933 			TInt nameLen = Kern::ThreadGetDesLength(iClient, a2);
       
  2934 			if (nameLen < 0) err = nameLen;
       
  2935 			HBuf* codeseg = NULL;
       
  2936 			if (!err)
       
  2937 				{
       
  2938 				codeseg = HBuf::New(nameLen);
       
  2939 				if (!codeseg) err = KErrNoMemory;
       
  2940 				}
       
  2941 			if (!err) err = Kern::ThreadDesRead(iClient, a2, *codeseg, 0);
       
  2942 			if (!err) err = handler->SetSymbolicBreakpoint(thread, codeseg, args[1], cond);
       
  2943 			
       
  2944 			if (err < 0) delete codeseg;
       
  2945 			thread->Close(NULL);
       
  2946 			break;
       
  2947 			}
       
  2948 		case RMemoryAccess::EControlSetBreakpointEnabled:
       
  2949 			return handler->SetBreakpointEnabled((TInt)a1, (TBool)a2);
       
  2950 		case RMemoryAccess::EControlClearBreakpoint:
       
  2951 			return handler->ClearBreakpoint((TInt)a1);
       
  2952 		case RMemoryAccess::EControlContinueFromBreakpoint:
       
  2953 			{
       
  2954 			DThread* thread = ThreadFromHandle((TInt)a1);
       
  2955 			if (!thread) return KErrBadHandle;
       
  2956 			err = handler->ContinueFromBreakpoint(thread, 0);
       
  2957 			thread->Close(NULL);
       
  2958 			break;
       
  2959 			}
       
  2960 		case RMemoryAccess::EControlGetBreakpoints:
       
  2961 			{
       
  2962 			HBuf* breakpoints = handler->GetBreakpoints();
       
  2963 			if (breakpoints)
       
  2964 				{
       
  2965 				err = Kern::ThreadDesWrite(iClient, a1, *breakpoints, 0, KTruncateToMaxLength, NULL);
       
  2966 				if (err == KErrNone || err == KErrOverflow) err = breakpoints->Length();
       
  2967 				delete breakpoints;
       
  2968 				}
       
  2969 			else
       
  2970 				{
       
  2971 				err = KErrNoMemory;
       
  2972 				}
       
  2973 			break;
       
  2974 			}
       
  2975 		case RMemoryAccess::EControlRegisterPersistantBreakpoint:
       
  2976 			return handler->RegisterPersistantBreakpoint(iClient, (TLinAddr)a1);
       
  2977 		default:
       
  2978 			err = KErrNotSupported;
       
  2979 		}
       
  2980 	return err;
       
  2981 	}
       
  2982 
       
  2983 DThread* DMemoryAccess::ThreadFromHandle(TInt aHandle)
       
  2984 	{
       
  2985 	if (aHandle == KCurrentThreadHandle)
       
  2986 		{
       
  2987 		iClient->Open();
       
  2988 		return iClient;
       
  2989 		}
       
  2990 	else
       
  2991 		{
       
  2992 		NKern::LockSystem();
       
  2993 		DThread* thread = (DThread*)Kern::ObjectFromHandle(iClient, aHandle, EThread);
       
  2994 		if (thread) thread->Open();
       
  2995 		NKern::UnlockSystem();
       
  2996 		return thread;
       
  2997 		}
       
  2998 	}
       
  2999 
       
  3000 DMemoryAccessFactory::~DMemoryAccessFactory()
       
  3001 	{
       
  3002 	if (iSharedEventHandler)
       
  3003 		{
       
  3004 		iSharedEventHandler->SetZombieMode(0); // This is needed because its iAccessCount is incremented while threads are blocked in its Event function, therefore Close will otherwise never get to the destructor (Which is what otherwise calls CompleteZombies)
       
  3005 		iSharedEventHandler->Close();
       
  3006 		iSharedEventHandler = NULL;
       
  3007 		}
       
  3008 	if (iDfcQueWrapper)
       
  3009 		{
       
  3010 		iDfcQueWrapper->Destroy();
       
  3011 		}
       
  3012 	}
       
  3013 
       
  3014 TInt DMemoryAccess::GetRegisters(TAny* a1, TAny* /*a2*/)
       
  3015 	{
       
  3016 	TUint32 args[4];
       
  3017 	TInt err = Kern::ThreadRawRead(iClient, a1, &args[0], sizeof(args));
       
  3018 	if (err) return err;
       
  3019 	TInt threadHandle = args[0];
       
  3020 	TBool userMode = args[1];
       
  3021 	TAny* regBuf = (TAny*)args[2];
       
  3022 	TAny* validPtr = (TAny*)args[3];
       
  3023 
       
  3024 	DThread* thread = ThreadFromHandle(threadHandle);
       
  3025 	if (!thread) return KErrBadHandle;
       
  3026 	TUint32 regs[32];
       
  3027 	TUint32 valid = 0;
       
  3028 
       
  3029 #if !defined(__WINS__) && !defined(FSHELL_9_1_SUPPORT) // win32 ekern doesn't even export this API let alone implement it
       
  3030 	if (!thread->iSupervisorStack)
       
  3031 		{
       
  3032 		// Thread has not only died but has got as far as deallocating its supervisor stack - in which case we can't
       
  3033 		// get the registers, and moreover NKern::ThreadGetXXXContext will crash if we try
       
  3034 		thread->Close(NULL);
       
  3035 		return KErrDied;
       
  3036 		}
       
  3037 	if (userMode)
       
  3038 		{
       
  3039 		NKern::ThreadGetUserContext(&thread->iNThread, &regs[0], valid);
       
  3040 		}
       
  3041 	else
       
  3042 		{
       
  3043 		NKern::ThreadGetSystemContext(&thread->iNThread, &regs[0], valid);
       
  3044 		}
       
  3045 #else
       
  3046 	(void)userMode;
       
  3047 #endif
       
  3048 
       
  3049 	thread->Close(NULL);
       
  3050 	TPckg<TUint32[32]> regsPkg(regs);
       
  3051 	err = Kern::ThreadDesWrite(iClient, regBuf, regsPkg, 0);
       
  3052 	if (err) return err;
       
  3053 	err = Kern::ThreadRawWrite(iClient, validPtr, &valid, sizeof(TUint32));
       
  3054 	return err;
       
  3055 	}
       
  3056 
       
  3057 void DMemoryAccess::BreakpointHit(TDes& aPkg)
       
  3058 	{
       
  3059 	TRequestStatus* stat = (TRequestStatus*)NKern::SafeSwap(NULL, (TAny*&)iClientBreakpointNotifyStatus);
       
  3060 	if (stat)
       
  3061 		{
       
  3062 		// Can't see how we could get here with it being null, but still
       
  3063 		TInt err = Kern::ThreadDesWrite(iClient, iClientBreakpointNotifyPkg, aPkg, 0);
       
  3064 		Kern::RequestComplete(iClient, stat, err);
       
  3065 		iClientBreakpointNotifyPkg = NULL;
       
  3066 		}
       
  3067 	}