From 7ce252fb36a5006650ed34a5419d17e98b86f979 Mon Sep 17 00:00:00 2001 From: DavidXanatos Date: Thu, 12 Jan 2023 23:10:50 +0100 Subject: [PATCH] 1.6.6 --- CHANGELOG.md | 2 + Sandboxie/core/drv/session.c | 12 +- Sandboxie/core/drv/util.c | 29 +++- Sandboxie/core/drv/util.h | 4 +- SandboxiePlus/MiscHelpers/Common/Finder.cpp | 156 ++++++++++++++++-- SandboxiePlus/MiscHelpers/Common/Finder.h | 28 +++- SandboxiePlus/MiscHelpers/Common/PanelView.h | 8 +- .../MiscHelpers/Common/SortFilterProxyModel.h | 116 +------------ SandboxiePlus/QSbieAPI/SbieAPI.cpp | 8 +- SandboxiePlus/QSbieAPI/SbieTrace.cpp | 4 +- SandboxiePlus/QSbieAPI/SbieTrace.h | 6 +- SandboxiePlus/SandMan/Models/TraceModel.cpp | 28 +++- SandboxiePlus/SandMan/Models/TraceModel.h | 6 + SandboxiePlus/SandMan/Views/SbieView.cpp | 7 +- SandboxiePlus/SandMan/Views/TraceView.cpp | 63 ++++--- SandboxiePlus/SandMan/Views/TraceView.h | 25 +-- .../SandMan/Windows/RecoveryWindow.cpp | 7 +- .../SandMan/Windows/SnapshotsWindow.cpp | 2 +- 18 files changed, 319 insertions(+), 192 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 023d5d8d..4c038dd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## Changed - improved trace log retrival greately improving performance +- improved list/tree finder +- improved trace logging ### Fixed - fixed potential BSOD issue in the driver diff --git a/Sandboxie/core/drv/session.c b/Sandboxie/core/drv/session.c index 780450db..389a4041 100644 --- a/Sandboxie/core/drv/session.c +++ b/Sandboxie/core/drv/session.c @@ -553,6 +553,8 @@ _FX void Session_MonitorPutEx(ULONG type, const WCHAR** strings, ULONG* lengths, if (session->monitor_log) { + LARGE_INTEGER timestamp = Util_GetTimestamp(); + ULONG pid = (ULONG)hpid; ULONG tid = (ULONG)htid; @@ -561,12 +563,13 @@ _FX void Session_MonitorPutEx(ULONG type, const WCHAR** strings, ULONG* lengths, data_len += ((lengths ? lengths [i] : wcslen(strings[i])) + 1) * sizeof(WCHAR); - //[Type 4][PID 4][TID 4][Data n*2] - SIZE_T entry_size = 4 + 4 + 4 + data_len; + //[Time 8][Type 4][PID 4][TID 4][Data n*2] + SIZE_T entry_size = 8 + 4 + 4 + 4 + data_len; CHAR* write_ptr = log_buffer_push_entry((LOG_BUFFER_SIZE_T)entry_size, session->monitor_log, FALSE); if (write_ptr) { WCHAR null_char = L'\0'; + log_buffer_push_bytes((CHAR*)×tamp.QuadPart, 8, &write_ptr, session->monitor_log); log_buffer_push_bytes((CHAR*)&type, 4, &write_ptr, session->monitor_log); log_buffer_push_bytes((CHAR*)&pid, 4, &write_ptr, session->monitor_log); log_buffer_push_bytes((CHAR*)&tid, 4, &write_ptr, session->monitor_log); @@ -925,6 +928,7 @@ _FX NTSTATUS Session_Api_MonitorGetEx(PROCESS* proc, ULONG64* parms) API_MONITOR_GET_EX_ARGS* args = (API_MONITOR_GET_EX_ARGS*)parms; NTSTATUS status; //ULONG* seq_num; + LARGE_INTEGER timestamp; ULONG* log_type; ULONG* log_pid; ULONG* log_tid; @@ -1007,7 +1011,9 @@ _FX NTSTATUS Session_Api_MonitorGetEx(PROCESS* proc, ULONG64* parms) // __leave; //} - //[Type 4][PID 4][TID 4][Data n*2] + //[Time 8][Type 4][PID 4][TID 4][Data n*2] + + log_buffer_get_bytes((CHAR*)×tamp.QuadPart, 8, &read_ptr, session->monitor_log); log_buffer_get_bytes((CHAR*)log_type, 4, &read_ptr, session->monitor_log); diff --git a/Sandboxie/core/drv/util.c b/Sandboxie/core/drv/util.c index ac750773..b81546d2 100644 --- a/Sandboxie/core/drv/util.c +++ b/Sandboxie/core/drv/util.c @@ -1,6 +1,6 @@ /* * Copyright 2004-2020 Sandboxie Holdings, LLC - * Copyright 2020-2021 David Xanatos, xanasoft.com + * Copyright 2020-2023 David Xanatos, xanasoft.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -443,3 +443,30 @@ retry: return pid; } + +//--------------------------------------------------------------------------- +// Util_GetTime +//--------------------------------------------------------------------------- + + +_FX LARGE_INTEGER Util_GetTimestamp(void) +{ + static LARGE_INTEGER gMonitorStartCounter; + static LARGE_INTEGER gPerformanceFrequency; + static LARGE_INTEGER gMonitorStartTime = { 0 }; + + if (gMonitorStartTime.QuadPart == 0) { + KeQuerySystemTime(&gMonitorStartTime); + gMonitorStartCounter = KeQueryPerformanceCounter(&gPerformanceFrequency); + } + + LARGE_INTEGER Time; + LARGE_INTEGER CounterNow = KeQueryPerformanceCounter(NULL); + LONGLONG CounterOff = CounterNow.QuadPart - gMonitorStartCounter.QuadPart; + + Time.QuadPart = gMonitorStartTime.QuadPart + + (10000000 * (CounterOff / gPerformanceFrequency.QuadPart)) + + ((10000000 * (CounterOff % gPerformanceFrequency.QuadPart)) / gPerformanceFrequency.QuadPart); + + return Time; +} \ No newline at end of file diff --git a/Sandboxie/core/drv/util.h b/Sandboxie/core/drv/util.h index a0cd35ee..fdda19d5 100644 --- a/Sandboxie/core/drv/util.h +++ b/Sandboxie/core/drv/util.h @@ -1,6 +1,6 @@ /* * Copyright 2004-2020 Sandboxie Holdings, LLC - * Copyright 2020 David Xanatos, xanasoft.com + * Copyright 2020-2023 David Xanatos, xanasoft.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -110,6 +110,8 @@ NTSTATUS MyValidateCertificate(void); HANDLE Util_GetProcessPidByName(const WCHAR* name); +LARGE_INTEGER Util_GetTimestamp(void); + //--------------------------------------------------------------------------- diff --git a/SandboxiePlus/MiscHelpers/Common/Finder.cpp b/SandboxiePlus/MiscHelpers/Common/Finder.cpp index 9c70f0e2..646c90f7 100644 --- a/SandboxiePlus/MiscHelpers/Common/Finder.cpp +++ b/SandboxiePlus/MiscHelpers/Common/Finder.cpp @@ -3,15 +3,16 @@ bool CFinder::m_DarkMode = false; -QWidget* CFinder::AddFinder(QWidget* pList, QObject* pFilterTarget, int iOptions, CFinder** ppFinder) +QWidget* CFinder::AddFinder(QTreeView* pTree, QObject* pFilterTarget, int iOptions, CFinder** ppFinder) { QWidget* pWidget = new QWidget(); QVBoxLayout* pLayout = new QVBoxLayout(); pLayout->setContentsMargins(0,0,0,0); pWidget->setLayout(pLayout); - pLayout->addWidget(pList); + pLayout->addWidget(pTree); CFinder* pFinder = new CFinder(pFilterTarget, pWidget, iOptions); + pFinder->SetTree(pTree); pLayout->addWidget(pFinder); if (ppFinder) @@ -52,9 +53,10 @@ CFinder::CFinder(QObject* pFilterTarget, QWidget *parent, int iOptions) else m_pRegExp = NULL; - m_pSortProxy = qobject_cast(pFilterTarget); + m_pTree = NULL; + m_pModel = qobject_cast(pFilterTarget); - if (m_pSortProxy) { + if (m_pModel) { m_pColumn = new QComboBox(); m_pSearchLayout->addWidget(m_pColumn); connect(m_pColumn, SIGNAL(currentIndexChanged(int)), this, SLOT(OnUpdate())); @@ -66,7 +68,8 @@ CFinder::CFinder(QObject* pFilterTarget, QWidget *parent, int iOptions) if ((iOptions & eHighLight) != 0) { m_pHighLight = new QCheckBox(tr("Highlight")); - //m_pHighLight->setChecked(true); + if ((iOptions & eHighLightDefault) == eHighLightDefault) + m_pHighLight->setChecked(true); m_pSearchLayout->addWidget(m_pHighLight); connect(m_pHighLight, SIGNAL(stateChanged(int)), this, SLOT(OnUpdate())); } @@ -103,7 +106,7 @@ CFinder::CFinder(QObject* pFilterTarget, QWidget *parent, int iOptions) if (pFilterTarget) { QObject::connect(this, SIGNAL(SetFilter(const QString&, int, int)), pFilterTarget, SLOT(SetFilter(const QString&, int, int))); - QObject::connect(this, SIGNAL(SelectNext()), pFilterTarget, SLOT(SelectNext())); + //QObject::connect(this, SIGNAL(SelectNext()), pFilterTarget, SLOT(SelectNext())); } m_pTimer = new QTimer(this); @@ -118,6 +121,12 @@ CFinder::~CFinder() { } +void CFinder::SetTree(QTreeView* pTree) +{ + m_pTree = pTree; + QObject::connect(this, SIGNAL(SelectNext()), this, SLOT(OnSelectNext())); +} + bool CFinder::eventFilter(QObject* source, QEvent* event) { if (event->type() == QEvent::KeyPress && ((QKeyEvent*)event)->key() == Qt::Key_Escape @@ -132,11 +141,11 @@ bool CFinder::eventFilter(QObject* source, QEvent* event) void CFinder::Open() { - if (m_pSortProxy && m_pColumn->count() == 0) + if (m_pModel && m_pColumn->count() == 0) { m_pColumn->addItem(tr("All columns"), -1); - for (int i = 0; i < m_pSortProxy->columnCount(); i++) - m_pColumn->addItem(m_pSortProxy->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(), i); + for (int i = 0; i < m_pModel->columnCount(); i++) + m_pColumn->addItem(m_pModel->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString(), i); m_pColumn->setVisible(true); } @@ -158,7 +167,12 @@ void CFinder::OnUpdate() iOptions |= eCaseSens; if (GetHighLight()) iOptions |= eHighLight; - SetFilter(m_pSearch->text(), iOptions, GetColumn()); + QString Exp = m_pSearch->text(); + + QString ExpStr = ((iOptions & CFinder::eRegExp) == 0) ? Exp : (".*" + QRegularExpression::escape(Exp) + ".*"); + m_RegExp = QRegularExpression(ExpStr, (iOptions & CFinder::eCaseSens) != 0 ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption); + + SetFilter(Exp, iOptions, GetColumn()); } void CFinder::OnText() @@ -178,4 +192,126 @@ void CFinder::Close() { emit SetFilter(QString()); hide(); +} + +//////////////////////////////////////////////////////////////// +// + +bool CFinder::MatchString(const QString& value) +{ + return value.contains(m_RegExp); +} + +bool CFinder::MatchCell(QModelIndex idx, int column) +{ + QModelIndex tmp = idx.sibling(idx.row(), column); + + QString str = m_pModel->data(tmp, Qt::DisplayRole).toString(); + return MatchString(str); +} + +bool CFinder::MatchRow(QModelIndex idx) +{ + int iColumn = GetColumn(); + if (iColumn != -1) + return MatchCell(idx, iColumn); + + for(int col = 0; col < m_pModel->columnCount(idx); col++) { + if (MatchCell(idx, col)) + return true; + } + return false; +} + +QModelIndex CFinder::FindNext(QModelIndex idx, bool next, int depth) +{ + if (MatchRow(idx) && !next) + return idx; + //Q_ASSERT(depth < 100); + + if (m_pModel->hasChildren(idx)) + { + int numRows = m_pModel->rowCount(idx); + for (int count = 0; count < numRows; count++) { + QModelIndex tmp = FindNext(m_pModel->index(count, 0, idx), false, depth + 1); + if (tmp.isValid()) + return tmp; + } + } + + for(;;) + { + QModelIndex par = m_pModel->parent(idx); + if (!par.isValid() && depth > 0) + break; + + int numRows = m_pModel->rowCount(par); + for (int count = idx.row() + 1; count < numRows; count++) { + QModelIndex tmp = FindNext(m_pModel->index(count, 0, par), false, depth + 1); + if (tmp.isValid()) + return tmp; + } + + if (!par.isValid()) + break; + idx = par; + } + + return QModelIndex(); +} + +QModelIndex CFinder::FindPrev(QModelIndex idx, bool next, int depth) +{ + if (MatchRow(idx) && !next) + return idx; + //Q_ASSERT(depth < 100); + + if (m_pModel->hasChildren(idx)) + { + int numRows = m_pModel->rowCount(idx); + for (int count = numRows-1; count >= 0; count++) { + QModelIndex tmp = FindNext(m_pModel->index(count, 0, idx), false, depth + 1); + if (tmp.isValid()) + return tmp; + } + } + + for(;;) + { + QModelIndex par = m_pModel->parent(idx); + if (!par.isValid() && depth > 0) + break; + + int numRows = m_pModel->rowCount(par); + for (int count = idx.row() - 1; count >= 0; count--) { + QModelIndex tmp = FindNext(m_pModel->index(count, 0, par), false, depth + 1); + if (tmp.isValid()) + return tmp; + } + + if (!par.isValid()) + break; + idx = par; + } + + return QModelIndex(); +} + +void CFinder::OnSelectNext() +{ + bool next = true; + QModelIndex idx = m_pTree->currentIndex(); + if (!(next = idx.isValid())) + idx = m_pModel->index(0, 0); + + //if (QApplication::keyboardModifiers() & Qt::ControlModifier) + if (QApplication::keyboardModifiers() & Qt::ShiftModifier) + idx = FindPrev(idx, next); + else + idx = FindNext(idx, next); + + if (idx.isValid()) + m_pTree->setCurrentIndex(idx); + else + QApplication::beep(); } \ No newline at end of file diff --git a/SandboxiePlus/MiscHelpers/Common/Finder.h b/SandboxiePlus/MiscHelpers/Common/Finder.h index 1d400bd6..e511794a 100644 --- a/SandboxiePlus/MiscHelpers/Common/Finder.h +++ b/SandboxiePlus/MiscHelpers/Common/Finder.h @@ -10,21 +10,21 @@ public: CFinder(QObject* pFilterTarget, QWidget *parent = NULL, int iOptions = eRegExp | eCaseSens | eHighLight); ~CFinder(); + void SetTree(QTreeView* pTree); + static void SetDarkMode(bool bDarkMode) { m_DarkMode = bDarkMode; } static bool GetDarkMode() { return m_DarkMode; } - static QWidget* AddFinder(QWidget* pList, QObject* pFilterTarget, int iOptions = eRegExp | eCaseSens | eHighLight, CFinder** ppFinder = NULL); + static QWidget* AddFinder(QTreeView* pTree, QObject* pFilterTarget, int iOptions = eRegExp | eCaseSens | eHighLight, CFinder** ppFinder = NULL); - bool GetCaseSensitive() const { return m_pCaseSensitive ? m_pCaseSensitive->isChecked() : false; } - bool GetRegExp() const { return m_pRegExp ? m_pRegExp->isChecked() : false; } - bool GetHighLight() const { return m_pHighLight ? m_pHighLight->isChecked() : false; } - int GetColumn() const { return m_pColumn ? m_pColumn->currentData().toInt() : -1; } + QRegularExpression GetSearchExp() const { return m_RegExp; } enum EOptions { eRegExp = 0x01, eCaseSens = 0x02, eHighLight = 0x04, + eHighLightDefault = eHighLight | 0x08, }; signals: @@ -40,9 +40,22 @@ private slots: void OnText(); void OnReturn(); + void OnSelectNext(); + protected: + bool GetCaseSensitive() const { return m_pCaseSensitive ? m_pCaseSensitive->isChecked() : false; } + bool GetRegExp() const { return m_pRegExp ? m_pRegExp->isChecked() : false; } + bool GetHighLight() const { return m_pHighLight ? m_pHighLight->isChecked() : false; } + int GetColumn() const { return m_pColumn ? m_pColumn->currentData().toInt() : -1; } + bool eventFilter(QObject* source, QEvent* event); + virtual bool MatchString(const QString& value); + bool MatchCell(QModelIndex idx, int column); + bool MatchRow(QModelIndex idx); + QModelIndex FindNext(QModelIndex idx, bool next = false, int depth = 0); + QModelIndex FindPrev(QModelIndex idx, bool next = false, int depth = 0); + private: QHBoxLayout* m_pSearchLayout; @@ -53,7 +66,10 @@ private: QComboBox* m_pColumn; QCheckBox* m_pHighLight; - QSortFilterProxyModel* m_pSortProxy; + QRegularExpression m_RegExp; + + QTreeView* m_pTree; + QAbstractProxyModel*m_pModel; QTimer* m_pTimer; diff --git a/SandboxiePlus/MiscHelpers/Common/PanelView.h b/SandboxiePlus/MiscHelpers/Common/PanelView.h index 91a3031f..330a9519 100644 --- a/SandboxiePlus/MiscHelpers/Common/PanelView.h +++ b/SandboxiePlus/MiscHelpers/Common/PanelView.h @@ -136,10 +136,10 @@ public: } private slots: - void SetFilter(const QString& Exp, int iFormat, int Col = -1) // -1 = any + void SetFilter(const QString& Exp, int iOptions, int Col = -1) // -1 = any { - QString ExpStr = ((iFormat & CFinder::eRegExp) == 0) ? Exp : (".*" + QRegularExpression::escape(Exp) + ".*"); - QRegularExpression RegExp(ExpStr, (iFormat & CFinder::eCaseSens) != 0 ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption); + QString ExpStr = ((iOptions & CFinder::eRegExp) == 0) ? Exp : (".*" + QRegularExpression::escape(Exp) + ".*"); + QRegularExpression RegExp(ExpStr, (iOptions & CFinder::eCaseSens) != 0 ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption); ApplyFilter(m_pTreeList, RegExp); } @@ -164,8 +164,6 @@ public: m_pSortProxy->setDynamicSortFilter(true); m_pTreeList->setModel(m_pSortProxy); - ((CSortFilterProxyModel*)m_pSortProxy)->setView(m_pTreeList); - m_pTreeList->setSelectionMode(QAbstractItemView::ExtendedSelection); #ifdef WIN32 diff --git a/SandboxiePlus/MiscHelpers/Common/SortFilterProxyModel.h b/SandboxiePlus/MiscHelpers/Common/SortFilterProxyModel.h index 1347b8ff..4d7809a2 100644 --- a/SandboxiePlus/MiscHelpers/Common/SortFilterProxyModel.h +++ b/SandboxiePlus/MiscHelpers/Common/SortFilterProxyModel.h @@ -14,16 +14,10 @@ public: { m_bHighLight = false; m_iColumn = 0; - m_pView = NULL; this->setSortCaseSensitivity(Qt::CaseInsensitive); } - void setView(QTreeView* pView) - { - m_pView = pView; - } - bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const { if (m_bHighLight) @@ -86,124 +80,16 @@ public slots: QRegularExpression RegExp(ExpStr, (iOptions & CFinder::eCaseSens) != 0 ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption); QModelIndex idx; - //if (m_pView) idx = m_pView->currentIndex(); m_iColumn = Col; m_bHighLight = (iOptions & CFinder::eHighLight) != 0; setFilterKeyColumn(Col); setFilterRegularExpression(RegExp); - //if (m_pView) m_pView->setCurrentIndex(idx); if (m_bHighLight) emit layoutChanged(); } - void SelectNext() - { - if (!m_pView) - return; - - bool next = true; - QModelIndex idx = m_pView->currentIndex(); - if (!(next = idx.isValid())) - idx = index(0, 0); - - //if (QApplication::keyboardModifiers() & Qt::ControlModifier) - if (QApplication::keyboardModifiers() & Qt::ShiftModifier) - idx = FindPrev(idx, next); - else - idx = FindNext(idx, next); - - if (idx.isValid()) - m_pView->setCurrentIndex(idx); - else - QApplication::beep(); - } - protected: bool m_bHighLight; int m_iColumn; - QTreeView* m_pView; - - bool MatchCell(QModelIndex idx, int column) - { - QModelIndex tmp = idx.sibling(idx.row(), column); - - QString str = data(tmp, filterRole()).toString(); - if (str.contains(filterRegularExpression())) - return true; - return false; - } - - bool MatchRow(QModelIndex idx) - { - if (m_iColumn != -1) - return MatchCell(idx, m_iColumn); - - for(int col = 0; col < columnCount(idx); col++) { - if (MatchCell(idx, col)) - return true; - } - return false; - } - - QModelIndex FindNext(QModelIndex idx, bool next = false) - { - if (MatchRow(idx) && !next) - return idx; - - if (hasChildren(idx)) - { - int numRows = rowCount(idx); - for (int count = 0; count < numRows; count++) { - QModelIndex tmp = FindNext(index(count, 0, idx)); - if (tmp.isValid()) - return tmp; - } - } - - do { - QModelIndex par = parent(idx); - - int numRows = rowCount(par); - for (int count = idx.row() + 1; count < numRows; count++) { - QModelIndex tmp = FindNext(index(count, 0, par)); - if (tmp.isValid()) - return tmp; - } - - idx = par; - } while (idx.isValid()); - - return QModelIndex(); - } - - QModelIndex FindPrev(QModelIndex idx, bool next = false) - { - if (MatchRow(idx) && !next) - return idx; - - if (hasChildren(idx)) - { - int numRows = rowCount(idx); - for (int count = numRows-1; count >= 0; count++) { - QModelIndex tmp = FindNext(index(count, 0, idx)); - if (tmp.isValid()) - return tmp; - } - } - - do { - QModelIndex par = parent(idx); - - int numRows = rowCount(par); - for (int count = idx.row() - 1; count >= 0; count--) { - QModelIndex tmp = FindNext(index(count, 0, par)); - if (tmp.isValid()) - return tmp; - } - - idx = par; - } while (idx.isValid()); - - return QModelIndex(); - } }; + diff --git a/SandboxiePlus/QSbieAPI/SbieAPI.cpp b/SandboxiePlus/QSbieAPI/SbieAPI.cpp index 8555b502..f527eecb 100644 --- a/SandboxiePlus/QSbieAPI/SbieAPI.cpp +++ b/SandboxiePlus/QSbieAPI/SbieAPI.cpp @@ -2533,7 +2533,7 @@ bool CSbieAPI::GetMonitor() pos += (len + 1) * sizeof(WCHAR); } - CTraceEntryPtr LogEntry = CTraceEntryPtr(new CTraceEntry(pid, tid, type, LogData)); + CTraceEntryPtr LogEntry = CTraceEntryPtr(new CTraceEntry(0, pid, tid, type, LogData)); QMutexLocker Lock(&m_TraceMutex); m_TraceCache.append(LogEntry); @@ -2570,6 +2570,10 @@ bool CSbieAPI::GetMonitor() ULONG uSize = *(ULONG*)ptr; ptr += sizeof(ULONG); + LONGLONG uTimestamp = *(LONGLONG*)ptr; + ptr += sizeof(LONGLONG); + uSize -= sizeof(LONGLONG); + ULONG uType = *(ULONG*)ptr; ptr += sizeof(ULONG); uSize -= sizeof(ULONG); @@ -2590,7 +2594,7 @@ bool CSbieAPI::GetMonitor() } ptr += uSize; - CTraceEntryPtr LogEntry = CTraceEntryPtr(new CTraceEntry(uPid, uTid, uType, LogData)); + CTraceEntryPtr LogEntry = CTraceEntryPtr(new CTraceEntry(FILETIME2ms(uTimestamp), uPid, uTid, uType, LogData)); QMutexLocker Lock(&m_TraceMutex); m_TraceCache.append(LogEntry); diff --git a/SandboxiePlus/QSbieAPI/SbieTrace.cpp b/SandboxiePlus/QSbieAPI/SbieTrace.cpp index fbb77829..6ac2f302 100644 --- a/SandboxiePlus/QSbieAPI/SbieTrace.cpp +++ b/SandboxiePlus/QSbieAPI/SbieTrace.cpp @@ -60,7 +60,7 @@ QString ErrorString(qint32 err) return Error; } -CTraceEntry::CTraceEntry(quint32 ProcessId, quint32 ThreadId, quint32 Type, const QStringList& LogData) +CTraceEntry::CTraceEntry(quint64 Timestamp, quint32 ProcessId, quint32 ThreadId, quint32 Type, const QStringList& LogData) { m_ProcessId = ProcessId; m_ThreadId = ThreadId; @@ -69,7 +69,7 @@ CTraceEntry::CTraceEntry(quint32 ProcessId, quint32 ThreadId, quint32 Type, cons m_SubType = LogData.length() > 2 ? LogData.at(2) : QString(); m_Type.Flags = Type; - m_TimeStamp = QDateTime::currentDateTime(); // ms resolution + m_TimeStamp = Timestamp ? Timestamp : QDateTime::currentDateTime().toMSecsSinceEpoch(); m_BoxPtr = 0; diff --git a/SandboxiePlus/QSbieAPI/SbieTrace.h b/SandboxiePlus/QSbieAPI/SbieTrace.h index 110035d8..7ba05b46 100644 --- a/SandboxiePlus/QSbieAPI/SbieTrace.h +++ b/SandboxiePlus/QSbieAPI/SbieTrace.h @@ -28,13 +28,13 @@ class QSBIEAPI_EXPORT CTraceEntry : public QSharedData { public: - CTraceEntry(quint32 ProcessId, quint32 ThreadId, quint32 Type, const QStringList& LogData); + CTraceEntry(quint64 Timestamp, quint32 ProcessId, quint32 ThreadId, quint32 Type, const QStringList& LogData); virtual QString GetName() const { return m_Name; } virtual QString GetMessage() const { return m_Message; } virtual quint32 GetProcessId() const { return m_ProcessId; } virtual quint32 GetThreadId() const { return m_ThreadId; } - virtual QDateTime GetTimeStamp() const { return m_TimeStamp; } + virtual quint64 GetTimeStamp() const { return m_TimeStamp; } virtual quint8 GetType() const { return m_Type.Type; } static QListAllTypes(); @@ -72,7 +72,7 @@ protected: QString m_SubType; quint32 m_ProcessId; quint32 m_ThreadId; - QDateTime m_TimeStamp; + quint64 m_TimeStamp; QString m_ProcessName; void* m_BoxPtr; diff --git a/SandboxiePlus/SandMan/Models/TraceModel.cpp b/SandboxiePlus/SandMan/Models/TraceModel.cpp index 2ec38c15..b1f50118 100644 --- a/SandboxiePlus/SandMan/Models/TraceModel.cpp +++ b/SandboxiePlus/SandMan/Models/TraceModel.cpp @@ -144,6 +144,17 @@ void CTraceModel::FreeNode(STreeNode* pNode) //delete pNode; } +bool CTraceModel::TestHighLight(STreeNode* pNode) const +{ + if (m_HighLightExp.isEmpty()) + return false; + for (int i = 0; i < eCount; i++) { + if (NodeData(pNode, Qt::DisplayRole, i).toString().contains(m_HighLightExp)) + return true; + } + return false; +} + QVariant CTraceModel::NodeData(STreeNode* pNode, int role, int section) const { const CTraceEntryPtr& pEntry = pNode->pEntry; @@ -183,9 +194,10 @@ QVariant CTraceModel::NodeData(STreeNode* pNode, int role, int section) const if(!m_bTree) { QString Name = pEntry->GetProcessName(); return QString("%1 (%2, %3) - %4").arg(Name.isEmpty() ? tr("Unknown") : Name) - .arg(pEntry->GetProcessId()).arg(pEntry->GetThreadId()).arg(pEntry->GetTimeStamp().toString("hh:mm:ss.zzz")); + .arg(pEntry->GetProcessId()).arg(pEntry->GetThreadId()) + .arg(QDateTime::fromMSecsSinceEpoch(pEntry->GetTimeStamp()).toString("hh:mm:ss.zzz")); } else - return pEntry->GetTimeStamp().toString("hh:mm:ss.zzz"); + return QDateTime::fromMSecsSinceEpoch(pEntry->GetTimeStamp()).toString("hh:mm:ss.zzz"); } case eType: return pEntry->GetTypeStr(); case eStatus: return pEntry->GetStautsStr(); @@ -198,6 +210,18 @@ QVariant CTraceModel::NodeData(STreeNode* pNode, int role, int section) const } } } + case Qt::BackgroundRole: + { + if(!CTreeItemModel::GetDarkMode()) + return TestHighLight(pNode) ? QColor(Qt::yellow) : QVariant(); + break; + } + case Qt::ForegroundRole: + { + if(CTreeItemModel::GetDarkMode()) + return TestHighLight(pNode) ? QColor(Qt::yellow) : QVariant(); + break; + } } return QVariant(); diff --git a/SandboxiePlus/SandMan/Models/TraceModel.h b/SandboxiePlus/SandMan/Models/TraceModel.h index 094d0b40..78b6a332 100644 --- a/SandboxiePlus/SandMan/Models/TraceModel.h +++ b/SandboxiePlus/SandMan/Models/TraceModel.h @@ -15,6 +15,8 @@ public: void SetTree(bool bTree) { m_bTree = bTree; } bool IsTree() const { return m_bTree; } + void SetHighLight(const QString& Exp) { m_HighLightExp = Exp; } + QList Sync(const QVector& EntryList); CTraceEntryPtr GetEntry(const QModelIndex& index) const; @@ -96,5 +98,9 @@ protected: STreeNode* m_Root; QHash m_Branches; + QString m_HighLightExp; + + bool TestHighLight(STreeNode* pNode) const; + static PoolAllocator m_NodeAllocator; }; diff --git a/SandboxiePlus/SandMan/Views/SbieView.cpp b/SandboxiePlus/SandMan/Views/SbieView.cpp index a32cd788..fa414955 100644 --- a/SandboxiePlus/SandMan/Views/SbieView.cpp +++ b/SandboxiePlus/SandMan/Views/SbieView.cpp @@ -25,7 +25,7 @@ CSbieView::CSbieView(QWidget* parent) : CPanelView(parent) //m_UserConfigChanged = false; - m_pSbieModel = new CSbieModel(); + m_pSbieModel = new CSbieModel(this); m_pSbieModel->SetTree(true); m_pSbieModel->SetUseIcons(true); @@ -50,7 +50,6 @@ CSbieView::CSbieView(QWidget* parent) : CPanelView(parent) m_pSbieModel->SetLargeIcons(); m_pSbieTree->setIconSize(QSize(32, 32)); } - ((CSortFilterProxyModel*)m_pSortProxy)->setView(m_pSbieTree); m_pSbieTree->setDragDropMode(QAbstractItemView::InternalMove); @@ -82,7 +81,9 @@ CSbieView::CSbieView(QWidget* parent) : CPanelView(parent) m_pMainLayout->addWidget(m_pSbieTree); // - m_pMainLayout->addWidget(new CFinder(m_pSortProxy, this)); + CFinder* pFinder = new CFinder(m_pSortProxy, this); + m_pMainLayout->addWidget(pFinder); + pFinder->SetTree(m_pSbieTree); connect(m_pSbieModel, SIGNAL(ToolTipCallback(const QVariant&, QString&)), this, SLOT(OnToolTipCallback(const QVariant&, QString&)), Qt::DirectConnection); diff --git a/SandboxiePlus/SandMan/Views/TraceView.cpp b/SandboxiePlus/SandMan/Views/TraceView.cpp index 3dc57d68..035fb45f 100644 --- a/SandboxiePlus/SandMan/Views/TraceView.cpp +++ b/SandboxiePlus/SandMan/Views/TraceView.cpp @@ -51,6 +51,9 @@ CTraceTree::CTraceTree(QWidget* parent) : CPanelWidget(parent) { + m_bHighLight = false; + //m_FilterCol = -1; + m_pTreeList->setAlternatingRowColors(theConf->GetBool("Options/AltRowColors", false)); m_pTreeList->setSelectionMode(QAbstractItemView::ExtendedSelection); @@ -83,7 +86,8 @@ CTraceTree::CTraceTree(QWidget* parent) //connect(m_pBoxTree, SIGNAL(ColumnChanged(int, bool)), this, SLOT(OnColumnsChanged())); //m_pMainLayout->addWidget(CFinder::AddFinder(m_pTreeList, m_pSortProxy)); - m_pMainLayout->addWidget(CFinder::AddFinder(m_pTreeList, this, CFinder::eHighLight)); + m_pMainLayout->addWidget(CFinder::AddFinder(m_pTreeList, this, CFinder::eHighLightDefault)); + //QObject::connect(pFinder, SIGNAL(SelectNext()), this, SLOT(SelectNext())); QByteArray Columns = theConf->GetBlob("MainWindow/TraceLog_Columns"); @@ -98,6 +102,23 @@ CTraceTree::~CTraceTree() theConf->SetBlob("MainWindow/TraceLog_Columns", GetView()->header()->saveState()); } +void CTraceTree::SetFilter(const QString& Exp, int iOptions, int Column) +{ + bool bReset = m_FilterExp != Exp || m_bHighLight != ((iOptions & CFinder::eHighLight) != 0); + + //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(); +} + + + //////////////////////////////////////////////////////////////////////////////////////// // CMonitorList @@ -117,8 +138,6 @@ CMonitorList::CMonitorList(QWidget* parent) m_pSortProxy->setDynamicSortFilter(true); m_pTreeList->setModel(m_pSortProxy); - m_pSortProxy->setView(m_pTreeList); - QStyle* pStyle = QStyleFactory::create("windows"); m_pTreeList->setStyle(pStyle); @@ -163,8 +182,6 @@ CTraceView::CTraceView(bool bStandAlone, QWidget* parent) : QWidget(parent) m_LastCount = 0; m_bUpdatePending = false; - m_bHighLight = false; - //m_FilterCol = -1; m_FilterPid = 0; m_FilterTid = 0; m_FilterStatus = 0; @@ -177,7 +194,7 @@ CTraceView::CTraceView(bool bStandAlone, QWidget* parent) : QWidget(parent) m_pMonitorMode = m_pTraceToolBar->addAction(CSandMan::GetIcon("Monitor"), tr("Monitor mode"), this, SLOT(OnSetMode())); m_pMonitorMode->setCheckable(true); - m_pMonitorMode->setChecked(theConf->GetBool("Options/UseMonitorMode")); + m_pMonitorMode->setChecked(theConf->GetBool("Options/UseMonitorMode", true)); m_pTraceTree = m_pTraceToolBar->addAction(CSandMan::GetIcon("Tree"), tr("Show as task tree"), this, SLOT(OnSetTree())); m_pTraceTree->setCheckable(true); @@ -258,7 +275,7 @@ CTraceView::CTraceView(bool bStandAlone, QWidget* parent) : QWidget(parent) m_pLayout->addWidget(m_pTrace); - QObject::connect(m_pTrace, SIGNAL(FilterSet(const QString&, int, int)), this, SLOT(SetFilter(const QString&, int, int))); + QObject::connect(m_pTrace, SIGNAL(FilterChanged()), this, SLOT(OnFilterChanged())); m_pMonitor = new CMonitorList(this); m_pMonitor->m_pMonitorModel->SetObjTree(m_pObjectTree->isChecked()); @@ -335,8 +352,8 @@ void CTraceView::Refresh() if (m_LastCount == ResourceLog.count()) return; - //bool bHasFilter = !m_FilterExp.pattern().isEmpty(); - bool bHasFilter = !m_FilterExp.isEmpty(); + //bool bHasFilter = !m_pTrace->m_FilterExp.pattern().isEmpty(); + bool bHasFilter = !m_pTrace->m_FilterExp.isEmpty(); quint64 start = GetCurCycle(); for (; i < ResourceLog.count(); i++) @@ -381,12 +398,12 @@ void CTraceView::Refresh() } else { - if (bHasFilter && !m_bHighLight) { - if (!pEntry->GetName().contains(m_FilterExp) - && !pEntry->GetMessage().contains(m_FilterExp) - //&& !pEntry->GetTypeStr().contains(m_FilterExp) // dont filter on non static strings !!! - //&& !pEntry->GetStautsStr().contains(m_FilterExp) // dont filter on non static strings !!! - && !pEntry->GetProcessName().contains(m_FilterExp)) + if (bHasFilter && !m_pTrace->m_bHighLight) { + if (!pEntry->GetName().contains(m_pTrace->m_FilterExp) + && !pEntry->GetMessage().contains(m_pTrace->m_FilterExp) + //&& !pEntry->GetTypeStr().contains(m_pTrace->m_FilterExp) // dont filter on non static strings !!! + //&& !pEntry->GetStautsStr().contains(m_pTrace->m_FilterExp) // dont filter on non static strings !!! + && !pEntry->GetProcessName().contains(m_pTrace->m_FilterExp)) continue; } @@ -434,6 +451,11 @@ void CTraceView::Refresh() } else { + if (m_pTrace->m_bHighLight) + m_pTrace->m_pTraceModel->SetHighLight(m_pTrace->m_FilterExp); + else + m_pTrace->m_pTraceModel->SetHighLight(QString()); + quint64 start = GetCurCycle(); QList NewBranches = m_pTrace->m_pTraceModel->Sync(m_TraceList); qDebug() << "Sync took" << (GetCurCycle() - start) / 1000000.0 << "s"; @@ -538,15 +560,8 @@ void CTraceView::UpdateFilters() } } -void CTraceView::SetFilter(const QString& Exp, int iOptions, int Col) +void CTraceView::OnFilterChanged() { - //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; - m_FullRefresh = true; } @@ -626,7 +641,7 @@ void CTraceView::SaveToFile() const CTraceEntryPtr& pEntry = ResourceLog.at(i); QStringList Line; - Line.append(pEntry->GetTimeStamp().toString("hh:mm:ss.zzz")); + Line.append(QDateTime::fromMSecsSinceEpoch(pEntry->GetTimeStamp()).toString("hh:mm:ss.zzz")); QString Name = pEntry->GetProcessName(); Line.append(Name.isEmpty() ? tr("Unknown") : Name); Line.append(QString("%1").arg(pEntry->GetProcessId())); diff --git a/SandboxiePlus/SandMan/Views/TraceView.h b/SandboxiePlus/SandMan/Views/TraceView.h index 076a261a..3b751644 100644 --- a/SandboxiePlus/SandMan/Views/TraceView.h +++ b/SandboxiePlus/SandMan/Views/TraceView.h @@ -5,8 +5,8 @@ #include "../Models/SbieModel.h" #include "../Models/TraceModel.h" #include "../Models/MonitorModel.h" +#include "../../MiscHelpers/Common/SortFilterProxyModel.h" -class CTraceFilterProxyModel; class CTraceTree : public CPanelWidget { @@ -19,13 +19,20 @@ public: CTraceModel* m_pTraceModel; public slots: - void SetFilter(const QString& Exp, int iOptions = 0, int Column = -1) { - emit FilterSet(Exp, iOptions, Column); - } - void SelectNext() {} + void SetFilter(const QString& Exp, int iOptions = 0, int Column = -1); signals: - void FilterSet(const QString& Exp, int iOptions = 0, int Column = -1); + void FilterChanged(); + +protected: + friend class CTraceView; + + QString GetFilterExp() const { return m_FilterExp; } + + //QRegularExpression m_FilterExp; + QString m_FilterExp; + bool m_bHighLight; + //int m_FilterCol; }; class CMonitorList : public CPanelWidget @@ -61,7 +68,7 @@ public slots: private slots: void UpdateFilters(); - void SetFilter(const QString& Exp, int iOptions = 0, int Col = -1); // -1 = any + void OnFilterChanged(); void SaveToFile(); @@ -85,10 +92,6 @@ protected: protected: bool m_FullRefresh; - //QRegularExpression m_FilterExp; - QString m_FilterExp; - bool m_bHighLight; - //int m_FilterCol; quint32 m_FilterPid; quint32 m_FilterTid; QList m_FilterTypes; diff --git a/SandboxiePlus/SandMan/Windows/RecoveryWindow.cpp b/SandboxiePlus/SandMan/Windows/RecoveryWindow.cpp index 4ef98c75..17ce9a0f 100644 --- a/SandboxiePlus/SandMan/Windows/RecoveryWindow.cpp +++ b/SandboxiePlus/SandMan/Windows/RecoveryWindow.cpp @@ -65,7 +65,7 @@ CRecoveryWindow::CRecoveryWindow(const CSandBoxPtr& pBox, bool bImmediate, QWidg ui.btnDeleteAll->setVisible(false); - m_pFileModel = new CSimpleTreeModel(); + m_pFileModel = new CSimpleTreeModel(this); m_pFileModel->SetUseIcons(true); m_pFileModel->AddColumn(tr("File Name"), "FileName"); m_pFileModel->AddColumn(tr("File Size"), "FileSize"); @@ -79,13 +79,14 @@ CRecoveryWindow::CRecoveryWindow(const CSandBoxPtr& pBox, bool bImmediate, QWidg //ui.treeFiles->setItemDelegate(theGUI->GetItemDelegate()); ui.treeFiles->setModel(m_pSortProxy); - ((CSortFilterProxyModel*)m_pSortProxy)->setView(ui.treeFiles); ui.treeFiles->setSelectionMode(QAbstractItemView::ExtendedSelection); ui.treeFiles->setSortingEnabled(true); //ui.treeFiles->setUniformRowHeights(true); - ui.gridLayout->addWidget(new CFinder(m_pSortProxy, this, true), 3, 0, 1, 5); + CFinder* pFinder = new CFinder(m_pSortProxy, this); + ui.gridLayout->addWidget(pFinder, 3, 0, 1, 5); + pFinder->SetTree(ui.treeFiles); ui.finder->deleteLater(); // remove place holder //connect(ui.treeFiles, SIGNAL(clicked(const QModelIndex&)), this, SLOT(UpdateSnapshot(const QModelIndex&))); diff --git a/SandboxiePlus/SandMan/Windows/SnapshotsWindow.cpp b/SandboxiePlus/SandMan/Windows/SnapshotsWindow.cpp index fe68cbc8..be94c8d4 100644 --- a/SandboxiePlus/SandMan/Windows/SnapshotsWindow.cpp +++ b/SandboxiePlus/SandMan/Windows/SnapshotsWindow.cpp @@ -34,7 +34,7 @@ CSnapshotsWindow::CSnapshotsWindow(const CSandBoxPtr& pBox, QWidget *parent) ui.treeSnapshots->setItemDelegate(new CTreeItemDelegate()); ui.treeSnapshots->setExpandsOnDoubleClick(false); - m_pSnapshotModel = new CSimpleTreeModel(); + m_pSnapshotModel = new CSimpleTreeModel(this); m_pSnapshotModel->AddColumn(tr("Snapshot"), "Name"); /*m_pSortProxy = new CSortFilterProxyModel(this);