Sandboxie/SandboxiePlus/SandMan/Views/TraceView.cpp

826 lines
25 KiB
C++
Raw Normal View History

2021-10-15 16:39:43 +01:00
#include "stdafx.h"
#include "TraceView.h"
#include "..\SandMan.h"
2023-07-01 17:54:53 +01:00
#include "..\AddonManager.h"
2021-10-15 16:39:43 +01:00
#include "../QSbieAPI/SbieAPI.h"
#include "..\Models\TraceModel.h"
#include "..\..\MiscHelpers\Common\Common.h"
2021-10-30 08:46:49 +01:00
#include "..\..\MiscHelpers\Common\CheckList.h"
2021-10-15 16:39:43 +01:00
#include "SbieView.h"
2023-07-01 17:54:53 +01:00
#include <QtConcurrent>
2021-10-15 16:39:43 +01:00
//class CTraceFilterProxyModel : public CSortFilterProxyModel
//{
//public:
2022-12-07 16:32:40 +00:00
// CTraceFilterProxyModel(QObject* parent = 0) : CSortFilterProxyModel(parent)
2021-10-15 16:39:43 +01:00
// {
// m_FilterPid = 0;
// m_FilterTid = 0;
// }
//
// bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
// {
// CTraceModel* pTraceModel = (CTraceModel*)sourceModel();
//
// QModelIndex index = pTraceModel->index(source_row, 0, source_parent);
// //CTraceEntryPtr pEntry = pTraceModel->GetEntry(index);
// //if (pEntry.data() == NULL)
// {
// QVariant Id = pTraceModel->GetItemID(index);
// StrPair typeId = Split2(Id.toString(), "_");
//
// if (m_FilterPid != 0 && typeId.first == "pid") {
// if (m_FilterPid != typeId.second.toUInt())
// return false;
// }
//
// if (m_FilterTid != 0 && typeId.first == "tid") {
// if (m_FilterTid != typeId.second.toUInt())
// return false;
// }
// }
//
// return CSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
// }
//
// quint32 m_FilterPid;
// quint32 m_FilterTid;
//};
2022-03-26 09:09:24 +00:00
////////////////////////////////////////////////////////////////////////////////////////
// CTraceTree
CTraceTree::CTraceTree(QWidget* parent)
2023-05-27 08:03:42 +01:00
: CPanelView(parent)
2022-03-26 09:09:24 +00:00
{
2023-05-27 08:03:42 +01:00
m_pMainLayout = new QVBoxLayout();
m_pMainLayout->setContentsMargins(0,0,0,0);
this->setLayout(m_pMainLayout);
m_pSplitter = new QSplitter();
m_pSplitter->setOrientation(Qt::Horizontal);
m_pMainLayout->addWidget(m_pSplitter);
m_pTreeList = new QTreeViewEx();
m_pTreeList->setColumnFixed(0, true);
m_pTreeList->setColumnFixed(1, true);
m_pTreeList->setColumnFixed(2, true);
m_pTreeList->setColumnFixed(3, true);
m_pTreeList->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_pTreeList, SIGNAL(customContextMenuRequested( const QPoint& )), this, SLOT(OnMenu(const QPoint &)));
//m_pSplitter->addWidget(m_pTreeList);
m_pTreeList->setMinimumHeight(50);
AddPanelItemsToMenu();
2023-01-12 22:10:50 +00:00
m_bHighLight = false;
//m_FilterCol = -1;
2022-07-29 09:24:32 +01:00
m_pTreeList->setAlternatingRowColors(theConf->GetBool("Options/AltRowColors", false));
2022-03-26 09:09:24 +00:00
m_pTreeList->setSelectionMode(QAbstractItemView::ExtendedSelection);
2023-01-07 15:57:55 +00:00
m_pTreeList->setUniformRowHeights(true); // critical for good performance with huge data sets
2022-03-26 09:09:24 +00:00
2023-01-07 15:57:55 +00:00
m_pTraceModel = new CTraceModel(this);
2022-03-26 09:09:24 +00:00
//connect(m_pTraceModel, SIGNAL(NewBranche()), this, SLOT(UpdateFilters()));
//m_pSortProxy = new CTraceFilterProxyModel(this);
//m_pSortProxy->setSortRole(Qt::EditRole);
//m_pSortProxy->setSourceModel(m_pTraceModel);
//m_pSortProxy->setDynamicSortFilter(true);
//m_pTreeList->setModel(m_pSortProxy);
//m_pSortProxy->setView(m_pTreeList);
m_pTreeList->setModel(m_pTraceModel);
QStyle* pStyle = QStyleFactory::create("windows");
m_pTreeList->setStyle(pStyle);
2022-08-09 17:19:46 +01:00
m_pTreeList->setItemDelegate(new CTreeItemDelegate());
2022-03-26 09:09:24 +00:00
m_pTreeList->setExpandsOnDoubleClick(false);
//m_pTreeList->setSortingEnabled(true);
m_pTreeList->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_pTreeList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(OnMenu(const QPoint&)));
m_pTreeList->setColumnReset(1);
//connect(m_pTreeList, SIGNAL(ResetColumns()), m_pTreeList, SLOT(OnResetColumns()));
//connect(m_pBoxTree, SIGNAL(ColumnChanged(int, bool)), this, SLOT(OnColumnsChanged()));
//m_pMainLayout->addWidget(CFinder::AddFinder(m_pTreeList, m_pSortProxy));
2023-05-27 08:03:42 +01:00
/*CFinder* pFinder = new CFinder(this, this, CFinder::eHighLightDefault);
pFinder->SetTree(m_pTreeList);
m_pMainLayout->addWidget(pFinder);*/
2023-02-04 13:37:39 +00:00
CFinder* pFinder;
2023-05-27 08:03:42 +01:00
//m_pMainLayout->addWidget(CFinder::AddFinder(m_pTreeList, this, CFinder::eHighLightDefault, &pFinder));
m_pSplitter->addWidget(CFinder::AddFinder(m_pTreeList, this, CFinder::eHighLightDefault, &pFinder));
2023-02-04 13:42:45 +00:00
pFinder->SetModel(m_pTraceModel);
2023-01-12 22:10:50 +00:00
//QObject::connect(pFinder, SIGNAL(SelectNext()), this, SLOT(SelectNext()));
2022-03-26 09:09:24 +00:00
2023-05-27 08:03:42 +01:00
m_pStackView = new CStackView();
m_pSplitter->addWidget(m_pStackView);
connect(m_pTreeList->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(ItemSelection(QItemSelection, QItemSelection)));
2022-03-26 09:09:24 +00:00
QByteArray Columns = theConf->GetBlob("MainWindow/TraceLog_Columns");
if (!Columns.isEmpty())
((QTreeViewEx*)GetView())->restoreState(Columns);
2023-05-27 08:03:42 +01:00
QByteArray Split = theConf->GetBlob("MainWindow/TraceSplitter");
if(!Split.isEmpty())
m_pSplitter->restoreState(Split);
2023-08-14 19:20:54 +01:00
//else { // by default collapse the details panel
2023-05-27 08:03:42 +01:00
// auto Sizes = m_pSplitter->sizes();
// Sizes[1] = 0;
// m_pSplitter->setSizes(Sizes);
//}
2022-03-26 09:09:24 +00:00
}
CTraceTree::~CTraceTree()
{
theConf->SetBlob("MainWindow/TraceLog_Columns", GetView()->header()->saveState());
2023-05-27 08:03:42 +01:00
theConf->SetBlob("MainWindow/TraceSplitter", m_pSplitter->saveState());
2022-03-26 09:09:24 +00:00
}
2023-01-12 22:10:50 +00:00
void CTraceTree::SetFilter(const QString& Exp, int iOptions, int Column)
{
2023-03-12 15:36:22 +00:00
bool bReset = m_bHighLight != ((iOptions & CFinder::eHighLight) != 0) || (!m_bHighLight && m_FilterExp != Exp);
2023-01-12 22:10:50 +00:00
//QString ExpStr = ((iOptions & CFinder::eRegExp) == 0) ? Exp : (".*" + QRegularExpression::escape(Exp) + ".*");
//QRegularExpression RegExp(ExpStr, (iOptions & CFinder::eCaseSens) != 0 ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption);
//m_FilterExp = RegExp;
m_FilterExp = Exp;
m_bHighLight = (iOptions & CFinder::eHighLight) != 0;
//m_FilterCol = Col;
if(bReset)
emit FilterChanged();
}
2023-05-27 08:03:42 +01:00
void CTraceTree::ItemSelection(const QItemSelection& selected, const QItemSelection& deselected)
{
QItemSelectionModel* selectionModel = m_pTreeList->selectionModel();
QItemSelection selection = selectionModel->selection();
if (selection.indexes().isEmpty())
return;
CTraceEntryPtr pEntry = m_pTraceModel->GetEntry(selection.indexes().first());
2023-06-17 20:13:12 +01:00
if (pEntry.data() == NULL)
return;
2023-05-27 08:03:42 +01:00
CBoxedProcessPtr pProcess = theAPI->GetProcessById(pEntry->GetProcessId());
if(!pProcess.isNull())
m_pStackView->ShowStack(pEntry->GetStack(), pProcess);
}
2023-01-12 22:10:50 +00:00
2022-03-26 09:09:24 +00:00
////////////////////////////////////////////////////////////////////////////////////////
// CMonitorList
CMonitorList::CMonitorList(QWidget* parent)
: CPanelWidget<QTreeViewEx>(parent)
{
2022-07-29 09:24:32 +01:00
m_pTreeList->setAlternatingRowColors(theConf->GetBool("Options/AltRowColors", false));
2022-03-26 09:09:24 +00:00
m_pTreeList->setSelectionMode(QAbstractItemView::ExtendedSelection);
2023-01-07 15:57:55 +00:00
m_pMonitorModel = new CMonitorModel(this);
2022-04-16 14:01:01 +01:00
//connect(m_pMonitorModel, SIGNAL(NewBranche()), this, SLOT(UpdateFilters()));
2022-03-26 09:09:24 +00:00
2022-07-29 09:24:32 +01:00
m_pSortProxy = new CSortFilterProxyModel(this);
2022-03-26 09:09:24 +00:00
m_pSortProxy->setSortRole(Qt::EditRole);
m_pSortProxy->setSourceModel(m_pMonitorModel);
m_pSortProxy->setDynamicSortFilter(true);
m_pTreeList->setModel(m_pSortProxy);
QStyle* pStyle = QStyleFactory::create("windows");
m_pTreeList->setStyle(pStyle);
2022-07-20 08:35:07 +01:00
m_pTreeList->setItemDelegate(new CTreeItemDelegate());
2022-03-26 09:09:24 +00:00
m_pTreeList->setExpandsOnDoubleClick(false);
m_pTreeList->setSortingEnabled(true);
m_pTreeList->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_pTreeList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(OnMenu(const QPoint&)));
2023-05-25 19:07:13 +01:00
m_pTreeList->setColumnFixed(0, true);
m_pTreeList->setColumnFixed(1, true);
m_pTreeList->setColumnFixed(2, true);
2022-03-26 09:09:24 +00:00
m_pTreeList->setColumnReset(1);
//connect(m_pTreeList, SIGNAL(ResetColumns()), m_pTreeList, SLOT(OnResetColumns()));
//connect(m_pBoxTree, SIGNAL(ColumnChanged(int, bool)), this, SLOT(OnColumnsChanged()));
m_pMainLayout->addWidget(CFinder::AddFinder(m_pTreeList, m_pSortProxy));
QByteArray Columns = theConf->GetBlob("MainWindow/Monitor_Columns");
if (!Columns.isEmpty())
((QTreeViewEx*)GetView())->restoreState(Columns);
}
CMonitorList::~CMonitorList()
{
theConf->SetBlob("MainWindow/Monitor_Columns", GetView()->header()->saveState());
}
2023-01-07 15:57:55 +00:00
2022-03-26 09:09:24 +00:00
////////////////////////////////////////////////////////////////////////////////////////
// CTraceView
2022-07-09 10:46:07 +01:00
CTraceView::CTraceView(bool bStandAlone, QWidget* parent) : QWidget(parent)
2021-10-15 16:39:43 +01:00
{
m_FullRefresh = true;
2022-03-26 09:09:24 +00:00
m_LastID = 0;
m_LastCount = 0;
m_bUpdatePending = false;
2021-10-15 16:39:43 +01:00
m_FilterPid = 0;
m_FilterTid = 0;
m_FilterStatus = 0;
2022-03-26 09:09:24 +00:00
m_pMainLayout = new QVBoxLayout();
2022-09-29 17:28:48 +01:00
m_pMainLayout->setContentsMargins(0,0,0,0);
2022-03-26 09:09:24 +00:00
this->setLayout(m_pMainLayout);
2021-10-15 16:39:43 +01:00
m_pTraceToolBar = new QToolBar();
2022-03-26 09:09:24 +00:00
m_pMonitorMode = m_pTraceToolBar->addAction(CSandMan::GetIcon("Monitor"), tr("Monitor mode"), this, SLOT(OnSetMode()));
m_pMonitorMode->setCheckable(true);
2023-01-12 22:10:50 +00:00
m_pMonitorMode->setChecked(theConf->GetBool("Options/UseMonitorMode", true));
2022-03-26 09:09:24 +00:00
2021-10-15 16:39:43 +01:00
m_pTraceTree = m_pTraceToolBar->addAction(CSandMan::GetIcon("Tree"), tr("Show as task tree"), this, SLOT(OnSetTree()));
m_pTraceTree->setCheckable(true);
m_pTraceTree->setChecked(theConf->GetBool("Options/UseLogTree"));
2022-03-26 09:09:24 +00:00
2023-01-07 15:57:55 +00:00
m_pObjectTree = m_pTraceToolBar->addAction(CSandMan::GetIcon("Objects"), tr("Show NT Object Tree"), this, SLOT(OnObjTree()));
m_pObjectTree->setCheckable(true);
m_pObjectTree->setChecked(theConf->GetBool("Options/UseObjectTree"));
2021-10-15 16:39:43 +01:00
m_pTraceToolBar->addSeparator();
m_pTraceToolBar->layout()->setSpacing(3);
m_pTraceToolBar->addWidget(new QLabel(tr("PID:")));
m_pTracePid = new QComboBox();
m_pTracePid->addItem(tr("[All]"), 0);
m_pTracePid->setMinimumWidth(225);
connect(m_pTracePid, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSetPidFilter()));
m_pTraceToolBar->addWidget(m_pTracePid);
m_pTraceToolBar->addWidget(new QLabel(tr("TID:")));
m_pTraceTid = new QComboBox();
m_pTraceTid->addItem(tr("[All]"), 0);
m_pTraceTid->setMinimumWidth(75);
2023-03-12 15:36:22 +00:00
m_pTraceTid->setEditable(true);
2021-10-15 16:39:43 +01:00
connect(m_pTraceTid, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSetTidFilter()));
m_pTraceToolBar->addWidget(m_pTraceTid);
m_pTraceToolBar->addWidget(new QLabel(tr("Type:")));
2021-10-30 08:46:49 +01:00
m_pTraceType = new QCheckList();
//m_pTraceType->addItem(tr("[All]"), 0);
m_pTraceType->setAllCheckedText(tr("[All]"));
m_pTraceType->setNoneCheckedText(tr("[All]"));
foreach(quint32 type, CTraceEntry::AllTypes())
m_pTraceType->addCheckItem(CTraceEntry::GetTypeStr(type), type, Qt::Unchecked);
m_pTraceType->setMinimumWidth(100);
connect(m_pTraceType, SIGNAL(globalCheckStateChanged(int)), this, SLOT(OnSetFilter()));
2021-10-15 16:39:43 +01:00
m_pTraceToolBar->addWidget(m_pTraceType);
m_pTraceToolBar->addWidget(new QLabel(tr("Status:")));
m_pTraceStatus = new QComboBox();
m_pTraceStatus->addItem(tr("[All]"), 0);
m_pTraceStatus->addItem(tr("Open"), 1);
m_pTraceStatus->addItem(tr("Closed"), 2);
m_pTraceStatus->addItem(tr("Trace"), 3);
m_pTraceStatus->addItem(tr("Other"), 4);
m_pTraceStatus->setMinimumWidth(75);
connect(m_pTraceStatus, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSetFilter()));
m_pTraceToolBar->addWidget(m_pTraceStatus);
2022-07-09 10:46:07 +01:00
if (bStandAlone)
m_pAllBoxes = NULL;
else {
m_pAllBoxes = m_pTraceToolBar->addAction(CSandMan::GetIcon("All"), tr("Show All Boxes"), this, SLOT(OnSetFilter()));
m_pAllBoxes->setCheckable(true);
}
2021-10-16 17:24:16 +01:00
2023-05-27 08:03:42 +01:00
m_pShowStack = m_pTraceToolBar->addAction(CSandMan::GetIcon("Stack"), tr("Show Stack Trace"), this, SLOT(OnShowStack()));
m_pShowStack->setCheckable(true);
2021-10-16 17:24:16 +01:00
m_pTraceToolBar->addSeparator();
m_pSaveToFile = m_pTraceToolBar->addAction(CSandMan::GetIcon("Save"), tr("Save to file"), this, SLOT(SaveToFile()));
2021-10-15 16:39:43 +01:00
m_pMainLayout->setSpacing(0);
2022-03-26 09:09:24 +00:00
m_pMainLayout->addWidget(m_pTraceToolBar);
2021-10-15 16:39:43 +01:00
2022-03-26 09:09:24 +00:00
m_pView = new QWidget(this);
m_pLayout = new QStackedLayout(m_pView);
m_pTrace = new CTraceTree(this);
2023-01-07 15:57:55 +00:00
m_pTrace->m_pTraceModel->SetTree(m_pTraceTree->isChecked());
2022-07-09 10:46:07 +01:00
2023-07-22 10:59:54 +01:00
m_pTrace->m_pAutoScroll = new QAction(tr("Auto Scroll"));
2023-07-24 18:08:26 +01:00
m_pTrace->m_pAutoScroll->setCheckable(true);
2023-07-22 10:59:54 +01:00
m_pTrace->m_pAutoScroll->setChecked(theConf->GetBool("Options/TraceAutoScroll"));
m_pTrace->GetMenu()->insertAction(m_pTrace->GetMenu()->actions()[0], m_pTrace->m_pAutoScroll);
2022-07-09 10:46:07 +01:00
if (bStandAlone) {
QAction* pAction = new QAction(tr("Cleanup Trace Log"));
connect(pAction, SIGNAL(triggered()), this, SLOT(Clear()));
2023-07-22 10:59:54 +01:00
m_pTrace->GetMenu()->insertAction(m_pTrace->GetMenu()->actions()[1], pAction);
2022-07-09 10:46:07 +01:00
}
2022-03-26 09:09:24 +00:00
m_pLayout->addWidget(m_pTrace);
2021-10-15 16:39:43 +01:00
2023-01-12 22:10:50 +00:00
QObject::connect(m_pTrace, SIGNAL(FilterChanged()), this, SLOT(OnFilterChanged()));
2021-10-15 16:39:43 +01:00
2022-03-26 09:09:24 +00:00
m_pMonitor = new CMonitorList(this);
2023-01-07 15:57:55 +00:00
m_pMonitor->m_pMonitorModel->SetObjTree(m_pObjectTree->isChecked());
2022-03-26 09:09:24 +00:00
m_pLayout->addWidget(m_pMonitor);
2021-10-15 16:39:43 +01:00
2022-03-26 09:09:24 +00:00
m_pView->setLayout(m_pLayout);
m_pMainLayout->addWidget(m_pView);
2021-10-15 16:39:43 +01:00
2022-03-26 09:09:24 +00:00
OnSetMode();
2022-07-09 10:46:07 +01:00
m_uTimerID = startTimer(1000);
2021-10-15 16:39:43 +01:00
}
CTraceView::~CTraceView()
{
2023-07-22 10:59:54 +01:00
theConf->SetValue("Options/TraceAutoScroll", m_pTrace->m_pAutoScroll->isChecked());
2022-07-09 10:46:07 +01:00
killTimer(m_uTimerID);
}
void CTraceView::timerEvent(QTimerEvent* pEvent)
{
if (pEvent->timerId() != m_uTimerID)
return;
Refresh();
2021-10-15 16:39:43 +01:00
}
2023-05-27 08:03:42 +01:00
void CTraceView::SetEnabled(bool bSet)
{
setEnabled(bSet);
m_pShowStack->setChecked(theAPI->GetGlobalSettings()->GetBool("MonitorStackTrace", false));
m_pTrace->m_pStackView->setVisible(m_pShowStack->isChecked());
}
void CTraceView::OnShowStack()
{
2023-08-24 17:39:00 +01:00
if (m_pShowStack->isChecked() && !theGUI->GetAddonManager()->GetAddon("DbgHelp", CAddonManager::eInstalled).isNull())
2023-07-01 17:54:53 +01:00
theGUI->GetAddonManager()->TryInstallAddon("DbgHelp", this, tr("To use the stack traces feature the DbgHelp.dll and SymSrv.dll are required, do you want to download and install them?"));
2023-05-27 08:03:42 +01:00
theAPI->GetGlobalSettings()->SetBool("MonitorStackTrace", m_pShowStack->isChecked());
m_pTrace->m_pStackView->setVisible(m_pShowStack->isChecked());
}
2021-10-15 16:39:43 +01:00
void CTraceView::Refresh()
{
QList<CSandBoxPtr>Boxes;
2022-07-09 10:46:07 +01:00
if(m_pAllBoxes && !m_pAllBoxes->isChecked())
2021-10-15 16:39:43 +01:00
Boxes = theGUI->GetBoxView()->GetSelectedBoxes();
if (m_pCurrentBox != (Boxes.count() == 1 ? Boxes.first().data() : NULL)) {
m_pCurrentBox = Boxes.count() == 1 ? Boxes.first().data() : NULL;
m_FullRefresh = true;
}
2022-03-26 09:09:24 +00:00
bool bMonitorMode = m_pMonitorMode->isChecked();
if (m_FullRefresh)
{
m_LastID = 0;
m_LastCount = 0;
m_PidMap.clear();
2023-01-07 15:57:55 +00:00
quint64 start = GetCurCycle();
2022-03-26 09:09:24 +00:00
m_pTrace->m_pTraceModel->Clear();
2023-01-08 10:49:09 +00:00
qDebug() << "Clear took" << (GetCurCycle() - start) / 1000000.0 << "s";
2023-01-07 15:57:55 +00:00
2022-03-26 09:09:24 +00:00
m_pMonitor->m_pMonitorModel->Clear();
2021-10-15 16:39:43 +01:00
m_FullRefresh = false;
}
2023-01-07 15:57:55 +00:00
const QVector<CTraceEntryPtr> &ResourceLog = theAPI->GetTrace();
2022-03-26 09:09:24 +00:00
2023-01-07 15:57:55 +00:00
bool bUpdateFilters = false;
2022-03-26 09:09:24 +00:00
int i = 0;
if (ResourceLog.count() >= m_LastCount && m_LastCount > 0)
2021-10-15 16:39:43 +01:00
{
2022-03-26 09:09:24 +00:00
i = m_LastCount - 1;
if (m_LastID == ResourceLog.at(i)->GetUID())
i++;
else
i = 0;
}
if (i == 0) {
m_PidMap.clear();
2023-01-07 15:57:55 +00:00
m_TraceList.clear();
2022-03-26 09:09:24 +00:00
m_MonitorMap.clear();
}
2023-01-07 15:57:55 +00:00
if (m_LastCount == ResourceLog.count())
return;
2023-01-12 22:10:50 +00:00
//bool bHasFilter = !m_pTrace->m_FilterExp.pattern().isEmpty();
bool bHasFilter = !m_pTrace->m_FilterExp.isEmpty();
2023-01-07 15:57:55 +00:00
2023-01-08 10:49:09 +00:00
quint64 start = GetCurCycle();
2022-03-26 09:09:24 +00:00
for (; i < ResourceLog.count(); i++)
{
2023-01-07 15:57:55 +00:00
const CTraceEntryPtr& pEntry = ResourceLog.at(i);
2022-03-26 09:09:24 +00:00
SProgInfo& Info = m_PidMap[pEntry->GetProcessId()];
if (Info.Name.isEmpty()) {
Info.Name = pEntry->GetProcessName();
2023-01-07 15:57:55 +00:00
bUpdateFilters = true;
2022-03-26 09:09:24 +00:00
}
if (!Info.Threads.contains(pEntry->GetThreadId())) {
Info.Threads.insert(pEntry->GetThreadId());
2023-01-07 15:57:55 +00:00
bUpdateFilters = true;
2022-03-26 09:09:24 +00:00
}
2023-01-07 15:57:55 +00:00
if (m_pCurrentBox != NULL && m_pCurrentBox != pEntry->GetBoxPtr())
continue;
2022-03-26 09:09:24 +00:00
2023-01-07 15:57:55 +00:00
if (m_FilterPid != 0 && m_FilterPid != pEntry->GetProcessId())
continue;
2022-03-26 09:09:24 +00:00
2023-01-07 15:57:55 +00:00
if (m_FilterTid != 0 && m_FilterTid != pEntry->GetThreadId())
continue;
2022-03-26 09:09:24 +00:00
2023-01-07 15:57:55 +00:00
if (!m_FilterTypes.isEmpty() && !m_FilterTypes.contains(pEntry->GetType()))
continue;
2022-03-26 09:09:24 +00:00
2023-01-07 15:57:55 +00:00
if (bMonitorMode)
{
CMonitorEntryPtr& pItem = m_MonitorMap[pEntry->GetName().toLower()];
if (pItem.data() == NULL) {
QString Name = pEntry->GetName();
//if (Name.left(9).compare("\\REGISTRY", Qt::CaseInsensitive) == 0) {
// int pos = Name.indexOf("\\", 10);
// Name = Name.left(pos).toUpper() + Name.mid(pos);
//}
pItem = CMonitorEntryPtr(new CMonitorEntry(Name, pEntry->GetType()));
}
2022-03-26 09:09:24 +00:00
pItem->Merge(pEntry);
}
2023-01-07 15:57:55 +00:00
else
{
2023-01-12 22:10:50 +00:00
if (bHasFilter && !m_pTrace->m_bHighLight) {
2023-01-27 19:43:26 +00:00
if (!pEntry->GetName().contains(m_pTrace->m_FilterExp, Qt::CaseInsensitive)
&& !pEntry->GetMessage().contains(m_pTrace->m_FilterExp, Qt::CaseInsensitive)
2023-02-03 07:05:10 +00:00
//&& !pEntry->GetTypeStr().contains(m_pTrace->m_FilterExp, Qt::CaseInsensitive) // don't filter on non static strings !!!
//&& !pEntry->GetStautsStr().contains(m_pTrace->m_FilterExp, Qt::CaseInsensitive) // don't filter on non static strings !!!
2023-01-27 19:43:26 +00:00
&& !pEntry->GetProcessName().contains(m_pTrace->m_FilterExp, Qt::CaseInsensitive))
2023-01-07 15:57:55 +00:00
continue;
}
if (m_FilterStatus != 0) {
if (pEntry->IsOpen()) {
if (m_FilterStatus != 1) continue;
} else if (pEntry->IsClosed()) {
if (m_FilterStatus != 2) continue;
} else if (pEntry->IsTrace()) {
if (m_FilterStatus != 3) continue;
} else {
if (m_FilterStatus != 4) continue;
}
}
m_TraceList.append(pEntry);
}
2022-03-26 09:09:24 +00:00
}
2023-01-08 10:49:09 +00:00
qDebug() << "Filtering took" << (GetCurCycle() - start) / 1000000.0 << "s";
2022-03-26 09:09:24 +00:00
m_LastCount = ResourceLog.count();
if(m_LastCount)
m_LastID = ResourceLog.last()->GetUID();
2023-01-07 15:57:55 +00:00
if (bUpdateFilters && !m_bUpdatePending)
2022-03-26 09:09:24 +00:00
{
m_bUpdatePending = true;
QTimer::singleShot(500, this, SLOT(UpdateFilters()));
}
if (bMonitorMode)
{
2023-01-07 15:57:55 +00:00
QList<QModelIndex> NewBranches = m_pMonitor->m_pMonitorModel->Sync(m_MonitorMap, this);
if (m_pMonitor->m_pMonitorModel->IsObjTree())
{
2023-05-27 08:03:42 +01:00
QTimer::singleShot(10, this, [this, NewBranches]() {
2023-01-07 15:57:55 +00:00
CSortFilterProxyModel* pSortProxy = m_pMonitor->m_pSortProxy;
foreach(const QModelIndex& Index, NewBranches) {
m_pMonitor->GetTree()->expand(pSortProxy->mapFromSource(Index));
}
});
}
2022-03-26 09:09:24 +00:00
}
else
{
2023-01-12 22:10:50 +00:00
if (m_pTrace->m_bHighLight)
m_pTrace->m_pTraceModel->SetHighLight(m_pTrace->m_FilterExp);
else
m_pTrace->m_pTraceModel->SetHighLight(QString());
2023-01-07 15:57:55 +00:00
quint64 start = GetCurCycle();
QList<QModelIndex> NewBranches = m_pTrace->m_pTraceModel->Sync(m_TraceList);
2023-01-08 10:49:09 +00:00
qDebug() << "Sync took" << (GetCurCycle() - start) / 1000000.0 << "s";
2022-03-26 09:09:24 +00:00
if (m_pTrace->m_pTraceModel->IsTree())
{
2023-05-27 08:03:42 +01:00
QTimer::singleShot(10, this, [this, NewBranches]() {
2023-01-07 15:57:55 +00:00
quint64 start = GetCurCycle();
foreach(const QModelIndex& Index, NewBranches)
m_pTrace->GetTree()->expand(Index);
qDebug() << "Expand took" << (GetCurCycle() - start) / 1000000.0 << "s";
2022-03-26 09:09:24 +00:00
});
}
2023-07-22 10:59:54 +01:00
if(m_pTrace->m_pAutoScroll->isChecked())
m_pTrace->m_pTreeList->scrollToBottom();
2021-10-15 16:39:43 +01:00
}
}
void CTraceView::Clear()
{
m_pTracePid->clear();
m_pTracePid->addItem(tr("[All]"), 0);
m_pTraceTid->clear();
m_pTraceTid->addItem(tr("[All]"), 0);
theAPI->ClearTrace();
2023-01-07 15:57:55 +00:00
m_pTrace->m_pTraceModel->Clear(true);
2022-03-26 09:09:24 +00:00
m_pMonitor->m_pMonitorModel->Clear();
2021-10-15 16:39:43 +01:00
}
2022-04-07 19:49:13 +01:00
void CTraceView::AddAction(QAction* pAction)
{
m_pTrace->GetMenu()->insertAction(m_pTrace->GetMenu()->actions()[0], pAction);
m_pTrace->GetMenu()->insertSeparator(m_pTrace->GetMenu()->actions()[0]);
m_pMonitor->GetMenu()->insertAction(m_pMonitor->GetMenu()->actions()[0], pAction);
m_pMonitor->GetMenu()->insertSeparator(m_pMonitor->GetMenu()->actions()[0]);
}
2021-10-15 16:39:43 +01:00
void CTraceView::OnSetTree()
{
2023-01-07 15:57:55 +00:00
m_pTrace->m_pTraceModel->SetTree(m_pTraceTree->isChecked());
//m_pTrace->m_pTraceModel->Clear();
m_FullRefresh = true;
2022-09-29 17:28:48 +01:00
Refresh();
2023-01-07 15:57:55 +00:00
//m_pTrace->GetTree()->expandAll();
2022-09-29 17:28:48 +01:00
2021-10-15 16:39:43 +01:00
theConf->SetValue("Options/UseLogTree", m_pTraceTree->isChecked());
}
2022-03-26 09:09:24 +00:00
void CTraceView::OnSetMode()
{
if (m_pMonitorMode->isChecked())
m_pLayout->setCurrentIndex(1); // monitor
else
m_pLayout->setCurrentIndex(0); // trace
m_pTraceTree->setEnabled(!m_pMonitorMode->isChecked());
2023-01-07 15:57:55 +00:00
m_pObjectTree->setEnabled(m_pMonitorMode->isChecked());
2022-03-26 09:09:24 +00:00
m_pTraceStatus->setEnabled(!m_pMonitorMode->isChecked());
2023-05-27 08:03:42 +01:00
m_pShowStack->setEnabled(!m_pMonitorMode->isChecked());
2022-03-26 09:09:24 +00:00
m_FullRefresh = true;
2023-01-07 15:57:55 +00:00
Refresh();
2022-03-26 09:09:24 +00:00
2023-01-07 15:57:55 +00:00
theConf->SetValue("Options/UseMonitorMode", m_pMonitorMode->isChecked());
}
void CTraceView::OnObjTree()
{
m_pMonitor->m_pMonitorModel->SetObjTree(m_pObjectTree->isChecked());
//m_pMonitor->m_pMonitorModel->Clear();
m_FullRefresh = true;
2022-03-26 09:09:24 +00:00
Refresh();
2023-01-07 15:57:55 +00:00
//m_pTrace->GetTree()->expandAll();
theConf->SetValue("Options/UseObjectTree", m_pObjectTree->isChecked());
2022-03-26 09:09:24 +00:00
}
2021-10-15 16:39:43 +01:00
void CTraceView::UpdateFilters()
{
2022-03-26 09:09:24 +00:00
m_bUpdatePending = false;
2021-10-15 16:39:43 +01:00
quint32 cur_pid = m_pTracePid->currentData().toUInt();
2022-03-26 09:09:24 +00:00
QMap<quint32, SProgInfo> pids = m_PidMap;
2022-09-29 17:28:48 +01:00
foreach(quint32 pid, pids.keys()) {
2022-03-26 09:09:24 +00:00
SProgInfo& Info = pids[pid];
2021-10-15 16:39:43 +01:00
if(m_pTracePid->findData(pid) == -1)
m_pTracePid->addItem(tr("%1 (%2)").arg(Info.Name).arg(pid), pid);
if (cur_pid != 0 && cur_pid != pid)
continue;
foreach(quint32 tid, Info.Threads) {
if (m_pTraceTid->findData(tid) == -1)
m_pTraceTid->addItem(tr("%1").arg(tid), tid);
}
}
}
2023-01-12 22:10:50 +00:00
void CTraceView::OnFilterChanged()
2021-10-15 16:39:43 +01:00
{
m_FullRefresh = true;
}
void CTraceView::OnSetPidFilter()
{
m_FilterPid = m_pTracePid->currentData().toUInt();
m_FilterTid = 0;
//m_pSortProxy->m_FilterPid = m_pTracePid->currentData().toUInt();
//m_pSortProxy->m_FilterTid = 0;
QTimer::singleShot(100, this, [this]() {
m_pTraceTid->clear();
m_pTraceTid->addItem(tr("[All]"), 0);
UpdateFilters();
});
//m_pSortProxy->setFilterKeyColumn(m_pSortProxy->filterKeyColumn());
m_FullRefresh = true;
2023-01-07 15:57:55 +00:00
//if(!m_pMonitorMode->isChecked())
// m_pTrace->GetTree()->expandAll();
2021-10-15 16:39:43 +01:00
}
void CTraceView::OnSetTidFilter()
{
2023-03-12 15:36:22 +00:00
//m_FilterTid = m_pTraceTid->currentData().toUInt();
m_FilterTid = m_pTraceTid->currentText().toUInt();
2021-10-15 16:39:43 +01:00
//m_pSortProxy->m_FilterTid = m_pTraceTid->currentData().toUInt();
//m_pSortProxy->setFilterKeyColumn(m_pSortProxy->filterKeyColumn());
m_FullRefresh = true;
2023-01-07 15:57:55 +00:00
//if(!m_pMonitorMode->isChecked())
// m_pTrace->GetTree()->expandAll();
2021-10-15 16:39:43 +01:00
}
void CTraceView::OnSetFilter()
{
2021-10-30 08:46:49 +01:00
m_FilterTypes.clear();
for (int i = 0; i < m_pTraceType->count(); i++) {
if (m_pTraceType->itemData(i, Qt::CheckStateRole).toInt() == Qt::Checked) {
m_FilterTypes.append(m_pTraceType->itemData(i, Qt::UserRole + 1).toUInt());
}
}
2021-10-15 16:39:43 +01:00
m_FilterStatus = m_pTraceStatus->currentData().toUInt();
m_FullRefresh = true;
2023-01-07 15:57:55 +00:00
//if(!m_pMonitorMode->isChecked())
// m_pTrace->GetTree()->expandAll();
2021-10-15 16:39:43 +01:00
}
2021-10-16 17:24:16 +01:00
void CTraceView::SaveToFile()
{
QString Path = QFileDialog::getSaveFileName(this, tr("Save trace log to file"), "", QString("Log files (*.log)")).replace("/", "\\");
2021-10-16 19:13:16 +01:00
if (Path.isEmpty())
return;
2021-10-16 17:24:16 +01:00
QFile File(Path);
if (!File.open(QFile::WriteOnly)) {
QMessageBox::critical(this, "Sandboxie-Plus", tr("Failed to open log file for writing"));
return;
}
2022-05-15 11:27:33 +01:00
if (m_pMonitorMode->isChecked())
2021-10-16 17:24:16 +01:00
{
2022-05-15 11:27:33 +01:00
QList<QStringList> Rows = m_pMonitor->DumpPanel();
foreach(const QStringList& Row, Rows)
File.write(Row.join("\t").toLatin1() + "\n");
}
else
{
2023-07-01 17:54:53 +01:00
SaveToFile(&File);
2021-10-16 17:24:16 +01:00
}
File.close();
2022-07-09 10:46:07 +01:00
}
2023-07-01 17:54:53 +01:00
void CTraceView::SaveToFileAsync(const CSbieProgressPtr& pProgress, QVector<CTraceEntryPtr> ResourceLog, QIODevice* pFile)
{
pProgress->ShowMessage(tr("Saving TraceLog..."));
QByteArray Unknown = "Unknown";
quint64 LastTimeStamp = 0;
QByteArray LastTimeStampStr;
for (int i = 0; i < ResourceLog.count() && !pProgress->IsCanceled(); i++)
{
if (i % 10000 == 0)
pProgress->SetProgress(100 * i / ResourceLog.count());
const CTraceEntryPtr& pEntry = ResourceLog.at(i);
if (LastTimeStamp != pEntry->GetTimeStamp()) {
LastTimeStamp = pEntry->GetTimeStamp();
2023-12-14 12:58:37 +00:00
LastTimeStampStr = QDateTime::fromMSecsSinceEpoch(pEntry->GetTimeStamp()).toString("dd.MM.yyyy hh:mm:ss.zzz").toUtf8();
2023-07-01 17:54:53 +01:00
}
pFile->write(LastTimeStampStr);
pFile->write("\t");
QString Name = pEntry->GetProcessName();
pFile->write(Name.isEmpty() ? Unknown : Name.toUtf8());
pFile->write("\t");
pFile->write(QByteArray::number(pEntry->GetProcessId()));
pFile->write("\t");
pFile->write(QByteArray::number(pEntry->GetThreadId()));
pFile->write("\t");
pFile->write(pEntry->GetTypeStr().toUtf8());
pFile->write("\t");
pFile->write(pEntry->GetStautsStr().toUtf8());
pFile->write("\t");
pFile->write(pEntry->GetName().toUtf8());
pFile->write("\t");
pFile->write(pEntry->GetMessage().toUtf8());
pFile->write("\n");
}
pProgress->Finish(SB_OK);
}
bool CTraceView::SaveToFile(QIODevice* pFile)
{
pFile->write("Timestamp\tProcess\tPID\tTID\tType\tStatus\tName\tMessage\n"); // don't translate log
QVector<CTraceEntryPtr> ResourceLog = theAPI->GetTrace();
CSbieProgressPtr pProgress = CSbieProgressPtr(new CSbieProgress());
QtConcurrent::run(CTraceView::SaveToFileAsync, pProgress, ResourceLog, pFile);
theGUI->AddAsyncOp(pProgress, true);
return !pProgress->IsCanceled();
}
2022-07-09 10:46:07 +01:00
////////////////////////////////////////////////////////////////////////////////////////
// CTraceWindow
CTraceWindow::CTraceWindow(QWidget *parent)
: QDialog(parent)
{
Qt::WindowFlags flags = windowFlags();
flags |= Qt::CustomizeWindowHint;
//flags &= ~Qt::WindowContextHelpButtonHint;
//flags &= ~Qt::WindowSystemMenuHint;
//flags &= ~Qt::WindowMinMaxButtonsHint;
//flags |= Qt::WindowMinimizeButtonHint;
//flags &= ~Qt::WindowCloseButtonHint;
flags &= ~Qt::WindowContextHelpButtonHint;
//flags &= ~Qt::WindowSystemMenuHint;
setWindowFlags(flags);
this->setWindowTitle(tr("Sandboxie-Plus - Trace Monitor"));
2023-10-21 21:15:07 +01:00
this->setWindowFlag(Qt::WindowStaysOnTopHint, theGUI->IsAlwaysOnTop());
2022-07-11 18:30:09 +01:00
2022-07-09 10:46:07 +01:00
QGridLayout* pLayout = new QGridLayout();
2022-09-29 17:28:48 +01:00
pLayout->setContentsMargins(3,3,3,3);
2022-07-09 10:46:07 +01:00
pLayout->addWidget(new CTraceView(true, this), 0, 0);
this->setLayout(pLayout);
restoreGeometry(theConf->GetBlob("TraceWindow/Window_Geometry"));
}
CTraceWindow::~CTraceWindow()
{
theConf->SetBlob("TraceWindow/Window_Geometry", saveGeometry());
2022-07-11 18:30:09 +01:00
if(!theAPI) theAPI->EnableMonitor(false);
2022-07-09 10:46:07 +01:00
}
void CTraceWindow::closeEvent(QCloseEvent *e)
{
emit Closed();
this->deleteLater();
2022-12-07 16:32:40 +00:00
}
2023-01-07 15:57:55 +00:00