// Copyright (c) 2007-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:
//
/**
@file
@internalComponent
*/
#include "coretargetobserver.h"
CTargetObserver::CTargetObserver(RSecuritySvrSession &aSecSession, CCrashHandler &aHandler)
: CActive(CActive::EPriorityStandard),
iSecSess(aSecSession),
iHandler(aHandler),
iEventInfoPtr( (TUint8*)&iCrashEventInfo, 0, sizeof(TEventInfo) )
{
CActiveScheduler::Add(this);
}
CTargetObserver* CTargetObserver::NewL(RSecuritySvrSession &aSecSession, CCrashHandler &aHandler, const TDesC &aProcessName)
{
LOG_MSG("->CTargetObserver::NewL()\n");
CTargetObserver* self = CTargetObserver::NewLC(aSecSession, aHandler, aProcessName);
CleanupStack::Pop(self);
return self;
}
CTargetObserver* CTargetObserver::NewLC(RSecuritySvrSession &aSession, CCrashHandler &aHandler, const TDesC& aProcessName)
{
LOG_MSG("->CTargetObserver::NewLC()\n");
CTargetObserver *self = new (ELeave) CTargetObserver(aSession, aHandler);
CleanupStack::PushL(self);
self->ConstructL(aProcessName);
return self;
}
void CTargetObserver::ConstructL(const TDesC& aTargetName)
{
LOG_MSG("->CTargetObserver::ConstructL()\n");
iTargetName.CreateL(aTargetName.Length());
iTargetName.Copy(aTargetName);
LOG_MSG("CTargetObserver::Observe -> AttachExecutable\n");
User::LeaveIfError(iSecSess.AttachExecutable( iTargetName, EFalse));
}
void CTargetObserver::SetCrashEventL(TEventType aType, TKernelEventAction aAction)
{
LOG_MSG3("->CTargetObserver::SetCrashEventL(type=%d, action=%d)\n", aType, aAction );
User::LeaveIfError( iSecSess.SetEventAction( iTargetName, aType, aAction ));
}
CTargetObserver::~CTargetObserver()
{
LOG_MSG("->CTargetObserver::~CTargetObserver()\n");
Cancel();
iTargetName.Close();
iThreadList.ResetAndDestroy();
}
void CTargetObserver::DoCancel()
{
LOG_MSG( "CTargetObserver::DoCancel -> CancelGetEvent\n");
TInt err = iSecSess.CancelGetEvent( iTargetName );
if(err != KErrNone)
{
LOG_MSG2( "CTargetObserver::DoCancel - iSecSess.DetachExecutable returned:%d!", err);
//panic client?? close DSS session??
}
LOG_MSG("CTargetObserver::DoCancel -> iSecSess.DetachExecutable\n");
err = iSecSess.DetachExecutable( iTargetName );
if(err != KErrNone)
{
LOG_MSG2( "CTargetObserver::DoCancel iSecSess.DetachExecutable returned:%d!\n", err);
//panic client?? close DSS session??
}
}
const TDesC& CTargetObserver::TargetName() const
{
return iTargetName;
}
TInt CTargetObserver::ThreadCount() const
{
return iThreadList.Count();
}
const TDesC& CTargetObserver::Thread(TInt aIndex) const
{
LOG_MSG2("CTargetObserver::Thread(%d)\n", aIndex);
return *iThreadList[aIndex];
}
void CTargetObserver::AddThreadL(const TDesC &aThreadName)
{
LOG_MSG("->CTargetObserver::AddThreadL()\n");
if(HasThread(aThreadName))
{
LOG_MSG("->CTargetObserver::AddThreadL() - already exists!\n");
User::Leave(KErrAlreadyExists);
}
HBufC *thread;
thread = HBufC::NewL(aThreadName.Length());
*thread = aThreadName;
iThreadList.AppendL(thread);
LOG_MSG("CTargetObserver::AddThreadL - thread added\n");
}
TBool CTargetObserver::HasThread(const TDesC &aThreadName) const
{
LOG_MSG("->CTargetObserver::HasThread()");
TInt count = iThreadList.Count();
for(TInt i = 0; i < count; ++i)
{
if(iThreadList[i]->Des() == aThreadName)
{
LOG_MSG("CTargetObserver::HasThreadL - thread found");
return ETrue;
}
}
LOG_MSG("CTargetObserver::HasThreadL - thread not found");
return EFalse;
}
void CTargetObserver::DelThreadL(const TDesC &aThreadName)
{
LOG_MSG("->CTargetObserver::DelThreadL()");
TInt count = iThreadList.Count();
for(TInt i = 0; i < count; ++i)
{
if(iThreadList[i]->Des() == aThreadName)
{
delete iThreadList[i];
iThreadList.Remove(i);
LOG_MSG("CTargetObserver::DelThreadL - thread deleted");
return;
}
}
LOG_MSG("CTargetObserver::DelThreadL - thread not found!");
User::Leave(KErrNotFound);
}
void CTargetObserver::ClearThreads()
{
LOG_MSG("->CTargetObserver::ClearThreadsL()\n");
iThreadList.ResetAndDestroy();
}
// RunL() completes a previously issued Observe call
void CTargetObserver::RunL()
{
LOG_MSG2("->CTargetObserver::RunL(status:%d)", iStatus.Int());
User::LeaveIfError(iStatus.Int()); //something bad happened
iCrashEventInfo.iEventTime.UniversalTime(); //not 100% exact time of the crash, but as soon as we are notified about it
Observe();
RThread thread;
LOG_MSG2("CTargetObserver::RunL() - opening handle to crashed thread:%Lu\n", iCrashEventInfo.iThreadId);
TInt err = thread.Open(iCrashEventInfo.iThreadId);
if(err != KErrNone)
{
LOG_MSG2("CTargetObserver::RunL - unable to open thread handle! err:%d\n", err);
User::Leave(err);
}
CleanupClosePushL(thread);
if( (iThreadList.Count() == 0) || (HasThread(thread.FullName())) )
{
//crash event of the whole process or thread that we observe
LOG_MSG("CTargetObserver::RunL() -> HandleCrashEventL()");
iHandler.HandleCrashEventL(iCrashEventInfo);
}
else //crash event of thread that we don't care about
{
LOG_MSG("CTargetObserver::RunL() - resuming crashed thread");
iSecSess.ResumeThread(iCrashEventInfo.iThreadId);
}
CleanupStack::PopAndDestroy(); //thread
}
// Report any leave to the client if possible.
TInt CTargetObserver::RunError(TInt aError)
{
return KErrNone;
}
void CTargetObserver::Observe()
{
LOG_MSG("->CTargetObserver::Observe()\n");
iSecSess.GetEvent( iTargetName, iStatus, iEventInfoPtr );
SetActive(); //wait for crash event
}