--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dbgsrv/coredumpserver/server/src/coredumpsessioncalls.cpp Tue Mar 02 10:33:16 2010 +0530
@@ -0,0 +1,2851 @@
+// 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:
+// core_dump_session_calls.cpp
+//
+
+
+
+/**
+ @file
+ @internalTechnology
+ @released
+*/
+
+#include <crashlogwalker.h>
+#include <scmconfigitem.h>
+#include "coredumpsession.h"
+
+using namespace Debug;
+
+// Creates and returns a heap descriptor which holds contents of list
+HBufC8* CCoreDumpSession::MarshalListL( TListRequest & req, TAny * list )
+ {
+
+ LOG_MSG("->CCoreDumpSession::MarshalListL()\n" );
+
+ // Create a dynamic flat buffer to hold this object's member data
+ // Can only use CBufFlat due to Store supporting CBufFlat and CBufSeg
+ // See Symbian OS guide » System libraries » Using Store » Streaming » Templated stream operators
+
+ const TInt KExpandSize = 128; // "Granularity" of dynamic buffer
+
+ CBufFlat* buf = CBufFlat::NewL( KExpandSize );
+ CleanupStack::PushL( buf );
+
+ RBufWriteStream stream( *buf ); // Stream over the buffer
+ CleanupClosePushL( stream );
+
+ for( TInt i = 0; i < req.iRemaining; i ++ )
+ {
+ switch( req.iListType )
+ {
+ case TListRequest::EThreadList:
+ {
+ //LOG_MSG2( " -> ((*threadPointerList)[%d])->ExternalizeL( )\n", i );
+ iThreadPointerList[i]->ExternalizeL( stream, buf );
+ //LOG_MSG2( " buf->Size()=%d\n", buf->Size() );
+ break;
+ }
+ case TListRequest::EProcessList:
+ {
+ //LOG_MSG2( " -> ((*processPointerList)[%d])->ExternalizeL( )\n", i );
+ iProcessPointerList[i]->ExternalizeL( stream, buf );
+ //LOG_MSG2( " buf->Size()=%d\n", buf->Size() );
+ break;
+ }
+
+ case TListRequest::EExecutableList:
+ {
+ //LOG_MSG2( " -> ((*processPointerList)[%d])->ExternalizeL( )\n", i );
+ iExecutablePointerList[i]->ExternalizeL( stream, buf );
+ //LOG_MSG2( " buf->Size()=%d\n", buf->Size() );
+ break;
+ }
+ case TListRequest::EFormatterList:
+ {
+ LOG_MSG2( " -> ((*formatterInfos)[%d])->ExternalizeL( )\n", i );
+ iFormatterInfos[i]->ExternalizeL( stream, buf );
+ //LOG_MSG2( " buf->Size()=%d\n", buf->Size() );
+ break;
+ }
+ case TListRequest::EWriterList:
+ {
+ LOG_MSG2( " -> ((*writerInfos)[%d])->ExternalizeL( )\n", i );
+ iWriterInfos[i]->ExternalizeL( stream, buf );
+ //LOG_MSG2( " buf->Size()=%d\n", buf->Size() );
+ break;
+ }
+ case TListRequest::ECrashList:
+ {
+ LOG_MSG2( " -> ((*iCrashList)[%d])->ExternalizeL( )\n", i );
+ iCrashList[i]->ExternalizeL(stream, buf);
+ //LOG_MSG2( " buf->Size()=%d\n", buf->Size() );
+ break;
+ }
+ default:
+ {
+ LOG_MSG("CCoreDumpSession::MarshalListL : Received unknown list type");
+ User::Leave( KErrNotSupported );
+ }
+ }
+ }
+
+ stream.CommitL();
+
+ TInt bufSize = buf->Size();
+
+ // Create a heap descriptor from the buffer
+ HBufC8* des = HBufC8::NewL( buf->Size() );
+ TPtr8 ptr( des->Des() );
+
+ buf->Read( 0, ptr, buf->Size() );
+
+ CleanupStack::PopAndDestroy( &stream );
+ CleanupStack::PopAndDestroy( buf );
+
+ return des;
+ }
+
+
+void CCoreDumpSession::GetListL( const RMessage2& aMessage )
+ {
+ LOG_MSG( "CCoreDumpSession::GetListL()\n" );
+
+ TListRequest listRequest;
+ HBufC8 *listDes = NULL;
+
+ TPtr8 listReqPtr( (TUint8 *)&listRequest, sizeof(TListRequest) );
+
+ aMessage.ReadL( 0, listReqPtr );
+
+ switch( listRequest.iListType )
+ {
+ case TListRequest::EThreadList :
+ {
+ if( listRequest.iRequiredDescriptorSize != iTotalThreadListDescSize )
+ {
+ LOG_MSG( " ERROR !* listReq.iRequiredDescriptorSize != iTotalThreadListDescSize\n" );
+ User::Leave( KErrBadDescriptor );
+ }
+ listDes = iMarshalledThreadList;
+ break;
+ }
+ case TListRequest::EProcessList :
+ {
+ if( listRequest.iRequiredDescriptorSize != iTotalProcessListDescSize )
+ {
+ LOG_MSG( " ERROR !* listReq.iRequiredDescriptorSize != iTotalProcessListDescSize\n" );
+ User::Leave( KErrBadDescriptor );
+ }
+ listDes = iMarshalledProcessList;
+ break;
+ }
+ case TListRequest::EExecutableList :
+ {
+ if( listRequest.iRequiredDescriptorSize != iTotalExecutableListDescSize )
+ {
+ LOG_MSG( " ERROR !* listReq.iRequiredDescriptorSize != iTotalExecutableListDescSize\n" );
+ User::Leave( KErrBadDescriptor );
+ }
+ listDes = iMarshalledExecutableList;
+ break;
+ }
+ case TListRequest::EFormatterList :
+ {
+ if( listRequest.iRequiredDescriptorSize != iTotalFormatterListDescSize )
+ {
+ LOG_MSG( " ERROR !* listReq.iRequiredDescriptorSize != iTotalFormatterListDescSize\n" );
+ User::Leave( KErrBadDescriptor );
+ }
+ listDes = iMarshalledFormatterList;
+ break;
+ }
+ case TListRequest::EWriterList :
+ {
+ if( listRequest.iRequiredDescriptorSize != iTotalWriterListDescSize )
+ {
+ LOG_MSG( " ERROR !* listReq.iRequiredDescriptorSize != iTotalWriterListDescSize\n" );
+ User::Leave( KErrBadDescriptor );
+ }
+ listDes = iMarshalledWriterList;
+ break;
+ }
+ case TListRequest::ECrashList :
+ {
+ if( listRequest.iRequiredDescriptorSize != iTotalCrashInfoDescSize )
+ {
+ LOG_MSG( " ERROR !* listReq.iRequiredDescriptorSize != iTotalWriterListDescSize\n" );
+ User::Leave( KErrBadDescriptor );
+ }
+ listDes = iMarshalledCrashList;
+ break;
+ }
+ default :
+ {
+ LOG_MSG2( " ERROR !* : CCoreDumpSession::ListInfoL() : invalid TListRequestType %d\n", listRequest.iListType );
+ User::Leave( KErrArgument );
+ }
+ }
+
+ if ( listDes == NULL )
+ {
+
+ LOG_MSG( " ERROR !* MarshalData returned null buf\n" );
+ User::Leave( KErrBadDescriptor );
+
+ }
+ else
+ {
+
+ //LOG_MSG( " -> TPtr8 lsitPtr( listDes->Des() )\n" );
+ TPtr8 listPtr( listDes->Des() );
+ //LOG_MSG2( " listPtr->Size()=%d\n", listPtr.Size() );
+
+ if( listPtr.Size() == 0 )
+ {
+ LOG_MSG( " ERROR !* : if( lsitPtr.Size() == 0 )\n" );
+ User::Leave( KErrBadDescriptor );
+ }
+
+ //LOG_MSG( " -> WriteL( 1, listPtr )\n" );
+ aMessage.WriteL( 1, listPtr );
+
+ }
+
+ }
+
+
+void CCoreDumpSession::ListInfoL( const RMessage2& aMessage )
+ {
+ LOG_MSG( "CCoreDumpSession::ListInfoL()\n" );
+
+ TListRequest listRequest;
+ TUint64 procId;
+
+ TPtr8 listReqPtr( (TUint8 *)&listRequest, sizeof(TListRequest) );
+
+ aMessage.ReadL( 0, listReqPtr );
+
+ switch( listRequest.iListType )
+ {
+ case TListRequest::EThreadList :
+ {
+ procId = MAKE_TUINT64( listRequest.iSubId2, listRequest.iSubId1 );
+ iDataSource->GetThreadListL( procId, iThreadPointerList, iTotalThreadListDescSize );
+
+ listRequest.iRemaining = iThreadPointerList.Count();
+
+ //mark those that we observe
+ for(TInt i = 0; i < iObservationList.Count(); i++)
+ {
+ for(TInt j = 0; j < iThreadPointerList.Count(); j++)
+ {
+ if(iObservationList[i]->HasThread(iThreadPointerList[j]->Name()))
+ {
+ iThreadPointerList[j]->Observed(ETrue);
+ }
+ }
+ }
+
+ if( NULL != iMarshalledThreadList )
+ {
+ delete iMarshalledThreadList;
+ }
+
+ //LOG_MSG( " EThreadList -> MarshalDataL()\n" );
+ iMarshalledThreadList = MarshalListL( listRequest, (TAny*) &iThreadPointerList );
+ listRequest.iRequiredDescriptorSize = iMarshalledThreadList->Des().Size();
+ iTotalThreadListDescSize = listRequest.iRequiredDescriptorSize;
+
+ break;
+ }
+ case TListRequest::EProcessList :
+ {
+ iDataSource->GetProcessListL( iProcessPointerList, iTotalProcessListDescSize );
+
+ listRequest.iRemaining = iProcessPointerList.Count();
+
+ //mark those that we observe
+ for(TInt i = 0; i < iObservationList.Count(); i++)
+ {
+ for(TInt j = 0; j < iProcessPointerList.Count(); j++)
+ {
+ if( (iObservationList[i]->TargetName() == iProcessPointerList[j]->Name()) && //attached to it
+ (iObservationList[i]->ThreadCount() == 0) ) //and no threads on the list
+ {
+ iProcessPointerList[j]->Observed(ETrue);
+ }
+ }
+ }
+
+ if( NULL != iMarshalledProcessList )
+ {
+ delete iMarshalledProcessList;
+ }
+
+ //LOG_MSG( " EProcessList -> MarshalDataL()\n" );
+ iMarshalledProcessList = MarshalListL( listRequest, (TAny*) &iProcessPointerList );
+ listRequest.iRequiredDescriptorSize = iMarshalledProcessList->Des().Size();
+ iTotalProcessListDescSize = listRequest.iRequiredDescriptorSize;
+
+ break;
+ }
+ case TListRequest::EExecutableList :
+ {
+ iDataSource->GetExecutableListL( iExecutablePointerList, iTotalExecutableListDescSize );
+
+ listRequest.iRemaining = iExecutablePointerList.Count();
+ //LOG_MSG2( " listRequest.iRemaining=%d\n", listRequest.iRemaining );
+
+ //mark those that we observe
+ for(TInt i = 0; i < iObservationList.Count(); i++)
+ {
+ for(TInt j = 0; j < iExecutablePointerList.Count(); j++)
+ {
+ if( iObservationList[i]->TargetName() == iExecutablePointerList[j]->Name() )//attached to it
+ {
+ iExecutablePointerList[j]->Observed(ETrue);
+ }
+ }
+ }
+
+ if( NULL != iMarshalledExecutableList )
+ {
+ delete iMarshalledExecutableList;
+ }
+
+ //LOG_MSG( " EExecutableList -> MarshalDataL()\n" );
+ iMarshalledExecutableList = MarshalListL( listRequest, (TAny*) &iExecutablePointerList );
+ listRequest.iRequiredDescriptorSize = iMarshalledExecutableList->Des().Size();
+ iTotalExecutableListDescSize = listRequest.iRequiredDescriptorSize;
+
+ break;
+ }
+ case TListRequest::EFormatterList :
+ {
+ listRequest.iRemaining = iFormatterInfos.Count();
+
+ if(iMarshalledFormatterList)
+ {
+ delete iMarshalledFormatterList;
+ }
+
+ iMarshalledFormatterList = MarshalListL( listRequest, (TAny*) &iFormatterInfos );
+ listRequest.iRequiredDescriptorSize = iMarshalledFormatterList->Des().Size();
+ iTotalFormatterListDescSize = listRequest.iRequiredDescriptorSize;
+
+ break;
+ }
+ case TListRequest::EWriterList :
+ {
+ listRequest.iRemaining = iWriterInfos.Count();
+
+ if(iMarshalledWriterList)
+ {
+ delete iMarshalledWriterList;
+ }
+
+ iMarshalledWriterList = MarshalListL( listRequest, (TAny*) &iWriterInfos );
+ listRequest.iRequiredDescriptorSize = iMarshalledWriterList->Des().Size();
+ iTotalWriterListDescSize = listRequest.iRequiredDescriptorSize;
+
+ break;
+ }
+ case TListRequest::ECrashList :
+ {
+ //Dealing with listing crashes from flash. Refresh the list and then
+ //serialise the list onto iMarshalledCrashList
+
+ RefreshCrashListFromFlashL();
+ listRequest.iRemaining = iCrashList.Count();
+
+ if(iMarshalledCrashList)
+ {
+ delete iMarshalledCrashList;
+ iMarshalledCrashList = NULL;
+ }
+
+ iMarshalledCrashList = MarshalListL(listRequest, (TAny*)&iCrashList);
+ listRequest.iRequiredDescriptorSize = iMarshalledCrashList->Des().Size();
+ iTotalCrashInfoDescSize = listRequest.iRequiredDescriptorSize;
+
+ break;
+ }
+ default :
+ {
+ LOG_MSG2( " ERROR !* : CCoreDumpSession::ListInfoL() : invalid TListRequestType %d\n", listRequest.iListType );
+ User::Leave( KErrArgument );
+ }
+ }
+
+ aMessage.WriteL( 0, listReqPtr );
+
+ }
+
+/**
+ * This method looks at the crash logs in the flash partition
+ * and caches them
+ */
+void CCoreDumpSession::RefreshCrashListFromFlashL()
+ {
+ LOG_MSG("CCoreDumpSession::RefreshCrashListFromFlashL()");
+
+ TBuf8<Debug::KMaxCoreHeaderSize> buf;
+ iCrashList.ResetAndDestroy();
+
+ //Start looking where the config ends if it exists
+ TInt crashLogPos = 0;
+ SCMConfiguration* config = FlashDataSource()->GetSCMConfigFromFlashL();
+ if(config)
+ {
+ crashLogPos = config->GetSize();
+ }
+
+ delete config;
+
+ do
+ {
+ LOG_MSG3("Looking for crash at [%d] [0x%X]", crashLogPos, crashLogPos);
+
+ //Read in the 2 headers and the context, while we are in the crash log
+ TInt err = iSecSess.ReadCrashLog(crashLogPos, buf, Debug::KMaxCoreHeaderSize);
+ if(err != KErrNone)
+ {
+ if(err == KErrPermissionDenied)
+ {
+ User::Leave(err);
+ }
+
+ //We have reached the end of the crash partition
+ return;
+ }
+
+ TCrashLogWalker wlk(buf);
+
+ if(KErrNone == wlk.ReadLogHeader(0))
+ {
+ LOG_MSG("Found a valid crash");
+ const TCrashInfoHeader hdr = wlk.GetCrashHeader();
+ TCrashInfo* inf = TCrashInfo::NewL(hdr);
+ inf->iCrashSource = TCrashInfo::ESystemCrash;
+ inf->iContext = wlk.GetCrashContext();
+
+ iCrashList.Append(inf);
+
+ //Increment this so it goes up by the log size AND then enough to align it to a flash block
+ TUint32 flashPadding = 0x20000 - (crashLogPos + hdr.iLogSize)%0x20000;
+ crashLogPos += (hdr.iLogSize + flashPadding);
+ }
+ else
+ {
+ //otherwise we dont have any more crashes
+ return;
+ }
+
+ }
+ while(true);
+
+ }
+
+
+/**
+ * Processes the crash log in the flash partition corrosponding to the crash ID of the parameter
+ * passed through. If this doesnt match a crash in the partition, or the flash cannot be read
+ * this will leave with KErrCorrupted
+ * @param aMessage
+ * @leave one of the OS wide codes
+ */
+void CCoreDumpSession::ProcessCrashLogL(const RMessage2& aMessage)
+ {
+ TInt crashId = aMessage.Int0();
+ LOG_MSG2("->CCoreDumpSession::ProcessCrashLogL(ID = [%d])\n", crashId);
+
+ RefreshCrashListFromFlashL();
+
+ for(TInt cnt = 0; cnt < iCrashList.Count(); cnt++)
+ {
+ if(iCrashList[cnt]->iCrashId == crashId)
+ {
+ RDebug::Printf("Going to the crash handler");
+ iCrashHandler->HandleCrashFromFlashL(*(iCrashList[cnt]));
+ }
+ }
+ }
+
+/**
+ * Processes the crash log in the flash partition Asynchronously corrosponding to the crash ID of the parameter
+ * passed through. It refreshes the crash list and then calls the crash handler. Leaves with standard leave codes
+ * when the underlying methods leave.
+ * @param aMessage
+ * @leave one of the OS wide codes
+ */
+void CCoreDumpSession::ProcessCrashLogAsyncL(const RMessage2& aMessage)
+ {
+ TInt crashId = aMessage.Int0();
+ LOG_MSG2("->CCoreDumpSession::ProcessCrashLogAsyncL(ID = [%d])\n", crashId);
+
+ RefreshCrashListFromFlashL();
+
+ for(TInt cnt = 0; cnt < iCrashList.Count(); cnt++)
+ {
+ if(iCrashList[cnt]->iCrashId == crashId)
+ {
+ LOG_MSG("Going to the crash handler using the async mechanism");
+ iCrashHandler->HandleCrashFromFlashL(*(iCrashList[cnt]), aMessage);
+ }
+ }
+ }
+
+/**
+ * Cancels asynchronous processing of the crash log in the flash partition
+ * @param aMessage
+ */
+void CCoreDumpSession::CancelProcessCrashLogAsync(const RMessage2& aMessage)
+ {
+ TInt crashId = aMessage.Int0();
+ LOG_MSG2("->CCoreDumpSession::CancelProcessCrashLogAsyncL(ID = [%d])\n", crashId);
+
+ for(TInt cnt = 0; cnt < iCrashList.Count(); cnt++)
+ {
+ if(iCrashList[cnt]->iCrashId == crashId)
+ {
+ LOG_MSG("Going to the cancel async crash handler processing");
+ iCrashHandler->CancelHandleCrashFromFlash(*(iCrashList[cnt]));
+ }
+ }
+ }
+
+/**
+ * From a crash ID gets a TCrashInfo
+ * @param aCrashId crash ID to search for
+ * @param aCrashInfo the crash info for supplied crash ID
+ * @leave one of the OS wide codes
+ */
+void CCoreDumpSession::GetCrashInfoL(TInt aCrashId, TCrashInfo& aCrashInfo)
+ {
+ for(TInt i = 0; i<iCrashList.Count(); i++)
+ {
+ if(iCrashList[i]->iCrashId == aCrashId)
+ {
+ aCrashInfo = *(iCrashList[i]);
+ return;
+ }
+ }
+
+ User::Leave(KErrNotFound);
+ }
+
+/**
+ Retrives the 'cancel crash' property value and checks if required to abort the crash dump. Updates 'crash progress' property.
+
+@param aProgress descriptor with the crash progress value.
+@leave KErrAbort if crash cancel property has been set
+ */
+void CCoreDumpSession::UpdateProgressL(const TDesC &aProgress) const
+ {
+ LOG_MSG("->CCoreDumpSession::UpdateProgressL()\n");
+ TInt cancelCrash = EFalse;
+ TInt err = RProperty::Get(KCoreDumpServUid, ECrashProgress, cancelCrash);
+ if(err != KErrNone)
+ {
+ LOG_MSG2("CCoreDumpSession::UpdateProgressL - unable to retrive 'ECrashProgress' value! err:%d\n", err);
+ }
+
+ if(cancelCrash)
+ {
+ LOG_MSG("CCoreDumpSession::UpdateProgressL - aborting dump in progress\n");
+ User::Leave(KErrNotReady);
+ }
+
+ err = RProperty::Set(KCoreDumpServUid, ECrashProgress, aProgress);
+ if(err != KErrNone)
+ {
+ LOG_MSG2("CCoreDumpSession::UpdateProgressL - unable to retrive 'crash progress' value! err:%d\n", err);
+ }
+#ifdef DEBUG
+ User::After(1000000);
+#endif
+ }
+
+/**
+ * This method removes a crash log from the flash partition
+ * @param aMessage
+ * @leave one of the OS wide codes
+ */
+void CCoreDumpSession::DeleteCrashLogL(const RMessage2& aMessage)
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+void CCoreDumpSession::DeleteCrashPartitionL()
+ {
+ LOG_MSG("CCoreDumpSession::DeleteCrashPartitionL()");
+
+ UpdateProgressL(_L("Erasing Entire Log"));
+
+ //Read in config first
+ SCMConfiguration* config = FlashDataSource()->GetSCMConfigFromFlashL();
+ TCleanupItem scmCleanup(CCoreDumpSession::CleanupSCMConfiguration, (TAny*)config);
+ if(config)
+ CleanupStack::PushL(scmCleanup);
+
+ TInt err = iSecSess.EraseCrashFlashPartition();
+ User::LeaveIfError(err);
+
+ if(config)
+ {
+ //Now we rewrite the config
+ RBuf8 data;
+ data.CreateL(config->GetSize());
+ data.SetLength(config->GetSize());
+ data.CleanupClosePushL();
+
+ TByteStreamWriter writer(const_cast<TUint8*>(data.Ptr()), EFalse);
+ config->Serialize(writer);
+
+ TUint32 written = 0;
+ User::LeaveIfError(iSecSess.WriteCrashConfig(0, data, written));
+
+ CleanupStack::PopAndDestroy(2);//data and scmCleanup
+ }
+
+ RefreshCrashListFromFlashL();
+
+ UpdateProgressL(_L("Idle"));
+ }
+
+void CCoreDumpSession::CreateWriterL( const TUid loadRequestUid )
+ {
+ LOG_MSG("->CCoreDumpSession::CreateWriterL()\n" );
+
+ ValidatePluginL( loadRequestUid );
+
+ if(iPluginList.Count() == 0)
+ {
+ RefreshPluginListL();
+ }
+
+ CPluginInfo *info = NULL;
+ for(TInt i = 0; i < iPluginList.Count(); i++)
+ {
+ if(iPluginList[i].iUid == loadRequestUid)
+ {
+ info = CPluginInfo::NewL(iPluginList[i].iName,
+ loadRequestUid.iUid,
+ iPluginList[i].iVersion,
+ TPluginRequest::EWriter);
+ CleanupStack::PushL(info);
+ break;
+ }
+ }
+
+ if(!info)
+ {
+ LOG_MSG2("CCoreDumpSession::CreateWriterL - unable to find writer uid:%d on plugin type list!\n", loadRequestUid);
+ User::Leave(KErrArgument);
+ }
+
+ iWriterInfos.AppendL(info);
+ CleanupStack::Pop(info);
+
+ CCrashDataSave *writer = CCrashDataSave::NewL( (TUid)( loadRequestUid ) );
+
+ CleanupStack::PushL(writer);
+ iWriterPlugins.AppendL(writer);
+ CleanupStack::Pop(writer);
+
+ LOG_MSG3("CCoreDumpSession::CreateFormatter fmt:%d, wrt:%d\n", iFormatterPlugins.Count(), iWriterPlugins.Count());
+ //for compatibility, first pair is bound by default
+ if( (iFormatterPlugins.Count() == 1) && (iWriterPlugins.Count() == 1) )
+ {
+ LOG_MSG("CCoreDumpSession::CreateFormatter binding default plugin pair\n" );
+ iFormatterInfos[0]->Pair(0);
+ iFormatterPlugins[0]->ConfigureDataSaveL(iWriterPlugins[0]);
+ }
+ }
+
+void CCoreDumpSession::CreateFormatterL( const TUid loadRequestUid )
+ {
+ LOG_MSG( "->CCoreDumpSession::CreateFormatter()\n" );
+
+ ValidatePluginL( loadRequestUid );
+
+ if(iPluginList.Count() == 0)
+ {
+ RefreshPluginListL();
+ }
+
+ CPluginInfo *info = NULL;
+ for(TInt i = 0; i < iPluginList.Count(); i++)
+ {
+ if(iPluginList[i].iUid == loadRequestUid)
+ {
+ info = CPluginInfo::NewL(iPluginList[i].iName,
+ loadRequestUid.iUid,
+ iPluginList[i].iVersion,
+ TPluginRequest::EFormatter);
+ CleanupStack::PushL(info);
+ break;
+ }
+ }
+
+ if(!info)
+ {
+ LOG_MSG2("CCoreDumpSession::CreateFormatterL - unable to find formatter uid:%X on plugin type list!\n", loadRequestUid);
+ User::Leave(KErrArgument);
+ }
+
+ iFormatterInfos.AppendL(info);
+ CleanupStack::Pop(info);
+
+ CCoreDumpFormatter *formatter = CCoreDumpFormatter::NewL( (TUid)( loadRequestUid ) );
+
+ CleanupStack::PushL(formatter);
+ iFormatterPlugins.AppendL(formatter);
+ CleanupStack::Pop(formatter);
+
+ LOG_MSG3("CCoreDumpSession::CreateFormatter fmt:%d, wrt:%d\n", iFormatterPlugins.Count(), iWriterPlugins.Count());
+ //for compatibility, first pair is bound by default
+ if( (iFormatterPlugins.Count() == 1) && (iWriterPlugins.Count() == 1) )
+ {
+ LOG_MSG("CCoreDumpSession::CreateFormatter binding default plugin pair\n" );
+ iFormatterInfos[0]->Pair(0);
+ iFormatterPlugins[0]->ConfigureDataSaveL(iWriterPlugins[0]);
+ }
+ }
+
+void CCoreDumpSession::DeleteFormatterL( const TUid aFreeRequestUid, const TUint aIndex )
+{
+ LOG_MSG("->CCoreDumpSession::DeleteFormatterL()\n");
+ if( (iFormatterInfos.Count() > aIndex) && (iFormatterInfos[aIndex]->Uid() == aFreeRequestUid.iUid) )
+ {
+ delete iFormatterPlugins[aIndex];
+ iFormatterPlugins.Remove(aIndex);
+
+ delete iFormatterInfos[aIndex];
+ iFormatterInfos.Remove(aIndex);
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+}
+
+void CCoreDumpSession::DeleteWriterL( const TUid aFreeRequestUid, const TUint aIndex )
+{
+ LOG_MSG("->CCoreDumpSession::DeleteWriterL()\n");
+ if( (iWriterInfos.Count() > aIndex) && (iWriterInfos[aIndex]->Uid() == aFreeRequestUid.iUid) )
+ {
+ for(TInt i = 0; i < iFormatterInfos.Count(); i++)
+ {
+ if(iFormatterInfos[i]->Pair() == aIndex)
+ {
+ iFormatterInfos[i]->Pair(KMaxTUint32);
+ }
+ }
+
+ delete iWriterPlugins[aIndex];
+ iWriterPlugins.Remove(aIndex);
+
+ delete iWriterInfos[aIndex];
+ iWriterInfos.Remove(aIndex);
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+}
+
+void CCoreDumpSession::PluginRequestL(const RMessage2& aMessage)
+{
+ LOG_MSG("->CCoreDumpSession::PluginRequestL()\n");
+
+ TPluginRequest request;
+ TPtr8 pluginReqPtr((TUint8 *)&request, sizeof(TPluginRequest));
+ aMessage.ReadL(0, pluginReqPtr);
+
+ if(request.iUid.iUid != 0) //(un)load a plugin
+ {
+ if(request.iPluginType == TPluginRequest::EFormatter)
+ {
+ if(request.iLoad)
+ {
+ CreateFormatterL(request.iUid);
+ }
+ else
+ {
+ //index mapping compatibility - one plugin at a time case
+ TUint index = (request.iIndex == request.iPair) ? request.iIndex : 0;
+ DeleteFormatterL(request.iUid, index);
+ }
+ }
+ else if(request.iPluginType == TPluginRequest::EWriter)
+ {
+ if(request.iLoad)
+ {
+ CreateWriterL(request.iUid);
+ }
+ else
+ {
+ //index mapping compatibility - one plugin at a time case
+ TUint index = (request.iIndex == request.iPair) ? request.iIndex : 0;
+ DeleteWriterL(request.iUid, index);
+ }
+ }
+ else
+ {
+ LOG_MSG2("CCoreDumpSession::PluginRequestL() - invalid plugin type:%d!\n", request.iPluginType);
+ User::Leave(KErrNotSupported);
+ }
+ UpdateConfigParametersL();
+ }
+ else //bind a plugin pair
+ {
+ BindPluginsL(request.iIndex, request.iPair);
+ }
+}
+
+void CCoreDumpSession::BindPluginsL(const TUint aFormatterIndex, const TUint aWriterIndex)
+{
+ LOG_MSG3("->CCoreDumpSession::BindPluginsL(fmt=%d, wrt=%d)\n", aFormatterIndex, aWriterIndex);
+ if( (aFormatterIndex < iFormatterInfos.Count()) && (aWriterIndex < iWriterInfos.Count()) )
+ {
+ iFormatterInfos[aFormatterIndex]->Pair(aWriterIndex);
+ iFormatterPlugins[aFormatterIndex]->ConfigureDataSaveL(iWriterPlugins[aWriterIndex]);
+ }
+ else
+ {
+ LOG_MSG5("CCoreDumpSession::BindPluginsL -> fmtIndex:%d/%d wrtIndex:%d/%d\n", aFormatterIndex, iFormatterInfos.Count(),
+ aWriterIndex, iWriterInfos.Count());
+ User::Leave(KErrNotFound);
+ }
+}
+
+CCoreDumpFormatter* CCoreDumpSession::GetValidFormatter(const TUint aCount)
+{
+ LOG_MSG2("->CCoreDumpSession::ValidFormatter(aCount=%d)", aCount);
+ TUint counter = 0;
+
+ for(TInt i = 0; i < iFormatterInfos.Count(); i++)
+ {
+ LOG_MSG3("CCoreDumpSession::ValidFormatter() - fmt[%d]->pair=%d", i, iFormatterInfos[i]->Pair());
+ if( (iFormatterInfos[i]->Pair() < iWriterInfos.Count()) && ( counter++ == aCount))
+ {
+ LOG_MSG2("CCoreDumpSession::ValidFormatter() - found valid formatter=%d", iFormatterPlugins[i]);
+ return iFormatterPlugins[i];
+ }
+ }
+ return NULL;
+}
+
+static void CleanupEComArray(TAny* aArray)
+{
+ (static_cast<RImplInfoPtrArray*> (aArray))->ResetAndDestroy();
+ (static_cast<RImplInfoPtrArray*> (aArray))->Close();
+}
+
+void CCoreDumpSession::RefreshPluginListL()
+{
+ LOG_MSG("->CCoreDumpSession::RefreshPluginList()\n");
+
+ iPluginList.Close();
+ TPluginInfo ref;
+
+ RImplInfoPtrArray infoArray;
+ TCleanupItem cleanup(CleanupEComArray, &infoArray);
+ CleanupStack::PushL(cleanup);
+
+ CCoreDumpFormatter::ListAllImplementationsL( infoArray );
+
+ for ( TInt i = 0; i < infoArray.Count(); i++ )
+ {
+ ref.iVersion = infoArray[i]->Version();
+ ref.iName = infoArray[i]->DisplayName();
+ ref.iUid = infoArray[i]->ImplementationUid();
+ ref.iType = TPluginRequest::EFormatter;
+
+ ref.iLoaded = EFalse; //iLoaded on this list means we have an instance of that plugin
+ for(TInt j = 0; j < iFormatterInfos.Count(); j++)
+ {
+ if(iFormatterInfos[j]->Uid() == ref.iUid.iUid)
+ {
+ ref.iLoaded = ETrue;
+ break;
+ }
+ }
+
+ iPluginList.AppendL(ref);
+ }
+
+ infoArray.ResetAndDestroy();
+
+ CCrashDataSave::ListAllImplementationsL( infoArray );
+
+ for ( TInt i = 0; i < infoArray.Count(); i++ )
+ {
+ ref.iVersion = infoArray[i]->Version();
+ ref.iName = infoArray[i]->DisplayName();
+ ref.iUid = infoArray[i]->ImplementationUid();
+ ref.iType = TPluginRequest::EWriter;
+
+ ref.iLoaded = EFalse; //iLoaded on this list means we have an instance of that plugin
+ for(TInt j = 0; j < iWriterInfos.Count(); j++)
+ {
+ if(iWriterInfos[j]->Uid() == ref.iUid.iUid)
+ {
+ ref.iLoaded = ETrue;
+ break;
+ }
+ }
+
+ iPluginList.AppendL(ref);
+ }
+
+ CleanupStack::PopAndDestroy();
+}
+
+void CCoreDumpSession::GetPluginListL(const RMessage2& aMessage)
+ {
+ //LOG_MSG("->CCoreDumpSession::GetPluginList()\n");
+
+ TListRequest listRequest;
+
+ TPtr8 pluginReqPtr((TUint8 *)&listRequest, sizeof(TListRequest));
+
+ //read target debug app address and size from debug agent
+ aMessage.ReadL(0, pluginReqPtr);
+
+ TPluginInfoBlock * plugins = new (ELeave) TPluginInfoBlock;
+ CleanupStack::PushL(plugins);
+
+ if( 0 == listRequest.iIndex )
+ {
+ iPluginList.Reset();
+ RefreshPluginListL();
+ }
+
+ TUint toSupply = iPluginList.Count() - listRequest.iIndex;
+ if ( toSupply > KNumPluginDetails )
+ {
+ toSupply = KNumPluginDetails;
+ }
+
+ for( TUint index = 0; index < toSupply; index ++ )
+ {
+ plugins->plugins[index].iVersion = iPluginList[index+listRequest.iIndex].iVersion;
+ plugins->plugins[index].iName = iPluginList[index+listRequest.iIndex].iName;
+ plugins->plugins[index].iDescription = iPluginList[index+listRequest.iIndex].iDescription;
+ plugins->plugins[index].iUid = iPluginList[index+listRequest.iIndex].iUid;
+ plugins->plugins[index].iType = iPluginList[index+listRequest.iIndex].iType;
+ plugins->plugins[index].iLoaded = iPluginList[index+listRequest.iIndex].iLoaded;
+ //RDebug::Print( _L(" loaded[%d]=%d\n"), index, plugins->plugins[index].iLoaded );
+ }
+
+ listRequest.iSupplied = toSupply;
+ listRequest.iRemaining = iPluginList.Count() - (listRequest.iIndex + listRequest.iSupplied);
+
+ //RDebug::Print( _L(" supplying=%d, remaining=%d\n"), toSupply, listRequest.iRemaining );
+
+ aMessage.WriteL(0, pluginReqPtr);
+ TPtr8 pluginArrPtr( (TUint8 *)plugins, sizeof(TPluginInfoBlock) );
+ pluginArrPtr.Set( (TUint8 *)plugins, sizeof(TPluginInfoBlock), sizeof(TPluginInfoBlock) );
+
+ aMessage.WriteL(1, pluginArrPtr);
+ CleanupStack::PopAndDestroy(plugins);
+ }
+
+void CCoreDumpSession::ObservationRequestL( const RMessage2& aMessage )
+ {
+ //RDebug::Print(_L("->CCoreDumpSession::ObservationRequestL()\n"));
+ TInt deslen;
+ deslen = aMessage.GetDesLengthL(0);
+ if (deslen == 0)
+ {
+ // Zero-length target name supplied
+ User::Leave(KErrArgument);
+ }
+
+ RBuf targetName;
+ targetName.CleanupClosePushL();
+ targetName.CreateL(deslen);
+ // Read the target name into targetName
+ aMessage.ReadL(0, targetName);
+
+ deslen = aMessage.GetDesLengthL(1);
+ if (deslen == 0)
+ {
+ // Zero-length target owner name supplied
+ User::Leave(KErrArgument);
+ }
+
+ RBuf targetOwnerName;
+ targetOwnerName.CleanupClosePushL();
+ targetOwnerName.CreateL(deslen);
+ // Read the target owner name into targetOwnerName
+ aMessage.ReadL(1, targetOwnerName);
+
+ TBool observe = static_cast<TBool>(aMessage.Int2());
+ if(observe)
+ {
+ LOG_MSG("CCoreDumpSession::ObservationRequestL - KAttach\n" );
+ AttachTargetL(targetName, targetOwnerName);
+ }
+ else
+ {
+ LOG_MSG("CCoreDumpSession::ObservationRequestL - KDetach\n");
+ DetachTargetL(targetName, targetOwnerName);
+ }
+
+ CleanupStack::PopAndDestroy(&targetOwnerName);
+ CleanupStack::PopAndDestroy(&targetName);
+ }
+
+void CCoreDumpSession::AttachTargetL( const TDesC &aTargetName, const TDesC &aTargetOwnerName )
+ {
+ //LOG_MSG("->CoreDumpSession::AttachTargetL()\n");
+ TBool found = EFalse;
+
+ for(TInt i = 0; i < iObservationList.Count(); ++i)
+ {
+ if(iObservationList[i]->TargetName() == aTargetOwnerName)
+ {
+ if(aTargetName != aTargetOwnerName) //attach thread
+ {
+ iObservationList[i]->AddThreadL(aTargetName);
+ //LOG_MSG("CoreDumpSession::AttachTargetL - thread added\n");
+ }
+ else
+ {
+ LOG_MSG("CoreDumpSession::AttachTargetL - process added\n");
+ iObservationList[i]->ClearThreads();
+ }
+ found = ETrue;
+ break;
+ }
+ }
+
+ if(!found)
+ {
+ //RDebug::Printf( "CoreDumpSession::AttachTargetL - creating new observer", &aTargetOwnerName );
+ CTargetObserver *observer = CTargetObserver::NewLC( iSecSess, *iCrashHandler, aTargetOwnerName );
+ User::LeaveIfError( iObservationList.Insert(observer, 0) );
+
+ if(aTargetName != aTargetOwnerName) //attach thread
+ {
+ observer->AddThreadL(aTargetName);
+ //LOG_MSG("CoreDumpSession::AttachTargetL - thread added\n");
+ }
+
+ if( (iPreCrashEventAction & ESuspendThread) ||
+ (iPreCrashEventAction & ESuspendProcess) )
+ {
+ LOG_MSG("CCoreDumpSession::AttachTargetL() ->SetCrashEventsL(EActionSuspend)\n" );
+ SetCrashEventsL(*observer, EActionSuspend);
+ }
+ else
+ {
+ LOG_MSG("CCoreDumpSession::AttachTargetL() ->SetCrashEventsL(EActionContinue)\n" );
+ SetCrashEventsL(*observer, EActionContinue);
+ }
+
+ observer->Observe();
+
+ //LOG_MSG("CoreDumpSession::AttachTargetL - observer started\n");
+ CleanupStack::Pop(); //observer is now in the iObservationList
+ }
+ }
+
+void CCoreDumpSession::SetCrashEventsL(CTargetObserver &aObserver, TKernelEventAction aAction)
+{
+ LOG_MSG2("CCoreDumpSession::SetCrashEventsL(aAction=%d)\n", aAction);
+
+ if(iCrashEventTypes & ECrashHwExc)
+ {
+ LOG_MSG2(" aObserver.SetCrashEventL(EEventsHwExc, aAction=%d)\n", aAction);
+ aObserver.SetCrashEventL(EEventsHwExc, aAction);
+ }
+ else
+ {
+ LOG_MSG(" aObserver.SetCrashEventL(EEventsHwExc, EActionIgnore)\n");
+ aObserver.SetCrashEventL(EEventsHwExc, EActionIgnore);
+ }
+
+ if(iCrashEventTypes & ECrashKillThread)
+ {
+ LOG_MSG2(" aObserver.SetCrashEventL(EEventsKillThread, aAction=%d)\n", aAction);
+ aObserver.SetCrashEventL(EEventsKillThread, aAction);
+ }
+ else
+ {
+ LOG_MSG(" aObserver.SetCrashEventL(EEventsKillThread, EActionIgnore)\n");
+ aObserver.SetCrashEventL(EEventsKillThread, EActionIgnore);
+ }
+}
+
+void CCoreDumpSession::DetachTargetL( const TDesC &aTargetName, const TDesC &aTargetOwnerName )
+ {
+ //LOG_MSG("->CoreDumpSession::DetachTargetL()\n");
+ TBool found = EFalse;
+
+ RBuf ton;
+ ton.CreateL(aTargetName);
+ char *tonp = (char*) ton.Collapse().PtrZ();
+ LOG_MSG2("CCoreDumpSession::DetachTargetL(%s)\n", tonp);
+ ton.Close();
+
+ RBuf otn;
+ TInt count = iObservationList.Count();
+ for(TInt i = 0; i < count; ++i)
+ {
+ otn.CreateL(iObservationList[i]->TargetName());
+ char* otnp = (char*) otn.Collapse().PtrZ();
+ LOG_MSG3("CCoreDumpSession::DetachTargetL - iObservationList[%d]->TargetName=%s\n", i, otnp);
+ otn.Close();
+ if (iObservationList[i]->TargetName() == aTargetOwnerName)
+ {
+ if(aTargetName != aTargetOwnerName) //detach thread
+ {
+ iObservationList[i]->DelThreadL(aTargetName);
+ LOG_MSG("CoreDumpSession::DetachTargetL - thread removed\n");
+ }
+ if(iObservationList[i]->ThreadCount() == 0) //no more threads to observe or detach process
+ {
+ LOG_MSG("CoreDumpSession::DetachTargetL - destroying observer\n");
+ delete iObservationList[i];
+ iObservationList.Remove(i);
+ }
+ found = ETrue;
+ break;
+ }
+ }
+
+ if(!found)
+ {
+ LOG_MSG("CoreDumpSession::DetachTargetL - target not found\n");
+ User::Leave(KErrNotFound);
+ }
+ }
+
+void CCoreDumpSession::UpdateConfigParametersL()
+{
+ LOG_MSG( "->CCoreDumpSession::UpdateConfigParametersL()\n" );
+
+ COptionConfig *config = NULL;
+ iTotalConfigList.Reset();
+ TUint configParamSize;
+
+ TInt paramNum = iConfigList.Count();
+ for(TInt i = 0; i < paramNum; i++ )
+ {
+ config = iConfigList[i];
+
+ if(!config)
+ {
+ User::Leave(KErrBadHandle);
+ }
+
+ configParamSize = config->Size();
+ if(configParamSize > iMaxConfigParamSize)
+ {
+ iMaxConfigParamSize = configParamSize ;
+ }
+ iTotalConfigList.AppendL(config);
+ }
+
+
+ for(TInt i = 0; i < iFormatterPlugins.Count(); i++)
+ {
+ paramNum = iFormatterPlugins[i]->GetNumberConfigParametersL();
+ for(TInt index = 0; index < paramNum; index++)
+ {
+ config = iFormatterPlugins[i]->GetConfigParameterL(index);
+ if(!config)
+ {
+ User::Leave(KErrBadHandle);
+ }
+
+ configParamSize = config->Size();
+ if(configParamSize > iMaxConfigParamSize)
+ {
+ iMaxConfigParamSize = configParamSize ;
+ }
+
+ config->Instance(i);
+ iTotalConfigList.AppendL(config);
+ }
+ }
+
+ for(TInt i = 0; i < iWriterPlugins.Count(); i++)
+ {
+ paramNum = iWriterPlugins[i]->GetNumberConfigParametersL();
+ for(TInt index = 0; index < paramNum; index++)
+ {
+ config = iWriterPlugins[i]->GetConfigParameterL(index);
+ if(!config)
+ {
+ User::Leave(KErrBadHandle);
+ }
+
+ configParamSize = config->Size();
+ if(configParamSize > iMaxConfigParamSize)
+ {
+ iMaxConfigParamSize = configParamSize ;
+ }
+
+ config->Instance(i);
+ iTotalConfigList.AppendL(config);
+ }
+ }
+
+
+ TRAPD(err, iFlashDataSource->ReadSCMConfigL(iScmConfigList));
+ if(err != KErrNone)
+ {
+ LOG_MSG("Unable to retrieve config params for the SCM: [%d]");
+ return;
+ }
+
+ for(TInt i=0;i<iScmConfigList.Count();i++)
+ {
+ iTotalConfigList.AppendL(iScmConfigList[i]);
+ }
+ }
+
+/**
+ * This logs the current SCM Config to serial
+ */
+void CCoreDumpSession::PrintScmConfigL()
+ {
+ for(TInt i=0;i<iScmConfigList.Count();i++)
+ {
+ COptionConfig* optCon = iScmConfigList[i];
+ LOG_DES(optCon->Prompt());
+ LOG_MSG2("\t\tHas a value of %d", optCon->Value());
+ }
+ }
+
+// Gather all conifg params from CDS, formatter and iWriter,
+// collent into an array and set num to the number of configs avaliable
+void CCoreDumpSession::GetNumberConfigParametersL( const RMessage2& aMessage )
+ {
+ //LOG_MSG( "->CCoreDumpSession::GetNumberConfigParametersL()\n" );
+ UpdateConfigParametersL( );
+
+ TInt numConfigParams = iTotalConfigList.Count();
+ //LOG_MSG2( " numConfigParams=%d", numConfigParams );
+
+ TPtr8 numParamPtr( (TUint8 *) & numConfigParams, sizeof(TInt) );
+ // Else it does not get passed back
+ numParamPtr.Set( (TUint8 *)& numConfigParams, sizeof(TInt), sizeof(TInt) );
+
+ TPtr8 maxParamSizePtr( (TUint8 *) & iMaxConfigParamSize, sizeof(TInt) );
+ // Else it does not get passed back
+ maxParamSizePtr.Set( (TUint8 *)& iMaxConfigParamSize, sizeof(TInt), sizeof(TInt) );
+
+ /*
+ RDebug::Printf( " CCoreDumpSession::GetNumberConfigParameters(): iConfigList.Count()=%d, passing back nParams=%d, iMaxConfigParamSize=%d \n",
+ iConfigList.Count(), numConfigParams, iMaxConfigParamSize );
+ */
+
+ aMessage.WriteL( 0, numParamPtr );
+
+ aMessage.WriteL( 1, maxParamSizePtr );
+ }
+
+void CCoreDumpSession::GetConfigParameterL( const RMessage2& aMessage )
+ {
+// LOG_MSG( "->CCoreDumpSession::GetConfigParameterL()\n" );
+
+
+ if( iTotalConfigList.Count() == 0 )
+ {
+ // The user has never called GetNumberConfigParametersL(),
+ // so update the parameters first.
+ UpdateConfigParametersL( );
+ }
+
+ if( iTotalConfigList.Count() == 0 )
+ {
+ RDebug::Printf( " ERROR !* : Have not gathered the configuration parameters\n" );
+ User::Leave( KErrBadHandle );
+ }
+
+ TInt configIndex = aMessage.Int0();
+ //RDebug::Printf( " configIndex=%d\n", configIndex );
+
+ if ( ( configIndex < 0 ) || ( configIndex >= iTotalConfigList.Count() ) )
+ {
+ RDebug::Printf( " ERROR !* : config Index out of bounds\n" );
+ User::Leave( KErrBadHandle );
+ }
+
+ COptionConfig * config = iTotalConfigList[configIndex];
+
+ HBufC8 * configDes = config->MarshalDataL();
+ CleanupStack::PushL( configDes );
+
+ if ( configDes == NULL )
+ {
+ RDebug::Printf( " ERROR !* MarshalData returned null buf\n" );
+ User::Leave( KErrBadDescriptor );
+ }
+ else
+ {
+ TPtr8 configPtr( configDes->Des() );
+ if( configPtr.Size() == 0 )
+ {
+ RDebug::Printf( " ERROR !* : if( configPtr.Size() == 0 )\n" );
+ User::Leave( KErrBadDescriptor );
+ }
+
+ aMessage.WriteL( 1, configPtr );
+ }
+
+ CleanupStack::PopAndDestroy( configDes );
+ }
+
+void CCoreDumpSession::SetConfigParameterL( const RMessage2& aMessage )
+ {
+ LOG_MSG( "->CCoreDumpSession::SetConfigParameterL()\n" );
+
+ TConfigRequest configRequest;
+
+ TPtr8 configReqPtr( (TUint8 *)&configRequest, sizeof(TConfigRequest) );
+ aMessage.ReadL( 0, configReqPtr );
+
+ TInt32 value = aMessage.Int1();
+
+ HBufC *valueDesc = NULL;
+ TInt valueDesLen = aMessage.GetDesLength( 2 );
+ if( valueDesLen > 0 )
+ {
+ valueDesc = HBufC::NewL( valueDesLen );
+ CleanupStack::PushL( valueDesc );
+ TPtr ptr( valueDesc->Des() );
+ aMessage.ReadL( 2, ptr );
+ }
+ else
+ {
+ valueDesc = KNullDesC().AllocL();
+ CleanupStack::PushL( valueDesc );
+ }
+
+ switch(configRequest.iSource)
+ {
+ case COptionConfig::ECoreDumpServer:
+
+ SetConfigParameterL( configRequest.iIndex, value, *valueDesc );
+ break;
+
+ case COptionConfig::EFormatterPlugin:
+ {
+ if(configRequest.iInstance < iFormatterPlugins.Count())
+ {
+ iFormatterPlugins[configRequest.iInstance]->SetConfigParameterL(configRequest.iIndex, value, *valueDesc);
+ break;
+ }
+ break;
+ }
+ case COptionConfig::EWriterPlugin:
+ {
+ if(configRequest.iInstance < iWriterPlugins.Count())
+ {
+ iWriterPlugins[configRequest.iInstance]->SetConfigParameterL(configRequest.iIndex, value, *valueDesc);
+ break;
+ }
+ break;
+ }
+ case COptionConfig::ESCMConfig:
+ {
+
+ LOG_MSG4("(CCoreDumpSession::SetConfigParameterL) Updating config param instance %d value %d index =%d"
+ , configRequest.iInstance , value, configRequest.iIndex);
+ iFlashDataSource->ModifySCMConfigItemL(configRequest.iInstance, value);
+ break;
+ }
+
+ default:
+ User::Leave(KErrArgument);
+ }
+
+ CleanupStack::PopAndDestroy( valueDesc );
+ }
+
+
+TInt32 CCoreDumpSession::PreProcessingAction() const
+ {
+ return iConfigList[EPreCrashEventAction]->Value();
+ }
+
+TInt32 CCoreDumpSession::PostProcessingAction() const
+ {
+ return iConfigList[EPostCrashEventAction]->Value();
+ }
+
+void CCoreDumpSession::SetConfigParameterL( const TInt aIndex,
+ const TInt32 & aValue,
+ const TDesC & aDescValue )
+ {
+ LOG_MSG3( "->CCoreDumpSession::SetConfigParameterL( aIndex=%d, aValue=0x%X )\n", aIndex, aValue );
+
+ if ( ( aIndex < 0 ) || ( aIndex >= iConfigList.Count() ) )
+ {
+ LOG_MSG2( " ERROR !* : config Index out of bounds, max=%d\n", iConfigList.Count() - 1 );
+ User::Leave( KErrBadHandle );
+ }
+
+ //Match the parameter passed in to one of our own parameters via the index
+ COptionConfig &config = *iConfigList[aIndex];
+
+ if( config.Index() != aIndex )
+ {
+ RDebug::Printf( " ERROR !* : config Index %d does not match internal index %d\n", aIndex, config.Index() );
+ User::Leave( KErrBadHandle );
+ }
+
+ if( aIndex == (TInt)EPreCrashEventAction )
+ {
+ switch( aValue )
+ {
+ case ENoPreAction:
+ case ESuspendThread:
+ case ESuspendProcess:
+
+ LOG_MSG2(" Changing EPreCrashEventAction to =%d\n", aValue );
+
+ iPreCrashEventAction = aValue;
+
+ for(TInt i = 0; i < iObservationList.Count(); i++)
+ {
+ if( (iPreCrashEventAction & ESuspendThread) ||
+ (iPreCrashEventAction & ESuspendProcess) )
+ {
+ LOG_MSG2(" SetCrashEventsL(*iObservationList[%d], EActionSuspend)\n", i );
+ SetCrashEventsL(*iObservationList[i], EActionSuspend);
+ }
+ else
+ {
+ LOG_MSG2(" SetCrashEventsL(*iObservationList[%d], EActionContinue);\n", i );
+ SetCrashEventsL(*iObservationList[i], EActionContinue);
+ }
+ }
+
+ break;
+ default:
+ RDebug::Printf(" ERROR !* EPreCrashEventAction cannot be %d\n", aValue );
+ User::Leave(KErrArgument);
+ }
+ }
+ else if( aIndex == (TInt)EPostCrashEventAction )
+ {
+ switch( aValue )
+ {
+ case ENoPostAction:
+ case EResumeThread:
+ case EResumeProcess:
+ case EKillProcess:
+ iPostCrashEventAction = aValue;
+ break;
+ default:
+ RDebug::Printf(" ERROR !* EPostCrashEventAction cannot be %d\n", aValue );
+ User::Leave(KErrArgument);
+ }
+ }
+ else if( aIndex == (TInt)ECrashEventTypes )
+ {
+ switch( aValue )
+ {
+ case ECrashHwExc:
+ case ECrashKillThread:
+ case ECrashHwExcAndKillThread:
+
+ LOG_MSG2(" Changing trigger ECrashEventTypes to =%d\n", aValue );
+ iCrashEventTypes = aValue;
+
+ for(TInt i = 0; i < iObservationList.Count(); i++)
+ {
+ if( (iPreCrashEventAction & ESuspendThread) ||
+ (iPreCrashEventAction & ESuspendProcess) )
+ SetCrashEventsL(*iObservationList[i], EActionSuspend);
+ else
+ SetCrashEventsL(*iObservationList[i], EActionContinue);
+ }
+
+ break;
+ default:
+ RDebug::Printf( " ERROR !* ECrashEventTypes cannot be %d\n", aValue );
+ User::Leave(KErrArgument);
+ }
+ }
+ else
+ {
+ RDebug::Printf(
+ "CCoreDumpSession::SetConfigParameterL() : parameter with index %d does is not valid\n",
+ aIndex );
+ User::Leave(KErrArgument);
+ }
+
+ // Change our internal values
+ config.Value( aValue );
+ //LOG_MSG( " config->ValueL( aDescValue )\n" );
+ config.ValueL( aDescValue );
+
+ }
+
+
+
+/**
+Save one parameter for a specific section.
+@param aParam COptionConfig pointer to save
+@param aSectName Section name in the file to save this parameter to
+@param aSaveIndex This parameter is only used to create key strings that are unique.
+@param aPersistConfigData Object used to save the configuration to.
+*/
+void CCoreDumpSession::SaveConfigParamL( const COptionConfig * aParam,
+ const TPtrC & aSectName,
+ const TInt aSaveIndex,
+ CIniDocument16 * aPersistConfigData )
+ {
+
+ LOG_MSG2( "CCoreDumpSession::SaveConfigParamL( aSaveIndex=%d )\n", aSaveIndex );
+
+ HBufC * iniStringKey;
+ TInt err;
+
+ // Save the Configuration Parameter Value
+ {
+ iniStringKey = GenerateKeyStringLC( aSaveIndex, EIniKeyValue );
+ TInt keyIntValue = aParam->Value();
+
+ // Size of character buffer required to represent a 32bit
+ // interger as decimal should be 10.
+ TBuf<16> intValueBuf;
+
+ switch( aParam->Type() )
+ {
+ case COptionConfig::ETInt:
+ case COptionConfig::ETUInt:
+ case COptionConfig::ETBool:
+
+ LOG_MSG2( " -> SetKey( int value=%d)\n", keyIntValue );
+ intValueBuf.AppendNum( keyIntValue );
+ err = aPersistConfigData->SetKey( aSectName, iniStringKey->Des(), intValueBuf );
+
+ /*
+ const TDesC & paramV = intValueBuf;
+ RBuf valueV;
+ valueV.Create( paramV );
+ char* cl = (char*) valueV.Collapse().PtrZ();
+ RDebug::Printf(" saving integer value=%s\n", cl );
+ */
+
+ break;
+
+ case COptionConfig::ETString:
+ case COptionConfig::ETFileName:
+ case COptionConfig::ETMultiEntryEnum:
+ case COptionConfig::ETSingleEntryEnum:
+ {
+ const TDesC & paramValue = aParam->ValueAsDesc();
+
+ if( paramValue == KNullDesC )
+ {
+ LOG_MSG( " Cannot save parameter value that is NULL\n" );
+ CleanupStack::PopAndDestroy( iniStringKey );
+ return;
+ }
+ /*
+ RBuf value;
+ value.Create( paramValue );
+ char* cl = (char*) value.Collapse().PtrZ();
+ RDebug::Printf(" saving string value=%s\n", cl );
+ */
+
+ LOG_MSG( " -> SetKey( string value )\n" );
+ err = aPersistConfigData->SetKey( aSectName, iniStringKey->Des(), paramValue );
+ }
+ break;
+ default:
+ {
+ // unknown type, Leave since the file could be corrupt or malformed
+ LOG_MSG2( " Invalid COptionConfig parameter type %d\n", aParam->Type() );
+ CleanupStack::PopAndDestroy( iniStringKey );
+ User::Leave( KErrCorrupt );
+ }
+ }// switch (COptionConfig::TOptionType)
+
+ LOG_MSG( " CleanupStack::PopAndDestroy( iniStringKey )" );
+ CleanupStack::PopAndDestroy( iniStringKey );
+ }
+
+
+
+ // Save the Configuration Parameter Index
+ {
+ iniStringKey = GenerateKeyStringLC( aSaveIndex, EIniKeyIndex );
+
+ TInt keyIndex = aParam->Index();
+ TBuf<4> intIndexBuf;
+ LOG_MSG3( " -> keyIndex%d = parameter index %d\n", aSaveIndex, keyIndex );
+ intIndexBuf.AppendNum( keyIndex );
+
+ err = aPersistConfigData->SetKey( aSectName, iniStringKey->Des(), intIndexBuf );
+
+ CleanupStack::PopAndDestroy( iniStringKey );
+
+ if( KErrNone != err )
+ {
+ LOG_MSG2( " ERROR !* aPersistConfigData->AddValue() returned %d\n", err );
+ }
+ User::LeaveIfError( err );
+ }
+
+
+ // Save the Configuration Parameter Type
+ {
+ iniStringKey = GenerateKeyStringLC( aSaveIndex, EIniKeyType );
+
+ TInt keyType = aParam->Type();
+ TBuf<8> intTypeBuf;
+ LOG_MSG3( " -> KeyType%d = parameter type %d\n", aSaveIndex, keyType );
+ intTypeBuf.AppendNum( keyType );
+
+ err = aPersistConfigData->SetKey( aSectName, iniStringKey->Des(), intTypeBuf );
+
+ CleanupStack::PopAndDestroy( iniStringKey );
+ if( KErrNone != err )
+ {
+ LOG_MSG2( " ERROR !* aPersistConfigData->AddValue() returned %d\n", err );
+ }
+ User::LeaveIfError( err );
+ }
+ }
+
+
+
+_LIT( KPluginExtension, ".plugin" );
+#define KPluginUIDCharsPerLine 8
+
+
+_LIT( KCDSConfig, "CoreDumpServerConfiguration" );
+_LIT( KWriterConfig, "WriterConfiguration" );
+_LIT( KFormatterConfig, "FormatterConfiguration" );
+_LIT( KObservedConfig, "ObservedConfiguration" );
+
+_LIT( KDefaultIniFile, "coredumpserver.ini" );
+_LIT( KUID, "UID" );
+_LIT( KPluginPair, "Pair" );
+
+
+
+
+
+/**
+Method to parse the set of files that contain the UIDs of the allowed plugins.
+The files are read our private directory in all drives. Thus installed .plugin
+files are also checked.
+
+The plugin files must have the extension ".plugin". The content must be in
+ASCII-8. The format must be one UID per line, with no empty lines.
+The EOL can be CR+LF or just CR.
+*/
+void CCoreDumpSession::ReadPluginUidFilesL( )
+ {
+
+ RFs fsSession;
+ CleanupClosePushL( fsSession );
+ User::LeaveIfError( fsSession.Connect() );
+
+ //RProcess thisProc;
+
+ TDriveList driveList;
+ TVolumeInfo volInfo;
+
+ User::LeaveIfError( fsSession.DriveList( driveList ) );
+
+ HBufC* sessionPath = HBufC::NewLC( KMaxFileName );
+ TPtr privPath( sessionPath->Des() );
+
+ RBuf8 allowedPluginUidStr;
+ allowedPluginUidStr.CleanupClosePushL();
+ allowedPluginUidStr.CreateL( KPluginUIDCharsPerLine );
+
+ RFile pluginFile;
+ CleanupClosePushL( pluginFile );
+
+ for( TInt driveNumber = EDriveA; driveNumber <= EDriveZ; driveNumber++ )
+ {
+ if( ( !driveList[driveNumber] ) ||
+ ( KErrNone != fsSession.Volume( volInfo, driveNumber) ) ||
+ ( volInfo.iDrive.iType==EMediaNotPresent ) )
+ {
+ continue;
+ }
+
+ // Get a list of the files in the private directory of drive <driveNumber>
+
+ fsSession.SetSessionToPrivate( driveNumber );
+ User::LeaveIfError( fsSession.SessionPath( privPath ) );
+ CDir * fileList = NULL;
+
+ // KEntryAttNormal gets only files (not dirs, hidden or system files)
+ TInt ret = fsSession.GetDir( privPath, KEntryAttNormal, ESortByName, fileList );
+ if( ( KErrNone != ret ) || ( !fileList ) )
+ {
+ if( fileList )
+ delete fileList;
+ continue;
+ }
+
+ CleanupStack::PushL( fileList );
+
+ for( TInt i = 0; i < fileList->Count(); i++ )
+ {
+ TEntry fileEntry = (*fileList)[i];
+ TParse fileNameParser;
+ fileNameParser.Set( fileEntry.iName, NULL, NULL );
+ if( fileNameParser.Ext() != KPluginExtension )
+ {
+ continue;
+ }
+
+ /*
+ RBuf8 pluginFilePrint;
+ pluginFilePrint.CreateL( fileEntry.iName.Length() + 1 );
+ pluginFilePrint.Copy( fileEntry.iName );
+ char* cl = (char*) pluginFilePrint.PtrZ();
+ LOG_MSG2(" Reading .plugin file %s\n", cl );
+ */
+
+ // File extension is .plugin, so add the list of UIDs contained inside
+ // the file to our list of allowed plugins
+ //
+ ret = pluginFile.Open( fsSession, fileEntry.iName, EFileRead );
+ if( KErrNone != ret )
+ {
+ LOG_MSG(" Error openning file. Ignoring this file\n" );
+ continue;
+ }
+
+ while( KErrNone == ret )
+ {
+ // Read the UID characters on a line. Exactly 8 * 1 byte non-UNICODE chars per line
+ ret = pluginFile.Read( allowedPluginUidStr, KPluginUIDCharsPerLine );
+ if( ( KErrNone != ret ) || (allowedPluginUidStr.Length() != KPluginUIDCharsPerLine ) )
+ {
+ // Reached the end of file, so go to the next file
+ break;
+ }
+
+ TLex8 uidLex( allowedPluginUidStr );
+ TUint pluginUidValue = 0;
+ uidLex.Val( pluginUidValue, EHex );
+ TUid allowedUid = TUid::Uid( pluginUidValue );
+ iAllowedPlugins.AppendL( allowedUid );
+
+ // Now skip the end of line character/s CR 0x0D and possibly LF 0x0A
+ ret = pluginFile.Read( allowedPluginUidStr, 1 );
+ if( ( KErrNone == ret ) && (allowedPluginUidStr.Length() == 1) )
+ {
+ //Could have read the CR or LF
+ if( 0x0D == *(allowedPluginUidStr.Ptr()) )
+ {
+ // CR should be followed by LF, so read that too
+ ret = pluginFile.Read( allowedPluginUidStr, 1 );
+ }
+ }
+
+ if( allowedPluginUidStr.Length() == 0 )
+ {
+ ret = KErrEof;
+ }
+
+ } // while have read 8 bytes
+
+ pluginFile.Close();
+ } // for each file in file list
+
+ CleanupStack::PopAndDestroy( fileList );
+ }
+
+ CleanupStack::PopAndDestroy( &pluginFile );
+ CleanupStack::PopAndDestroy( &allowedPluginUidStr );
+ CleanupStack::PopAndDestroy( sessionPath );
+ CleanupStack::PopAndDestroy( &fsSession );
+
+ if( 0 == iAllowedPlugins.Count() )
+ {
+ LOG_MSG( " Warning : No plugins will be allowed\n" );
+ }
+ else
+ {
+ for( TInt i=0; i < iAllowedPlugins.Count(); i++ )
+ {
+ LOG_MSG2( " Plugin 0x%X allowed\n", iAllowedPlugins[i] );
+ }
+ }
+
+ }
+
+void CCoreDumpSession::ValidatePluginL( const TUid aPluginUid ) const
+ {
+
+ LOG_MSG2( "->CCoreDumpSession::ValidatePlugin(aPluginId=0x%X)\n", aPluginUid.iUid );
+
+ for( TInt i = 0; i < iAllowedPlugins.Count(); i++ )
+ {
+ if( iAllowedPlugins[i] == aPluginUid )
+ {
+ LOG_MSG( " Plugin Allowed\n" );
+ return;
+ }
+ }
+ LOG_MSG( " Plugin Not Allowed\n" );
+ User::Leave(KErrPermissionDenied);
+ }
+
+/**
+@pre aFsSession FileSystem session must have been connected to and still be active
+@post aFileName and aPersistConfigData pushed onto the stack
+*/
+void CCoreDumpSession::OpenIniFileLC( const RMessage2 * aMessage,
+ const TBool aSaving,
+ RFs & aFsSession,
+ HBufC *& aFileName,
+ CIniDocument16 *& aPersistConfigData )
+ {
+
+
+ LOG_MSG( "CCoreDumpSession::OpenIniFileLC(RMessage2)\n" );
+
+ TInt ret;
+
+ TInt iniFileDesLen = 0;
+
+ if( aMessage )
+ {
+ LOG_MSG( " RMessage2 != NULL\n" );
+ iniFileDesLen = aMessage->GetDesLength( 0 );
+ if( iniFileDesLen > 0 )
+ {
+ //LOG_MSG( " User supplied ini file name\n" );
+ aFileName = HBufC::NewL( iniFileDesLen );
+
+ //LOG_MSG( " CleanupStack::PushL( aFileName )\n" );
+ CleanupStack::PushL( aFileName );
+
+ TPtr ptr( aFileName->Des() );
+ aMessage->ReadL( 0, ptr );
+ if( !aSaving && !aFsSession.IsValidName( ptr ) )
+ {
+ // If we are loading and the file and path are incorrect
+ //LOG_MSG( " IsValidName() == EFalse\n" );
+ User::Leave( KErrPathNotFound );
+ }
+ }
+ }
+
+ if( 0 == iniFileDesLen )
+ {
+ aFsSession.SetSessionToPrivate( EDriveE );
+
+ RBuf privPath;
+ privPath.CleanupClosePushL();
+ privPath.CreateL( KMaxFileName );
+
+ aFsSession.SessionPath( privPath );
+
+ privPath.Append( KDefaultIniFile );
+ aFileName = HBufC::NewL( privPath.Length() );
+ *aFileName = privPath;// Copy name
+
+ CleanupStack::PopAndDestroy( &privPath );
+
+ CleanupStack::PushL( aFileName );
+
+ if( aSaving )
+ {
+ //LOG_MSG( " aFsSession.CreatePrivatePath( EDriveE )\n" );
+ ret = aFsSession.CreatePrivatePath( EDriveE );
+ if( ( KErrNone != ret ) && ( KErrAlreadyExists != ret ) )
+ {
+ LOG_MSG2( " aFsSession.CreatePrivatePath( EDriveE ) returned ERROR %d\n", ret );
+ User::Leave( ret );
+ }
+ }
+ }
+
+ if( aSaving )
+ {
+ // delete existing file since CIniDocument16::NewL expects a correctly formed
+ // file or no file at all. An empty file makes the NewL Leave
+ //
+ //LOG_MSG( " -> aFsSession.Delete( aFileName->Des() )\n");
+ aFsSession.Delete( aFileName->Des() );
+ }
+ else
+ {
+ TEntry entry;
+ User::LeaveIfError(aFsSession.Entry(aFileName->Des(), entry));
+ }
+ //LOG_MSG( " ->CIniDocument16::NewL( aFsSession, aFileName->Des() )\n");
+ TRAPD(err, aPersistConfigData = CIniDocument16::NewL( aFsSession, aFileName->Des() ));
+
+ if( KErrNone != err )
+ {
+ LOG_MSG2( " <- CIniDocument16::NewL( ) left with %d\n", err );
+ }
+
+ CleanupStack::PushL( aPersistConfigData );
+ }
+
+
+
+_LIT( KIniFileCommentTitle, "CoreDumpServerSettingsFile" );
+_LIT( KIniFileCommentSymbian, "Symbian_Software_Ltd" );
+_LIT( KIniFileCommentSymbianYear, "2007" );
+_LIT( KIniFileCommentVersionString, "Version" );
+_LIT( KIniFileCommentVersionNumber, "1.0.0" );
+
+
+/*
+* Client request to load system configuration file
+*/
+void CCoreDumpSession::SaveConfigFileL( const RMessage2* aMessage )
+ {
+
+ LOG_MSG( "CCoreDumpSession::SaveConfigFileL(RMessage2)\n");
+
+ RFs fsSession;
+ CleanupClosePushL( fsSession );
+ User::LeaveIfError( fsSession.Connect() );
+
+
+ HBufC * fileName = NULL;
+ CIniDocument16 * persistConfigData = NULL;
+
+ OpenIniFileLC( aMessage, ETrue, fsSession, fileName, persistConfigData );
+
+ // persistConfigData is on top of the stack, and under it is fileName
+
+ TInt ret;
+ TPtrC uidString;
+ uidString.Set( KUID );
+ TPtrC sectName;
+
+ sectName.Set( KIniFileCommentTitle );
+ ret = persistConfigData->AddSection( sectName );
+ User::LeaveIfError( ret );
+
+ ret = persistConfigData->SetKey( sectName, KIniFileCommentSymbian, KIniFileCommentSymbianYear );
+ User::LeaveIfError( ret );
+
+ ret = persistConfigData->SetKey( sectName, KIniFileCommentVersionString, KIniFileCommentVersionNumber );
+ User::LeaveIfError( ret );
+
+
+ sectName.Set( KCDSConfig );
+ //LOG_MSG( " persistConfigData->AddSection( KCDSConfig )\n" );
+ ret = persistConfigData->AddSection( sectName );
+ //LOG_MSG2( " AddSection( KCDSConfig ) returned %d", ret );
+ User::LeaveIfError( ret );
+
+ RBuf cdsUidNumberString;
+ cdsUidNumberString.CleanupClosePushL();
+ cdsUidNumberString.CreateL( 8 );
+ cdsUidNumberString.AppendNumFixedWidth( (TUint)iOurSecureID.iUid, EHex, 8 ); // Width = 8 chars
+
+ //LOG_MSG( " persistConfigData->SetKey( KCDSConfig, uidString, cdsUidNumberString )\n" );
+ ret = persistConfigData->SetKey( sectName, uidString, cdsUidNumberString );
+ User::LeaveIfError( ret );
+
+ for( TInt i = 0; i < iConfigList.Count(); i++ )
+ {
+ SaveConfigParamL( iConfigList[i], sectName, i, persistConfigData );
+ }
+ CleanupStack::PopAndDestroy(&cdsUidNumberString);
+
+ if( iObservationList.Count() > 0 )
+ {
+
+ //LOG_MSG( " Saving Observed section\n");
+
+ // There is no point in saving the id of a thread since the id is not predictable
+ // and could be used in another boot session. Thus only save the names
+ // EIniKeyValue holds Target Name EIniKeyType holds TargetOwnerName
+ // Thus a process will have both the same, so we can differentiate them
+ HBufC * iniStringTargetValue;
+ HBufC * iniStringOwnerType;
+
+ TPtrC observationSection;
+ observationSection.Set( KObservedConfig );
+ //LOG_MSG( " persistConfigData->AddSection( KObservedConfig )\n" );
+ ret = persistConfigData->AddSection( observationSection );
+ User::LeaveIfError( ret );
+
+ TInt observeKey = 0;
+
+ for( TInt i = 0; i < iObservationList.Count(); i ++ )
+ {
+ CTargetObserver *observer = iObservationList[i];
+ TInt count = observer->ThreadCount();
+ TInt j = 0;
+ do
+ {
+ // Key string for target name
+ iniStringTargetValue = GenerateKeyStringLC( observeKey, EIniKeyValue );
+ TPtrC targetName;
+ if(count == 0) //whole process, no threads on list => targetName == targetOwnerName
+ {
+ targetName.Set(observer->TargetName());
+ }
+ else
+ {
+ targetName.Set(observer->Thread(j));
+ }
+
+ //LOG_MSG2( " iPersistConfigData->SetKey( KObservedConfig, target.Length()=%d )\n", targetName.Length() );
+ ret = persistConfigData->SetKey( observationSection,
+ iniStringTargetValue->Des(),
+ targetName );
+
+ CleanupStack::PopAndDestroy( iniStringTargetValue );
+ if( KErrNone != ret )
+ {
+ LOG_MSG2( " ERROR !* iPersistConfigData->AddValue() for observed target returned %d\n", ret );
+ User::Leave( ret );
+ }
+
+ // Key string for target owner name
+ iniStringOwnerType = GenerateKeyStringLC( observeKey, EIniKeyType );
+ TPtrC targetOwnerName( observer->TargetName() );
+
+ LOG_MSG2( " iPersistConfigData->SetKey( KObservedConfig, targetOwner.Length()=%d )\n", targetOwnerName.Length() );
+ ret = persistConfigData->SetKey( observationSection,
+ iniStringOwnerType->Des(),
+ targetOwnerName );
+
+ CleanupStack::PopAndDestroy( iniStringOwnerType );
+ if( KErrNone != ret )
+ {
+ LOG_MSG2( " ERROR !* iPersistConfigData->AddValue() for observed target owner returned %d\n", ret );
+ User::Leave( ret );
+ }
+
+ j++;
+ observeKey ++;
+
+ } while(j < count);
+
+ } //for(i)
+ }
+
+ TBuf<63> sectionName;
+
+
+ for(TInt i = 0; i < iFormatterPlugins.Count(); i++)
+ {
+ sectionName = KFormatterConfig;
+ sectionName.AppendFormat(_L("%d"), i);
+
+ ret = persistConfigData->AddSection( sectionName );
+ User::LeaveIfError(ret);
+
+
+ // Add a key "UID" with a value equal to the UID of the writer, so we can load it again
+ RBuf uidNumberString;
+ uidNumberString.CleanupClosePushL();
+ uidNumberString.CreateL( 8 );
+ uidNumberString.AppendNumFixedWidth( (TUint)iFormatterInfos[i]->Uid(), EHex, 8 ); // Width = 8 chars
+ ret = persistConfigData->SetKey( sectionName, uidString, uidNumberString );
+ User::LeaveIfError( ret );
+ CleanupStack::PopAndDestroy(&uidNumberString);
+
+ TPtrC pairString;
+ pairString.Set( KPluginPair );
+
+ //Add pair key with value equal to the paired writer plugin
+ RBuf pairNumberString;
+ pairNumberString.CleanupClosePushL();
+ pairNumberString.CreateL( 8 );
+ pairNumberString.AppendNumFixedWidth( (TUint)iFormatterInfos[i]->Pair(), EHex, 8 ); // Width = 8 chars
+ ret = persistConfigData->SetKey( sectionName, pairString, pairNumberString );
+ User::LeaveIfError( ret );
+ CleanupStack::PopAndDestroy(&pairNumberString);
+
+ for( TInt j = 0; j < iTotalConfigList.Count(); j++ )
+ {
+ if( iTotalConfigList[j] && (COptionConfig::EFormatterPlugin == iTotalConfigList[j]->Source()) && (i == iTotalConfigList[j]->Instance()))
+ {
+ SaveConfigParamL( iTotalConfigList[j], sectionName, iTotalConfigList[j]->Index(), persistConfigData );
+ }
+ }
+ }
+
+ for(TInt i = 0; i < iWriterPlugins.Count(); i++)
+ {
+ sectionName = KWriterConfig;
+ sectionName.AppendFormat(_L("%d"), i);
+
+ ret = persistConfigData->AddSection( sectionName );
+ User::LeaveIfError(ret);
+
+ // Add a key "UID" with a value equal to the UID of the writer, so we can load it again
+ RBuf uidNumberString;
+ uidNumberString.CleanupClosePushL();
+ uidNumberString.CreateL( 8 );
+ uidNumberString.AppendNumFixedWidth( (TUint)iWriterInfos[i]->Uid(), EHex, 8 ); // Width = 8 chars
+ ret = persistConfigData->SetKey( sectionName, uidString, uidNumberString );
+ User::LeaveIfError( ret );
+ CleanupStack::PopAndDestroy(&uidNumberString);
+
+ for( TInt j = 0; j < iTotalConfigList.Count(); j++ )
+ {
+ if( iTotalConfigList[j] && (COptionConfig::EWriterPlugin == iTotalConfigList[j]->Source()) && (i == iTotalConfigList[j]->Instance()))
+ {
+ SaveConfigParamL( iTotalConfigList[j], sectionName, iTotalConfigList[j]->Index(), persistConfigData );
+ }
+ }
+ }
+
+ if( NULL == persistConfigData )
+ {
+ LOG_MSG( " persistConfigData == NULL\n" );
+ }
+
+ // Now save the config to file
+ ret = persistConfigData->Externalise( fileName->Des() );
+ //LOG_MSG2( " <- iPersistConfigData->Externalise() returned %d\n", ret );
+
+ //LOG_MSG( " CleanupStack::PopAndDestroy( iPersistConfigData )" );
+ CleanupStack::PopAndDestroy( persistConfigData );
+
+ //LOG_MSG( " CleanupStack::PopAndDestroy( fileName )" );
+ CleanupStack::PopAndDestroy( fileName );
+
+ //LOG_MSG( " ->CleanupStack::PopAndDestroy( fsSession )" );
+ CleanupStack::PopAndDestroy( & fsSession );
+ //LOG_MSG( " <-CleanupStack::PopAndDestroy( fsSession )" );
+
+ }
+
+/*
+* Client request to load system configuration file
+*/
+void CCoreDumpSession::LoadConfigFileL( const RMessage2* aMessage )
+ {
+
+
+ LOG_MSG( "CCoreDumpSession::LoadConfigFileL(RMessage2)" );
+
+ RFs fsSession;
+ //LOG_MSG( " User::LeaveIfError( fsSession.Connect() )\n" );
+ User::LeaveIfError( fsSession.Connect() );
+ CleanupClosePushL( fsSession );
+
+ TPtrC16 value;
+
+ HBufC * fileName = NULL;
+ CIniDocument16 * persistConfigData = NULL;
+
+ //LOG_MSG( " -> CIniDocument16 * iPersistConfigData = OpenIniFileLC()" );
+ OpenIniFileLC( aMessage, EFalse, fsSession, fileName, persistConfigData );
+
+ //LOG_MSG( " -> RecreateConfigurationL( iPersistConfigData )\n" );
+ RecreateConfigurationL( persistConfigData );
+
+ //LOG_MSG( " -> CleanupStack::PopAndDestroy( iPersistConfigData )" );
+ CleanupStack::PopAndDestroy( persistConfigData );
+ //LOG_MSG( " -> CleanupStack::PopAndDestroy( fileName )" );
+ CleanupStack::PopAndDestroy( fileName );
+ //LOG_MSG( " -> CleanupStack::PopAndDestroy( & fsSession )" );
+ CleanupStack::PopAndDestroy( & fsSession );
+ //LOG_MSG( " returning from CCoreDumpSession::LoadConfigFileL(RMessage2)" );
+ }
+
+
+/**
+Method used to load and unload the formatter and writer plugins as a pair.
+Also configures the data source and data save for the formatter.
+If unloading the UIDs are still checked.
+*/
+void CCoreDumpSession::SetPluginsL( const TUid aFormatterUID,
+ const TUid aWriterUID,
+ const TBool aLoad )
+ {
+ ValidatePluginL( aFormatterUID );
+
+ ValidatePluginL( aWriterUID );
+
+ /*
+ if( iFormatter )
+ {
+ delete iFormatter;
+ iFormatterUid = TUid::Uid(0);
+ }
+
+ if( iWriter )
+ {
+ delete iWriter;
+ iWriterUid = TUid::Uid(0);
+ }
+
+ if( !aLoad )
+ {
+ return;
+ }
+
+ // We push the plugins onto the cleanup stack since if we leave here we
+ // want them destroyed so that there is always a valid pair or none are loaded
+ iWriter = CCrashDataSave::NewL( aWriterUID );
+ CleanupStack::PushL( iWriter );
+
+ iFormatter = CCoreDumpFormatter::NewL( aFormatterUID );
+ CleanupStack::PushL( iFormatter );
+
+ iFormatter->ConfigureDataSourceL( iDataSource );
+ iFormatter->ConfigureDataSaveL( iWriter );
+
+ iFormatterUid = aFormatterUID;
+ iWriterUid = aWriterUID;
+
+ // We can pop the plugins
+ CleanupStack::Pop( 2, iWriter );
+
+ */
+ }
+
+
+
+/**
+Look through the iPersistConfigData object (initialised from the ini file)
+and attempt to recreate the state described by the object.
+This means
+ - unloading current plugins,
+ - loading new plugins,
+ - updating the configuration list by calling UpdateConfigParametersL()
+ - recreating the configuration for section (CDS, formatter, writer )
+
+We have to be lax about the errors since we do not want to stop the
+loading of a configuration if there is a non-fatal error. This applies to
+loading of the plugins.
+*/
+void CCoreDumpSession::RecreateConfigurationL( CIniDocument16 * iPersistConfigData )
+ {
+
+ // for each section in ini file,
+ // read section's SID
+ // load plugins
+ // for each (type, index, value) triplet,
+ // create a COptionConfig
+ // append to aIniFileConfigList
+ //
+
+
+ TInt ret;
+ TBool foundCdsSection = EFalse;
+ TBool foundFormatterSection = EFalse;
+ TBool foundWriterSection = EFalse;
+
+ TPtrC uidString;
+ uidString.Set( KUID );
+
+ // Recreate CDS section
+ {
+ TPtrC cdsUidString;
+ //LOG_MSG(" iPersistConfigData->GetKeyValue( KCDSConfig, uidString, cdsUidString )\n" );
+ ret = iPersistConfigData->GetKeyValue( KCDSConfig, uidString, cdsUidString );
+ //LOG_MSG2(" iPersistConfigData->GetKeyValue( ) returned %d\n", ret );
+
+ if( KErrNone == ret )
+ {
+ foundCdsSection = ETrue;
+ }
+ else
+ {
+ // It an error for there to be no saved CDS configuration
+ User::Leave( ret );
+ }
+
+ if( foundCdsSection )
+ {
+ TLex cdsUidLex( cdsUidString );
+ TUint cdsUidValue;
+ cdsUidLex.Val( cdsUidValue, EHex );
+ TUid savedCdsUid = TUid::Uid( cdsUidValue );
+ //LOG_MSG2(" Found CDS Config Section with UID 0x%X\n", cdsUidValue );
+ //LOG_MSG2(" Current UID is 0x%X\n", iOurSecureID.iUid );
+ if( savedCdsUid != iOurSecureID )
+ {
+ // The UID for the CDS does not match our current CDS SID.
+ // This could arise if the config file was created by a previous version
+ // of the CDS, but more likely we are reading a corrupt file.
+ // Thus the safe option is to leave
+ LOG_MSG2( " ERROR !* Read CDS UID from ini file as 0x%X, which is not same as our current value\n",
+ cdsUidValue );
+ User::Leave( KErrCorrupt );
+ }
+ }//foundCdsSection
+ }
+
+ TBuf<63> sectionName;
+
+
+ foundWriterSection = -1;
+ for(TInt i = 0;;i++)
+ {
+ sectionName = KWriterConfig;
+ sectionName.AppendFormat(_L("%d"), i);
+
+ TPtrC writerUidString;
+ ret = iPersistConfigData->GetKeyValue( sectionName, uidString, writerUidString );
+
+ TUint writerUidValue;
+ if( KErrNone == ret )
+ {
+ foundWriterSection++;
+ TLex writerUidLex( writerUidString );
+ writerUidLex.Val( writerUidValue, EHex );
+ CreateWriterL( TUid::Uid( writerUidValue ) );
+ }
+ else
+ {
+ break;
+ }
+
+ }
+
+
+ foundFormatterSection = -1;
+ for(TInt i = 0;;i++)
+ {
+ sectionName = KFormatterConfig;
+ sectionName.AppendFormat(_L("%d"), i);
+
+ TPtrC formatterUidString;
+ ret = iPersistConfigData->GetKeyValue( sectionName, uidString, formatterUidString );
+
+ TUint formatterUidValue;
+ if( KErrNone == ret )
+ {
+ foundFormatterSection++;
+ TLex fromatterUidLex( formatterUidString );
+ fromatterUidLex.Val( formatterUidValue, EHex );
+ CreateFormatterL( TUid::Uid( formatterUidValue ) );
+
+ TPtrC pairString;
+ pairString.Set( KPluginPair );
+ TPtrC formatterPairString;
+ ret = iPersistConfigData->GetKeyValue(sectionName, pairString, formatterPairString);
+ if(ret == KErrNone)
+ {
+ TLex fromatterPairLex( formatterPairString );
+ TUint formatterPairValue;
+ fromatterPairLex.Val( formatterPairValue, EHex );
+ BindPluginsL(i, formatterPairValue);
+ }
+ }
+ else
+ {
+ break;
+ }
+
+ }
+
+
+ // Now that the old plugins are unloaded (if a new one was specified in the ini file),
+ // and the new ones loaded, reconstruct the list of configuration parameters.
+ // We will then change them with the ini file values that we are about to read.
+ // For plugins that have not been unloaded (because there was no mention in the init file)
+ // we will simply ask for the config params again, and we should get the current values.
+
+ UpdateConfigParametersL();
+
+ if( foundCdsSection )
+ {
+ //LOG_MSG( " -> ChangeConfigParamsL( COptionConfig::ECoreDumpServer\n" );
+ ChangeConfigParamsL( COptionConfig::ECoreDumpServer, iPersistConfigData );
+ }
+
+ for(TInt i = 0; i <= foundFormatterSection; i++)
+ {
+ //LOG_MSG( " -> ChangeConfigParamsL( COptionConfig::EFormatterPlugin\n" );
+ ChangeConfigParamsL( COptionConfig::EFormatterPlugin, iPersistConfigData, foundFormatterSection );
+ }
+
+ for(TInt i = 0; i <= foundWriterSection; i++)
+ {
+ //LOG_MSG( " -> ChangeConfigParamsL( COptionConfig::EWriterPlugin\n" );
+ ChangeConfigParamsL( COptionConfig::EWriterPlugin, iPersistConfigData, foundWriterSection );
+ }
+
+ // Now rebuild the Observed list from the file
+ {
+
+ //LOG_MSG( " About to Rebuild Observed Target List from Ini File\n" );
+
+ HBufC * iniTargetValue;
+ HBufC * iniOwnerType;
+ TInt observeIndex = 0;
+ TBool targetFound = ETrue;
+ while( targetFound )
+ {
+
+ // Each value obtained via EIniKeyIndex from the file is the CConfigOption index
+ // and is used to tie the saved to the live index.
+
+ //LOG_MSG2(" GenerateKeyStringLC( EIniKeyValue =%d)\n", observeIndex );
+ iniTargetValue = GenerateKeyStringLC( observeIndex, EIniKeyValue );
+
+ TPtrC observeTargetValue;
+
+ //LOG_MSG(" iPersistConfigData->GetKeyValue( KObservedConfig, targetName )\n" );
+ ret = iPersistConfigData->GetKeyValue( KObservedConfig,
+ iniTargetValue->Des(),
+ observeTargetValue );
+ //LOG_MSG2(" iPersistConfigData->GetKeyValue( ) returned %d\n", ret );
+
+ CleanupStack::PopAndDestroy( iniTargetValue );
+
+ if( KErrNone != ret )
+ {
+ LOG_MSG2( " Could not find a target : FindVar(EIniKeyValue) index %d returned false\n",
+ observeIndex );
+ break;
+ }
+
+ //LOG_MSG2(" GenerateKeyStringLC( EIniKeyType =%d)\n", observeIndex );
+ iniOwnerType = GenerateKeyStringLC( observeIndex, EIniKeyType );
+
+ TPtrC observeTargetOwner;
+
+ /*
+ LOG_MSG3( " ->FindVar( KObservedConfig, target owner %d. iniOwnerType.Length()=%d\n",
+ observeIndex, iniOwnerType->Des().Length() );
+ */
+
+ ret = iPersistConfigData->GetKeyValue( KObservedConfig,
+ iniOwnerType->Des(),
+ observeTargetOwner );
+ //LOG_MSG2(" iPersistConfigData->GetKeyValue( ) returned %d\n", ret );
+
+ CleanupStack::PopAndDestroy( iniOwnerType );
+
+ if( KErrNone != ret )
+ {
+ LOG_MSG2( " Could not find a target owner: FindVar(EIniKeyValue) index %d returned false\n",
+ observeIndex );
+ break;
+ }
+
+ //LOG_MSG(" Creating observation request\n" );
+
+ AttachTargetL(observeTargetValue, observeTargetOwner);
+
+ observeIndex++;
+
+ }// while targetFound
+
+ } // Now rebuild the Observed list from the file
+
+ //LOG_MSG( " <- returning from RecreateConfigurationL()\n" );
+
+ }
+
+
+/**
+Method that reads the saved configuration and attempts to recreate that state.
+For a given section of the ini file (indicated by the parameter aSource),
+recreate each parameter from a triplet of settings (index, type, value)
+and then apply the setting by calling SetConfigParameterL().
+
+@param aSource Section of the config file to read and update state for.
+@param aPersistConfigData Pointer to CIniDocument16 object that contains
+the parameters to restore
+
+@see CIniDocument16
+*/
+void CCoreDumpSession::ChangeConfigParamsL( const COptionConfig::TParameterSource aSource,
+ CIniDocument16 * aPersistConfigData, const TInt aInstance)
+ {
+
+ //LOG_MSG2( "ChangeConfigParamsL( source=%d )\n", aSource );
+
+ TPtrC sectName;
+ TInt ret = KErrNone;
+
+ switch( aSource )
+ {
+ case COptionConfig::ECoreDumpServer:
+ sectName.Set( KCDSConfig );
+ break;
+ case COptionConfig::EFormatterPlugin:
+ sectName.Set( KFormatterConfig );
+ break;
+ case COptionConfig::EWriterPlugin:
+ sectName.Set( KWriterConfig );
+ break;
+ default:
+ User::Leave( KErrArgument );
+ }
+
+
+ HBufC * iniStringKey;
+ TUint index = 0;
+
+ // Loop to recreate all the parameters for a given section and then
+ // call SetConfigParameterL() for each parameter
+ // As soon as one of the FindVar fails, we assume that there are no more entries for
+ // this section, and thus give up.
+
+ // Parameter index
+ TInt keyIndex;
+
+ // Parameter type
+ TInt keyType;
+
+ // Parameter integer value
+ TInt keyIntValue;
+
+ TLex paramLex;
+
+ while( KErrNone == ret )
+ {
+
+ keyIndex = ELastParam;
+ keyType = -1;
+ keyIntValue = 0;
+ TPtrC keyStringValue;
+
+ // Get parameter index
+ {
+ // Each value obtained via EIniKeyIndex from the file is the CConfigOption index
+ // and is used to tie the saved to the live index.
+ //LOG_MSG2(" ->GenerateKeyStringLC( index=%d, EIniKeyIndex )\n", index );
+ iniStringKey = GenerateKeyStringLC( index, EIniKeyIndex );
+ TPtrC keyIndexString;
+
+ //LOG_MSG(" ->aPersistConfigData->GetKeyValue( EIniKeyIndex )\n" );
+ ret = aPersistConfigData->GetKeyValue( sectName, iniStringKey->Des(), keyIndexString );
+ CleanupStack::PopAndDestroy( iniStringKey );
+ if( KErrNone != ret )
+ {
+ LOG_MSG3(" aPersistConfigData->GetKeyValue( EIniKeyIndex ) returned %d for index %d\n", ret, index );
+ break;
+ }
+
+ paramLex.Assign( keyIndexString );
+ keyIndex = 0;
+ paramLex.Val( keyIndex );
+ //LOG_MSG2( " found EIniKeyIndex =%d\n", keyIndex );
+ }
+
+
+ // Get parameter type
+ {
+
+ //LOG_MSG2(" ->GenerateKeyStringLC( index=%d, EIniKeyType )\n", index );
+ iniStringKey = GenerateKeyStringLC( index, EIniKeyType );
+ TPtrC keyTypeString;
+
+ //LOG_MSG(" ->aPersistConfigData->GetKeyValue( EIniKeyType )\n" );
+ ret = aPersistConfigData->GetKeyValue( sectName, iniStringKey->Des(), keyTypeString );
+ CleanupStack::PopAndDestroy( iniStringKey );
+ if( KErrNone != ret )
+ {
+ LOG_MSG3(" aPersistConfigData->GetKeyValue( EIniKeyType ) returned %d for index %d\n", ret, index );
+ break;
+ }
+
+ paramLex.Assign( keyTypeString );
+ paramLex.Val( keyType );
+ //LOG_MSG2( " found EIniKeyType =%d\n", keyType );
+ }
+
+ // Get parameter value
+ {
+
+ //LOG_MSG2(" ->GenerateKeyStringLC( index=%d, EIniKeyValue )\n", index );
+ iniStringKey = GenerateKeyStringLC( index, EIniKeyValue );
+
+ //LOG_MSG( " aPersistConfigData->GetKeyValue( EIniKeyValue )\n" );
+ ret = aPersistConfigData->GetKeyValue( sectName, iniStringKey->Des(), keyStringValue );
+
+ //LOG_MSG2( " aPersistConfigData->GetKeyValue( EIniKeyValue ) returned string with length=%d\n", keyStringValue.Length() );
+ CleanupStack::PopAndDestroy( iniStringKey );
+ if( KErrNone != ret )
+ {
+ LOG_MSG3(" aPersistConfigData->GetKeyValue( EIniKeyValue ) returned %d for index %d\n", ret, index );
+ break;
+ }
+
+ switch( (COptionConfig::TOptionType) keyType )
+ {
+ case COptionConfig::ETInt:
+ case COptionConfig::ETUInt:
+ case COptionConfig::ETBool:
+ paramLex.Assign( keyStringValue );
+ paramLex.Val( keyIntValue );
+ keyStringValue.Set( KNullDesC );
+ break;
+ }
+ }
+
+
+ /*
+ {
+ if( -1 != keyIntValue )
+ {
+ LOG_MSG2( " found EIniKeyValue as Int =%d\n", keyIntValue );
+ }
+
+ RBuf value;
+ value.Create( keyStringValue );
+ char* cl = (char*) value.Collapse().PtrZ();
+ RDebug::Printf(" found EIniKeyValue as String =%s\n", cl );
+ }
+ */
+
+ LOG_MSG3( " SetConfigParameterL( value=%d, string length=%d\n", keyIntValue, keyStringValue.Length() );
+
+ switch( aSource )
+ {
+
+ case COptionConfig::ECoreDumpServer:
+ SetConfigParameterL( keyIndex, keyIntValue, keyStringValue );
+ break;
+
+ case COptionConfig::EFormatterPlugin:
+
+ if( (iFormatterPlugins.Count() > 0 ) && (iFormatterPlugins.Count() < aInstance) )
+ {
+ iFormatterPlugins[aInstance]->SetConfigParameterL( keyIndex, keyIntValue, keyStringValue );
+ }
+ else
+ {
+ LOG_MSG2("CCoreDumpSession::ChangeConfigParamsL() : formatter:%d not loaded\n", aInstance);
+ User::Leave( KErrArgument );
+ }
+ break;
+
+ case COptionConfig::EWriterPlugin:
+
+ if( (iWriterPlugins.Count() > 0 ) && (iWriterPlugins.Count() < aInstance) )
+ {
+ iWriterPlugins[aInstance]->SetConfigParameterL( keyIndex, keyIntValue, keyStringValue );
+ }
+ else
+ {
+ LOG_MSG2("CCoreDumpSession::ChangeConfigParamsL() : writer:%d not loaded\n", aInstance);
+ User::Leave( KErrArgument );
+ }
+ break;
+
+ default:
+ User::Leave( KErrArgument );
+ }
+
+ index ++;
+ }//while
+ }
+
+
+_LIT(KKey,"Key");
+_LIT(KType,"Type");
+_LIT(KIndex,"Index");
+_LIT(KValue,"Value");
+
+/**
+This method allocates a string of two concatenated components. The first component is based on
+the parameter aKey. The second component is the string representation of aIndex.
+Thus it maps an enum to a string and then it appends the index. The string is left on the
+cleanup stack and it is the responsibility of the caller to remove it from the cleanup stack.
+*/
+HBufC * CCoreDumpSession::GenerateKeyStringLC( TUint aIndex,
+ CCoreDumpSession::TCoreDumpIniKey aKey )
+ {
+
+ HBufC * keyString = HBufC::NewL( 20 );
+ CleanupStack::PushL( keyString );
+
+ TPtr ptr = keyString->Des();
+ ptr.Append( KKey );
+
+ switch( aKey )
+ {
+ case EIniKeyType:
+ ptr.Append( KType );
+ break;
+
+ case EIniKeyIndex:
+ ptr.Append( KIndex );
+ break;
+
+ case EIniKeyValue:
+ ptr.Append( KValue );
+ break;
+ }
+
+ ptr.AppendNum( aIndex );
+ return keyString;
+ }
+
+void CCoreDumpSession::SuspendProcessL(TUint64 aPid)
+ {
+ LOG_MSG("->CCoreDumpSession::SuspendProcessL()\n");
+ iDataSource->GetThreadListL( aPid, iThreadPointerList, iTotalThreadListDescSize );
+ TInt err = KErrNone;
+ for(TInt i = 0; i < iThreadPointerList.Count(); i++)
+ {
+ LOG_MSG2("CCoreDumpSession::SuspenProcessL - suspending thread:%Ld\n", iThreadPointerList[i]->Id());
+ err = iSecSess.SuspendThread(iThreadPointerList[i]->Id());
+ if( (err != KErrNone) && (err != KErrAlreadyExists) )
+ {
+ LOG_MSG2("CCoreDumpSession::SuspendProcessL - unable to suspend thread! err:%d\n", err);
+ User::LeaveIfError(err);
+ }
+ }
+ }
+
+void CCoreDumpSession::ResumeThreadL(TUint64 aTid)
+{
+ LOG_MSG2("->CCoreDumpSession::ResumeThreadL(aTid=%Ld)\n", aTid);
+
+ TInt err = iSecSess.ResumeThread(TThreadId(aTid));
+ if(err != KErrNone)
+ {
+ LOG_MSG2("CCoreDumpSession::ResumeThreadL - unable to resume thread! err:%d\n", err);
+ User::LeaveIfError(err);
+ }
+}
+
+/**
+Called to resume all the threads of the specified process. CCoreCrashHandler executes it as a post-processing action.
+@param aPid ID of process to be resumed
+@leave err one of the system wide error codes
+@see SuspendProcessL
+*/
+void CCoreDumpSession::ResumeProcessL(TUint64 aPid)
+ {
+ LOG_MSG2("->CCoreDumpSession::ResumeProcessL(aPid=%Ld)\n", aPid);
+
+ iDataSource->GetThreadListL( aPid, iThreadPointerList, iTotalThreadListDescSize );
+
+ TInt err = KErrNone;
+ //first resume child threads
+ TInt looperr = KErrNone;
+ for(TInt j = 1; j < iThreadPointerList.Count(); j++)
+ {
+ LOG_MSG2("CCoreDumpSession::ResumeProcessL - resuming thread:%Ld\n", iThreadPointerList[j]->Id());
+ looperr = iSecSess.ResumeThread( iThreadPointerList[j]->Id() );
+ if( (looperr != KErrNone) && (looperr != KErrNotFound) )
+ {
+ err = looperr;
+ LOG_MSG2("CCoreDumpSession::ResumeProcessL - unable to resume thread! err:%d\n", err);
+ }
+ }
+
+ looperr = KErrNone;
+ //then resume the main thread
+ if(iThreadPointerList.Count())
+ {
+ LOG_MSG2("CCoreDumpSession::ResumeProcessL - resuming main thread:%Ld\n", iThreadPointerList[0]->Id());
+ looperr = iSecSess.ResumeThread(iThreadPointerList[0]->Id());
+ }
+
+ if( (looperr != KErrNone) && (looperr != KErrNotFound) )
+ {
+ err = looperr;
+ LOG_MSG2("CCoreDumpSession::ResumeProcessL - unable to resume main thread! err:%d\n", err);
+ }
+
+ User::LeaveIfError(err);
+ }
+
+
+void CCoreDumpSession::KillProcessL(TUint64 aPid)
+ {
+ LOG_MSG2("->CCoreDumpSession::KillProcessL(aPid=%Ld)\n", aPid);
+ RProcess target;
+ //LOG_MSG("CCoreDumpSession::KillProcessL - opening crashed process handle\n");
+ TInt err = target.Open(aPid);
+ if(err != KErrNone)
+ {
+ LOG_MSG2("CCoreDumpSession::KillProcessL - unable to open process handle! err:%d\n", err);
+ User::Leave(err);
+ }
+
+ CleanupClosePushL(target);
+
+ TInt i;
+ for(i = 0; i < iObservationList.Count(); i++)
+ {
+ if(iObservationList[i]->TargetName().CompareF(target.FileName()) == 0) break;
+ }
+
+ ResumeProcessL(aPid);
+
+ if(i == iObservationList.Count())
+ {
+ LOG_MSG("CCoreDumpSession::KillProcessL - unable to find process observer!\n");
+ User::Leave(KErrNotFound);
+ }
+
+ LOG_MSG(" -> SetCrashEventsL(*iObservationList[i], EActionIgnore)\n" );
+ SetCrashEventsL(*iObservationList[i], EActionIgnore);
+
+ LOG_MSG(" -> target.Terminate(KErrAbort)\n" );
+ target.Terminate(KErrAbort);
+
+ TRequestStatus logonStatus;
+ LOG_MSG(" -> target.Logon( logonStatus );\n" );
+ target.Logon( logonStatus );
+ LOG_MSG(" <- target.Logon( logonStatus );\n" );
+
+ CleanupStack::PopAndDestroy(&target); //target
+
+ User::WaitForRequest( logonStatus );
+ LOG_MSG(" <- User::WaitForRequest( logonStatus );\n" );
+
+
+ if( (iPreCrashEventAction & ESuspendThread) ||
+ (iPreCrashEventAction & ESuspendProcess) )
+ SetCrashEventsL(*iObservationList[i], EActionSuspend);
+ else
+ SetCrashEventsL(*iObservationList[i], EActionContinue);
+ }
+
+/**
+ * Cleanup item implementation for SCMConfiguration
+*/
+void CCoreDumpSession::CleanupSCMConfiguration(TAny* aScmConfig)
+ {
+ SCMConfiguration* config = static_cast<SCMConfiguration*> (aScmConfig);
+ delete config;
+ config = NULL;
+ }
+
+
+//void CCoreDumpSession::ReadSCMConfigListL()
+// {
+// // read the config data from the flash data source
+// }
+//
+//void CCoreDumpSession::WriteSCMConfigListL()
+// {
+// // read the config data from the flash data source
+// iFlashDataSource->WriteSCMConfigL();
+// }
+//
+