memspyui/source/MemSpyViewKernelObjects.cpp
author andy simpson <andrews@symbian.org>
Tue, 13 Jul 2010 17:34:47 +0100
branchRCL_3
changeset 15 3dfaf7faf506
parent 0 d6fe6244b863
permissions -rw-r--r--
DEADHEAD repo replaced by http://developer.symbian.org/oss/MCL/sf/app/rndtools/

/*
* 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 "MemSpyViewKernelObjects.h"

// System includes
#include <eikspane.h>
#include <aknnavide.h> 
#include <akntabgrp.h>
#include <eikclbd.h>
#include <AknQueryDialog.h>
#include <aknnotewrappers.h>
#include <apgwgnam.h>
#include <aknmessagequerydialog.h>

// Engine includes
#include <memspy/engine/memspyengine.h>
#include <memspy/engine/memspyengineobjectprocess.h>
#include <memspy/engine/memspyengineobjectthread.h>
#include <memspy/engine/memspyengineobjectcontainer.h>
#include <memspy/engine/memspyengineobjectthreadinfoobjects.h>
#include <memspy/engine/memspyengineobjectthreadinfocontainer.h>
#include <memspy/engine/memspyenginehelperkernelcontainers.h>
#include <memspy/engine/memspyenginehelperserver.h>
#include <memspy/engine/memspyenginehelpercondvar.h>

// User includes
#include "MemSpyUiUtils.h"
#include "MemSpyViewKernel.h"
#include "MemSpyContainerObserver.h"
#include "MemSpyViewKernelContainers.h"

const TInt KMaxInfoLength = 128;

CMemSpyViewKernelObjects::CMemSpyViewKernelObjects( CMemSpyEngine& aEngine, MMemSpyViewObserver& aObserver, TMemSpyDriverContainerType aObjectType )
:   CMemSpyViewBase( aEngine, aObserver ),
    iObjectType( aObjectType ),
    iCurrItemIndex( KErrNotFound )
    {
    }


CMemSpyViewKernelObjects::~CMemSpyViewKernelObjects()
    {
    if ( iNavContainer && iNavDecorator )
        {
        iNavContainer->Pop( iNavDecorator );
        delete iNavDecorator;
        }
    delete iModel;
    delete iItems;
    delete iObjectList;
    }


void CMemSpyViewKernelObjects::ConstructL( const TRect& aRect, CCoeControl& aContainer, TAny* aSelectionRune )
    {
    _LIT( KTitle, "Kernel Objects" );
    SetTitleL( KTitle );
    iItems = new(ELeave) CDesCArrayFlat(5);
    //
    CMemSpyViewBase::ConstructL( aRect, aContainer, aSelectionRune );
    CreateTabsL();
    }


CEikListBox* CMemSpyViewKernelObjects::ConstructListBoxL()
    {
    delete iListBox;
    iListBox = NULL;
    CAknSingleStyleListBox* listbox = new (ELeave) CAknSingleStyleListBox();
    iListBox = listbox;
    listbox->ConstructL( this, EAknListBoxSelectionList | EAknListBoxLoopScrolling );
    listbox->SetContainerWindowL( *this );
    listbox->CreateScrollBarFrameL( ETrue );
    SetListBoxModelL();
    listbox->ScrollBarFrame()->SetScrollBarVisibilityL( CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto );
    listbox->SetListBoxObserver( this );
    listbox->ItemDrawer()->ColumnData()->EnableMarqueeL(ETrue);
    listbox->SetObserver( this );
    return listbox;
    }


void CMemSpyViewKernelObjects::RefreshL()
    {
    SetListBoxModelL();
    CMemSpyViewBase::RefreshL();
    }


TMemSpyViewType CMemSpyViewKernelObjects::ViewType() const
    {
    return EMemSpyViewTypeKernelObjects;
    }


CMemSpyViewBase* CMemSpyViewKernelObjects::PrepareParentViewL()
    {
    if ( iNavContainer && iNavDecorator )
        {
        iNavContainer->Pop( iNavDecorator );
        delete iNavDecorator;
        iNavDecorator = NULL;
        }
    CMemSpyViewBase* parent = new(ELeave) CMemSpyViewKernelContainers( iEngine, iObserver );
    CleanupStack::PushL( parent );
    parent->ConstructL( Rect(), *Parent(), (TAny*) ViewType() );
    CleanupStack::Pop( parent );
    return parent;
    }


CMemSpyViewBase* CMemSpyViewKernelObjects::PrepareChildViewL()
    {
    CMemSpyViewBase* child = NULL;
    if ( iListBox && 
         iListBox->Model()->NumberOfItems() && 
         iListBox->CurrentItemIndex() > KErrNotFound )
        {
        DetailsL();
        }
    return child;
    }


void CMemSpyViewKernelObjects::DynInitMenuPaneL( TInt aResourceId, CEikMenuPane* aMenuPane )
    {
    if  ( aResourceId == R_MEMSPY_MENUPANE )
       {
       if ( iObjectType > EMemSpyDriverContainerTypeProcess )
           {
           // Display Terminate, Switch to, End and Panic
           // commands only for Threads and processes
           aMenuPane->SetItemDimmed( EMemSpyCmdKernelObjects, ETrue );
           }
        }
    }


void CMemSpyViewKernelObjects::SetListBoxModelL()
    {
    _LIT( KLineFormatSpec, "\t%S" );
    
    // Take ownership of new model
    CMemSpyEngineHelperKernelContainers& kernelContainerManager = iEngine.HelperKernelContainers();
    CMemSpyEngineGenericKernelObjectContainer* model = kernelContainerManager.ObjectsAllL();
    
    delete iModel;
    iModel = model;
    
    iItems->Reset();
    delete iObjectList;
    iObjectList = NULL;
    iObjectList = kernelContainerManager.ObjectsForSpecificContainerL( iObjectType );
    
    // TODO: CMemSpyEngineGenericKernelObjectList could inherit MDesCArray like
    // CMemSpyEngineGenericKernelObjectContainer does. iObjectList could then be passed
    // to listbox model:
    // listbox->Model()->SetItemTextArray( iObjectList );
    
    TName item;
    TName name;
    for ( TInt i = 0; i < iObjectList->Count(); i++ )
        {
        name.Copy( iObjectList->At( i ).iName );
        item.Format( KLineFormatSpec, &name );
        iItems->AppendL( item );
        }
    
    // Set up list box
    CAknSettingStyleListBox* listbox = static_cast< CAknSettingStyleListBox* >( iListBox );
    listbox->Model()->SetItemTextArray( iItems );
    listbox->Model()->SetOwnershipType( ELbmDoesNotOwnItemArray );
    }


TBool CMemSpyViewKernelObjects::HandleCommandL( TInt aCommand )
    {
    TBool handled = ETrue;
    //
    switch ( aCommand )
        {
        case EMemSpyCmdKernelObjectTerminate:
            {
            TRAPD( err, OnCmdTerminateL() );
            if ( err )
                {
                CAknConfirmationNote* note = new(ELeave) CAknConfirmationNote( ETrue );
                note->ExecuteLD( _L("Cannot terminate task") );
                }
            break;
            }
        case EMemSpyCmdKernelObjectSwitchTo:
            {
            TRAPD( err, OnCmdSwitchToL() );
            if ( err )
                {
                CAknConfirmationNote* note = new(ELeave) CAknConfirmationNote( ETrue );
                note->ExecuteLD( _L("Cannot bring to foreground") );
                }
            break;
            }
        case EMemSpyCmdKernelObjectEnd:
            {
            TRAPD( err, OnCmdEndL() );
            if ( err )
                {
                CAknConfirmationNote* note = new(ELeave) CAknConfirmationNote( ETrue );
                note->ExecuteLD( _L("Cannot end task") );
                }
            break;
            }
        case EMemSpyCmdKernelObjectPanic:
            {
            TRAPD( err, OnCmdPanicL() );
            if ( err )
                {
                CAknConfirmationNote* note = new(ELeave) CAknConfirmationNote( ETrue );
                note->ExecuteLD( _L("Cannot panic task") );
                }
            break;
            }
        default:
            {
            handled = CMemSpyViewBase::HandleCommandL( aCommand );
            break;        
            }
        }
    //
    return handled;
    }


TKeyResponse CMemSpyViewKernelObjects::OfferKeyEventL( const TKeyEvent& aKeyEvent, TEventCode aType )
    {
    TKeyResponse resp = EKeyWasNotConsumed;
    if  ( iTabs && ( aKeyEvent.iScanCode == EStdKeyRightArrow || aKeyEvent.iScanCode == EStdKeyLeftArrow ) )
        {
        resp = iTabs->OfferKeyEventL( aKeyEvent, aType );
        }
    else
        {
        resp = CMemSpyViewBase::OfferKeyEventL( aKeyEvent, aType );    
        }
    return resp;
    }


void CMemSpyViewKernelObjects::TabChangedL( TInt /*aIndex*/ )
    {
    iObjectType = (TMemSpyDriverContainerType)iTabs->ActiveTabId();
    RefreshL();
    }


void CMemSpyViewKernelObjects::OnCmdTerminateL()
    {
    switch ( iObjectType )
        {
        case EMemSpyDriverContainerTypeThread:
            {
            TBool doTerminate = ETrue;
            
            CMemSpyEngineObjectContainer& container = iEngine.Container();
            TThreadId id( iObjectList->At( iListBox->CurrentItemIndex() ).iId );
            
            // Try to find the thread in question...
            CMemSpyProcess* process = NULL;
            CMemSpyThread* thread = NULL; 
            User::LeaveIfError( container.ProcessAndThreadByThreadId( id, process, thread ) );

            if ( thread )
                {
                thread->Open();
                //
                if  ( thread->IsSystemPermanent() || thread->IsSystemCritical() )
                    {
                    CAknQueryDialog* importDialog = CAknQueryDialog::NewL();
                    doTerminate = ( importDialog->ExecuteLD( R_MEMSPY_PANIC_SYSTEM_CRITICAL_THREAD_OR_PROCESS ) );
                    }
                //
                if  ( doTerminate )
                    {
                    thread->TerminateL();
                    }                
                }
            RefreshL();
            break;
            }
        case EMemSpyDriverContainerTypeProcess:
            {
            TBool doTerminate = ETrue;
            // Obtain the process that corresponds to the selected item
            CMemSpyEngineObjectContainer& container = iEngine.Container();
            TProcessId id( iObjectList->At( iListBox->CurrentItemIndex() ).iId );
            CMemSpyProcess& process = container.ProcessByIdL( id );
            process.Open();

            if  ( process.IsSystemPermanent() || process.IsSystemCritical() )
                {
                CAknQueryDialog* importDialog = CAknQueryDialog::NewL();
                doTerminate = ( importDialog->ExecuteLD( R_MEMSPY_PANIC_SYSTEM_CRITICAL_THREAD_OR_PROCESS ) );
                }
            //
            if  ( doTerminate )
                {
                process.TerminateL();
                RefreshL();
                }
            break;
            }
        default:
            {
            // Programming error
            __ASSERT_ALWAYS( EFalse, User::Panic( _L("MemSpy-View"), 0 ) );
            }
        }
    }


void CMemSpyViewKernelObjects::OnCmdSwitchToL()
    {
    TInt wgCount;
    RWsSession wsSession;
    User::LeaveIfError( wsSession.Connect() );
    CleanupClosePushL( wsSession );
    User::LeaveIfError( wgCount = wsSession.NumWindowGroups() );
    RArray<RWsSession::TWindowGroupChainInfo> wgArray;
    CleanupClosePushL( wgArray );
    User::LeaveIfError( wsSession.WindowGroupList( &wgArray ) );
    TApaTask task( wsSession );
    TBool brought( EFalse );
    TInt wgId( KErrNotFound );
    TThreadId threadId;
    switch ( iObjectType )
        {
        case EMemSpyDriverContainerTypeThread:
            {
            TThreadId currentThreadId( iObjectList->At( iListBox->CurrentItemIndex() ).iId );
            
            // loop trough all window groups and see if a thread id matches
            while( !brought && wgCount-- )
                {
                wgId = wgArray[wgCount].iId;
                User::LeaveIfError( wsSession.GetWindowGroupClientThreadId( wgId, threadId ) );
                if ( threadId == currentThreadId )
                    {
                    CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC( wsSession, wgId );
                    task.SetWgId( wgId );
                    if ( !wgName->Hidden() && task.Exists() )
                        {
                        task.BringToForeground();
                        brought = ETrue;                        
                        }
                    CleanupStack::PopAndDestroy( wgName );
                    }
                }                
            break;
            }
        case EMemSpyDriverContainerTypeProcess:
            {
            CMemSpyEngineObjectContainer& container = iEngine.Container();
            TProcessId id( iObjectList->At( iListBox->CurrentItemIndex() ).iId );
            CMemSpyProcess& process = container.ProcessByIdL( id );
            
            // loop trough threads in a process
            for ( TInt i = 0; i < process.MdcaCount(); i++ )
                {
                TInt wgCountLocal = wgCount;
                
                // loop trough all window groups and see if a thread id matches
                while( !brought && wgCountLocal-- )
                    {
                    wgId = wgArray[wgCountLocal].iId;
                    User::LeaveIfError( wsSession.GetWindowGroupClientThreadId( wgId, threadId ) );
                    if ( threadId == process.At( i ).Id() )
                        {
                        CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC( wsSession, wgId );
                        task.SetWgId( wgId );
                        if ( !wgName->Hidden() && task.Exists() )
                            {
                            task.BringToForeground();
                            brought = ETrue;                        
                            }
                        CleanupStack::PopAndDestroy( wgName );
                        }
                    }
                }

            break;
            }
        default:
            {
            // Programming error
            __ASSERT_ALWAYS( EFalse, User::Panic( _L("MemSpy-View"), 0 ) );
            }
        }
    if ( !brought )
        {
        // Error handling in HandleCommandL
        User::Leave( KErrGeneral );
        }
    CleanupStack::PopAndDestroy( 2 ); //wgArray,wsSession
    }


void CMemSpyViewKernelObjects::OnCmdEndL()
    {
    switch ( iObjectType )
        {
        case EMemSpyDriverContainerTypeThread:
            {
            TBool doTerminate = ETrue;
            
            CMemSpyEngineObjectContainer& container = iEngine.Container();
            TThreadId id( iObjectList->At( iListBox->CurrentItemIndex() ).iId );
            
            // Try to find the thread in question...
            CMemSpyProcess* process = NULL;
            CMemSpyThread* thread = NULL; 
            User::LeaveIfError( container.ProcessAndThreadByThreadId( id, process, thread ) );

            if ( thread )
                {
                thread->Open();
                //
                if  ( thread->IsSystemPermanent() || thread->IsSystemCritical() )
                    {
                    CAknQueryDialog* importDialog = CAknQueryDialog::NewL();
                    doTerminate = ( importDialog->ExecuteLD( R_MEMSPY_PANIC_SYSTEM_CRITICAL_THREAD_OR_PROCESS ) );
                    }
                //
                if  ( doTerminate )
                    {
                    thread->KillL();
                    }                
                }
            RefreshL();
            break;
            }
        case EMemSpyDriverContainerTypeProcess:
            {
            TBool doTerminate = ETrue;
            // Obtain the process that corresponds to the selected item
            CMemSpyEngineObjectContainer& container = iEngine.Container();
            TProcessId id( iObjectList->At( iListBox->CurrentItemIndex() ).iId );
            CMemSpyProcess& process = container.ProcessByIdL( id );
            process.Open();

            if  ( process.IsSystemPermanent() || process.IsSystemCritical() )
                {
                CAknQueryDialog* importDialog = CAknQueryDialog::NewL();
                doTerminate = ( importDialog->ExecuteLD( R_MEMSPY_PANIC_SYSTEM_CRITICAL_THREAD_OR_PROCESS ) );
                }
            if  ( doTerminate )
                {
                process.KillL();
                RefreshL();
                }

            break;
            }
        default:
            {
            // Programming error
            __ASSERT_ALWAYS( EFalse, User::Panic( _L("MemSpy-View"), 0 ) );
            }
        }    
    }


void CMemSpyViewKernelObjects::OnCmdPanicL()
    {
    switch ( iObjectType )
        {
        case EMemSpyDriverContainerTypeThread:
            {
            TBool doTerminate = ETrue;
            
            CMemSpyEngineObjectContainer& container = iEngine.Container();
            TThreadId id( iObjectList->At( iListBox->CurrentItemIndex() ).iId );
            
            // Try to find the thread in question...
            CMemSpyProcess* process = NULL;
            CMemSpyThread* thread = NULL; 
            User::LeaveIfError( container.ProcessAndThreadByThreadId( id, process, thread ) );

            if ( thread )
                {
                thread->Open();
                //
                if  ( thread->IsSystemPermanent() || thread->IsSystemCritical() )
                    {
                    CAknQueryDialog* importDialog = CAknQueryDialog::NewL();
                    doTerminate = ( importDialog->ExecuteLD( R_MEMSPY_PANIC_SYSTEM_CRITICAL_THREAD_OR_PROCESS ) );
                    }
                //
                if  ( doTerminate )
                    {
                    thread->PanicL();
                    }                
                }
            RefreshL();
            break;
            }
        case EMemSpyDriverContainerTypeProcess:
            {
            TBool doTerminate = ETrue;
            // Obtain the process that corresponds to the selected item
            CMemSpyEngineObjectContainer& container = iEngine.Container();
            TProcessId id( iObjectList->At( iListBox->CurrentItemIndex() ).iId );
            CMemSpyProcess& process = container.ProcessByIdL( id );
            process.Open();

            if  ( process.IsSystemPermanent() || process.IsSystemCritical() )
                {
                CAknQueryDialog* importDialog = CAknQueryDialog::NewL();
                doTerminate = ( importDialog->ExecuteLD( R_MEMSPY_PANIC_SYSTEM_CRITICAL_THREAD_OR_PROCESS ) );
                }
            if  ( doTerminate )
                {
                process.PanicL();
                RefreshL();
                }
            break;
            }
        default:
            {
            // Programming error
            __ASSERT_ALWAYS( EFalse, User::Panic( _L("MemSpy-View"), 0 ) );
            }
        }
    }


void CMemSpyViewKernelObjects::CreateTabsL()
    {
    CEikStatusPane* statusPane = static_cast<CAknAppUi*> ( iEikonEnv->EikAppUi() )->StatusPane();
    TUid uid;
    uid.iUid = EEikStatusPaneUidNavi;
    iNavDecorator = ((CAknNavigationControlContainer*)(statusPane->ControlL(uid)))->Top();

    if ( !iNavDecorator )
        {
        iNavContainer = (CAknNavigationControlContainer*)statusPane->ControlL(uid);
        iNavDecorator = iNavContainer->CreateTabGroupL();

        iTabs = ( CAknTabGroup* )iNavDecorator->DecoratedControl();
        iTabs->SetTabFixedWidthL( KTabWidthWithThreeLongTabs );
    
        for ( TInt i = 0; i < iModel->Count(); i++ )
            {
            const CMemSpyEngineGenericKernelObjectList& item = iModel->At( i );
            iTabs->AddTabL( item.Type(), item.TypeAsString( item.Type() ) );
            }
        iTabs->SetActiveTabById( iObjectType );
        iTabs->SetObserver( this );
        iNavContainer->PushL( *iNavDecorator );
        }
    }


void CMemSpyViewKernelObjects::DetailsL()
    {
    HBufC* messageBuf = HBufC::NewLC( 40960 );
    TPtr messagePtr = messageBuf->Des();

    const TMemSpyDriverHandleInfoGeneric& selectedObject = iObjectList->At( iListBox->CurrentItemIndex() );

    // General attributes:
    TFullName name;
    name.Copy( selectedObject.iNameDetail );
    AppendFormatString( messagePtr, _L("Name: %S\n"), &name );
    name.Zero();
    name.Copy( selectedObject.iName );
    AppendFormatString( messagePtr, _L("FullName: %S\n"), &name );
    name.Zero();
    AppendFormatString( messagePtr, _L("AccessCount: %d\n"), selectedObject.iAccessCount );
    AppendFormatString( messagePtr, _L("UniqueID: %d\n"), selectedObject.iUniqueID );
    AppendFormatString( messagePtr, _L("Protection: %u\n"), selectedObject.iProtection );
    AppendFormatString( messagePtr, _L("OwnrAddr: 0x%08X\n"), selectedObject.iAddressOfKernelOwner );
    AppendFormatString( messagePtr, _L("KernelAddr: 0x%08X"), selectedObject.iHandle );
    
    // Object type specific attributes:
    switch ( selectedObject.iType )
        {
        case EMemSpyDriverContainerTypeUnknown:
            {
            break;
            }
        case EMemSpyDriverContainerTypeThread:
            {
            AppendFormatString( messagePtr, _L("\nOwnrPrAddr: 0x%08X\n"), selectedObject.iAddressOfOwningProcess );
            AppendFormatString( messagePtr, _L("ThreadID: %d\n"), selectedObject.iId );
            AppendFormatString( messagePtr, _L("Priority: %d\n"), selectedObject.iPriority );
            TFullName procName;
            procName.Copy( selectedObject.iNameOfOwner );
            AppendFormatString( messagePtr, _L("Proc: %S"), &procName );
            procName.Zero();
            break;
            }
        case EMemSpyDriverContainerTypeProcess:
            {
            AppendFormatString( messagePtr, _L("\nOwnrPrAddr: 0x%08X\n"), selectedObject.iAddressOfOwningProcess );
            AppendFormatString( messagePtr, _L("CreatorId: %u\n"), selectedObject.iCreatorId );
            AppendFormatString( messagePtr, _L("Attributes: 0x%08X\n"), selectedObject.iAttributes );
            AppendFormatString( messagePtr, _L("StckChnk: 0x%08X\n"), selectedObject.iAddressOfDataBssStackChunk );
            AppendFormatString( messagePtr, _L("ProcessID: %d\n"), selectedObject.iId );
            AppendFormatString( messagePtr, _L("Priority: %d\n"), selectedObject.iPriority );
            AppendFormatString( messagePtr, _L("SecurityZone: %d"), selectedObject.iSecurityZone );
            CMemSpyEngineObjectContainer& container = iEngine.Container();
            TProcessId id( selectedObject.iId );
            TRAP_IGNORE(
                CMemSpyProcess& process = container.ProcessByIdL( id );
                AppendFormatString( messagePtr, _L("\nSID: 0x%08X\n"), process.SID() );
                AppendFormatString( messagePtr, _L("VID: 0x%08X\n"), process.VID() );
                AppendFormatString( messagePtr, _L("UID1: 0x%08X\n"), process.UIDs()[0].iUid  );
                AppendFormatString( messagePtr, _L("UID2: 0x%08X\n"), process.UIDs()[1].iUid  );
                AppendFormatString( messagePtr, _L("UID3: 0x%08X\n"), process.UIDs()[2].iUid );
                AppendFormatString( messagePtr, _L("Caps: 0x%08X%08X"), process.Capabilities().iCaps[0], process.Capabilities().iCaps[1]);
                );
            break;
            }
        case EMemSpyDriverContainerTypeChunk:
            {
            AppendFormatString( messagePtr, _L("\nOwnrPrAddr: 0x%08X\n"), selectedObject.iAddressOfOwningProcess );
            AppendFormatString( messagePtr, _L("Size: %d\n"), selectedObject.iSize );
            AppendFormatString( messagePtr, _L("MaxSize: %d\n"), selectedObject.iMaxSize );
            AppendFormatString( messagePtr, _L("Bottom: %d\n"), selectedObject.iBottom );
            AppendFormatString( messagePtr, _L("Top: %d\n"), selectedObject.iTop );
            AppendFormatString( messagePtr, _L("Attr: 0x%08X\n"), selectedObject.iAttributes );
            AppendFormatString( messagePtr, _L("Start: %d\n"), selectedObject.iStartPos );
            AppendFormatString( messagePtr, _L("CntrlID: %u\n"), selectedObject.iControllingOwner );
            AppendFormatString( messagePtr, _L("Restrictions: %u\n"), selectedObject.iRestrictions );
            AppendFormatString( messagePtr, _L("MapAttr: %u\n"), selectedObject.iMapAttr );
            AppendFormatString( messagePtr, _L("Type: %u\n"), selectedObject.iChunkType );
            TFullName procName;
            procName.Copy( selectedObject.iNameOfOwner );
            AppendFormatString( messagePtr, _L("Proc: %S"), &procName );
            procName.Zero();
            // OwnerAddr iAddressOfKernelOwner already listed
            // ProcAddr iAddressOfOwningProcess already listed
            break;
            }
        case EMemSpyDriverContainerTypeLibrary:
            {
            AppendFormatString( messagePtr, _L("\nMapCount: %d\n"), selectedObject.iMapCount );
            AppendFormatString( messagePtr, _L("State: %u\n"), selectedObject.iState );
            AppendFormatString( messagePtr, _L("CodeSeg: 0x%08X"), selectedObject.iAddressOfCodeSeg );
            break;
            }
        case EMemSpyDriverContainerTypeSemaphore:
            {
            AppendFormatString( messagePtr, _L("\nCount: %d\n"), selectedObject.iCount );
            AppendFormatString( messagePtr, _L("Resetting: %u"), selectedObject.iResetting );
            break;
            }
        case EMemSpyDriverContainerTypeMutex:
            {
            AppendFormatString( messagePtr, _L("\nHoldCount: %d\n"), selectedObject.iCount );
            AppendFormatString( messagePtr, _L("WaitCount: %d\n"), selectedObject.iWaitCount );
            AppendFormatString( messagePtr, _L("Resetting: %u\n"), selectedObject.iResetting );
            AppendFormatString( messagePtr, _L("Order: %u"), selectedObject.iOrder );
            break;
            }
        case EMemSpyDriverContainerTypeTimer:
            {
            AppendFormatString( messagePtr, _L("\nState: %d\n"), selectedObject.iTimerState );
            AppendFormatString( messagePtr, _L("Type: %d"), selectedObject.iTimerType );
            break;
            }
        case EMemSpyDriverContainerTypeServer:
            {
            // Owner == ThrdAddr
            AppendFormatString( messagePtr, _L("\nThrdAddr: 0x%08X\n"), selectedObject.iAddressOfOwningThread );
            TFullName thrName;
            thrName.Copy( selectedObject.iNameOfOwner );
            AppendFormatString( messagePtr, _L("Thr: %S\n"), &thrName );
            thrName.Zero();
            AppendFormatString( messagePtr, _L("Type: %d\n"), selectedObject.iSessionType );
            TBuf8<55>buf;
            RArray<TMemSpyDriverServerSessionInfo> sessions;
            CleanupClosePushL( sessions );
            iEngine.HelperServer().GetServerSessionsL( selectedObject, sessions );
            const TInt count = sessions.Count();
            for ( TInt i = 0; i < count; i++ )
                {
                const TMemSpyDriverServerSessionInfo& session = sessions[ i ];
                AppendFormatString( messagePtr, _L("SessAddr: 0x%08X\n"), session.iAddress );
                TFullName sessName;
                sessName.Copy( session.iName );
                AppendFormatString( messagePtr, _L("Sess: %S\n"), &sessName );
                }
            CleanupStack::PopAndDestroy( &sessions );
            break;
            }
        case EMemSpyDriverContainerTypeSession:
            {
            // Server == SvrAddr
            AppendFormatString( messagePtr, _L("\nServer: 0x%08X\n"), selectedObject.iAddressOfServer );
            TFullName srvName;
            srvName.Copy( selectedObject.iName );
            AppendFormatString( messagePtr, _L("Srv: %S\n"), &srvName );
            srvName.Zero();
            // Session: not supported
            AppendFormatString( messagePtr, _L("AccCount: %u\n"), selectedObject.iTotalAccessCount );
            AppendFormatString( messagePtr, _L("SesType: %u\n"), selectedObject.iSessionType );
            AppendFormatString( messagePtr, _L("SvrType: %u\n"), selectedObject.iSvrSessionType );
            AppendFormatString( messagePtr, _L("MsgCount: %d\n"),  selectedObject.iMsgCount );
            AppendFormatString( messagePtr, _L("MsgLimit: %d"), selectedObject.iMsgLimit );
            break;
            }
        case EMemSpyDriverContainerTypeLogicalDevice:
            {
            AppendFormatString( messagePtr, 
                                _L("\nVersion: %d.%d.%d\n"), 
                                selectedObject.iVersion.iMajor,
                                selectedObject.iVersion.iMinor,
                                selectedObject.iVersion.iBuild );
            AppendFormatString( messagePtr, _L("ParseMask: 0x%08X\n"), selectedObject.iParseMask );
            AppendFormatString( messagePtr, _L("UnitsMask: 0x%08X\n"), selectedObject.iUnitsMask );
            AppendFormatString( messagePtr, _L("Open channels: %d"), selectedObject.iOpenChannels );
            break;
            }
        case EMemSpyDriverContainerTypePhysicalDevice:
            {
            AppendFormatString( messagePtr, 
                                _L("\nVersion: %d.%d.%d\n"), 
                                selectedObject.iVersion.iMajor,
                                selectedObject.iVersion.iMinor,
                                selectedObject.iVersion.iBuild );
            AppendFormatString( messagePtr, _L("UnitsMask: 0x%08X\n"), selectedObject.iUnitsMask );
            AppendFormatString( messagePtr, _L("CodeSeg: 0x%08X"), selectedObject.iAddressOfCodeSeg );
            break;
            }
        case EMemSpyDriverContainerTypeLogicalChannel:
            {
            // No other details
            break;
            }
        case EMemSpyDriverContainerTypeChangeNotifier:
            {
            AppendFormatString( messagePtr, _L("\nChanges: %u\n"), selectedObject.iChanges );
            // Thread == ThrdAddr
            AppendFormatString( messagePtr, _L("ThrdAddr: 0x%08X\n"), selectedObject.iAddressOfOwningThread );
            TFullName thrName;
            thrName.Copy( selectedObject.iNameOfOwner );
            AppendFormatString( messagePtr, _L("Thr: %S"), &thrName );
            thrName.Zero();
            break;
            }
        case EMemSpyDriverContainerTypeUndertaker:
            {
            // Thread == ThrdAddr
            AppendFormatString( messagePtr, _L("\nThrdAddr: 0x%08X\n"), selectedObject.iAddressOfOwningThread );
            TFullName thrName;
            thrName.Copy( selectedObject.iNameOfOwner );
            AppendFormatString( messagePtr, _L("Thr: %S"), &thrName );
            thrName.Zero();
            break;
            }
        case EMemSpyDriverContainerTypeMsgQueue:
            {
            // No other details
            break;
            }
        case EMemSpyDriverContainerTypePropertyRef:
            {
            /*
            Not listing details here, as propertyRef is not listed in TaskMgr.
            Following propertyRef attributes are available at engine side. 
            
            IsReady
            Type
            Category
            Key
            RefCount
            ThreadId
            CreatorSID
            */
            break;
            }
        case EMemSpyDriverContainerTypeCondVar:
            {
            AppendFormatString( messagePtr, _L("\nResetting: %u\n"), selectedObject.iResetting );
            // Using iAddressOfOwningThread for mutex
            AppendFormatString( messagePtr, _L("Mutex: 0x%08X\n"), selectedObject.iAddressOfOwningThread );
            // Using iNameOfOwner for mutex
            TFullName mtxName;
            mtxName.Copy( selectedObject.iNameOfOwner );
            AppendFormatString( messagePtr, _L("Mtx: %S\n"), &mtxName );
            mtxName.Zero();
            AppendFormatString( messagePtr, _L("WaitCount: %d\n"), selectedObject.iWaitCount );
            
            RArray<TMemSpyDriverCondVarSuspendedThreadInfo> threads;
            CleanupClosePushL( threads );
            iEngine.HelperCondVar().GetCondVarSuspendedThreadsL( selectedObject, threads );
            const TInt count = threads.Count();
            for ( TInt i = 0; i < count; i++ )
                {
                const TMemSpyDriverCondVarSuspendedThreadInfo& thr = threads[ i ];
                AppendFormatString( messagePtr, _L("SuspThrdAddr: 0x%08X\n"), thr.iAddress );
                TFullName thrName;
                thrName.Copy( thr.iName );
                AppendFormatString( messagePtr, _L("Thr: %S\n"), &thrName );
                }
            CleanupStack::PopAndDestroy( &threads );
            break;
            }
        default:
            {
            // Programming error
            __ASSERT_ALWAYS( EFalse, User::Panic( _L("MemSpy-View"), 0 ) );
            }
        }
    
    CAknMessageQueryDialog* dialog = new(ELeave) CAknMessageQueryDialog( CAknQueryDialog::ENoTone );
    dialog->PrepareLC( R_MEMSPY_KERNEL_OBJECT_DETAILS_DIALOG );
    TFileName headerText;
    headerText.Copy( selectedObject.iName );
    dialog->SetHeaderTextL( headerText );
    dialog->SetMessageTextL(messagePtr);
    dialog->RunLD();
    CleanupStack::PopAndDestroy( messageBuf );
    }


void CMemSpyViewKernelObjects::AppendFormatString( TPtr& aPtr, TRefByValue<const TDesC> aFmt, ... )
    {
    TBuf<KMaxInfoLength> infoString;
    VA_LIST list;
    VA_START ( list, aFmt );
    infoString.FormatList( aFmt, list );
    aPtr.Append( infoString );
    }