--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/perfsrv/analyzetool/kerneleventhandler/src/analyzetoolchannel.cpp Fri Sep 17 08:38:31 2010 +0300
@@ -0,0 +1,1019 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Definitions for the class DAnalyzeToolChannel.
+*
+*/
+
+
+// INCLUDE FILES
+#include "analyzetoolchannel.h"
+#include "analyzetooldevice.h"
+#include "analyzetooleventhandler.h"
+
+#include <kernel/kern_priv.h>
+#ifdef __WINSCW__
+#include <emulator.h>
+#endif // __WINSCW__
+
+#include "atlog.h"
+
+// ================= MEMBER FUNCTIONS =========================================
+
+// -----------------------------------------------------------------------------
+// DAnalyzeToolChannel::DoCreate()
+// Creates the logical channel.
+// -----------------------------------------------------------------------------
+//
+TInt DAnalyzeToolChannel::DoCreate( TInt /*aUnit*/,
+ const TDesC8* /*aInfo*/, const TVersion &aVer )
+ {
+ LOGSTR1( "ATDD DAnalyzeToolChannel::DoCreate()" );
+
+ // Check client version.
+ if ( !Kern::QueryVersionSupported( KAnalyzeToolLddVersion(), aVer ) )
+ {
+ return KErrNotSupported;
+ }
+
+ TInt error = Kern::DynamicDfcQCreate( iOwnDfcQ,
+ KAnalyzeToolThreadPriority,
+ KAnalyzeToolThreadName );
+
+ if ( KErrNone != error )
+ {
+ return error;
+ }
+
+ SetDfcQ( iOwnDfcQ );
+
+ iMsgQ.Receive();
+
+ // Create the event handler
+ iEventHandler = new DAnalyzeToolEventHandler( iOwnDfcQ );
+
+ // Check that everything is OK
+ if ( !iEventHandler )
+ {
+ return KErrNoMemory;
+ }
+
+ // 2nd stage constructor for event handler
+ return iEventHandler->Create( iDevice, Kern::CurrentProcess().iId );
+ }
+
+// -----------------------------------------------------------------------------
+// DAnalyzeToolChannel::DAnalyzeToolChannel()
+// Constructor.
+// -----------------------------------------------------------------------------
+//
+DAnalyzeToolChannel::DAnalyzeToolChannel()
+ {
+ LOGSTR1( "ATDD DAnalyzeToolChannel::DAnalyzeToolChannel()" );
+ }
+
+// -----------------------------------------------------------------------------
+// DAnalyzeToolChannel::~DAnalyzeToolChannel()
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+DAnalyzeToolChannel::~DAnalyzeToolChannel()
+ {
+ LOGSTR1( "ATDD DAnalyzeToolChannel::~DAnalyzeToolChannel()" );
+
+ if ( iEventHandler )
+ {
+ // Cancel all processing that we may be doing
+ DoCancel();
+
+ // Client code should use Close() instead the operator delete
+ // to destroy the event handler.
+ TInt error( iEventHandler->Close() );
+ if ( KErrNone != error )
+ {
+ LOGSTR2( "ATDD iEventHandler->Close(%d)", error );
+ }
+ }
+ #ifdef __WINSCW__
+ iCodeSeg.Close();
+ #endif // __WINSCW__
+
+ // Destroy the queqe
+ if ( iOwnDfcQ )
+ {
+ iOwnDfcQ->Destroy();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// DAnalyzeToolChannel::DoControl()
+// Handles a client request.
+// -----------------------------------------------------------------------------
+//
+TInt DAnalyzeToolChannel::DoControl( TInt aFunction,
+ TAny* a1,
+ TAny* /*a2*/,
+ TThreadMessage& aMessage )
+ {
+ LOGSTR1( "ATDD DAnalyzeToolChannel::Request()" );
+
+ TInt ret( KErrNone );
+
+ // Check the requested function
+ switch (aFunction)
+ {
+ case RAnalyzeTool::EGetProcessInfo:
+ ret = GetProcessInfo( a1, aMessage );
+ break;
+
+ case RAnalyzeTool::EGetCodesegInfo:
+ ret = GetCodesegInfo( a1, aMessage );
+ break;
+
+ case RAnalyzeTool::EGetLibraryInfo:
+ ret = GetLibraryInfo( a1, aMessage );
+ break;
+
+ case RAnalyzeTool::ECancelLibraryEvent:
+ iEventHandler->CancelInformLibraryEvent();
+ break;
+
+ case RAnalyzeTool::ECurrentClientCount:
+ ret = ClientCount( a1, aMessage );
+ break;
+
+ case RAnalyzeTool::EMainThreadAlloctor:
+ ret = MainThreadAllocator( a1, aMessage );
+ break;
+
+ case RAnalyzeTool::EThreadStack:
+ ret = ThreadStack( a1, aMessage );
+ break;
+
+ case RAnalyzeTool::EGetProcessHandle:
+ ret = GetProcessHandleInfo( a1, aMessage );
+ break;
+
+ case RAnalyzeTool::EGetCurrentHandles:
+ ret = GetCurrentHandleCount( a1, aMessage );
+ break;
+ case RAnalyzeTool::EGetMemoryModel:
+ ret = GetMemoryModel( a1, aMessage );
+ break;
+
+ // Unsupported function. Panic
+ default:
+ Kern::PanicCurrentThread( KClientPanic, EPanicUnsupportedRequest );
+ break;
+ }
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// DAnalyzeToolChannel::DoRequest()
+// Handles a client asynchronous request.
+// -----------------------------------------------------------------------------
+//
+TInt DAnalyzeToolChannel::DoRequest( TInt aFunction,
+ TRequestStatus* aStatus,
+ TAny* a1,
+ TAny* /*a2*/,
+ TThreadMessage& aMessage )
+ {
+ LOGSTR1( "ATDD DAnalyzeToolChannel::DoRequest()" );
+
+ // Check the requested function
+ switch (aFunction)
+ {
+ case RAnalyzeTool::ELibraryEvent:
+ iEventHandler->InformLibraryEvent( aStatus, a1, aMessage );
+ break;
+
+ // Unsupported function. Panic
+ default:
+ aMessage.PanicClient( KClientPanic, EPanicUnsupportedRequest );
+ break;
+ }
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// DAnalyzeToolChannel::DoCancel()
+// Cancels outstanding asynchronous request.
+// -----------------------------------------------------------------------------
+//
+void DAnalyzeToolChannel::DoCancel()
+ {
+ LOGSTR1( "ATDD DAnalyzeToolChannel::DoCancel()" );
+
+ iEventHandler->CancelInformLibraryEvent();
+ }
+
+// -----------------------------------------------------------------------------
+// DAnalyzeToolChannel::HandleMsg()
+// Processes a message for this logical channel.
+// -----------------------------------------------------------------------------
+//
+void DAnalyzeToolChannel::HandleMsg(TMessageBase* aMsg)
+ {
+ LOGSTR1( "ATDD DAnalyzeToolChannel::HandleMsg()" );
+
+ TThreadMessage& message = *(TThreadMessage*)aMsg;
+
+ // Get message type
+ TInt id = message.iValue;
+
+ // Decode the message type and dispatch it to the relevent handler function...
+ if ( id == (TInt) ECloseMsg )
+ {
+ // Channel Close
+ DoCancel();
+ message.Complete( KErrNone, EFalse );
+ }
+ else if ( id == KMaxTInt )
+ {
+ // DoCancel
+ DoCancel();
+ message.Complete( KErrNone, ETrue );
+ }
+ else if ( id < 0 )
+ {
+ // DoRequest
+ TRequestStatus* status = (TRequestStatus*) message.Ptr0();
+ TInt error = DoRequest( ~id, status, message.Ptr1(), message.Ptr2(), message );
+ if ( KErrNone != error )
+ {
+ Kern::RequestComplete( message.Client(), status, error);
+ }
+ message.Complete(KErrNone, ETrue );
+ }
+ else
+ {
+ // DoControl
+ TInt ret = DoControl( id, message.Ptr0(), message.Ptr1(), message );
+ message.Complete( ret, ETrue );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// DAnalyzeToolChannel::GetProcessInfo()
+// Acquires current process information
+// -----------------------------------------------------------------------------
+//
+TInt DAnalyzeToolChannel::GetProcessInfo( TAny* aProcessInfo,
+ TThreadMessage& aMessage )
+ {
+ LOGSTR1( "ATDD DAnalyzeToolChannel::GetProcessInfo()" );
+
+ // Variable for reading parameters from user side
+ TProcessIdentityParamsBuf params;
+
+ // Reads a descriptor from a thread's process.
+ TInt error = Kern::ThreadDesRead( aMessage.Client(), aProcessInfo, params, 0 );
+
+ if ( KErrNone != error )
+ {
+ LOGSTR2( "ATDD ThreadDesRead error %d", error );
+ return error;
+ }
+
+ // Gets the current process
+ Kern::Containers()[ EProcess ]->Wait();
+ DProcess& process = *Kern::ProcessFromId( params().iProcessId );
+ Kern::Containers()[ EProcess ]->Signal();
+
+ if ( NULL == &process )
+ {
+ return KErrNotFound;
+ }
+
+ // Temporary variable for collecting information from the process
+ TProcessIdentityParamsBuf info;
+
+ // Collect needed information from the process
+ process.AppendName( info().iProcessName );//lint !e64 !e1514
+
+ // Gets the current thread
+ Kern::Containers()[ EThread ]->Wait();
+ DThread& thread = *Kern::ThreadFromId( params().iThreadId );
+ Kern::Containers()[ EThread ]->Signal();
+
+ if ( NULL == &thread )
+ {
+ return KErrNotFound;
+ }
+
+ // Stack address of the main thread
+ info().iStackAddress = thread.iUserStackRunAddress;
+ info().iStackSize = thread.iUserStackSize;
+
+ // Enters thread critical section and acquires code segment mutex.
+ Kern::AccessCode();
+
+ // Collect needed information from the process
+ info().iDynamicCount = process.iDynamicCode.Count();
+
+ // Temporary queue for acquiring the count of codesegments
+ SDblQue queue;
+
+ // Acquire the count of codesegments
+ TInt codesegCount = process.TraverseCodeSegs( &queue,
+ NULL,
+ DCodeSeg::EMarkDebug,
+ DProcess::ETraverseFlagAdd );
+
+ #ifndef __WINSCW__
+ info().iCodesegCount = codesegCount;
+ #else
+ // Reset codesegment array
+ iCodeSeg.Reset();
+
+ if ( codesegCount > 0 )
+ {
+ SDblQueLink* link = queue.iA.iNext;
+ TCodesegInfo codeinfo;
+ // Iterate through codesegments
+ for ( TInt i = 0; i < codesegCount; ++i, link = link->iNext )
+ {
+ DWin32CodeSeg* codeseg =
+ (DWin32CodeSeg*)_LOFF( link, DCodeSeg, iTempLink );
+
+ // Aqcuire codeseg information
+ codeinfo.iFileEntryPoint = codeseg->iFileEntryPoint;
+ codeinfo.iSize = codeseg->iSize;
+ codeinfo.iFullName.Copy( codeseg->iRootName );
+ codeinfo.iRunAddress = codeseg->iRunAddress;
+ iCodeSeg.Append( codeinfo );
+ }
+ }
+
+ // Add dependency codesegments
+ DWin32CodeSeg* pcodeSeg = (DWin32CodeSeg*)process.iCodeSeg;
+
+ // Get dependency codesegments
+ GetModuleDependencies( pcodeSeg->iModuleHandle );
+
+ // Set codesegment count
+ info().iCodesegCount = iCodeSeg.Count();
+ #endif
+
+ // Removes all code segments from a queue and clear specified mark(s)
+ DCodeSeg::EmptyQueue( queue, DCodeSeg::EMarkDebug );
+
+ // Exits thread critical section and releases code segment mutex.
+ Kern::EndAccessCode();
+
+ // Writes a descriptor to a thread's process.
+ error = Kern::ThreadDesWrite( aMessage.Client(), aProcessInfo, info, 0 );
+
+ if ( KErrNone != error )
+ {
+ LOGSTR2( "ATDD ThreadDesWrite error %d", error );
+ return error;
+ }
+
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// DAnalyzeToolChannel::GetCodesegInfo()
+// Acquires codeseg information.
+// -----------------------------------------------------------------------------
+//
+TInt DAnalyzeToolChannel::GetCodesegInfo( TAny* aCodesegInfo,
+ TThreadMessage& aMessage )
+ {
+ LOGSTR1( "ATDD DAnalyzeToolChannel::GetCodesegInfo()" );
+
+ // Temporary variable for collecting information from the codeseg
+ TCodesegInfoBuf params;
+
+ TInt error( KErrArgument );
+
+ // Reads a descriptor from a thread's process.
+ error = Kern::ThreadDesRead( aMessage.Client(), aCodesegInfo, params, 0 );
+
+ if ( KErrNone != error )
+ {
+ LOGSTR2( "ATDD ThreadDesRead error %d", error );
+ return error;
+ }
+
+ if ( params().iIndex < 0 )
+ {
+ return KErrArgument;
+ }
+
+ // Gets the current process
+ Kern::Containers()[ EProcess ]->Wait();
+ DProcess& process = *Kern::ProcessFromId( params().iProcessId );
+ Kern::Containers()[ EProcess ]->Signal();
+
+ if ( NULL == &process )
+ {
+ return KErrNotFound;
+ }
+
+ // Temporary variable for collecting information
+ TCodesegInfoBuf output;
+
+ // Enters thread critical section and acquires code segment mutex.
+ Kern::AccessCode();
+
+ #ifndef __WINSCW__
+ // Temporary queue for acquiring the codesegments
+ SDblQue queue;
+
+ // Acquire the codesegments
+ TInt actcount = process.TraverseCodeSegs( &queue,
+ NULL,
+ DCodeSeg::EMarkDebug,
+ DProcess::ETraverseFlagAdd );
+ if ( actcount >= params().iIndex )
+ {
+ LOGSTR1( "ATDD DAnalyzeToolChannel::GetCodesegInfo() - actcount >= params.iIndex" );
+ SDblQueLink* link = queue.iA.iNext;
+
+ // Iterate through codesegments
+ for (TInt i = 0; i < actcount; ++i, link = link->iNext)
+ {
+ DCodeSeg* codeseg = _LOFF( link, DCodeSeg, iTempLink );
+
+ // Is the codesegments which information client wants
+ if ( i == params().iIndex )
+ {
+ // Aqcuire codeseg information
+ output().iFileEntryPoint = codeseg->iFileEntryPoint;
+ output().iSize = codeseg->iSize;
+ output().iFullName.Copy( codeseg->iRootName );
+ output().iRunAddress = codeseg->iRunAddress;
+ error = codeseg->GetMemoryInfo( output().iMemoryInfo, &process );
+
+ if ( KErrNone == error )
+ {
+ // Writes a descriptor to a thread's process.
+ error = Kern::ThreadDesWrite( aMessage.Client(),
+ aCodesegInfo,
+ output,
+ 0 );
+ if ( KErrNone != error )
+ {
+ LOGSTR2( "ATDD ThreadDesWrite error %d", error );
+ }
+ }
+ break;
+ }
+ }
+ }
+ // Removes all code segments from a queue and clear specified mark(s).
+ DCodeSeg::EmptyQueue( queue, DCodeSeg::EMarkDebug );
+
+ // Exits thread critical section and releases code segment mutex.
+ Kern::EndAccessCode();
+
+ return error;
+ #else // WINSCW
+
+ if ( iCodeSeg.Count() > params().iIndex )
+ {
+ // Aqcuire codeseg information
+ output().iSize = iCodeSeg[params().iIndex].iSize;
+ output().iFullName.Copy( iCodeSeg[params().iIndex].iFullName );
+ output().iRunAddress = iCodeSeg[params().iIndex].iRunAddress;
+
+ // Writes a descriptor to a thread's process.
+ error = Kern::ThreadDesWrite( aMessage.Client(), aCodesegInfo, output, 0 );
+
+ if ( KErrNone != error )
+ {
+ LOGSTR2( "ATDD ThreadDesWrite error %d", error );
+ }
+ }
+
+ // Exits thread critical section and releases code segment mutex.
+ Kern::EndAccessCode();
+
+ return error;
+ #endif
+ }
+
+// -----------------------------------------------------------------------------
+// DAnalyzeToolChannel::GetLibraryInfo()
+// Acquires library information.
+// -----------------------------------------------------------------------------
+//
+TInt DAnalyzeToolChannel::GetLibraryInfo( TAny* aLibraryInfo,
+ TThreadMessage& aMessage )
+ {
+ LOGSTR1( "ATDD DAnalyzeToolChannel::GetLibraryInfo()" );
+
+ // Temporary variable for reading informationfrom the user side
+ TLibraryInfoBuf params;
+
+ // Reads a descriptor from a thread's process.
+ TInt error = Kern::ThreadDesRead( aMessage.Client(), aLibraryInfo, params, 0 );
+
+ if ( KErrNone != error )
+ {
+ LOGSTR2( "ATDD ThreadDesRead error %d", error );
+ return error;
+ }
+
+ if ( params().iIndex < 0 )
+ {
+ return KErrArgument;
+ }
+
+ // Gets the current process
+ Kern::Containers()[ EProcess ]->Wait();
+ DProcess& process = *Kern::ProcessFromId( params().iProcessId );
+ Kern::Containers()[ EProcess ]->Signal();
+
+ if ( NULL == &process )
+ {
+ return KErrNotFound;
+ }
+
+ // Temporary variable for collecting information from the library
+ TLibraryInfoBuf output;
+
+ // Enters thread critical section and acquires code segment mutex.
+ Kern::AccessCode();
+
+ // Iterate to find the right library
+ if ( params().iIndex < process.iDynamicCode.Count() )
+ {
+ // Acquire entry to the codeseg
+ SCodeSegEntry entry = process.iDynamicCode[ params().iIndex ];
+
+ // Acquire library information
+ entry.iLib->AppendName( output().iLibraryName );//lint !e64 !e1514
+ output().iRunAddress = entry.iSeg->iRunAddress;
+ output().iSize = entry.iSeg->iSize;
+
+ // Writes a descriptor to a thread's process.
+ error = Kern::ThreadDesWrite( aMessage.Client(), aLibraryInfo, output, 0 );
+
+ if ( KErrNone != error )
+ {
+ LOGSTR2( "ATDD ThreadDesWrite error %d", error );
+ }
+
+ // Exits thread critical section and releases code segment mutex.
+ Kern::EndAccessCode();
+
+ return error;
+ }
+ else
+ {
+ // Exits thread critical section and releases code segment mutex.
+ Kern::EndAccessCode();
+
+ return KErrArgument;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// DAnalyzeToolChannel::MainThreadAllocator()
+// Acquires information about process main thread RAllocator
+// -----------------------------------------------------------------------------
+//
+TInt DAnalyzeToolChannel::MainThreadAllocator( TAny* aMainThreadParams,
+ TThreadMessage& aMessage )
+ {
+ LOGSTR1( "ATDD DAnalyzeToolChannel::MainThreadAllocator()" );
+
+ // Temporary variable for reading client side parameters
+ TMainThreadParamsBuf params;
+
+ // Reads a descriptor from a thread's process.
+ TInt error = Kern::ThreadDesRead( aMessage.Client(),
+ aMainThreadParams,
+ params,
+ 0 );
+
+ if ( KErrNone != error )
+ {
+ LOGSTR2( "ATDD ThreadDesRead error %d", error );
+ return error;
+ }
+
+ // Gets the current process
+ Kern::Containers()[ EProcess ]->Wait();
+ DProcess& process = *Kern::ProcessFromId( params().iProcessId );
+ Kern::Containers()[ EProcess ]->Signal();
+
+ if ( NULL == &process )
+ {
+ return KErrNotFound;
+ }
+
+ // Gets the current process
+ Kern::AccessCode();
+
+ // Temporary variable for collecting information from the RAllocator
+ TMainThreadParamsBuf output;
+
+ // Aqcuire a reference to the main thread RAllocator
+ output().iAllocator = process.FirstThread()->iAllocator;
+
+ // Is this only thread in the process
+ output().iAlone = process.iThreadQ.First()->Alone();
+
+ // Exits thread critical section and releases code segment mutex.
+ Kern::EndAccessCode();
+
+ // Writes a descriptor to a thread's process.
+ error = Kern::ThreadDesWrite( aMessage.Client(),
+ aMainThreadParams,
+ output,
+ 0 );
+
+ if ( KErrNone != error )
+ {
+ LOGSTR2( "ATDD ThreadDesWrite error %d", error );
+ }
+
+ return error;
+ }
+
+// -----------------------------------------------------------------------------
+// DAnalyzeToolChannel::ThreadStack()
+// Acquires main thread stack address
+// -----------------------------------------------------------------------------
+//
+TInt DAnalyzeToolChannel::ThreadStack( TAny* aThreadStack,
+ TThreadMessage& aMessage )
+ {
+ LOGSTR1( "ATDD DAnalyzeToolChannel::ThreadStack()" );
+
+ // Temporary variable for reading client side parameters
+ TThreadParamsBuf params;
+
+ // Reads a descriptor from a thread's process.
+ TInt error = Kern::ThreadDesRead( aMessage.Client(),
+ aThreadStack,
+ params,
+ 0 );
+
+ if ( KErrNone != error )
+ {
+ LOGSTR2( "ATDD ThreadDesRead error %d", error );
+ return error;
+ }
+
+ // Gets the current process
+ Kern::Containers()[ EThread ]->Wait();
+ DThread& thread = *Kern::ThreadFromId( params().iThreadId );
+ Kern::Containers()[ EThread ]->Signal();
+
+ if ( NULL == &thread )
+ {
+ return KErrNotFound;
+ }
+
+ // Gets the current process
+ Kern::AccessCode();
+
+ // Temporary variable for collecting information from the RAllocator
+ TThreadParamsBuf output;
+
+ // Stack address of the main thread
+ output().iStackAddress = thread.iUserStackRunAddress;
+ output().iStackSize = thread.iUserStackSize;
+
+ // Exits thread critical section and releases code segment mutex.
+ Kern::EndAccessCode();
+
+ // Writes a descriptor to a thread's process.
+ error = Kern::ThreadDesWrite( aMessage.Client(),
+ aThreadStack,
+ output,
+ 0 );
+
+ if ( KErrNone != error )
+ {
+ LOGSTR2( "ATDD ThreadDesWrite error %d", error );
+ }
+
+ return error;
+ }
+
+// -----------------------------------------------------------------------------
+// DAnalyzeToolChannel::GetProcessHandleInfo()
+// Acquires information about process global handles
+// -----------------------------------------------------------------------------
+//
+TInt DAnalyzeToolChannel::GetProcessHandleInfo( TAny* aProcessHandleInfo,
+ TThreadMessage& aMessage )
+ {
+ LOGSTR1( "ATDD DAnalyzeToolChannel::GetProcessHandleInfo()" );
+
+ // Temporary variable for collecting information from the codeseg
+ TProcessHandleInfoBuf params;
+
+ // Reads a descriptor from a thread's process.
+ TInt error = Kern::ThreadDesRead( aMessage.Client(),
+ aProcessHandleInfo,
+ params,
+ 0 );
+
+ if ( KErrNone != error )
+ {
+ LOGSTR2( "ATDD ThreadDesRead error %d", error );
+ return error;
+ }
+
+ // Gets the current process
+ Kern::Containers()[ EProcess ]->Wait();
+ DProcess& process = *Kern::ProcessFromId( params().iProcessId );
+ Kern::Containers()[ EProcess ]->Signal();
+
+ if ( NULL == &process )
+ {
+ return KErrNotFound;
+ }
+
+ // Variable holding wanted information
+ TProcessHandleInfoBuf output;
+
+ // Enters thread critical section and acquires code segment mutex.
+ Kern::AccessCode();
+
+ // Get the process thread queue.
+ SDblQue queue = process.iThreadQ;
+ error = KErrNotFound;
+
+ // Tests whether this doubly linked list is empty.
+ if ( !queue.IsEmpty() )
+ {
+ // Gets a pointer to the first item in this doubly linked list.
+ SDblQueLink* link = queue.First();
+ DThread* thread = _LOFF( link, DThread, iProcessLink );
+
+ if ( thread )
+ {
+
+#ifdef MCL_ROBJECTIX
+ TInt threadHandles( thread->iHandles.ActiveCount() );
+#else
+ TInt threadHandles( thread->iHandles->ActiveCount() );
+#endif
+
+ // Aqcuire thread information
+ //thread->AppendName( output.iThreadName );
+ output().iUserStackRunAddress = thread->iUserStackRunAddress;
+ output().iUserStackSize = thread->iUserStackSize;
+ output().iThreadHandleCount = threadHandles;
+
+#ifdef MCL_ROBJECTIX
+ RObjectIx objectIx = process.iHandles;
+ output().iProcessHandleCount = objectIx.ActiveCount();
+#else
+ DObjectIx* objectIx = process.iHandles;
+ output().iProcessHandleCount = objectIx->ActiveCount();
+#endif
+
+ // Writes a descriptor to a thread's process.
+ error = Kern::ThreadDesWrite( aMessage.Client(),
+ aProcessHandleInfo,
+ output,
+ 0 );
+
+ if ( KErrNone != error )
+ {
+ LOGSTR2( "ATDD ThreadDesWrite error %d", error );
+ }
+ }
+ }
+
+ // Exits thread critical section and releases code segment mutex.
+ Kern::EndAccessCode();
+
+ return error;
+ }
+
+// -----------------------------------------------------------------------------
+// DAnalyzeToolChannel::GetCurrentHandleCount()
+// Acquires a process's current handle count
+// -----------------------------------------------------------------------------
+//
+TInt DAnalyzeToolChannel::GetCurrentHandleCount( TAny* aProcessHandles,
+ TThreadMessage& aMessage )
+ {
+ LOGSTR1( "ATDD DAnalyzeToolChannel::GetCurrentHandleCount()" );
+
+ // Temporary variable for collecting information from the codeseg
+ TATProcessHandlesBuf params;
+
+ // Reads a descriptor from a thread's process.
+ TInt error = Kern::ThreadDesRead( aMessage.Client(),
+ aProcessHandles,
+ params,
+ 0 );
+
+ if ( KErrNone != error )
+ {
+ LOGSTR2( "ATDD ThreadDesRead error %d", error );
+ return error;
+ }
+
+ // Gets the current process
+ Kern::Containers()[ EProcess ]->Wait();
+ DProcess* process = Kern::ProcessFromId( params().iProcessId );
+ Kern::Containers()[ EProcess ]->Signal();
+
+ if ( NULL == process )
+ {
+ return KErrNotFound;
+ }
+
+ // Variable holding wanted information
+ TATProcessHandlesBuf output;
+
+ // Enters thread critical section and acquires code segment mutex.
+ Kern::AccessCode();
+
+ SDblQue queue = process->iThreadQ;
+ SDblQueLink* link = queue.First();
+ TInt threadHandles( 0 );
+
+ // Iterate through current processes's threads
+ while ( link != queue.Last() )
+ {
+ DThread* thread = _LOFF( link, DThread, iProcessLink );
+
+#ifdef MCL_ROBJECTIX
+ threadHandles += thread->iHandles.ActiveCount();
+#else
+ threadHandles += thread->iHandles->ActiveCount();
+#endif
+
+ link = link->iNext;
+ }
+
+ if ( link == queue.Last() )
+ {
+ DThread* thread = _LOFF( link, DThread, iProcessLink );
+
+#ifdef MCL_ROBJECTIX
+ threadHandles += thread->iHandles.ActiveCount();
+#else
+ threadHandles += thread->iHandles->ActiveCount();
+#endif
+ }
+
+ output().iCurrentHandleCount = threadHandles;
+
+ // Writes a descriptor to a thread's process.
+ error = Kern::ThreadDesWrite( aMessage.Client(),
+ aProcessHandles,
+ output,
+ 0 );
+
+ if ( KErrNone != error )
+ {
+ LOGSTR2( "ATDD ThreadDesWrite error %d", error );
+ }
+
+ // Exits thread critical section and releases code segment mutex.
+ Kern::EndAccessCode();
+
+ return error;
+ }
+
+// -----------------------------------------------------------------------------
+// DAnalyzeToolChannel::ClientCount()
+// Acquires the count of current device driver users.
+// -----------------------------------------------------------------------------
+//
+TInt DAnalyzeToolChannel::ClientCount( TAny* aClientCount,
+ TThreadMessage& aMessage )
+ {
+ LOGSTR1( "ATDD DAnalyzeToolChannel::ClientCount()" );
+
+ // Enters thread critical section and acquires code segment mutex.
+ Kern::AccessCode();
+
+ // Variable holding wanted information
+ TClientCountBuf output;
+
+ // Get the number of DLogicalChannelBase objects currently in existence which
+ // have been created from this LDD.
+ output().iClientCount = DLogicalChannelBase::iDevice->iOpenChannels;
+ LOGSTR2( "ATDD > iOpenChannels count: %d", output().iClientCount );
+
+ // Writes a descriptor to a thread's process.
+ TInt error = Kern::ThreadDesWrite( aMessage.Client(),
+ aClientCount,
+ output,
+ 0 );
+
+ if ( KErrNone != error )
+ {
+ LOGSTR2( "ATDD ThreadDesWrite error %d", error );
+ }
+
+ // Exits thread critical section and releases code segment mutex.
+ Kern::EndAccessCode();
+
+ return error;
+ }
+
+#ifdef __WINSCW__
+// -----------------------------------------------------------------------------
+// DAnalyzeToolChannel::GetModuleDependencies()
+// Get module dependencies
+// -----------------------------------------------------------------------------
+//
+void DAnalyzeToolChannel::GetModuleDependencies( HMODULE aModule )
+ {
+ LOGSTR1( "ATDD DAnalyzeToolChannel::GetModuleDependencies()" );
+
+ Emulator::TModule etm( aModule );
+ TUint32 dllSize( 0 );
+ // Temporary variable for collecting information from the codeseg
+ TCodesegInfo info;
+ TBool found( EFalse );
+
+ const IMAGE_IMPORT_DESCRIPTOR* imports = etm.Imports();
+ while( imports->Characteristics != 0 )
+ {
+ // Reset flag
+ found = EFalse;
+
+ // Get dll name
+ const TUint8* nameAddr = ( const TUint8* )( imports->Name + ( TInt )etm.iBase );
+ TPtrC8 namePtr( nameAddr );
+
+ // Get dll run address
+ Emulator::TModule imp_etm( ( PCSTR )etm.Translate( imports->Name ) );
+ const TUint8* runAddr = ( const TUint8* )imp_etm.iBase;
+
+ // Get dll size
+ const IMAGE_NT_HEADERS32* ntHeader = imp_etm.NtHeader();
+ dllSize = ntHeader->OptionalHeader.SizeOfImage;
+
+ // Check if DLL already exists in codesegment list
+ for( TInt i = 0; i < iCodeSeg.Count(); i++ )
+ {
+ if ( iCodeSeg[i].iFullName.Compare( namePtr ) == KErrNone )
+ {
+ found = ETrue;
+ break;
+ }
+ }
+
+ if ( !found )
+ {
+ info.iSize = dllSize;
+ info.iFullName.Copy( namePtr );
+ info.iRunAddress = (TUint32) runAddr;
+ // Append codesegment to array
+ iCodeSeg.Append( info );
+ }
+ imports++;
+ }
+ }
+
+#endif // __WINSCW__
+
+// -----------------------------------------------------------------------------
+// DAnalyzeToolChannel::GetMemoryModel()
+// Acquires memory model system uses.
+// -----------------------------------------------------------------------------
+//
+TInt DAnalyzeToolChannel::GetMemoryModel(TAny* aMemoryModel,
+ TThreadMessage& aMessage)
+ {
+ LOGSTR1( "ATDD DAnalyzeToolChannel::GetMemoryModel()" );
+
+ // Model buffer.
+ TATMemoryModelBuf model;
+ // Get current model.
+ model().iMemoryModel = (TUint32) Kern::HalFunction( EHalGroupKernel, EKernelHalMemModelInfo, NULL, NULL );
+ model().iMemoryModel &= EMemModelTypeMask; // Mask out other stuff.
+ // Write it to client side.
+ TInt error = Kern::ThreadDesWrite( aMessage.Client(),
+ aMemoryModel,
+ model,
+ 0);
+ if ( error != KErrNone )
+ {
+ LOGSTR2( "ATDD ThreadDesWrite error %d", error );
+ }
+ return error;
+ }
+// End of File