diff -r 000000000000 -r a03f92240627 memspy/Engine/Source/ThreadAndProcess/MemSpyEngineObjectProcess.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memspy/Engine/Source/ThreadAndProcess/MemSpyEngineObjectProcess.cpp Tue Feb 02 01:57:15 2010 +0200 @@ -0,0 +1,632 @@ +/* +* 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: +* +*/ + +#include + +// System includes +#include +#include + +// Driver includes +#include +#include // for terminate + +// User includes +#include +#include +#include + +// Literal constants +_LIT( KMemSpyUnknownProcessName, "Unknown" ); +_LIT( KMemSpyUnknownExitCategory, "Unknown ExitCat" ); +_LIT( KMemSpyStandardProcessExtension, ".exe" ); + + +CMemSpyProcess::CMemSpyProcess( TProcessId aId, CMemSpyEngine& aEngine ) +: iId( aId ), iEngine( aEngine ) + { + } + + +CMemSpyProcess::~CMemSpyProcess() + { +#ifdef _DEBUG + if ( iName != NULL ) + { + RDebug::Print(_L( "MEMSPY - dtor - CMemSpyProcess() - this: 0x%08x, name: %S"), this, iName); + } + else + { + RDebug::Printf( "MEMSPY - dtor - CMemSpyProcess() - this: 0x%08x", this ); + } +#endif + + CloseAllThreads(); + iThreads.Close(); + delete iName; + delete iInfo; + } + + +void CMemSpyProcess::ConstructL() + { + iInfo = new(ELeave) TMemSpyDriverProcessInfo(); + + RMemSpyDriverClient& driver = iEngine.Driver(); + RProcess process; + User::LeaveIfError( driver.OpenProcess( iId, process ) ); + CleanupClosePushL( process ); + + // Find the threads before we start tinkering with the process + // name + LocateThreadsL( process ); + + // Now build the process name + RefreshL( process ); + + CleanupStack::PopAndDestroy( &process ); + + +#ifdef _DEBUG + if ( iName != NULL ) + { + RDebug::Print(_L( "MEMSPY - ctor - CMemSpyProcess() - this: 0x%08x, name: %S"), this, iName); + } + else + { + RDebug::Printf( "MEMSPY - ctor - CMemSpyProcess() - this: 0x%08x", this ); + } +#endif + } + + +EXPORT_C CMemSpyProcess* CMemSpyProcess::NewL( const CMemSpyProcess& aCopyMe ) + { + CMemSpyProcess* self = NewL( aCopyMe.Id(), aCopyMe.iEngine ); + return self; + } + + +CMemSpyProcess* CMemSpyProcess::NewL( TProcessId aId, CMemSpyEngine& aEngine ) + { + CMemSpyProcess* self = CMemSpyProcess::NewL( aId, aEngine ); + CleanupStack::Pop( self ); + return self; + } + + +CMemSpyProcess* CMemSpyProcess::NewLC( TProcessId aId, CMemSpyEngine& aEngine ) + { + CMemSpyProcess* self = new(ELeave) CMemSpyProcess( aId, aEngine ); + CleanupClosePushL( *self ); + self->ConstructL(); + return self; + } + + +EXPORT_C void CMemSpyProcess::Close() + { + if ( !OpenOrCloseInProgress() ) + { + const TInt ac = AccessCount(); + SetOpenOrCloseInProgress( ETrue ); + + // Calling close can do a "delete this" so make sure + // we don't try to access the object again in that situation... + CMemSpyEngineObject::Close(); + if ( ac - 1 > 0 ) + { + SetOpenOrCloseInProgress( EFalse ); + } + else + { + // We don't care - we've just been deleted! + } + } + } + + +EXPORT_C void CMemSpyProcess::Open() + { + if ( !OpenOrCloseInProgress() ) + { + SetOpenOrCloseInProgress( ETrue ); + CMemSpyEngineObject::Open(); + SetOpenOrCloseInProgress( EFalse ); + } + } + + +EXPORT_C TInt CMemSpyProcess::MdcaCount() const + { + return iThreads.Count(); + } + + +EXPORT_C TPtrC CMemSpyProcess::MdcaPoint(TInt aIndex) const + { + const CMemSpyThread* thread = iThreads[ aIndex ]; + return TPtrC( thread->NameForListBox() ); + } + + +EXPORT_C TInt CMemSpyProcess::ThreadIndexById( TThreadId aId ) const + { + TInt index = KErrNotFound; + // + const TInt count = iThreads.Count(); + for( TInt i=0; iId() == aId ) + { + index = i; + break; + } + } + // + return index; + } + + +EXPORT_C CMemSpyThread& CMemSpyProcess::ThreadByIdL( TThreadId aId ) const + { + CMemSpyThread* ret = NULL; + // + const TInt count = iThreads.Count(); + for( TInt i=0; iId() == aId ) + { + ret = thread; + break; + } + } + // + if ( ret == NULL ) + { + User::Leave( KErrNotFound ); + } + // + return *ret; + } + + + +EXPORT_C TPtrC CMemSpyProcess::Name() const + { + // Just return the pure name, minus the leading tab + TPtrC pRet( iName->Mid(2) ); + + // Find the last tab position + TInt pos = pRet.Locate(TChar('\t')); + if ( pos > 0 ) + { + pRet.Set( pRet.Left( pos ) ); + } + // + return pRet; + } + + +EXPORT_C CMemSpyThread& CMemSpyProcess::At( TInt aIndex ) const + { + CMemSpyThread* ret = iThreads[ aIndex ]; + return *ret; + } + + +EXPORT_C void CMemSpyProcess::TerminateL() + { + RMemSpyDriverClient& driver = iEngine.Driver(); + RProcess process; + User::LeaveIfError( driver.OpenProcess( iId, process ) ); + process.Terminate( EPanicForcedTerminate ); + process.Close(); + // + RefreshL(); + } + + +EXPORT_C void CMemSpyProcess::KillL() + { + RMemSpyDriverClient& driver = iEngine.Driver(); + RProcess process; + User::LeaveIfError( driver.OpenProcess( iId, process ) ); + process.Kill( EPanicForcedKill ); + process.Close(); + // + RefreshL(); + } + + +EXPORT_C void CMemSpyProcess::PanicL() + { + RMemSpyDriverClient& driver = iEngine.Driver(); + RProcess process; + User::LeaveIfError( driver.OpenProcess( iId, process ) ); + process.Panic( KMemSpyClientPanic, EPanicForcedPanic ); + process.Close(); + // + RefreshL(); + } + + +EXPORT_C TBool CMemSpyProcess::IsSystemPermanent() const + { + const TBool ret = ( iInfo->iFlags & KProcessFlagSystemPermanent ); + return ret; + } + + +EXPORT_C TBool CMemSpyProcess::IsSystemCritical() const + { + const TBool ret = ( iInfo->iFlags & KProcessFlagSystemCritical ); + return ret; + } + + +void CMemSpyProcess::LocateThreadsL( RProcess& aProcess ) + { + __ASSERT_ALWAYS( aProcess.Handle() != KNullHandle, MemSpyEngineUtils::Panic( EMemSpyEnginePanicProcessHandleNullWhenAttemptingToIdentifyThreads ) ); + +#ifdef _DEBUG + RDebug::Printf("CMemSpyProcess::LocateThreadsL() - START - this: 0x%08x, pid: %d (0x%04x)", this, (TUint) aProcess.Id(), (TUint) aProcess.Id() ); +#endif + + RArray threadIds; + CleanupClosePushL( threadIds ); + + // Get list of child threads from driver. + iEngine.Driver().GetThreadsL( aProcess.Id(), threadIds ); + + // Create therad object for each thread the driver returned to us... + const TInt count = threadIds.Count(); +#ifdef _DEBUG + RDebug::Printf("CMemSpyProcess::LocateThreadsL() - got %d threads", count ); +#endif + + for( TInt i=0; i priority; + AppendPriority( priority, iPriority ); + + // Convert the full name to the format we want in the UI + TBuf name; + TMemSpyTruncateOverflow overflow; + + // FOR ALIVE PROCESSES: + // + // 1] Space, followed by tab + // 2] Process name (minus .exe) + // 3] Tab, Tab + // 4] Process uid + // 5] Thread count + // 6] Process priority + // + // FOR DEAD PROCESSES: + // + // 1] Space, followed by tab + // 2] Process name (minus .exe) + // 3] Tab, Tab + // 4] Process uid + // 5] Exit info + + // Common + _LIT( KMemSpyProcessNameFormatSpecBasicName, " \t%S\t\t%8x, " ); + name.AppendFormat( KMemSpyProcessNameFormatSpecBasicName, &overflow, rawProcessName, iInfo->SID() ); + CleanupStack::PopAndDestroy( rawProcessName ); + + if ( IsDead() ) + { + CMemSpyThread::AppendExitInfo( name, iExitType, iExitReason, iExitCategory ); + } + else + { + _LIT( KMemSpyProcessNameFormatSpecAlive, "%2d thr, %S" ); + name.AppendFormat( KMemSpyProcessNameFormatSpecAlive, &overflow, iThreads.Count(), &priority ); + } + + // Save end result + HBufC* finalName = name.AllocL(); + delete iName; + iName = finalName; + } + + +void CMemSpyProcess::SetDeadL() + { + RefreshL(); + } + + +void CMemSpyProcess::SetDeadL( const RProcess& aProcess ) + { + RefreshL( aProcess ); + } + + +EXPORT_C TBool CMemSpyProcess::IsDead() const + { + const TBool isDead = ( iExitType != EExitPending ); + return isDead; + } + + +EXPORT_C TUint32 CMemSpyProcess::SID() const + { + return iInfo->SID(); + } + + +EXPORT_C TUint32 CMemSpyProcess::VID() const + { + return iInfo->VID(); + } + + +EXPORT_C TUidType CMemSpyProcess::UIDs() const + { + return iInfo->iUids; + } + + +EXPORT_C SCapabilitySet CMemSpyProcess::Capabilities() const + { + return iInfo->iSecurityInfo.iCaps; + } + +void CMemSpyProcess::FullName( TDes& aFullName ) const + { + // c32exe.exe[101f7989]0001 + aFullName.Zero(); + aFullName.Append( Name() ); + if ( iFlags & EFlagsIncludedExecutableWithinName ) + { + // Add .exe + aFullName.Append( KMemSpyStandardProcessExtension ); + } + + aFullName.Append( '[' ); + aFullName.AppendNumFixedWidth( iInfo->iUids[ 2 ].iUid, EHex, 8 ); + aFullName.Append( ']' ); + aFullName.AppendNumFixedWidth( iInfo->iGeneration, EDecimal, 4 ); + } + + +void CMemSpyProcess::HandleThreadIsBornL( const TThreadId& aId ) + { + // A new thread has been created in this process. Just in case, we'll + // check there isn't already an existing thread with the same id... + const TInt index = ThreadIndexById( aId ); + if ( index < 0 ) + { + TRAP_IGNORE( + CMemSpyThread* threadObj = CMemSpyThread::NewLC( aId, *this ); + iThreads.AppendL( threadObj ); + CleanupStack::Pop( threadObj ); + ); + } + } + + +HBufC* CMemSpyProcess::GetProcessNameLC( const RProcess& aProcessOrNull, TBool& aProcessNameIncludesExeSuffix ) const + { + _LIT( KMemSpySquareBraceOpen, "[" ); + // + TFullName processName; + + // Assume the flags have already been set once previously in order to form default response + aProcessNameIncludesExeSuffix = ( iFlags & EFlagsIncludedExecutableWithinName ); + + const TBool handleValid = aProcessOrNull.Handle() != KNullHandle; + if ( handleValid ) + { + // Easy case - we have a valid thread handle... + // + // Get full name, e.g.: + // + // c32exe.exe[101f7989]0001 + aProcessOrNull.FullName( processName ); + + // ... but we need to clean up the name so that it + // doesn't include the process UID, and neither does it + // include the extension (.exe). + TInt pos = processName.FindF( KMemSpySquareBraceOpen ); + if ( pos > 0 ) + { + processName.SetLength( pos ); + } + + // Discard '.exe' + pos = processName.FindF( KMemSpyStandardProcessExtension ); + if ( pos > 0 ) + { + aProcessNameIncludesExeSuffix = ETrue; + processName.SetLength( pos ); + } + } + else + { + // Since we don't have the possibility to enquire after the process's name + // we'll assume that it used to be alive and therefore at some point we did + // manage to grep it's name... + if ( iName ) + { + const TPtrC pOriginalName( Name() ); + processName.Append( pOriginalName ); + } + else + { + // Don't have a process handle, don't have any possibility to get the + // name from a prior cached version. Must use "unknown" + processName.Append( KMemSpyUnknownProcessName ); + } + } + // + HBufC* ret = processName.AllocLC(); + return ret; + } + + +void CMemSpyProcess::CloseAllThreads() + { + const TInt count = iThreads.Count(); + for(TInt i=count-1; i>=0; i--) + { + CMemSpyThread* thread = iThreads[ i ]; + thread->Close(); + } + } +