memspy/Engine/Source/ThreadAndProcess/MemSpyEngineObjectProcess.cpp
changeset 51 98307c651589
parent 42 0ff24a8f6ca2
child 52 c2f44e33b468
equal deleted inserted replaced
42:0ff24a8f6ca2 51:98307c651589
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "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 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 #include <memspy/engine/memspyengineobjectprocess.h>
       
    19 
       
    20 // System includes
       
    21 #include <e32svr.h>
       
    22 #include <u32std.h>
       
    23 
       
    24 // Driver includes
       
    25 #include <memspy/driver/memspydriverclient.h>
       
    26 #include <memspy/driver/memspydriverpanics.h> // for terminate
       
    27 
       
    28 // User includes
       
    29 #include <memspy/engine/memspyengine.h>
       
    30 #include <memspy/engine/memspyengineutils.h>
       
    31 #include <memspy/engine/memspyengineobjectthread.h>
       
    32 
       
    33 // Literal constants
       
    34 _LIT( KMemSpyUnknownProcessName, "Unknown" );
       
    35 _LIT( KMemSpyUnknownExitCategory, "Unknown ExitCat" );
       
    36 _LIT( KMemSpyStandardProcessExtension, ".exe" );
       
    37 
       
    38 
       
    39 CMemSpyProcess::CMemSpyProcess( TProcessId aId, CMemSpyEngine& aEngine  )
       
    40 :   iId( aId ), iEngine( aEngine )
       
    41     {
       
    42     }
       
    43 
       
    44 
       
    45 CMemSpyProcess::~CMemSpyProcess()
       
    46     {
       
    47 #ifdef _DEBUG
       
    48     if  ( iName != NULL )
       
    49         {
       
    50         RDebug::Print(_L( "MEMSPY - dtor - CMemSpyProcess() - this: 0x%08x, name: %S"), this, iName);
       
    51         }
       
    52     else
       
    53         {
       
    54         RDebug::Printf( "MEMSPY - dtor - CMemSpyProcess() - this: 0x%08x", this );
       
    55         }
       
    56 #endif
       
    57 
       
    58     CloseAllThreads();
       
    59     iThreads.Close();
       
    60     delete iName;
       
    61     delete iInfo;
       
    62     }
       
    63 
       
    64 
       
    65 void CMemSpyProcess::ConstructL()
       
    66     {
       
    67     iInfo = new(ELeave) TMemSpyDriverProcessInfo();
       
    68 
       
    69     RMemSpyDriverClient& driver = iEngine.Driver();
       
    70     RProcess process;
       
    71     User::LeaveIfError( driver.OpenProcess( iId, process ) );
       
    72     CleanupClosePushL( process );
       
    73 
       
    74     // Find the threads before we start tinkering with the process
       
    75     // name
       
    76     LocateThreadsL( process );
       
    77 
       
    78     // Now build the process name
       
    79     RefreshL( process );
       
    80 
       
    81     CleanupStack::PopAndDestroy( &process );
       
    82 
       
    83     
       
    84 #ifdef _DEBUG
       
    85     if  ( iName != NULL )
       
    86         {
       
    87         RDebug::Print(_L( "MEMSPY - ctor - CMemSpyProcess() - this: 0x%08x, name: %S"), this, iName);
       
    88         }
       
    89     else
       
    90         {
       
    91         RDebug::Printf( "MEMSPY - ctor - CMemSpyProcess() - this: 0x%08x", this );
       
    92         }
       
    93 #endif
       
    94     }
       
    95 
       
    96 
       
    97 EXPORT_C CMemSpyProcess* CMemSpyProcess::NewL( const CMemSpyProcess& aCopyMe )
       
    98     {
       
    99     CMemSpyProcess* self = NewL( aCopyMe.Id(), aCopyMe.iEngine );
       
   100     return self;
       
   101     }
       
   102 
       
   103 
       
   104 CMemSpyProcess* CMemSpyProcess::NewL( TProcessId aId, CMemSpyEngine& aEngine )
       
   105     {
       
   106     CMemSpyProcess* self = CMemSpyProcess::NewL( aId, aEngine );
       
   107     CleanupStack::Pop( self );
       
   108     return self;
       
   109     }
       
   110 
       
   111 
       
   112 CMemSpyProcess* CMemSpyProcess::NewLC( TProcessId aId, CMemSpyEngine& aEngine )
       
   113     {
       
   114     CMemSpyProcess* self = new(ELeave) CMemSpyProcess( aId, aEngine );
       
   115     CleanupClosePushL( *self );
       
   116     self->ConstructL();
       
   117     return self;
       
   118     }
       
   119 
       
   120 
       
   121 EXPORT_C void CMemSpyProcess::Close()
       
   122     {
       
   123     if  ( !OpenOrCloseInProgress() )
       
   124         {
       
   125         const TInt ac = AccessCount();
       
   126         SetOpenOrCloseInProgress( ETrue );
       
   127 
       
   128         // Calling close can do a "delete this" so make sure
       
   129         // we don't try to access the object again in that situation...
       
   130         CMemSpyEngineObject::Close();
       
   131         if  ( ac - 1 > 0 )
       
   132             {
       
   133             SetOpenOrCloseInProgress( EFalse );
       
   134             }
       
   135         else
       
   136             {
       
   137             // We don't care - we've just been deleted!
       
   138             }
       
   139         }
       
   140     }
       
   141 
       
   142 
       
   143 EXPORT_C void CMemSpyProcess::Open()
       
   144     {
       
   145     if  ( !OpenOrCloseInProgress() )
       
   146         {
       
   147         SetOpenOrCloseInProgress( ETrue );
       
   148         CMemSpyEngineObject::Open();
       
   149         SetOpenOrCloseInProgress( EFalse );
       
   150         }
       
   151     }
       
   152 
       
   153 
       
   154 EXPORT_C TInt CMemSpyProcess::MdcaCount() const
       
   155     {
       
   156     return iThreads.Count();
       
   157     }
       
   158 
       
   159 
       
   160 EXPORT_C TPtrC CMemSpyProcess::MdcaPoint(TInt aIndex) const
       
   161     {
       
   162     const CMemSpyThread* thread = iThreads[ aIndex ];
       
   163     return TPtrC( thread->NameForListBox() );
       
   164     }
       
   165 
       
   166 
       
   167 EXPORT_C TInt CMemSpyProcess::ThreadIndexById( TThreadId aId ) const
       
   168     {
       
   169     TInt index = KErrNotFound;
       
   170     //
       
   171     const TInt count = iThreads.Count();
       
   172     for( TInt i=0; i<count; i++ )
       
   173         {
       
   174         const CMemSpyThread* thread = iThreads[ i ];
       
   175         if  ( thread->Id() == aId )
       
   176             {
       
   177             index = i;
       
   178             break;
       
   179             }
       
   180         }
       
   181     //
       
   182     return index;
       
   183     }
       
   184 
       
   185 
       
   186 EXPORT_C CMemSpyThread& CMemSpyProcess::ThreadByIdL( TThreadId aId ) const
       
   187     {
       
   188     CMemSpyThread* ret = NULL;
       
   189     //
       
   190     const TInt count = iThreads.Count();
       
   191     for( TInt i=0; i<count; i++ )
       
   192         {
       
   193         CMemSpyThread* thread = iThreads[ i ];
       
   194         if  ( thread->Id() == aId )
       
   195             {
       
   196             ret = thread;
       
   197             break;
       
   198             }
       
   199         }
       
   200     //
       
   201     if  ( ret == NULL )
       
   202         {
       
   203         User::Leave( KErrNotFound );
       
   204         }
       
   205     //
       
   206     return *ret;
       
   207     }
       
   208 
       
   209 
       
   210 
       
   211 EXPORT_C TPtrC CMemSpyProcess::Name() const
       
   212     {
       
   213     // Just return the pure name, minus the leading tab
       
   214     TPtrC pRet( iName->Mid(2) );
       
   215     
       
   216     // Find the last tab position
       
   217     TInt pos = pRet.Locate(TChar('\t'));
       
   218     if  ( pos > 0 )
       
   219         {
       
   220         pRet.Set( pRet.Left( pos ) );
       
   221         }
       
   222     //    
       
   223     return pRet;
       
   224     }
       
   225 
       
   226 
       
   227 EXPORT_C CMemSpyThread& CMemSpyProcess::At( TInt aIndex ) const
       
   228     {
       
   229     CMemSpyThread* ret = iThreads[ aIndex ];
       
   230     return *ret;
       
   231     }
       
   232 
       
   233 
       
   234 EXPORT_C void CMemSpyProcess::TerminateL()
       
   235     {
       
   236     RMemSpyDriverClient& driver = iEngine.Driver();
       
   237     RProcess process;
       
   238     User::LeaveIfError( driver.OpenProcess( iId, process ) );
       
   239     process.Terminate( EPanicForcedTerminate );
       
   240     process.Close();
       
   241     //
       
   242     RefreshL();
       
   243     }
       
   244 
       
   245 
       
   246 EXPORT_C void CMemSpyProcess::KillL()
       
   247     {
       
   248     RMemSpyDriverClient& driver = iEngine.Driver();
       
   249     RProcess process;
       
   250     User::LeaveIfError( driver.OpenProcess( iId, process ) );
       
   251     process.Kill( EPanicForcedKill );
       
   252     process.Close();
       
   253     //
       
   254     RefreshL();
       
   255     }
       
   256 
       
   257 
       
   258 EXPORT_C void CMemSpyProcess::PanicL()
       
   259     {
       
   260     RMemSpyDriverClient& driver = iEngine.Driver();
       
   261     RProcess process;
       
   262     User::LeaveIfError( driver.OpenProcess( iId, process ) );
       
   263     process.Panic( KMemSpyClientPanic, EPanicForcedPanic );
       
   264     process.Close();
       
   265     //
       
   266     RefreshL();
       
   267     }
       
   268 
       
   269 
       
   270 EXPORT_C TBool CMemSpyProcess::IsSystemPermanent() const
       
   271     {
       
   272     const TBool ret = ( iInfo->iFlags & KProcessFlagSystemPermanent );
       
   273     return ret;
       
   274     }
       
   275 
       
   276 
       
   277 EXPORT_C TBool CMemSpyProcess::IsSystemCritical() const
       
   278     {
       
   279     const TBool ret = ( iInfo->iFlags & KProcessFlagSystemCritical );
       
   280     return ret;
       
   281     }
       
   282 
       
   283 
       
   284 void CMemSpyProcess::LocateThreadsL( RProcess& aProcess )
       
   285     {
       
   286     __ASSERT_ALWAYS( aProcess.Handle() != KNullHandle, MemSpyEngineUtils::Panic( EMemSpyEnginePanicProcessHandleNullWhenAttemptingToIdentifyThreads ) );
       
   287 
       
   288 #ifdef _DEBUG
       
   289     RDebug::Printf("CMemSpyProcess::LocateThreadsL() - START - this: 0x%08x, pid: %d (0x%04x)", this, (TUint) aProcess.Id(), (TUint) aProcess.Id() );
       
   290 #endif
       
   291 
       
   292     RArray<TThreadId> threadIds;
       
   293     CleanupClosePushL( threadIds );
       
   294 
       
   295     // Get list of child threads from driver.
       
   296     iEngine.Driver().GetThreadsL( aProcess.Id(), threadIds );
       
   297 
       
   298     // Create therad object for each thread the driver returned to us...
       
   299     const TInt count = threadIds.Count();
       
   300 #ifdef _DEBUG
       
   301     RDebug::Printf("CMemSpyProcess::LocateThreadsL() - got %d threads", count );
       
   302 #endif
       
   303 
       
   304     for( TInt i=0; i<count; i++ )
       
   305         {
       
   306         const TThreadId threadId( threadIds[ i ] );
       
   307 #ifdef _DEBUG
       
   308         RDebug::Printf("CMemSpyProcess::LocateThreadsL() - thread id: %d (0x%04d)", (TUint) threadId, (TUint) threadId );
       
   309 #endif
       
   310         //
       
   311         TRAP_IGNORE( 
       
   312             CMemSpyThread* threadObj = CMemSpyThread::NewLC( threadId, *this );
       
   313             iThreads.AppendL( threadObj );
       
   314             CleanupStack::Pop( threadObj );
       
   315             );
       
   316         }
       
   317 
       
   318     // Tidy up
       
   319     CleanupStack::PopAndDestroy( &threadIds );
       
   320     
       
   321 #ifdef _DEBUG
       
   322     RDebug::Printf("CMemSpyProcess::LocateThreadsL() - END - this: 0x%08x, pid: %d (0x%04x), thread count: %d", this, (TUint) aProcess.Id(), (TUint) aProcess.Id(), iThreads.Count() );
       
   323 #endif
       
   324     }
       
   325 
       
   326 
       
   327 void CMemSpyProcess::AppendPriority( TDes& aDes, TProcessPriority aPriority )
       
   328     {
       
   329     switch( aPriority )
       
   330         {
       
   331     case EPriorityLow:
       
   332         aDes += _L("[L]");
       
   333         break;
       
   334     case EPriorityBackground:
       
   335         aDes += _L("[B]");
       
   336         break;
       
   337     case EPriorityForeground:
       
   338         aDes += _L("[F]");
       
   339         break;
       
   340     case EPriorityHigh:
       
   341         aDes += _L("[H]");
       
   342         break;
       
   343     case EPriorityWindowServer:
       
   344         aDes += _L("[WS]");
       
   345         break;
       
   346     case EPriorityFileServer:
       
   347         aDes += _L("[FS]");
       
   348         break;
       
   349     case EPriorityRealTimeServer:
       
   350         aDes += _L("[RTS]");
       
   351         break;
       
   352     case EPrioritySupervisor:
       
   353         aDes += _L("[SUP]");
       
   354         break;
       
   355     default:
       
   356         aDes += _L("[?]");
       
   357         break;
       
   358         }
       
   359     }
       
   360 
       
   361 
       
   362 void CMemSpyProcess::GetFileName( TFileName& aFileName )
       
   363     {
       
   364     // Fallback
       
   365     const TPtrC pNameCleaned( Name() );
       
   366     aFileName.Zero();
       
   367     aFileName.AppendFormat( _L("%S.exe"), &pNameCleaned );
       
   368 
       
   369     // Try to get the proper name
       
   370     RProcess process;
       
   371     RMemSpyDriverClient& driver = iEngine.Driver();
       
   372     if  ( driver.OpenProcess( iId, process ) == KErrNone )
       
   373         {
       
   374         aFileName = process.FileName();
       
   375         process.Close();
       
   376         }
       
   377     }
       
   378 
       
   379 void CMemSpyProcess::RefreshL()
       
   380     {
       
   381     RMemSpyDriverClient& driver = iEngine.Driver();
       
   382     RProcess process;
       
   383 
       
   384     // Deliberately ignore error - the other overload of RefreshL can cope with
       
   385     // a null handle.
       
   386     driver.OpenProcess( iId, process );
       
   387     CleanupClosePushL( process );
       
   388 
       
   389     RefreshL( process );
       
   390 
       
   391     CleanupStack::PopAndDestroy( &process );
       
   392     }
       
   393 
       
   394 
       
   395 void CMemSpyProcess::RefreshL( const RProcess& aProcess )
       
   396     {
       
   397     const TBool handleValid = aProcess.Handle() != KNullHandle;
       
   398     if  ( handleValid )
       
   399         {
       
   400         RMemSpyDriverClient& driver = iEngine.Driver();
       
   401         User::LeaveIfError( driver.GetProcessInfo( iId, *iInfo ) );
       
   402         }
       
   403 
       
   404     // Get priority, exit info etc
       
   405     iExitType = handleValid ? aProcess.ExitType() : EExitKill;
       
   406     iPriority = handleValid ? aProcess.Priority() : EPriorityForeground;
       
   407 
       
   408     // If the process is dead then we may not be able to get some attributes
       
   409     // (it depends on whether the thread handle is valid anymore).
       
   410     iExitReason = 0;
       
   411     iExitCategory.Zero();
       
   412 
       
   413     if  ( IsDead() )
       
   414         {
       
   415         if  ( handleValid )
       
   416             {
       
   417             iExitReason = aProcess.ExitReason();
       
   418             iExitCategory = aProcess.ExitCategory(); 
       
   419             }
       
   420         else
       
   421             {
       
   422             iExitCategory = KMemSpyUnknownExitCategory;
       
   423             }
       
   424         }
       
   425     else
       
   426         {
       
   427         // We only reset the flags if the process is still alive.
       
   428         // If it is dead (i.e. 'if' branch) then we do not reset because
       
   429         // we have no way to fetch them any more.
       
   430         iFlags = EFlagsNone;
       
   431         }
       
   432 
       
   433     // Get raw process name and check whether it includes .exe suffix
       
   434     TBool includesExecutableSuffix = EFalse;
       
   435     HBufC* rawProcessName = GetProcessNameLC( aProcess, includesExecutableSuffix );
       
   436     if ( includesExecutableSuffix )
       
   437         {
       
   438         iFlags |= EFlagsIncludedExecutableWithinName;
       
   439         }
       
   440 
       
   441     // Format priority as string
       
   442     TBuf<10> priority;
       
   443     AppendPriority( priority, iPriority );
       
   444 
       
   445     // Convert the full name to the format we want in the UI
       
   446     TBuf<KMaxFullName + 60> name;
       
   447     TMemSpyTruncateOverflow overflow;
       
   448 
       
   449     // FOR ALIVE PROCESSES:
       
   450     //
       
   451     // 1] Space, followed by tab
       
   452     // 2] Process name (minus .exe)
       
   453     // 3] Tab, Tab
       
   454     // 4] Process uid
       
   455     // 5] Thread count
       
   456     // 6] Process priority
       
   457     //
       
   458     // FOR DEAD PROCESSES:
       
   459     //
       
   460     // 1] Space, followed by tab
       
   461     // 2] Process name (minus .exe)
       
   462     // 3] Tab, Tab
       
   463     // 4] Process uid
       
   464     // 5] Exit info
       
   465 
       
   466     // Common
       
   467     _LIT( KMemSpyProcessNameFormatSpecBasicName, " \t%S\t\t%8x, " );
       
   468     name.AppendFormat( KMemSpyProcessNameFormatSpecBasicName, &overflow, rawProcessName, iInfo->SID() );
       
   469     CleanupStack::PopAndDestroy( rawProcessName );
       
   470 
       
   471     if  ( IsDead() )
       
   472         {
       
   473         CMemSpyThread::AppendExitInfo( name, iExitType, iExitReason, iExitCategory );
       
   474         }
       
   475     else
       
   476         {
       
   477         _LIT( KMemSpyProcessNameFormatSpecAlive, "%2d thr, %S" );
       
   478         name.AppendFormat( KMemSpyProcessNameFormatSpecAlive, &overflow, iThreads.Count(), &priority );
       
   479         }
       
   480 
       
   481     // Save end result
       
   482     HBufC* finalName = name.AllocL();
       
   483     delete iName;
       
   484     iName = finalName;
       
   485     }
       
   486 
       
   487 
       
   488 void CMemSpyProcess::SetDeadL()
       
   489     {
       
   490     RefreshL();
       
   491     }
       
   492 
       
   493 
       
   494 void CMemSpyProcess::SetDeadL( const RProcess& aProcess )
       
   495     {
       
   496     RefreshL( aProcess );
       
   497     }
       
   498 
       
   499 
       
   500 EXPORT_C TBool CMemSpyProcess::IsDead() const
       
   501     {
       
   502     const TBool isDead = ( iExitType != EExitPending );
       
   503     return  isDead;
       
   504     }
       
   505 
       
   506 
       
   507 EXPORT_C TUint32 CMemSpyProcess::SID() const
       
   508     {
       
   509     return iInfo->SID();
       
   510     }
       
   511 
       
   512 
       
   513 EXPORT_C TUint32 CMemSpyProcess::VID() const
       
   514     {
       
   515     return iInfo->VID();
       
   516     }
       
   517 
       
   518 EXPORT_C TProcessPriority CMemSpyProcess::Priority() const
       
   519 	{
       
   520 	return iPriority;
       
   521 	}
       
   522 
       
   523 EXPORT_C TExitCategoryName CMemSpyProcess::ExitCategory() const
       
   524 	{
       
   525 	return iExitCategory;
       
   526 	}
       
   527 
       
   528 EXPORT_C TInt CMemSpyProcess::ExitReason() const
       
   529 	{
       
   530 	return iExitReason;
       
   531 	}
       
   532 
       
   533 EXPORT_C TExitType CMemSpyProcess::ExitType() const
       
   534 	{
       
   535 	return iExitType;
       
   536 	}
       
   537 
       
   538 EXPORT_C TUidType CMemSpyProcess::UIDs() const
       
   539     {
       
   540     return iInfo->iUids;
       
   541     }
       
   542 
       
   543 
       
   544 EXPORT_C SCapabilitySet CMemSpyProcess::Capabilities() const
       
   545     {
       
   546     return iInfo->iSecurityInfo.iCaps;
       
   547     }
       
   548 
       
   549 void CMemSpyProcess::FullName( TDes& aFullName ) const
       
   550     {
       
   551     // c32exe.exe[101f7989]0001
       
   552     aFullName.Zero();
       
   553     aFullName.Append( Name() );
       
   554     if ( iFlags & EFlagsIncludedExecutableWithinName )
       
   555         {
       
   556         // Add .exe
       
   557         aFullName.Append( KMemSpyStandardProcessExtension );
       
   558         }
       
   559 
       
   560     aFullName.Append( '[' );
       
   561 	aFullName.AppendNumFixedWidth( iInfo->iUids[ 2 ].iUid, EHex, 8 );
       
   562     aFullName.Append( ']' );
       
   563 	aFullName.AppendNumFixedWidth( iInfo->iGeneration, EDecimal, 4 );
       
   564     }
       
   565 
       
   566 
       
   567 void CMemSpyProcess::HandleThreadIsBornL( const TThreadId& aId )
       
   568     {
       
   569     // A new thread has been created in this process. Just in case, we'll
       
   570     // check there isn't already an existing thread with the same id...
       
   571     const TInt index = ThreadIndexById( aId );
       
   572     if  ( index < 0 )
       
   573         {
       
   574         TRAP_IGNORE( 
       
   575             CMemSpyThread* threadObj = CMemSpyThread::NewLC( aId, *this );
       
   576             iThreads.AppendL( threadObj );
       
   577             CleanupStack::Pop( threadObj );
       
   578             );
       
   579         }
       
   580     }
       
   581 
       
   582 
       
   583 HBufC* CMemSpyProcess::GetProcessNameLC( const RProcess& aProcessOrNull, TBool& aProcessNameIncludesExeSuffix ) const
       
   584     {
       
   585     _LIT( KMemSpySquareBraceOpen, "[" );
       
   586     //
       
   587     TFullName processName;
       
   588     
       
   589     // Assume the flags have already been set once previously in order to form default response
       
   590     aProcessNameIncludesExeSuffix = ( iFlags & EFlagsIncludedExecutableWithinName );
       
   591 
       
   592     const TBool handleValid = aProcessOrNull.Handle() != KNullHandle;
       
   593     if  ( handleValid )
       
   594         {
       
   595         // Easy case - we have a valid thread handle...
       
   596         //
       
   597         // Get full name, e.g.:
       
   598         //
       
   599         // c32exe.exe[101f7989]0001
       
   600         aProcessOrNull.FullName( processName );
       
   601 
       
   602         // ... but we need to clean up the name so that it
       
   603         // doesn't include the process UID, and neither does it
       
   604         // include the extension (.exe).
       
   605         TInt pos = processName.FindF( KMemSpySquareBraceOpen );
       
   606         if  ( pos > 0 )
       
   607             {
       
   608             processName.SetLength( pos );
       
   609             }
       
   610         
       
   611         // Discard '.exe'
       
   612         pos = processName.FindF( KMemSpyStandardProcessExtension );
       
   613         if  ( pos > 0 )
       
   614             {
       
   615             aProcessNameIncludesExeSuffix = ETrue;
       
   616             processName.SetLength( pos );
       
   617             }
       
   618         }
       
   619     else
       
   620         {
       
   621         // Since we don't have the possibility to enquire after the process's name
       
   622         // we'll assume that it used to be alive and therefore at some point we did
       
   623         // manage to grep it's name...
       
   624         if  ( iName )
       
   625             {
       
   626             const TPtrC pOriginalName( Name() );
       
   627             processName.Append( pOriginalName );
       
   628             }
       
   629         else
       
   630             {
       
   631             // Don't have a process handle, don't have any possibility to get the
       
   632             // name from a prior cached version. Must use "unknown"
       
   633             processName.Append( KMemSpyUnknownProcessName );
       
   634             }
       
   635         }
       
   636     //
       
   637     HBufC* ret = processName.AllocLC();
       
   638     return ret;
       
   639     }
       
   640 
       
   641 
       
   642 void CMemSpyProcess::CloseAllThreads()
       
   643     {
       
   644     const TInt count = iThreads.Count();
       
   645     for(TInt i=count-1; i>=0; i--)
       
   646         {
       
   647         CMemSpyThread* thread = iThreads[ i ];
       
   648         thread->Close();
       
   649         }
       
   650     }
       
   651