├── ProcMonX ├── ProcMonX.h ├── Settings.cpp ├── TraceData.cpp ├── TraceData.h ├── SortedFilteredVector.cpp ├── res │ ├── ok.ico │ ├── Play.ico │ ├── Stop.ico │ ├── add.ico │ ├── file.ico │ ├── find.ico │ ├── gear.ico │ ├── heap.ico │ ├── job.ico │ ├── save.ico │ ├── Driver.ico │ ├── Modules.ico │ ├── Pause.ico │ ├── cancel.ico │ ├── debug.ico │ ├── dll-add.ico │ ├── event.ico │ ├── event2.ico │ ├── event3.ico │ ├── filter.ico │ ├── handle.ico │ ├── heap2.ico │ ├── memory.ico │ ├── network.ico │ ├── object.ico │ ├── rename.ico │ ├── save_as.ico │ ├── search.ico │ ├── stack.ico │ ├── storage.ico │ ├── threads.ico │ ├── tools.ico │ ├── ProcMonX.ico │ ├── clip_copy.ico │ ├── letter-k.ico │ ├── letter-u.ico │ ├── ok_button.ico │ ├── processes.ico │ ├── registry.ico │ ├── autoscroll.ico │ ├── dll-delete.ico │ ├── execute-info.ico │ ├── filter-add.ico │ ├── filter-edit.ico │ ├── folder_open.ico │ ├── process-new.ico │ ├── properties.ico │ ├── threads-new.ico │ ├── arrow_up_blue.ico │ ├── delete_button.ico │ ├── filter-delete.ico │ ├── process-delete.ico │ ├── threads-delete.ico │ ├── arrow_down_blue.ico │ └── document_flat-download.ico ├── ProcMonX.rc ├── ClipboardHelper.h ├── SerializerFactory.h ├── pch.cpp ├── Settings.h ├── packages.config ├── FilterFactory.h ├── EventNameFilter.h ├── PropertyNameFilter.h ├── PropertyValueFilter.h ├── DialogHelper.h ├── CSVEventDataSerializer.h ├── ProcessNameFilter.h ├── EventNameFilter.cpp ├── FormatHelper.h ├── ProcessNameFilter.cpp ├── ProcessIdFilter.h ├── SerializerFactory.cpp ├── IEventDataSerializer.h ├── SymbolManager.h ├── CSVEventDataSerializer.cpp ├── PropertyNameFilter.cpp ├── ClipboardHelper.cpp ├── SortHelper.h ├── PropertyValueFilter.cpp ├── EventConfiguration.h ├── AboutDlg.cpp ├── ProcessIdFilter.cpp ├── FilterConfiguration.h ├── IniFile.h ├── Interfaces.h ├── DialogHelper.cpp ├── ProcMonX.cpp ├── BinaryEventDataSerializer.h ├── AboutDlg.h ├── FilterFactory.cpp ├── manifest.xml ├── EventPropertiesDlg.h ├── SymbolsHandler.h ├── SortHelper.cpp ├── QuickFindDlg.h ├── SymbolManager.cpp ├── CallStackDlg.h ├── QuickFindDlg.cpp ├── pch.h ├── ViewBase.h ├── SortedFilteredVector.h ├── FiltersDlg.h ├── ColumnManager.h ├── EventConfiguration.cpp ├── FilterConfiguration.cpp ├── IniFile.cpp ├── EventsDlg.h ├── BinaryEventDataSerializer.cpp ├── EventPropertiesDlg.cpp ├── CallStackDlg.cpp ├── MainFrm.h ├── View.h ├── SymbolsHandler.cpp ├── resource.h ├── ColumnManager.cpp ├── EventsDlg.cpp ├── FiltersDlg.cpp └── FormatHelper.cpp ├── procmonxv2.png ├── Utils ├── Utils.cpp ├── pch.cpp ├── pch.h ├── CompoundFileReaderWriter.cpp ├── Utils.vcxproj.filters ├── CompoundFile.h ├── CompoundFileReaderWriter.h ├── CompoundFile.cpp └── Utils.vcxproj ├── EventTracing ├── packages.config ├── pch.cpp ├── StringCompareFilterBase.h ├── pch.h ├── FilterBase.cpp ├── EventParser.h ├── FilterBase.h ├── StringCompareFilterBase.cpp ├── EventTracing.vcxproj.filters ├── EventData.h ├── TraceManager.h ├── EventParser.cpp ├── EventData.cpp ├── KernelEvents.cpp └── KernelEvents.h ├── ProcMonC ├── packages.config ├── ProcMonC.vcxproj.filters └── ProcMonC.cpp ├── README.md ├── LICENSE ├── ProcMonX.sln.startup.json ├── .gitattributes ├── ProcMonX.sln └── .gitignore /ProcMonX/ProcMonX.h: -------------------------------------------------------------------------------- 1 | // ProcMonX.h 2 | -------------------------------------------------------------------------------- /ProcMonX/Settings.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Settings.h" 3 | -------------------------------------------------------------------------------- /ProcMonX/TraceData.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "TraceData.h" 3 | -------------------------------------------------------------------------------- /ProcMonX/TraceData.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class TraceData { 4 | }; 5 | 6 | -------------------------------------------------------------------------------- /procmonxv2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/procmonxv2.png -------------------------------------------------------------------------------- /ProcMonX/SortedFilteredVector.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SortedFilteredVector.h" 3 | -------------------------------------------------------------------------------- /ProcMonX/res/ok.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/ok.ico -------------------------------------------------------------------------------- /ProcMonX/ProcMonX.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/ProcMonX.rc -------------------------------------------------------------------------------- /ProcMonX/res/Play.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/Play.ico -------------------------------------------------------------------------------- /ProcMonX/res/Stop.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/Stop.ico -------------------------------------------------------------------------------- /ProcMonX/res/add.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/add.ico -------------------------------------------------------------------------------- /ProcMonX/res/file.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/file.ico -------------------------------------------------------------------------------- /ProcMonX/res/find.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/find.ico -------------------------------------------------------------------------------- /ProcMonX/res/gear.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/gear.ico -------------------------------------------------------------------------------- /ProcMonX/res/heap.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/heap.ico -------------------------------------------------------------------------------- /ProcMonX/res/job.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/job.ico -------------------------------------------------------------------------------- /ProcMonX/res/save.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/save.ico -------------------------------------------------------------------------------- /ProcMonX/res/Driver.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/Driver.ico -------------------------------------------------------------------------------- /ProcMonX/res/Modules.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/Modules.ico -------------------------------------------------------------------------------- /ProcMonX/res/Pause.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/Pause.ico -------------------------------------------------------------------------------- /ProcMonX/res/cancel.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/cancel.ico -------------------------------------------------------------------------------- /ProcMonX/res/debug.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/debug.ico -------------------------------------------------------------------------------- /ProcMonX/res/dll-add.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/dll-add.ico -------------------------------------------------------------------------------- /ProcMonX/res/event.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/event.ico -------------------------------------------------------------------------------- /ProcMonX/res/event2.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/event2.ico -------------------------------------------------------------------------------- /ProcMonX/res/event3.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/event3.ico -------------------------------------------------------------------------------- /ProcMonX/res/filter.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/filter.ico -------------------------------------------------------------------------------- /ProcMonX/res/handle.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/handle.ico -------------------------------------------------------------------------------- /ProcMonX/res/heap2.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/heap2.ico -------------------------------------------------------------------------------- /ProcMonX/res/memory.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/memory.ico -------------------------------------------------------------------------------- /ProcMonX/res/network.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/network.ico -------------------------------------------------------------------------------- /ProcMonX/res/object.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/object.ico -------------------------------------------------------------------------------- /ProcMonX/res/rename.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/rename.ico -------------------------------------------------------------------------------- /ProcMonX/res/save_as.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/save_as.ico -------------------------------------------------------------------------------- /ProcMonX/res/search.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/search.ico -------------------------------------------------------------------------------- /ProcMonX/res/stack.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/stack.ico -------------------------------------------------------------------------------- /ProcMonX/res/storage.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/storage.ico -------------------------------------------------------------------------------- /ProcMonX/res/threads.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/threads.ico -------------------------------------------------------------------------------- /ProcMonX/res/tools.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/tools.ico -------------------------------------------------------------------------------- /ProcMonX/res/ProcMonX.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/ProcMonX.ico -------------------------------------------------------------------------------- /ProcMonX/res/clip_copy.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/clip_copy.ico -------------------------------------------------------------------------------- /ProcMonX/res/letter-k.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/letter-k.ico -------------------------------------------------------------------------------- /ProcMonX/res/letter-u.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/letter-u.ico -------------------------------------------------------------------------------- /ProcMonX/res/ok_button.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/ok_button.ico -------------------------------------------------------------------------------- /ProcMonX/res/processes.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/processes.ico -------------------------------------------------------------------------------- /ProcMonX/res/registry.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/registry.ico -------------------------------------------------------------------------------- /ProcMonX/res/autoscroll.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/autoscroll.ico -------------------------------------------------------------------------------- /ProcMonX/res/dll-delete.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/dll-delete.ico -------------------------------------------------------------------------------- /ProcMonX/res/execute-info.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/execute-info.ico -------------------------------------------------------------------------------- /ProcMonX/res/filter-add.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/filter-add.ico -------------------------------------------------------------------------------- /ProcMonX/res/filter-edit.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/filter-edit.ico -------------------------------------------------------------------------------- /ProcMonX/res/folder_open.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/folder_open.ico -------------------------------------------------------------------------------- /ProcMonX/res/process-new.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/process-new.ico -------------------------------------------------------------------------------- /ProcMonX/res/properties.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/properties.ico -------------------------------------------------------------------------------- /ProcMonX/res/threads-new.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/threads-new.ico -------------------------------------------------------------------------------- /ProcMonX/res/arrow_up_blue.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/arrow_up_blue.ico -------------------------------------------------------------------------------- /ProcMonX/res/delete_button.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/delete_button.ico -------------------------------------------------------------------------------- /ProcMonX/res/filter-delete.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/filter-delete.ico -------------------------------------------------------------------------------- /ProcMonX/res/process-delete.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/process-delete.ico -------------------------------------------------------------------------------- /ProcMonX/res/threads-delete.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/threads-delete.ico -------------------------------------------------------------------------------- /Utils/Utils.cpp: -------------------------------------------------------------------------------- 1 | // Utils.cpp : Defines the functions for the static library. 2 | // 3 | 4 | #include "pch.h" 5 | 6 | -------------------------------------------------------------------------------- /ProcMonX/res/arrow_down_blue.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/arrow_down_blue.ico -------------------------------------------------------------------------------- /ProcMonX/res/document_flat-download.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/ProcMonXv2/HEAD/ProcMonX/res/document_flat-download.ico -------------------------------------------------------------------------------- /ProcMonX/ClipboardHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class ClipboardHelper final { 4 | public: 5 | static bool CopyText(HWND hWnd, const CString& text); 6 | }; 7 | 8 | -------------------------------------------------------------------------------- /EventTracing/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ProcMonC/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Utils/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: source file corresponding to the pre-compiled header 2 | 3 | #include "pch.h" 4 | 5 | // When you are using pre-compiled headers, this source file is necessary for compilation to succeed. 6 | -------------------------------------------------------------------------------- /EventTracing/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: source file corresponding to the pre-compiled header 2 | 3 | #include "pch.h" 4 | 5 | // When you are using pre-compiled headers, this source file is necessary for compilation to succeed. 6 | -------------------------------------------------------------------------------- /ProcMonX/SerializerFactory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "IEventDataSerializer.h" 4 | 5 | struct SerializerFactory { 6 | static std::unique_ptr CreateFromExtension(const CString& ext); 7 | }; 8 | 9 | -------------------------------------------------------------------------------- /ProcMonX/pch.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // ProcMonX.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "pch.h" 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Process Monitor X v2 2 | 3 | Procmon-like tool that uses Event Tracing for Windows (ETW) instead of a kernel driver to provide event information. 4 | 5 | ![](https://github.com/zodiacon/ProcMonXv2/blob/master/procmonxv2.png) 6 | -------------------------------------------------------------------------------- /ProcMonX/Settings.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct Settings { 4 | WINDOWPLACEMENT WindowPlacement{ sizeof(WindowPlacement) }; 5 | LOGFONT Font{}; 6 | bool AlwaysOnTop{ false }; 7 | 8 | bool Save(PCWSTR path); 9 | bool Load(PCWSTR path); 10 | }; 11 | -------------------------------------------------------------------------------- /ProcMonX/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /ProcMonX/FilterFactory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "FilterBase.h" 4 | 5 | struct FilterFactory { 6 | static std::vector GetFilterNames(); 7 | static std::shared_ptr CreateFilter(PCWSTR name, CompareType compare, PCWSTR params, FilterAction action); 8 | }; 9 | 10 | -------------------------------------------------------------------------------- /ProcMonX/EventNameFilter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "StringCompareFilterBase.h" 3 | 4 | class EventNameFilter : public StringCompareFilterBase { 5 | public: 6 | EventNameFilter(std::wstring name, CompareType type, FilterAction action); 7 | 8 | virtual FilterAction Eval(FilterContext& context) const override; 9 | 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /ProcMonX/PropertyNameFilter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "StringCompareFilterBase.h" 3 | 4 | class PropertyNameFilter : public StringCompareFilterBase { 5 | public: 6 | PropertyNameFilter(std::wstring name, CompareType type, FilterAction action); 7 | 8 | virtual FilterAction Eval(FilterContext& context) const override; 9 | 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /ProcMonX/PropertyValueFilter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "StringCompareFilterBase.h" 3 | 4 | class PropertyValueFilter final : public StringCompareFilterBase { 5 | public: 6 | PropertyValueFilter(std::wstring name, CompareType type, FilterAction action); 7 | 8 | virtual FilterAction Eval(FilterContext& context) const override; 9 | }; 10 | 11 | -------------------------------------------------------------------------------- /ProcMonX/DialogHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | constexpr WCHAR SaveLoadIniFilter[] = L"ini files (*.ini)\0*.ini\0All Files\0*.*\0"; 4 | 5 | class DialogHelper abstract { 6 | public: 7 | static void AdjustOKCancelButtons(CWindow* dlg); 8 | static bool AddIconToButton(CWindow* dlg, WORD id, WORD icon); 9 | static void SetDialogIcon(CWindow* dlg, UINT icon); 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /ProcMonX/CSVEventDataSerializer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "IEventDataSerializer.h" 3 | 4 | class CSVEventDataSerializer : public IEventDataSerializer { 5 | public: 6 | virtual bool Save(const std::vector>& events, const EventDataSerializerOptions& options, PCWSTR path) override; 7 | virtual std::vector> Load(PCWSTR path) override; 8 | }; 9 | 10 | -------------------------------------------------------------------------------- /ProcMonX/ProcessNameFilter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "StringCompareFilterBase.h" 3 | 4 | class ProcessNameFilter final : public StringCompareFilterBase { 5 | public: 6 | using StringCompareFilterBase::StringCompareFilterBase; 7 | 8 | ProcessNameFilter(std::wstring name, CompareType type, FilterAction action); 9 | 10 | virtual FilterAction Eval(FilterContext& context) const override; 11 | 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /ProcMonX/EventNameFilter.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "EventNameFilter.h" 3 | #include "EventData.h" 4 | 5 | EventNameFilter::EventNameFilter(std::wstring name, CompareType type, FilterAction action) : 6 | StringCompareFilterBase(L"Event Name", name, type, action) { 7 | } 8 | 9 | FilterAction EventNameFilter::Eval(FilterContext& context) const { 10 | return Compare(context.Data->GetEventName()); 11 | } 12 | -------------------------------------------------------------------------------- /ProcMonX/FormatHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "EventData.h" 3 | 4 | struct FormatHelper { 5 | static std::wstring FormatProperty(const EventData* data, const EventProperty& prop); 6 | static CString FormatTime(LONGLONG ts); 7 | static CString VirtualAllocFlagsToString(DWORD flags, bool withNumeric = false); 8 | static CString MajorFunctionToString(UCHAR mf); 9 | static PCWSTR ObjectTypeToString(int type); 10 | }; 11 | 12 | -------------------------------------------------------------------------------- /ProcMonX/ProcessNameFilter.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ProcessNameFilter.h" 3 | #include "EventData.h" 4 | 5 | ProcessNameFilter::ProcessNameFilter(std::wstring name, CompareType type, FilterAction action) : 6 | StringCompareFilterBase(L"Process Name", name, type, action) { 7 | } 8 | 9 | FilterAction ProcessNameFilter::Eval(FilterContext& context) const { 10 | return Compare(context.Data->GetProcessName()); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /ProcMonX/ProcessIdFilter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "FilterBase.h" 4 | 5 | class ProcessIdFilter : public FilterBase { 6 | public: 7 | ProcessIdFilter(DWORD pid, CompareType compare, FilterAction action); 8 | 9 | void SetProcessId(DWORD pid); 10 | 11 | // Inherited via FilterBase 12 | virtual FilterAction Eval(FilterContext& context) const override; 13 | virtual bool InitFromParams(const std::wstring& params) override; 14 | virtual std::wstring GetParams() override; 15 | 16 | private: 17 | DWORD _pid; 18 | }; 19 | 20 | -------------------------------------------------------------------------------- /ProcMonX/SerializerFactory.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SerializerFactory.h" 3 | #include "CSVEventDataSerializer.h" 4 | #include "BinaryEventDataSerializer.h" 5 | 6 | std::unique_ptr SerializerFactory::CreateFromExtension(const CString& ext) { 7 | auto str(ext); 8 | str.MakeLower(); 9 | 10 | if (str == "pmx") 11 | return std::make_unique(); 12 | if (str == "csv") 13 | return std::make_unique(); 14 | 15 | return nullptr; 16 | } 17 | -------------------------------------------------------------------------------- /ProcMonX/IEventDataSerializer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "EventData.h" 4 | 5 | struct EventDataSerializerOptions { 6 | bool ResolveSymbols{ false }; 7 | bool WriteHeaderLine{ true }; 8 | bool CompressOutput{ false }; 9 | uint32_t StartIndex{ (uint32_t)-1 }; 10 | }; 11 | 12 | struct IEventDataSerializer abstract { 13 | virtual bool Save(const std::vector>& events, const EventDataSerializerOptions& options, PCWSTR path) = 0; 14 | virtual std::vector> Load(PCWSTR path) = 0; 15 | }; 16 | 17 | -------------------------------------------------------------------------------- /EventTracing/StringCompareFilterBase.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "FilterBase.h" 3 | 4 | class StringCompareFilterBase abstract : public FilterBase { 5 | public: 6 | using FilterBase::FilterBase; 7 | 8 | protected: 9 | StringCompareFilterBase(std::wstring name, std::wstring text, CompareType type, FilterAction action); 10 | FilterAction Compare(const std::wstring& str) const; 11 | 12 | virtual bool InitFromParams(const std::wstring& params) override; 13 | virtual std::wstring GetParams() override; 14 | 15 | private: 16 | std::wstring _text; 17 | }; 18 | 19 | -------------------------------------------------------------------------------- /ProcMonX/SymbolManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SymbolsHandler.h" 4 | 5 | class SymbolManager { 6 | public: 7 | static SymbolManager& Get(); 8 | ~SymbolManager(); 9 | void Term(); 10 | 11 | SymbolsHandler* GetCommon(); 12 | SymbolsHandler* GetForProcess(DWORD pid); 13 | 14 | std::unique_ptr GetSymbolFromAddress(DWORD pid, DWORD64 address, PDWORD64 offset = nullptr); 15 | 16 | private: 17 | SymbolManager(); 18 | 19 | SymbolsHandler _commonSymbols; 20 | std::unordered_map> _procSymbols; 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /ProcMonX/CSVEventDataSerializer.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "CSVEventDataSerializer.h" 3 | #include 4 | 5 | bool CSVEventDataSerializer::Save(const std::vector>& events, const EventDataSerializerOptions& options, PCWSTR path) { 6 | std::ofstream out; 7 | out.open(path); 8 | if(out.fail()) 9 | return false; 10 | 11 | for (auto& evt : events) { 12 | } 13 | return false; 14 | } 15 | 16 | std::vector> CSVEventDataSerializer::Load(PCWSTR path) { 17 | return std::vector>(); 18 | } 19 | -------------------------------------------------------------------------------- /ProcMonX/PropertyNameFilter.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "EventData.h" 3 | #include "PropertyNameFilter.h" 4 | 5 | PropertyNameFilter::PropertyNameFilter(std::wstring name, CompareType type, FilterAction action) 6 | : StringCompareFilterBase(L"Property Value", name, type, action) { 7 | } 8 | 9 | FilterAction PropertyNameFilter::Eval(FilterContext& context) const { 10 | auto action = FilterAction::None; 11 | for (auto& prop : context.Data->GetProperties()) { 12 | action = Compare(prop.Name); 13 | if (action == GetAction()) 14 | return action; 15 | } 16 | return action; 17 | } 18 | -------------------------------------------------------------------------------- /ProcMonX/ClipboardHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ClipboardHelper.h" 3 | 4 | 5 | bool ClipboardHelper::CopyText(HWND hWnd, const CString& text) { 6 | if (::OpenClipboard(hWnd)) { 7 | ::EmptyClipboard(); 8 | auto size = (text.GetLength() + 1) * sizeof(WCHAR); 9 | auto hData = ::GlobalAlloc(GMEM_MOVEABLE, size); 10 | if (hData) { 11 | auto p = ::GlobalLock(hData); 12 | if (p) { 13 | ::memcpy(p, text, size); 14 | ::GlobalUnlock(p); 15 | ::SetClipboardData(CF_UNICODETEXT, hData); 16 | } 17 | } 18 | ::CloseClipboard(); 19 | if (hData) 20 | return true; 21 | } 22 | return false; 23 | } 24 | -------------------------------------------------------------------------------- /Utils/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: This is a precompiled header file. 2 | // Files listed below are compiled only once, improving build performance for future builds. 3 | // This also affects IntelliSense performance, including code completion and many code browsing features. 4 | // However, files listed here are ALL re-compiled if any one of them is updated between builds. 5 | // Do not add files here that you will be updating frequently as this negates the performance advantage. 6 | 7 | #ifndef PCH_H 8 | #define PCH_H 9 | 10 | #define WIN32_LEAN_AND_MEAN 11 | 12 | #include 13 | #include 14 | 15 | #endif //PCH_H 16 | -------------------------------------------------------------------------------- /ProcMonX/SortHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct SortHelper final abstract { 4 | static bool SortStrings(const ATL::CString& s1, const ATL::CString& s2, bool ascending); 5 | static bool SortStrings(const std::string& s1, const std::string& s2, bool ascending); 6 | static bool SortStrings(const std::wstring& s1, const std::wstring& s2, bool ascending); 7 | static bool SortStrings(PCWSTR s1, PCWSTR s2, bool ascending); 8 | static bool SortBoolean(bool a, bool b, bool asc); 9 | 10 | template 11 | static bool SortNumbers(const Number& n1, const Number& n2, bool ascending) { 12 | return ascending ? n2 > n1 : n2 < n1; 13 | } 14 | }; 15 | 16 | 17 | -------------------------------------------------------------------------------- /ProcMonX/PropertyValueFilter.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "PropertyValueFilter.h" 3 | #include "EventData.h" 4 | #include "FormatHelper.h" 5 | 6 | PropertyValueFilter::PropertyValueFilter(std::wstring name, CompareType type, FilterAction action) 7 | : StringCompareFilterBase(L"Property Value", name, type, action){ 8 | } 9 | 10 | FilterAction PropertyValueFilter::Eval(FilterContext& context) const { 11 | auto action = FilterAction::None; 12 | for (auto& prop : context.Data->GetProperties()) { 13 | action = Compare(FormatHelper::FormatProperty(context.Data, prop)); 14 | if (action == GetAction()) 15 | return action; 16 | } 17 | return action; 18 | } 19 | -------------------------------------------------------------------------------- /ProcMonX/EventConfiguration.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "KernelEvents.h" 4 | 5 | struct EventConfigCategory { 6 | std::wstring Name; 7 | std::vector Opcodes; 8 | 9 | bool Contains(int opcode) const; 10 | }; 11 | 12 | class EventsConfiguration { 13 | public: 14 | void AddCategory(EventConfigCategory cat); 15 | void Clear(); 16 | const std::vector& GetCategories() const; 17 | const EventConfigCategory* const GetCategory(PCWSTR name) const; 18 | EventConfigCategory* GetCategory(PCWSTR name); 19 | int RemoveAdvanced(bool advanced); 20 | 21 | bool Save(PCWSTR path); 22 | bool Load(PCWSTR path, bool clean = true); 23 | 24 | private: 25 | std::vector _categories; 26 | }; 27 | 28 | -------------------------------------------------------------------------------- /ProcMonX/AboutDlg.cpp: -------------------------------------------------------------------------------- 1 | // aboutdlg.cpp : implementation of the CAboutDlg class 2 | // 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #include "pch.h" 6 | #include "aboutdlg.h" 7 | 8 | LRESULT CAboutDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { 9 | CenterWindow(GetParent()); 10 | return TRUE; 11 | } 12 | 13 | LRESULT CAboutDlg::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 14 | EndDialog(wID); 15 | return 0; 16 | } 17 | 18 | LRESULT CAboutDlg::OnClickSyslink(int, LPNMHDR, BOOL&) { 19 | ::ShellExecute(nullptr, L"open", L"https://github.com/zodiacon/procmonxv2", nullptr, nullptr, SW_SHOWDEFAULT); 20 | 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /EventTracing/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: This is a precompiled header file. 2 | // Files listed below are compiled only once, improving build performance for future builds. 3 | // This also affects IntelliSense performance, including code completion and many code browsing features. 4 | // However, files listed here are ALL re-compiled if any one of them is updated between builds. 5 | // Do not add files here that you will be updating frequently as this negates the performance advantage. 6 | 7 | #ifndef PCH_H 8 | #define PCH_H 9 | 10 | #define _HAS_EXCEPTIONS 0 11 | 12 | #include 13 | 14 | #define INITGUID 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #endif //PCH_H 24 | -------------------------------------------------------------------------------- /ProcMonX/ProcessIdFilter.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ProcessIdFilter.h" 3 | #include "EventData.h" 4 | 5 | ProcessIdFilter::ProcessIdFilter(DWORD pid, CompareType compare, FilterAction action) : FilterBase(L"ProcessId", compare, action), _pid(pid) { 6 | } 7 | 8 | void ProcessIdFilter::SetProcessId(DWORD pid) { 9 | _pid = pid; 10 | } 11 | 12 | FilterAction ProcessIdFilter::Eval(FilterContext& context) const { 13 | return _pid == context.Data->GetProcessId() ? GetAction() : GetDefaultAction(); 14 | } 15 | 16 | bool ProcessIdFilter::InitFromParams(const std::wstring& params) { 17 | if (params.empty()) 18 | return false; 19 | 20 | _pid = _wtoi(params.c_str()); 21 | return true; 22 | } 23 | 24 | std::wstring ProcessIdFilter::GetParams() { 25 | return std::to_wstring(_pid); 26 | } 27 | -------------------------------------------------------------------------------- /ProcMonX/FilterConfiguration.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "FilterBase.h" 4 | 5 | struct FilterDescription { 6 | std::wstring Name; 7 | FilterAction Action{ FilterAction::None }; 8 | FilterAction DefaultAction{ FilterAction::None }; 9 | CompareType Compare{ CompareType::Equals }; 10 | std::wstring Parameters; 11 | bool Enabled{ true }; 12 | }; 13 | 14 | class FilterConfiguration { 15 | public: 16 | bool AddFilter(FilterDescription desc); 17 | int GetFilterCount() const; 18 | bool SwapFilters(int index1, int index2); 19 | bool RemoveFilter(int index); 20 | FilterDescription* GetFilter(int index); 21 | const FilterDescription* GetFilter(int index) const; 22 | 23 | void Clear(); 24 | 25 | bool Save(PCWSTR path); 26 | bool Load(PCWSTR path); 27 | 28 | private: 29 | std::vector _filters; 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /ProcMonX/IniFile.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class IniFile { 4 | public: 5 | IniFile(PCWSTR path); 6 | 7 | CString ReadString(PCWSTR section, PCWSTR name, PCWSTR defaultValue = nullptr); 8 | int ReadInt(PCWSTR section, PCWSTR name, int defaultValue = 0); 9 | COLORREF ReadColor(PCWSTR section, PCWSTR name, COLORREF defaultValue = CLR_INVALID); 10 | std::vector ReadSection(PCWSTR section); 11 | bool ReadBool(PCWSTR section, PCWSTR name, bool defaultValue = false); 12 | 13 | bool WriteString(PCWSTR section, PCWSTR name, PCWSTR value); 14 | bool WriteInt(PCWSTR section, PCWSTR name, int value, bool hex = false); 15 | bool WriteBool(PCWSTR section, PCWSTR name, bool value); 16 | 17 | protected: 18 | COLORREF ParseHexColor(const CString& hex); 19 | COLORREF ParseDecColor(const CString& text); 20 | 21 | private: 22 | CString _path; 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /ProcMonX/Interfaces.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class TraceManager; 4 | 5 | struct QuickFindOptions { 6 | bool CaseSensitive : 1; 7 | bool SearchProcesses : 1 { true}; 8 | bool SearchEvents : 1 { true }; 9 | bool SearchDetails : 1; 10 | bool SearchDown : 1 { true }; 11 | bool FindNext : 1 { true }; 12 | }; 13 | 14 | struct IMainFrame { 15 | virtual BOOL TrackPopupMenu(HMENU hMenu, HWND hWnd, POINT* pt = nullptr, UINT flags = 0) = 0; 16 | virtual void ViewDestroyed(void* p) = 0; 17 | virtual TraceManager& GetTraceManager() = 0; 18 | virtual HFONT GetMonoFont() = 0; 19 | virtual BOOL SetPaneText(int index, PCWSTR text) = 0; 20 | virtual BOOL SetPaneIcon(int index, HICON hIcon) = 0; 21 | virtual CUpdateUIBase* GetUpdateUI() = 0; 22 | }; 23 | 24 | struct IQuickFind { 25 | virtual void DoFind(PCWSTR text, const QuickFindOptions& options) = 0; 26 | virtual void WindowClosed() = 0; 27 | }; 28 | -------------------------------------------------------------------------------- /ProcMonX/DialogHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "DialogHelper.h" 3 | #include "resource.h" 4 | 5 | void DialogHelper::AdjustOKCancelButtons(CWindow* dlg) { 6 | CButton ok(dlg->GetDlgItem(IDOK)); 7 | if (ok) { 8 | ok.SetWindowText(L" OK"); 9 | ok.SetIcon(AtlLoadIconImage(IDI_OK, 0, 16, 16)); 10 | } 11 | 12 | CButton cancel(dlg->GetDlgItem(IDCANCEL)); 13 | if (cancel) { 14 | cancel.SetWindowText(L" Cancel"); 15 | cancel.SetIcon(AtlLoadIconImage(IDI_CANCEL, 0, 16, 16)); 16 | } 17 | } 18 | 19 | bool DialogHelper::AddIconToButton(CWindow* dlg, WORD id, WORD icon) { 20 | CButton button(dlg->GetDlgItem(id)); 21 | if (button) { 22 | button.SetIcon(AtlLoadIconImage(icon, 0, 16, 16)); 23 | CString text; 24 | button.GetWindowText(text); 25 | button.SetWindowText(L" " + text); 26 | } 27 | return (bool)button; 28 | } 29 | 30 | void DialogHelper::SetDialogIcon(CWindow* dlg, UINT icon) { 31 | dlg->SetIcon(AtlLoadIconImage(icon, 0, 16, 16), FALSE); 32 | dlg->SetIcon(AtlLoadIconImage(icon, 0, 32, 32), TRUE); 33 | } 34 | -------------------------------------------------------------------------------- /EventTracing/FilterBase.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "FilterBase.h" 3 | 4 | FilterBase::FilterBase(std::wstring name, CompareType compare, FilterAction action) : _name(std::move(name)), _compare(compare), _action(action) { 5 | } 6 | 7 | FilterBase::~FilterBase() = default; 8 | 9 | const std::wstring& FilterBase::GetName() const { 10 | return _name; 11 | } 12 | 13 | void FilterBase::Enable(bool enable) { 14 | _enabled = enable; 15 | } 16 | 17 | bool FilterBase::IsEnabled() const { 18 | return _enabled; 19 | } 20 | 21 | void FilterBase::SetAction(FilterAction action) { 22 | _action = action; 23 | } 24 | 25 | CompareType FilterBase::GetCompareType() const { 26 | return _compare; 27 | } 28 | 29 | void FilterBase::SetCompareType(CompareType compare) { 30 | _compare = compare; 31 | } 32 | 33 | FilterAction FilterBase::GetAction() const { 34 | return _action; 35 | } 36 | 37 | FilterAction FilterBase::GetDefaultAction() { 38 | return _defaultAction; 39 | } 40 | 41 | void FilterBase::SetDefaultAction(FilterAction action) { 42 | _defaultAction = action; 43 | } 44 | -------------------------------------------------------------------------------- /ProcMonX/ProcMonX.cpp: -------------------------------------------------------------------------------- 1 | // ProcMonX.cpp : main source file for ProcMonX.exe 2 | // 3 | 4 | #include "pch.h" 5 | #include "MainFrm.h" 6 | 7 | CAppModule _Module; 8 | 9 | int Run(LPTSTR /*lpstrCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT) { 10 | CMessageLoop theLoop; 11 | _Module.AddMessageLoop(&theLoop); 12 | 13 | CMainFrame wndMain; 14 | 15 | if (wndMain.CreateEx() == nullptr) { 16 | ATLTRACE(_T("Main window creation failed!\n")); 17 | return 0; 18 | } 19 | 20 | wndMain.ShowWindow(nCmdShow); 21 | 22 | int nRet = theLoop.Run(); 23 | 24 | _Module.RemoveMessageLoop(); 25 | return nRet; 26 | } 27 | 28 | int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow) { 29 | HRESULT hRes = ::CoInitialize(nullptr); 30 | ATLASSERT(SUCCEEDED(hRes)); 31 | 32 | AtlInitCommonControls(ICC_BAR_CLASSES | ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES); 33 | 34 | hRes = _Module.Init(nullptr, hInstance); 35 | ATLASSERT(SUCCEEDED(hRes)); 36 | 37 | int nRet = Run(lpstrCmdLine, nCmdShow); 38 | 39 | _Module.Term(); 40 | ::CoUninitialize(); 41 | 42 | return nRet; 43 | } 44 | -------------------------------------------------------------------------------- /ProcMonC/ProcMonC.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Pavel Yosifovich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ProcMonX/BinaryEventDataSerializer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "IEventDataSerializer.h" 4 | #include "CompoundFile.h" 5 | 6 | class BinaryEventDataSerializer : public IEventDataSerializer { 7 | public: 8 | // Inherited via IEventDataSerializer 9 | virtual bool Save(const std::vector>& events, const EventDataSerializerOptions& options, PCWSTR path) override; 10 | virtual std::vector> Load(PCWSTR path) override; 11 | 12 | private: 13 | void WriteMetadata(StructuredStorage::CompoundFile* file, const std::vector>& events); 14 | void WriteEventData(StructuredStorage::StructuredDirectory* dir, const EventData* data); 15 | void WriteSimpleData(StructuredStorage::StructuredDirectory* dir, PCWSTR streamName, const void* data, int size); 16 | void WriteSimpleData(StructuredStorage::StructuredDirectory* dir, PCWSTR streamName, const std::wstring& value); 17 | template 18 | void WriteSimpleData(StructuredStorage::StructuredDirectory* dir, PCWSTR streamName, const T& data) { 19 | static_assert(std::is_trivially_constructible::value); 20 | WriteSimpleData(dir, streamName, &data, sizeof(data)); 21 | } 22 | }; 23 | 24 | -------------------------------------------------------------------------------- /Utils/CompoundFileReaderWriter.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "CompoundFileReaderWriter.h" 3 | 4 | using namespace std; 5 | using namespace StructuredStorage; 6 | 7 | CompoundFileReaderWriter::CompoundFileReaderWriter(StructuredFile& file) : m_File(file) { 8 | } 9 | 10 | void CompoundFileReaderWriter::Write(const std::wstring & value) { 11 | auto len = static_cast(value.size()); 12 | m_File.Write(&len, sizeof(len)); 13 | m_File.Write(value.c_str(), len * sizeof(wchar_t)); 14 | } 15 | 16 | void CompoundFileReaderWriter::Read(std::wstring & value) { 17 | uint32_t len; 18 | m_File.Read(&len, sizeof(len)); 19 | auto buffer = make_unique(len); 20 | m_File.Read(buffer.get(), len * 2); 21 | value.assign(buffer.get(), len); 22 | } 23 | 24 | void CompoundFileReaderWriter::Write(const std::string & value) { 25 | auto len = static_cast(value.size()); 26 | m_File.Write(&len, sizeof(len)); 27 | m_File.Write(value.c_str(), len * sizeof(char)); 28 | } 29 | 30 | void CompoundFileReaderWriter::Read(std::string & value) { 31 | uint32_t len; 32 | m_File.Read(&len, sizeof(len)); 33 | auto buffer = make_unique(len); 34 | m_File.Read(buffer.get(), len); 35 | value.assign(buffer.get(), len); 36 | } 37 | -------------------------------------------------------------------------------- /EventTracing/EventParser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct EventProperty { 4 | friend class EventParser; 5 | 6 | EventProperty(EVENT_PROPERTY_INFO& info); 7 | ~EventProperty(); 8 | 9 | std::wstring Name; 10 | BYTE* Data; 11 | ULONG Length; 12 | EVENT_PROPERTY_INFO& Info; 13 | 14 | template 15 | T GetValue() const { 16 | static_assert(std::is_pod() && !std::is_pointer()); 17 | return *(T*)Data; 18 | } 19 | 20 | PCWSTR GetUnicodeString() const; 21 | PCSTR GetAnsiString() const; 22 | 23 | private: 24 | void Allocate(ULONG size); 25 | bool _allocated{ false }; 26 | 27 | }; 28 | 29 | class EventParser { 30 | public: 31 | EventParser(PEVENT_RECORD record); 32 | 33 | PTRACE_EVENT_INFO GetEventInfo() const; 34 | PEVENT_RECORD GetEventRecord() const; 35 | const EVENT_HEADER& GetEventHeader() const; 36 | const std::vector& GetProperties() const; 37 | const EventProperty* GetProperty(PCWSTR name) const; 38 | 39 | DWORD GetProcessId() const; 40 | 41 | static std::wstring GetDosNameFromNtName(PCWSTR name); 42 | 43 | private: 44 | std::unique_ptr _buffer; 45 | PTRACE_EVENT_INFO _info{ nullptr }; 46 | PEVENT_RECORD _record; 47 | mutable std::vector _properties; 48 | }; 49 | 50 | -------------------------------------------------------------------------------- /ProcMonX/AboutDlg.h: -------------------------------------------------------------------------------- 1 | // aboutdlg.h : interface of the CAboutDlg class 2 | // 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #pragma once 6 | 7 | #include "resource.h" 8 | 9 | class CAboutDlg : public CDialogImpl { 10 | public: 11 | enum { IDD = IDD_ABOUTBOX }; 12 | 13 | BEGIN_MSG_MAP(CAboutDlg) 14 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 15 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd) 16 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) 17 | NOTIFY_CODE_HANDLER(NM_CLICK, OnClickSyslink) 18 | NOTIFY_CODE_HANDLER(NM_RETURN, OnClickSyslink) 19 | END_MSG_MAP() 20 | 21 | // Handler prototypes (uncomment arguments if needed): 22 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) 23 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 24 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) 25 | 26 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 27 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 28 | LRESULT OnClickSyslink(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/); 29 | }; 30 | -------------------------------------------------------------------------------- /EventTracing/FilterBase.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class EventData; 4 | 5 | enum class CompareType { 6 | Equals, 7 | NotEqual, 8 | Contains, 9 | NotContains, 10 | GreaterThan, 11 | LessThan, 12 | }; 13 | 14 | struct FilterContext { 15 | EventData* Data; 16 | }; 17 | 18 | enum class FilterAction { 19 | None, 20 | Include, 21 | Exclude, 22 | }; 23 | 24 | class FilterBase abstract { 25 | public: 26 | FilterBase(std::wstring name, CompareType compare, FilterAction action = FilterAction::None); 27 | ~FilterBase(); 28 | 29 | virtual FilterAction Eval(FilterContext& context) const = 0; 30 | 31 | const std::wstring& GetName() const; 32 | void Enable(bool enable); 33 | bool IsEnabled() const; 34 | 35 | FilterAction GetAction() const; 36 | void SetAction(FilterAction action); 37 | 38 | CompareType GetCompareType() const; 39 | void SetCompareType(CompareType compare); 40 | 41 | static FilterAction GetDefaultAction(); 42 | static void SetDefaultAction(FilterAction action); 43 | 44 | virtual bool InitFromParams(const std::wstring& params) = 0; 45 | virtual std::wstring GetParams() = 0; 46 | 47 | private: 48 | FilterAction _action; 49 | CompareType _compare; 50 | inline static FilterAction _defaultAction = FilterAction::None; 51 | std::wstring _name; 52 | bool _enabled{ true }; 53 | }; 54 | 55 | -------------------------------------------------------------------------------- /ProcMonX/FilterFactory.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "FilterFactory.h" 3 | #include "EventNameFilter.h" 4 | #include "ProcessIdFilter.h" 5 | #include "ProcessNameFilter.h" 6 | #include "PropertyValueFilter.h" 7 | #include "PropertyNameFilter.h" 8 | 9 | static PCWSTR names[] = { 10 | L"Process Name", L"Process Id", L"Event Name", L"Property Value", L"Property Name" 11 | }; 12 | 13 | std::vector FilterFactory::GetFilterNames() { 14 | return std::vector(std::begin(names), std::end(names)); 15 | } 16 | 17 | std::shared_ptr FilterFactory::CreateFilter(PCWSTR name, CompareType compare, PCWSTR params, FilterAction action) { 18 | std::shared_ptr filter; 19 | 20 | for (int i = 0; i < _countof(names); i++) { 21 | if (::wcscmp(name, names[i]) == 0) { 22 | switch (i) { 23 | case 0: 24 | filter = std::make_shared(params, compare, action); 25 | break; 26 | 27 | case 1: 28 | filter = std::make_shared(_wtoi(params), compare, action); 29 | break; 30 | 31 | case 2: 32 | filter = std::make_shared(params, compare, action); 33 | break; 34 | 35 | case 3: 36 | filter = std::make_shared(params, compare, action); 37 | break; 38 | 39 | case 4: 40 | filter = std::make_shared(params, compare, action); 41 | break; 42 | } 43 | } 44 | } 45 | return filter; 46 | } 47 | -------------------------------------------------------------------------------- /ProcMonX/manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /ProcMonX/EventPropertiesDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | 5 | class EventData; 6 | 7 | class CEventPropertiesDlg : 8 | public CDialogImpl, 9 | public CDialogResize { 10 | public: 11 | enum { IDD = IDD_EVENT_PROPS }; 12 | 13 | CEventPropertiesDlg(EventData* data); 14 | 15 | BEGIN_DLGRESIZE_MAP(CCallStackDlg) 16 | DLGRESIZE_CONTROL(IDC_LIST, DLSZ_SIZE_Y | DLSZ_SIZE_X) 17 | END_DLGRESIZE_MAP() 18 | 19 | BEGIN_MSG_MAP(CEventPropertiesDlg) 20 | NOTIFY_CODE_HANDLER(LVN_COLUMNCLICK, OnColumnClick) 21 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 22 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) 23 | COMMAND_ID_HANDLER(IDC_COPY, OnCopy) 24 | COMMAND_ID_HANDLER(IDC_STACK, OnCallStack) 25 | CHAIN_MSG_MAP(CDialogResize) 26 | END_MSG_MAP() 27 | 28 | private: 29 | int InsertItem(PCWSTR name, PCWSTR value); 30 | 31 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 32 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 33 | LRESULT OnCopy(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 34 | LRESULT OnColumnClick(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/); 35 | LRESULT OnCallStack(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 36 | 37 | private: 38 | EventData* m_pData; 39 | CListViewCtrl m_List; 40 | bool m_Ascending{ false }; 41 | }; 42 | 43 | -------------------------------------------------------------------------------- /ProcMonX/SymbolsHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #pragma warning(disable:4091) 4 | #include 5 | #pragma warning(default:4091) 6 | 7 | class SymbolInfo { 8 | public: 9 | SymbolInfo(); 10 | ~SymbolInfo(); 11 | 12 | operator PSYMBOL_INFO() const { 13 | return m_Symbol; 14 | } 15 | 16 | SYMBOL_INFO* GetSymbolInfo() const { 17 | return m_Symbol; 18 | } 19 | 20 | IMAGEHLP_MODULE64 ModuleInfo; 21 | 22 | private: 23 | SYMBOL_INFO* m_Symbol; 24 | }; 25 | 26 | class SymbolsHandler final { 27 | public: 28 | SymbolsHandler(HANDLE hProcess = ::GetCurrentProcess(), PCSTR searchPath = nullptr, DWORD symOptions = 29 | SYMOPT_UNDNAME | SYMOPT_CASE_INSENSITIVE | SYMOPT_AUTO_PUBLICS | SYMOPT_INCLUDE_32BIT_MODULES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_DEFERRED_LOADS); 30 | static std::unique_ptr CreateForProcess(DWORD pid, PCSTR searchPath = nullptr); 31 | ~SymbolsHandler(); 32 | 33 | HANDLE GetHandle() const; 34 | ULONG64 LoadSymbolsForModule(PCSTR moduleName, DWORD64 baseAddress = 0); 35 | std::unique_ptr GetSymbolFromName(PCSTR name); 36 | std::unique_ptr GetSymbolFromAddress(DWORD64 address, PDWORD64 offset = nullptr); 37 | IMAGEHLP_MODULE64 GetModuleInfo(DWORD64 address) const; 38 | bool LoadDefaultModules(); 39 | DWORD64 LoadKernelModule(DWORD64 address); 40 | 41 | private: 42 | BOOL Callback(ULONG code, ULONG64 data); 43 | 44 | HANDLE m_hProcess; 45 | }; 46 | 47 | -------------------------------------------------------------------------------- /ProcMonC/ProcMonC.cpp: -------------------------------------------------------------------------------- 1 | // ProcMonC.cpp : This file contains the 'main' function. Program execution begins and ends there. 2 | // 3 | 4 | #include 5 | #include 6 | #include 7 | #include "TraceManager.h" 8 | #include 9 | #include "EventData.h" 10 | 11 | void OnEvent(std::shared_ptr data) { 12 | printf("%-15ws PID: %5u (%ws) TID: %5u", 13 | data->GetEventName().c_str(), data->GetProcessId(), data->GetProcessName().c_str(), data->GetThreadId()); 14 | 15 | //switch (data->GetHeader().EventDescriptor.Opcode) { 16 | // case 1: // process created 17 | // printf(" Created: %u (%s)", data->GetProperty(L"ProcessId")->GetValue(), data->GetProperty(L"ImageFileName")->GetAnsiString()); 18 | // break; 19 | //} 20 | printf("\n"); 21 | } 22 | 23 | TraceManager* g_pMgr; 24 | HANDLE g_hEvent; 25 | 26 | int main(int argc, const char* argv[]) { 27 | TraceManager tm; 28 | tm.AddKernelEventTypes({ KernelEventTypes::ImageLoad, KernelEventTypes::Process }); 29 | 30 | g_pMgr = &tm; 31 | g_hEvent = ::CreateEvent(nullptr, FALSE, FALSE, nullptr); 32 | 33 | if (!tm.Start(OnEvent)) { 34 | printf("Failed to start session"); 35 | return 1; 36 | } 37 | 38 | ::SetConsoleCtrlHandler([](auto type) { 39 | if (type == CTRL_C_EVENT) { 40 | g_pMgr->Stop(); 41 | ::SetEvent(g_hEvent); 42 | return TRUE; 43 | } 44 | return FALSE; 45 | }, TRUE); 46 | 47 | ::WaitForSingleObject(g_hEvent, INFINITE); 48 | ::CloseHandle(g_hEvent); 49 | 50 | return 0; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /ProcMonX/SortHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SortHelper.h" 3 | 4 | bool SortHelper::SortStrings(const CString& s1, const CString& s2, bool ascending) { 5 | if (s1.IsEmpty() && s2.IsEmpty()) 6 | return false; 7 | if (s1.IsEmpty()) 8 | return false; 9 | if (s2.IsEmpty()) 10 | return true; 11 | 12 | return ascending ? s2.CompareNoCase(s1) > 0 : s2.CompareNoCase(s1) < 0; 13 | } 14 | 15 | bool SortHelper::SortStrings(const std::string& s1, const std::string& s2, bool ascending) { 16 | if (s1.empty() && s2.empty()) 17 | return false; 18 | if (s1.empty()) 19 | return false; 20 | if (s2.empty()) 21 | return true; 22 | 23 | auto compare = ::_stricmp(s2.c_str(), s1.c_str()); 24 | return ascending ? compare > 0 : compare < 0; 25 | } 26 | 27 | bool SortHelper::SortStrings(const std::wstring& s1, const std::wstring& s2, bool ascending) { 28 | if (s1.empty() && s2.empty()) 29 | return false; 30 | if (s1.empty()) 31 | return false; 32 | if (s2.empty()) 33 | return true; 34 | 35 | auto compare = ::_wcsicmp(s2.c_str(), s1.c_str()); 36 | return ascending ? compare > 0 : compare < 0; 37 | } 38 | 39 | bool SortHelper::SortStrings(PCWSTR s1, PCWSTR s2, bool ascending) { 40 | if ((s1 == nullptr || *s1 == 0) && (s2 == nullptr || *s2 == 0)) 41 | return false; 42 | if (s1 == nullptr || *s1 == 0) 43 | return false; 44 | if (s2 == nullptr || *s2 == 0) 45 | return true; 46 | 47 | auto compare = ::_wcsicmp(s2, s1); 48 | return ascending ? compare > 0 : compare < 0; 49 | } 50 | 51 | bool SortHelper::SortBoolean(bool a, bool b, bool asc) { 52 | return asc ? b > a : a > b; 53 | } 54 | -------------------------------------------------------------------------------- /ProcMonX/QuickFindDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | #include "Interfaces.h" 5 | 6 | class CQuickFindDlg : public CDialogImpl { 7 | public: 8 | enum { IDD = IDD_FIND }; 9 | 10 | CQuickFindDlg(IQuickFind* qf) : m_QuickFind(qf) {} 11 | 12 | static const QuickFindOptions& GetSearchOptions(); 13 | static const CString& GetSearchText(); 14 | 15 | void OnFinalMessage(HWND) override; 16 | 17 | BEGIN_MSG_MAP(CQuickFindDlg) 18 | COMMAND_CODE_HANDLER(EN_CHANGE, OnTextChanged) 19 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 20 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) 21 | COMMAND_ID_HANDLER(IDC_FINDNEXT, OnFindNext) 22 | END_MSG_MAP() 23 | 24 | // Handler prototypes (uncomment arguments if needed): 25 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) 26 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 27 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) 28 | private: 29 | void CheckButton(UINT id, bool check); 30 | bool IsChecked(UINT id) const; 31 | 32 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 33 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 34 | LRESULT OnFindNext(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 35 | LRESULT OnTextChanged(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 36 | 37 | IQuickFind* m_QuickFind; 38 | inline static QuickFindOptions m_Options; 39 | inline static CString m_SearchText; 40 | }; 41 | -------------------------------------------------------------------------------- /EventTracing/StringCompareFilterBase.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "StringCompareFilterBase.h" 3 | 4 | StringCompareFilterBase::StringCompareFilterBase(std::wstring name, std::wstring text, CompareType type, FilterAction action) : 5 | FilterBase(std::move(name), type, action), _text(std::move(text)) { 6 | } 7 | 8 | FilterAction StringCompareFilterBase::Compare(const std::wstring& str) const { 9 | auto compare = GetCompareType(); 10 | switch (compare) { 11 | case CompareType::Equals: 12 | case CompareType::NotEqual: 13 | { 14 | auto equal = ::_wcsicmp(str.c_str(), _text.c_str()) == 0; 15 | if (compare == CompareType::Equals && equal) 16 | return GetAction(); 17 | if (compare == CompareType::NotEqual && !equal) 18 | return GetAction(); 19 | } 20 | break; 21 | 22 | case CompareType::Contains: 23 | case CompareType::NotContains: 24 | { 25 | auto text2(_text); 26 | ::_wcslwr_s(text2.data(), text2.size() + 1); 27 | auto str2(str); 28 | ::_wcslwr_s(str2.data(), str2.size() + 1); 29 | 30 | auto substr = str2.find(text2) != std::wstring::npos; 31 | if (compare == CompareType::Contains && substr) 32 | return GetAction(); 33 | if (compare == CompareType::NotContains && !substr) 34 | return GetAction(); 35 | } 36 | break; 37 | 38 | default: 39 | return FilterAction::None; 40 | } 41 | if (GetAction() == FilterAction::Include) 42 | return FilterAction::Exclude; 43 | 44 | return GetDefaultAction(); 45 | } 46 | 47 | bool StringCompareFilterBase::InitFromParams(const std::wstring& params) { 48 | if (params.empty()) 49 | return false; 50 | 51 | _text = params; 52 | 53 | return true; 54 | } 55 | 56 | std::wstring StringCompareFilterBase::GetParams() { 57 | return _text; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /ProcMonX/SymbolManager.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SymbolManager.h" 3 | 4 | SymbolManager& SymbolManager::Get() { 5 | static SymbolManager mgr; 6 | return mgr; 7 | } 8 | 9 | SymbolManager::~SymbolManager() { 10 | Term(); 11 | } 12 | 13 | void SymbolManager::Term() { 14 | _procSymbols.clear(); 15 | } 16 | 17 | SymbolsHandler* SymbolManager::GetCommon() { 18 | return &_commonSymbols; 19 | } 20 | 21 | SymbolsHandler* SymbolManager::GetForProcess(DWORD pid) { 22 | auto it = _procSymbols.find(pid); 23 | if (it == _procSymbols.end()) { 24 | // attempt to get one 25 | 26 | auto symbols = SymbolsHandler::CreateForProcess(pid); 27 | if (symbols == nullptr) 28 | return nullptr; 29 | auto sym = symbols.get(); 30 | _procSymbols.insert({ pid, std::move(symbols) }); 31 | return sym; 32 | } 33 | if (::WaitForSingleObject(it->second->GetHandle(), 0) == WAIT_OBJECT_0) { 34 | // process dead, remove and try again 35 | _procSymbols.erase(pid); 36 | return GetForProcess(pid); 37 | } 38 | return it->second.get(); 39 | } 40 | 41 | std::unique_ptr SymbolManager::GetSymbolFromAddress(DWORD pid, DWORD64 address, PDWORD64 offset) { 42 | if ((int64_t)address < 0) { 43 | // kernel address 44 | _commonSymbols.LoadKernelModule(address); 45 | return _commonSymbols.GetSymbolFromAddress(address, offset); 46 | } 47 | 48 | auto handler = GetForProcess(pid); 49 | if (handler) { 50 | auto symbol = handler->GetSymbolFromAddress(address, offset); 51 | if (symbol) 52 | return symbol; 53 | } 54 | return nullptr; 55 | } 56 | 57 | SymbolManager::SymbolManager() { 58 | } 59 | -------------------------------------------------------------------------------- /ProcMonX/CallStackDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | #include 5 | #include 6 | 7 | class EventData; 8 | class SymbolsHandler; 9 | 10 | class CCallStackDlg : 11 | public CDialogImpl, 12 | public CDialogResize { 13 | public: 14 | enum { IDD = IDD_STACK }; 15 | 16 | CCallStackDlg(EventData* data); 17 | 18 | BEGIN_DLGRESIZE_MAP(CCallStackDlg) 19 | BEGIN_DLGRESIZE_GROUP() 20 | DLGRESIZE_CONTROL(IDC_LIST, DLSZ_SIZE_Y | DLSZ_SIZE_X) 21 | END_DLGRESIZE_GROUP() 22 | END_DLGRESIZE_MAP() 23 | 24 | BEGIN_MSG_MAP(CCallStackDlg) 25 | MESSAGE_HANDLER(WM_USER + 100, OnSymbolLoaded) 26 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 27 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) 28 | COMMAND_ID_HANDLER(IDC_COPY, OnCopy) 29 | CHAIN_MSG_MAP(CDialogResize) 30 | END_MSG_MAP() 31 | 32 | private: 33 | DWORD LoadSymbolsThread(); 34 | 35 | // Handler prototypes (uncomment arguments if needed): 36 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) 37 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 38 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) 39 | 40 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 41 | LRESULT OnSymbolLoaded(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 42 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 43 | LRESULT OnCopy(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 44 | 45 | private: 46 | std::atomic m_ExitSymbolThread{ false }; 47 | EventData* m_pData; 48 | CListViewCtrl m_List; 49 | wil::unique_handle m_hThread; 50 | }; 51 | 52 | -------------------------------------------------------------------------------- /ProcMonX/QuickFindDlg.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "QuickFindDlg.h" 3 | #include "DialogHelper.h" 4 | 5 | const QuickFindOptions& CQuickFindDlg::GetSearchOptions() { 6 | return m_Options; 7 | } 8 | 9 | const CString& CQuickFindDlg::GetSearchText() { 10 | return m_SearchText; 11 | } 12 | 13 | void CQuickFindDlg::OnFinalMessage(HWND) { 14 | m_QuickFind->WindowClosed(); 15 | delete this; 16 | } 17 | 18 | void CQuickFindDlg::CheckButton(UINT id, bool check) { 19 | CheckDlgButton(id, check ? BST_CHECKED : BST_UNCHECKED); 20 | } 21 | 22 | bool CQuickFindDlg::IsChecked(UINT id) const { 23 | return IsDlgButtonChecked(id) == BST_CHECKED; 24 | } 25 | 26 | LRESULT CQuickFindDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { 27 | DialogHelper::SetDialogIcon(this, IDI_FIND); 28 | 29 | CheckButton(IDC_CASESENSITIVE, m_Options.CaseSensitive); 30 | CheckButton(IDC_DOWN, m_Options.SearchDown); 31 | CheckButton(IDC_PROCESSES, m_Options.SearchProcesses); 32 | CheckButton(IDC_EVENT, m_Options.SearchEvents); 33 | CheckButton(IDC_DETAILS, m_Options.SearchDetails); 34 | 35 | return 0; 36 | } 37 | 38 | LRESULT CQuickFindDlg::OnCloseCmd(WORD, WORD wID, HWND, BOOL&) { 39 | m_Options.CaseSensitive = IsChecked(IDC_CASESENSITIVE); 40 | m_Options.SearchDetails = IsChecked(IDC_DETAILS); 41 | m_Options.SearchProcesses = IsChecked(IDC_PROCESSES); 42 | m_Options.SearchEvents = IsChecked(IDC_EVENT); 43 | m_Options.SearchDown = IsChecked(IDC_DOWN); 44 | 45 | DestroyWindow(); 46 | return 0; 47 | } 48 | 49 | LRESULT CQuickFindDlg::OnFindNext(WORD, WORD wID, HWND, BOOL&) { 50 | m_QuickFind->DoFind(m_SearchText, m_Options); 51 | 52 | return 0; 53 | } 54 | 55 | LRESULT CQuickFindDlg::OnTextChanged(WORD, WORD wID, HWND, BOOL&) { 56 | GetDlgItem(IDC_TEXT).GetWindowText(m_SearchText); 57 | GetDlgItem(IDC_FINDNEXT).EnableWindow(!m_SearchText.IsEmpty()); 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /ProcMonX.sln.startup.json: -------------------------------------------------------------------------------- 1 | /* 2 | This is a configuration file for the SwitchStartupProject Visual Studio Extension 3 | See https://bitbucket.org/thirteen/switchstartupproject/src/tip/Configuration.md 4 | */ 5 | { 6 | /* Configuration File Version */ 7 | "Version": 3, 8 | 9 | /* Create an item in the dropdown list for each project in the solution? */ 10 | "ListAllProjects": true, 11 | 12 | /* 13 | Dictionary of named configurations with one or multiple startup projects 14 | and optional parameters like command line arguments and working directory. 15 | Example: 16 | 17 | "MultiProjectConfigurations": { 18 | "A + B (Ext)": { 19 | "Projects": { 20 | "MyProjectA": {}, 21 | "MyProjectB": { 22 | "CommandLineArguments": "1234", 23 | "WorkingDirectory": "%USERPROFILE%\\test", 24 | "StartExternalProgram": "c:\\myprogram.exe" 25 | } 26 | } 27 | }, 28 | "A + B": { 29 | "Projects": { 30 | "MyProjectA": {}, 31 | "MyProjectB": { 32 | "CommandLineArguments": "", 33 | "WorkingDirectory": "", 34 | "StartProject": true 35 | } 36 | } 37 | }, 38 | "D (Debug x86)": { 39 | "Projects": { 40 | "MyProjectD": {} 41 | }, 42 | "SolutionConfiguration": "Debug", 43 | "SolutionPlatform": "x86", 44 | }, 45 | "D (Release x64)": { 46 | "Projects": { 47 | "MyProjectD": {} 48 | }, 49 | "SolutionConfiguration": "Release", 50 | "SolutionPlatform": "x64", 51 | } 52 | } 53 | */ 54 | "MultiProjectConfigurations": {} 55 | } 56 | -------------------------------------------------------------------------------- /ProcMonX/pch.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | // Change these values to use different versions 9 | #define WINVER 0x0601 10 | #define _WIN32_WINNT 0x0601 11 | #define _WIN32_IE 0x0700 12 | #define _RICHEDIT_VER 0x0500 13 | #define _HAS_EXCEPTIONS 0 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | extern CAppModule _Module; 23 | 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include 40 | #include 41 | 42 | #if defined _M_IX86 43 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") 44 | #elif defined _M_IA64 45 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") 46 | #elif defined _M_X64 47 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") 48 | #else 49 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 50 | #endif 51 | -------------------------------------------------------------------------------- /Utils/Utils.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {b2e43b8d-c28c-4840-a05c-5bf26cbe0945} 18 | 19 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | StructuredStorage 26 | 27 | 28 | StructuredStorage 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | StructuredStorage 40 | 41 | 42 | StructuredStorage 43 | 44 | 45 | -------------------------------------------------------------------------------- /ProcMonX/ViewBase.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Interfaces.h" 4 | 5 | template> 6 | class CViewBase abstract : 7 | public TBase, 8 | public CAutoUpdateUI, 9 | public CIdleHandler { 10 | public: 11 | // DECLARE_WND_CLASS(nullptr) 12 | 13 | CViewBase(IMainFrame* frame) : m_pFrame(frame) { 14 | ATLASSERT(frame); 15 | } 16 | 17 | protected: 18 | BEGIN_MSG_MAP(CViewBase) 19 | CHAIN_MSG_MAP(TBase) 20 | END_MSG_MAP() 21 | 22 | BOOL OnIdle() override { 23 | this->UIUpdateToolBar(); 24 | return FALSE; 25 | } 26 | 27 | IMainFrame* GetFrame() const { 28 | return m_pFrame; 29 | } 30 | 31 | LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled) { 32 | bHandled = FALSE; 33 | if(this->m_hWndToolBar) 34 | _Module.GetMessageLoop()->RemoveIdleHandler(this); 35 | return 0; 36 | } 37 | 38 | struct ToolBarButtonInfo { 39 | UINT id; 40 | int image; 41 | BYTE style = BTNS_BUTTON; 42 | PCWSTR text = nullptr; 43 | }; 44 | 45 | HWND CreateAndInitToolBar(const ToolBarButtonInfo* buttons, int count) { 46 | auto pT = static_cast(this); 47 | CToolBarCtrl tb; 48 | auto hWndToolBar = tb.Create(pT->m_hWnd, pT->rcDefault, nullptr, ATL_SIMPLE_TOOLBAR_PANE_STYLE | TBSTYLE_LIST, 0, ATL_IDW_TOOLBAR); 49 | tb.SetExtendedStyle(TBSTYLE_EX_MIXEDBUTTONS); 50 | 51 | CImageList tbImages; 52 | tbImages.Create(24, 24, ILC_COLOR32, 4, 4); 53 | tb.SetImageList(tbImages); 54 | 55 | for (int i = 0; i < count; i++) { 56 | auto& b = buttons[i]; 57 | if (b.id == 0) 58 | tb.AddSeparator(0); 59 | else { 60 | int image = b.image == 0 ? I_IMAGENONE : tbImages.AddIcon(AtlLoadIconImage(b.image, 0, 24, 24)); 61 | tb.AddButton(b.id, b.style | (b.text ? BTNS_SHOWTEXT : 0), TBSTATE_ENABLED, image, b.text, 0); 62 | } 63 | } 64 | pT->CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE); 65 | pT->AddSimpleReBarBand(tb); 66 | 67 | pT->UIAddToolBar(hWndToolBar); 68 | _Module.GetMessageLoop()->AddIdleHandler(this); 69 | 70 | return hWndToolBar; 71 | } 72 | 73 | private: 74 | IMainFrame* m_pFrame; 75 | }; 76 | -------------------------------------------------------------------------------- /ProcMonX/SortedFilteredVector.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | template 8 | class SortedFilteredVector { 9 | public: 10 | SortedFilteredVector(size_t capacity = 16) { 11 | _items.reserve(capacity); 12 | _indices.reserve(capacity); 13 | } 14 | 15 | void reserve(size_t capacity) { 16 | _items.reserve(capacity); 17 | _indices.reserve(capacity); 18 | } 19 | 20 | void clear() { 21 | _items.clear(); 22 | _indices.clear(); 23 | } 24 | 25 | void push_back(const T& value) { 26 | _items.push_back(value); 27 | _indices.push_back(_indices.size()); 28 | } 29 | 30 | void shrink_to_fit() { 31 | _items.shrink_to_fit(); 32 | _indices.shrink_to_fit(); 33 | } 34 | 35 | typename std::vector::const_iterator begin() const { 36 | return _items.begin(); 37 | } 38 | 39 | typename std::vector::const_iterator end() const { 40 | return _items.end(); 41 | } 42 | 43 | void Set(std::vector items) { 44 | _items = std::move(items); 45 | auto count = _items.size(); 46 | _indices.clear(); 47 | _indices.reserve(count); 48 | for (decltype(count) i = 0; i < count; i++) 49 | _indices.push_back(i); 50 | } 51 | 52 | const T& operator[](size_t index) const { 53 | return _items[_indices[index]]; 54 | } 55 | 56 | T& operator[](size_t index) { 57 | return _items[_indices[index]]; 58 | } 59 | 60 | void Sort(std::function compare) { 61 | std::sort(_indices.begin(), _indices.end(), [&](size_t i1, size_t i2) { 62 | return compare(_items[i1], _items[i2]); 63 | }); 64 | } 65 | 66 | size_t size() const { 67 | return _items.size(); 68 | } 69 | 70 | size_t FilteredSize() const { 71 | return _indices.size(); 72 | } 73 | 74 | void Filter(std::function predicate) { 75 | _indices.clear(); 76 | auto count = _items.size(); 77 | if (predicate == nullptr) { 78 | for (decltype(count) i = 0; i < count; i++) 79 | _indices.push_back(i); 80 | } 81 | else { 82 | for (decltype(count) i = 0; i < count; i++) 83 | if (predicate(_items[i])) 84 | _indices.push_back(i); 85 | } 86 | } 87 | 88 | private: 89 | std::vector _items; 90 | std::vector _indices; 91 | }; 92 | 93 | -------------------------------------------------------------------------------- /EventTracing/EventTracing.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | Source Files 52 | 53 | 54 | Source Files 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /ProcMonX/FiltersDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | #include "FilterBase.h" 5 | #include "FilterConfiguration.h" 6 | 7 | class CFiltersDlg : 8 | public CDialogImpl { 9 | public: 10 | enum { IDD = IDD_FILTERS }; 11 | 12 | CFiltersDlg(FilterConfiguration& fc); 13 | 14 | BEGIN_MSG_MAP(CFiltersDlg) 15 | COMMAND_CODE_HANDLER(CBN_EDITCHANGE, OnValueChanged) 16 | NOTIFY_CODE_HANDLER(LVN_ITEMCHANGED, OnItemChanged) 17 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 18 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) 19 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd) 20 | COMMAND_ID_HANDLER(IDC_UP, OnMoveUp) 21 | COMMAND_ID_HANDLER(IDC_DOWN, OnMoveDown) 22 | COMMAND_ID_HANDLER(IDC_DELETE, OnDelete) 23 | COMMAND_ID_HANDLER(IDC_ADD, OnAdd) 24 | COMMAND_ID_HANDLER(IDC_SAVE, OnSave) 25 | COMMAND_ID_HANDLER(IDC_LOAD, OnLoad) 26 | COMMAND_ID_HANDLER(IDC_EDIT, OnEdit) 27 | END_MSG_MAP() 28 | 29 | private: 30 | static CString CompareTypeToString(CompareType compare); 31 | static CString GetComboText(CComboBox& cb); 32 | static bool SwapItems(CListViewCtrl& lv, int i1, int i2); 33 | 34 | void InitList(const FilterConfiguration& config); 35 | void UpdateUI(); 36 | void UpdateConfig(FilterConfiguration& config); 37 | 38 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 39 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 40 | LRESULT OnAdd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 41 | LRESULT OnSave(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 42 | LRESULT OnLoad(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 43 | LRESULT OnEdit(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 44 | LRESULT OnMoveUp(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 45 | LRESULT OnMoveDown(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 46 | LRESULT OnDelete(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 47 | LRESULT OnValueChanged(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 48 | LRESULT OnItemChanged(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/); 49 | 50 | FilterConfiguration& m_Config; 51 | CListViewCtrl m_List; 52 | CComboBox m_FilterNames; 53 | CComboBox m_CompareTypes; 54 | CComboBox m_Text; 55 | CComboBox m_IncExc; 56 | }; 57 | -------------------------------------------------------------------------------- /EventTracing/EventData.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | struct EventProperty { 8 | friend class EventData; 9 | 10 | EventProperty(EVENT_PROPERTY_INFO& info); 11 | 12 | std::wstring Name; 13 | EVENT_PROPERTY_INFO& Info; 14 | ULONG GetLength() const { 15 | return (ULONG)Data.size(); 16 | } 17 | 18 | template 19 | T GetValue() const { 20 | static_assert(std::is_trivially_copyable() && !std::is_pointer()); 21 | assert(sizeof(T) == Data.size()); 22 | return *(T*)Data.data(); 23 | } 24 | 25 | BYTE* GetData() { 26 | return Data.data(); 27 | } 28 | 29 | const BYTE* GetData() const { 30 | return Data.data(); 31 | } 32 | 33 | PCWSTR GetUnicodeString() const; 34 | PCSTR GetAnsiString() const; 35 | 36 | private: 37 | std::vector Data; 38 | void* Allocate(ULONG size); 39 | }; 40 | 41 | class EventData { 42 | friend class TraceManager; 43 | public: 44 | EventData(PEVENT_RECORD rec, std::wstring processName, const std::wstring& eventName, uint32_t index); 45 | 46 | void* operator new(size_t size); 47 | void operator delete(void* p); 48 | 49 | DWORD GetProcessId() const; 50 | DWORD GetThreadId() const; 51 | ULONGLONG GetTimeStamp() const; 52 | const GUID& GetProviderId() const; 53 | const EVENT_DESCRIPTOR& GetEventDescriptor() const; 54 | const std::wstring& GetProcessName() const; 55 | const std::wstring& GetEventName() const; 56 | uint32_t GetIndex() const; 57 | 58 | const std::vector& GetProperties() const; 59 | const EventProperty* GetProperty(PCWSTR name) const; 60 | const EventData* GetStackEventData() const; 61 | std::wstring FormatProperty(const EventProperty& prop) const; 62 | uint64_t GetEventKey() const; 63 | 64 | protected: 65 | void SetStackEventData(std::shared_ptr data); 66 | void SetProcessName(std::wstring name); 67 | 68 | private: 69 | inline static HANDLE s_hHeap = nullptr; 70 | inline static CRITICAL_SECTION s_HeapLock = {0}; 71 | inline static volatile uint32_t s_Count = 0; 72 | 73 | ULONG _threadId, _processId; 74 | EVENT_DESCRIPTOR _eventDescriptor; 75 | ULONGLONG _timeStamp; 76 | ULONG _kernelTime, _userTime; 77 | GUID _providerId; 78 | std::wstring _processName; 79 | USHORT _headerFlags; 80 | const std::wstring& _eventName; 81 | mutable std::unique_ptr _buffer; 82 | PEVENT_RECORD _record; 83 | mutable std::vector _properties; 84 | uint32_t _index; 85 | std::shared_ptr _stackData; 86 | }; 87 | 88 | -------------------------------------------------------------------------------- /ProcMonX/ColumnManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | enum class ColumnFlags { 7 | None = 0, 8 | Visible = 1, 9 | Fixed = 2, 10 | Const = 4, // currently unused 11 | Mandatory = 8, 12 | Numeric = 0x10, 13 | Modified = 0x80 14 | }; 15 | DEFINE_ENUM_FLAG_OPERATORS(ColumnFlags); 16 | 17 | class ColumnManager { 18 | public: 19 | struct ColumnInfo { 20 | int DefaultWidth; 21 | int Format; 22 | CString Name; 23 | ColumnFlags Flags; 24 | CString Category; 25 | 26 | bool IsVisible() const; 27 | bool IsMandatory() const; 28 | void SetVisible(bool); 29 | }; 30 | 31 | ColumnManager(HWND hListView) : m_ListView(hListView) {} 32 | ~ColumnManager(); 33 | ColumnManager(const ColumnManager&) = default; 34 | ColumnManager& operator=(const ColumnManager&) = delete; 35 | 36 | HWND GetListView() const { 37 | return m_ListView; 38 | } 39 | 40 | bool CopyTo(ColumnManager& other) const; 41 | void AddFromControl(HWND hList = nullptr); 42 | void SetVisible(int column, bool visible); 43 | bool IsVisible(int column) const; 44 | bool IsModified(int column) const; 45 | void SetModified(int column, bool modified); 46 | bool IsConst(int column) const; 47 | int AddColumn(PCWSTR name, int format, int width, ColumnFlags flags = ColumnFlags::Visible); 48 | const ColumnInfo& GetColumn(int index) const; 49 | const std::vector& GetColumnsByCategory(PCWSTR category) const; 50 | const std::vector& GetCategories() const; 51 | 52 | void UpdateColumns(); 53 | int GetRealColumn(int index) const; 54 | 55 | int GetCount() const { 56 | return static_cast(m_Columns.size()); 57 | } 58 | 59 | protected: 60 | void SetColumn(int i, const ColumnInfo& info); 61 | 62 | private: 63 | CListViewCtrl m_ListView; 64 | std::vector m_Columns; 65 | std::map> m_ColumnsByCategory; 66 | std::vector m_Categories; 67 | }; 68 | 69 | inline bool ColumnManager::ColumnInfo::IsVisible() const { 70 | return (Flags & ColumnFlags::Visible) == ColumnFlags::Visible; 71 | } 72 | 73 | inline bool ColumnManager::ColumnInfo::IsMandatory() const { 74 | return (Flags & ColumnFlags::Mandatory) == ColumnFlags::Mandatory; 75 | } 76 | 77 | inline void ColumnManager::ColumnInfo::SetVisible(bool visible) { 78 | bool old = (Flags & ColumnFlags::Visible) == ColumnFlags::Visible; 79 | if (old == visible) 80 | return; 81 | 82 | if (visible) 83 | Flags |= ColumnFlags::Visible; 84 | else 85 | Flags &= ~ColumnFlags::Visible; 86 | Flags |= ColumnFlags::Modified; 87 | } 88 | 89 | -------------------------------------------------------------------------------- /Utils/CompoundFile.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace StructuredStorage { 9 | enum class CompoundFileMode { 10 | Read, 11 | ReadWrite 12 | }; 13 | 14 | enum class SeekMode { 15 | Set, 16 | Current, 17 | End 18 | }; 19 | 20 | struct ComException : std::exception { 21 | ComException(HRESULT hr) : HResult(hr) { 22 | } 23 | 24 | HRESULT HResult; 25 | }; 26 | 27 | class StructuredFile { 28 | friend class StructuredDirectory; 29 | 30 | public: 31 | void Write(const void* buffer, uint32_t count); 32 | void Read(void* buffer, uint32_t count); 33 | 34 | uint32_t Seek(uint32_t offset, SeekMode mode = SeekMode::Set); 35 | 36 | uint32_t GetSize() const; 37 | 38 | void Close(); 39 | 40 | private: 41 | StructuredFile(IStream* pStm) : m_spStream(pStm) {} 42 | 43 | CComPtr m_spStream; 44 | }; 45 | 46 | class StructuredDirectory { 47 | public: 48 | std::unique_ptr CreateStructuredDirectory(const std::wstring& name); 49 | std::unique_ptr CreateStructuredFile(const std::wstring& name); 50 | std::unique_ptr OpenStructuredDirectory(const std::wstring& name); 51 | std::unique_ptr OpenStructuredFile(const std::wstring& name); 52 | 53 | void Close(); 54 | 55 | ~StructuredDirectory() { 56 | Close(); 57 | } 58 | 59 | CompoundFileMode GetMode() const { 60 | return m_FileMode; 61 | } 62 | 63 | protected: 64 | IStorage* GetStorage() const { 65 | return m_spStorage.p; 66 | } 67 | 68 | StructuredDirectory(IStorage* pStg, CompoundFileMode mode = CompoundFileMode::ReadWrite) : m_spStorage(pStg), m_FileMode(mode) { 69 | } 70 | 71 | void CheckNameLength(const std::wstring& name) const; 72 | 73 | private: 74 | CComPtr m_spStorage; 75 | CompoundFileMode m_FileMode; 76 | }; 77 | 78 | class CompoundFile : public StructuredDirectory { 79 | public: 80 | // factory methods 81 | 82 | static std::unique_ptr Create(const std::wstring& path, PSECURITY_DESCRIPTOR securityDescriptor = nullptr); 83 | static std::unique_ptr Open(const std::wstring& path, CompoundFileMode mode = CompoundFileMode::Read); 84 | 85 | // ctors 86 | 87 | CompoundFile(const CompoundFile&) = delete; 88 | CompoundFile& operator=(const CompoundFile&) = delete; 89 | 90 | private: 91 | CompoundFile(IStorage* pStg, CompoundFileMode mode = CompoundFileMode::ReadWrite) : StructuredDirectory(pStg, mode) {} 92 | 93 | }; 94 | } -------------------------------------------------------------------------------- /ProcMonX/EventConfiguration.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "EventConfiguration.h" 3 | #include 4 | #include "IniFile.h" 5 | 6 | void EventsConfiguration::AddCategory(EventConfigCategory cat) { 7 | _categories.push_back(std::move(cat)); 8 | } 9 | 10 | void EventsConfiguration::Clear() { 11 | _categories.clear(); 12 | } 13 | 14 | const std::vector& EventsConfiguration::GetCategories() const { 15 | return _categories; 16 | } 17 | 18 | const EventConfigCategory* const EventsConfiguration::GetCategory(PCWSTR name) const { 19 | auto it = std::find_if(_categories.begin(), _categories.end(), [&](auto& c) { return c.Name == name; }); 20 | return it == _categories.end() ? nullptr : &(*it); 21 | } 22 | 23 | EventConfigCategory* EventsConfiguration::GetCategory(PCWSTR name) { 24 | auto it = std::find_if(_categories.begin(), _categories.end(), [&](auto& c) { return c.Name == name; }); 25 | return it == _categories.end() ? nullptr : &(*it); 26 | } 27 | 28 | int EventsConfiguration::RemoveAdvanced(bool advanced) { 29 | auto it = std::remove_if(_categories.begin(), _categories.end(), [&](const auto& cat) { 30 | return KernelEventCategory::GetCategory(cat.Name.c_str())->Advanced == advanced; 31 | }); 32 | _categories.erase(it, _categories.end()); 33 | 34 | return 0; 35 | } 36 | 37 | bool EventsConfiguration::Save(PCWSTR path) { 38 | ::DeleteFile(path); 39 | IniFile file(path); 40 | 41 | for (auto& cat : GetCategories()) { 42 | CString text; 43 | for (auto oc : cat.Opcodes) 44 | text.Format(L"%s%d,", (PCWSTR)text, oc); 45 | if (!file.WriteString(L"Events", cat.Name.c_str(), text)) 46 | return false; 47 | } 48 | 49 | return true; 50 | } 51 | 52 | bool EventsConfiguration::Load(PCWSTR path, bool clean) { 53 | IniFile file(path); 54 | if (clean) 55 | _categories.clear(); 56 | 57 | auto data = file.ReadSection(L"Events"); 58 | for (auto& cat : data) { 59 | auto equal = cat.Find(L'='); 60 | ATLASSERT(equal >= 0); 61 | if (equal < 0) 62 | return false; 63 | EventConfigCategory category; 64 | category.Name = cat.Left(equal); 65 | auto events = cat.Mid(equal + 1); 66 | if (!events.IsEmpty()) { 67 | int start = 0; 68 | for(;;) { 69 | auto id = events.Tokenize(L",", start); 70 | if (id.IsEmpty()) 71 | break; 72 | category.Opcodes.push_back(_wtoi(id)); 73 | } 74 | } 75 | _categories.push_back(category); 76 | } 77 | return true; 78 | } 79 | 80 | bool EventConfigCategory::Contains(int opcode) const { 81 | return std::find(Opcodes.begin(), Opcodes.end(), opcode) != Opcodes.end(); 82 | } 83 | -------------------------------------------------------------------------------- /Utils/CompoundFileReaderWriter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "CompoundFile.h" 7 | 8 | namespace StructuredStorage { 9 | class CompoundFileReaderWriter { 10 | public: 11 | CompoundFileReaderWriter(StructuredFile& file); 12 | 13 | template 14 | void Write(const T& value) { 15 | static_assert(std::is_trivially_copyable(), "T must be POD"); 16 | 17 | m_File.Write(&value, sizeof(value)); 18 | } 19 | 20 | template 21 | void Read(T& value) { 22 | static_assert(std::is_trivially_copyable() , "T must be POD"); 23 | 24 | m_File.Read(&value, sizeof(value)); 25 | } 26 | 27 | void Write(const std::wstring& value); 28 | void Read(std::wstring& value); 29 | void Write(const std::string& value); 30 | void Read(std::string& value); 31 | 32 | template 33 | void Write(const std::vector& vec) { 34 | auto count = static_cast(vec.size()); 35 | Write(count); 36 | if (std::is_pod::value) { 37 | m_File.Write(vec.data(), count * sizeof(T)); 38 | } 39 | else { 40 | for (const auto& item : vec) 41 | Write(item); 42 | } 43 | } 44 | 45 | template 46 | void Read(std::vector& vec) { 47 | uint32_t count; 48 | Read(count); 49 | if (count == 0) { 50 | vec.clear(); 51 | return; 52 | } 53 | 54 | vec.resize(count); 55 | if (std::is_pod::value) { 56 | m_File.Read(vec.data(), count * sizeof(T)); 57 | } 58 | else { 59 | for (uint32_t i = 0; i < count; ++i) { 60 | T value; 61 | Read(value); 62 | vec[i] = value; 63 | } 64 | } 65 | } 66 | 67 | template 68 | void Write(const std::pair& pair) { 69 | Write(pair.first); 70 | Write(pair.second); 71 | } 72 | 73 | template 74 | void Read(std::pair& pair) { 75 | Read(pair.first); 76 | Read(pair.second); 77 | } 78 | 79 | template 80 | void Write(const std::map& map) { 81 | Write(static_cast(map.size())); 82 | for (const auto& pair : map) 83 | Write(pair); 84 | } 85 | 86 | template 87 | void Read(std::map& map) { 88 | uint32_t count; 89 | Read(count); 90 | for (uint32_t i = 0; i < count; i++) { 91 | std::pair pair; 92 | Read(pair); 93 | map.insert(pair); 94 | } 95 | } 96 | 97 | private: 98 | StructuredFile& m_File; 99 | }; 100 | 101 | } 102 | -------------------------------------------------------------------------------- /ProcMonX/FilterConfiguration.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "FilterConfiguration.h" 3 | #include "IniFile.h" 4 | 5 | bool FilterConfiguration::AddFilter(FilterDescription desc) { 6 | _filters.push_back(std::move(desc)); 7 | return true; 8 | } 9 | 10 | int FilterConfiguration::GetFilterCount() const { 11 | return (int)_filters.size(); 12 | } 13 | 14 | bool FilterConfiguration::SwapFilters(int i1, int i2) { 15 | if (i1 < 0 || i2 < 0 || i1 >= _filters.size() || i2 >= _filters.size() || i1 == i2) 16 | return false; 17 | 18 | std::swap(_filters[i1], _filters[i2]); 19 | return true; 20 | } 21 | 22 | bool FilterConfiguration::RemoveFilter(int index) { 23 | if (index < 0 || index >= _filters.size()) 24 | return false; 25 | _filters.erase(_filters.begin() + index); 26 | return true; 27 | } 28 | 29 | FilterDescription* FilterConfiguration::GetFilter(int index) { 30 | if (index < 0 || index >= _filters.size()) 31 | return nullptr; 32 | 33 | return _filters.data() + index; 34 | } 35 | 36 | const FilterDescription* FilterConfiguration::GetFilter(int index) const { 37 | if (index < 0 || index >= _filters.size()) 38 | return nullptr; 39 | 40 | return _filters.data() + index; 41 | } 42 | 43 | void FilterConfiguration::Clear() { 44 | _filters.clear(); 45 | } 46 | 47 | bool FilterConfiguration::Save(PCWSTR path) { 48 | IniFile file(path); 49 | CString text; 50 | 51 | int i = 1; 52 | for (auto& filter : _filters) { 53 | text.Format(L"Filter%d", i); 54 | file.WriteString(text, L"Type", filter.Name.c_str()); 55 | file.WriteInt(text, L"Action", (int)filter.Action); 56 | file.WriteInt(text, L"DefaultAction", (int)filter.Action); 57 | file.WriteBool(text, L"Enabled", filter.Enabled); 58 | file.WriteString(text, L"Parameters", filter.Parameters.c_str()); 59 | i++; 60 | } 61 | 62 | return true; 63 | } 64 | 65 | bool FilterConfiguration::Load(PCWSTR path) { 66 | IniFile file(path); 67 | CString text; 68 | for (int i = 1;; i++) { 69 | text.Format(L"Filter%d", i); 70 | auto name = file.ReadString(text, L"Type"); 71 | if (name.IsEmpty() || name == L"") 72 | break; 73 | FilterDescription desc; 74 | desc.Name = name; 75 | desc.Action = (FilterAction)file.ReadInt(text, L"Action"); 76 | desc.DefaultAction = (FilterAction)file.ReadInt(text, L"DefaultAction"); 77 | desc.Enabled = file.ReadBool(text, L"Enabled", true); 78 | desc.Parameters = file.ReadString(text, L"Parameters"); 79 | AddFilter(desc); 80 | } 81 | return true; 82 | } 83 | -------------------------------------------------------------------------------- /ProcMonX/IniFile.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "IniFile.h" 3 | #include 4 | 5 | IniFile::IniFile(PCWSTR path) : _path(path) { 6 | } 7 | 8 | CString IniFile::ReadString(PCWSTR section, PCWSTR name, PCWSTR defaultValue) { 9 | CString result; 10 | auto count = ::GetPrivateProfileString(section, name, defaultValue, result.GetBufferSetLength(128), 128, _path); 11 | return result; 12 | } 13 | 14 | int IniFile::ReadInt(PCWSTR section, PCWSTR name, int defaultValue) { 15 | return ::GetPrivateProfileInt(section, name, defaultValue, _path); 16 | } 17 | 18 | COLORREF IniFile::ReadColor(PCWSTR section, PCWSTR name, COLORREF defaultValue) { 19 | auto text = ReadString(section, name); 20 | if (text.IsEmpty()) 21 | return defaultValue; 22 | 23 | if (text.Left(2) == L"0x") 24 | return ParseHexColor(text.Mid(2)); 25 | 26 | if (text.Find(L',')) 27 | return ParseDecColor(text); 28 | 29 | return ParseHexColor(text); 30 | } 31 | 32 | std::vector IniFile::ReadSection(PCWSTR section) { 33 | WCHAR buffer[1 << 10]; 34 | std::vector names; 35 | if (0 == ::GetPrivateProfileSection(section, buffer, _countof(buffer), _path)) 36 | return names; 37 | 38 | names.reserve(8); 39 | for (auto p = buffer; *p; ) { 40 | names.push_back(p); 41 | p += names.back().GetLength() + 1; 42 | } 43 | return names; 44 | } 45 | 46 | bool IniFile::ReadBool(PCWSTR section, PCWSTR name, bool defaultValue) { 47 | auto value = ReadInt(section, name, -1); 48 | if (value == -1) 49 | return defaultValue; 50 | return value ? true : false; 51 | } 52 | 53 | bool IniFile::WriteString(PCWSTR section, PCWSTR name, PCWSTR value) { 54 | return ::WritePrivateProfileString(section, name, value, _path); 55 | } 56 | 57 | bool IniFile::WriteInt(PCWSTR section, PCWSTR name, int value, bool hex) { 58 | CString text; 59 | text.Format(hex ? L"0x%X" : L"%d", value); 60 | return WriteString(section, name, text); 61 | } 62 | 63 | bool IniFile::WriteBool(PCWSTR section, PCWSTR name, bool value) { 64 | return WriteInt(section, name, value ? 1 : 0); 65 | } 66 | 67 | COLORREF IniFile::ParseHexColor(const CString& hex) { 68 | std::wstringstream ss; 69 | DWORD color; 70 | ss << std::hex << hex; 71 | ss >> color; 72 | return color; 73 | } 74 | 75 | COLORREF IniFile::ParseDecColor(const CString& text) { 76 | int start = 0; 77 | COLORREF color = 0; 78 | auto str = text.Tokenize(L",", start); 79 | if (str.IsEmpty()) 80 | return CLR_INVALID; 81 | color |= _wtoi(str); 82 | str = text.Tokenize(L",", start); 83 | if (str.IsEmpty()) 84 | return CLR_INVALID; 85 | color |= _wtoi(str) << 8; 86 | str = text.Tokenize(L",", start); 87 | if (str.IsEmpty()) 88 | return CLR_INVALID; 89 | color |= _wtoi(str) << 16; 90 | 91 | return color; 92 | } 93 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /EventTracing/TraceManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "KernelEvents.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class EventData; 14 | class FilterBase; 15 | 16 | using EventCallback = std::function)>; 17 | 18 | class TraceManager final { 19 | public: 20 | TraceManager(); 21 | ~TraceManager(); 22 | TraceManager(const TraceManager&) = delete; 23 | TraceManager& operator=(const TraceManager&) = delete; 24 | 25 | bool AddKernelEventTypes(std::initializer_list types); 26 | //bool RemoveKernelEventTypes(KernelEventTypes types); 27 | bool SetKernelEventTypes(std::initializer_list types); 28 | bool SetKernelEventStacks(std::initializer_list categories); 29 | bool SetBackupFile(PCWSTR path); 30 | void Pause(bool pause); 31 | bool Start(EventCallback callback); 32 | bool Stop(); 33 | bool IsRunning() const; 34 | bool IsPaused() const; 35 | 36 | void ResetIndex(uint32_t index = 0); 37 | int UpdateEventConfig(); 38 | 39 | std::wstring GetProcessImageById(DWORD pid) const; 40 | static std::wstring GetDosNameFromNtName(PCWSTR name); 41 | 42 | void AddFilter(std::shared_ptr filter); 43 | bool RemoveFilterAt(int index); 44 | void RemoveAllFilters(); 45 | int GetFilterCount() const; 46 | uint32_t GetFilteredEventsCount() const; 47 | 48 | bool SwapFilters(int i1, int i2); 49 | std::shared_ptr GetFilter(int index) const; 50 | 51 | private: 52 | const std::wstring& GetkernelEventName(EVENT_RECORD* rec) const; 53 | void AddProcessName(DWORD pid, std::wstring name); 54 | bool RemoveProcessName(DWORD pid); 55 | void EnumProcesses(); 56 | bool ParseProcessStartStop(EventData* data); 57 | void OnEventRecord(PEVENT_RECORD rec); 58 | DWORD Run(); 59 | void HandleNoProcessId(EventData* data); 60 | 61 | private: 62 | struct ProcessInfo { 63 | DWORD Id; 64 | std::wstring ImageName; 65 | LONGLONG CreateTime; 66 | }; 67 | 68 | TRACEHANDLE _handle{ 0 }; 69 | TRACEHANDLE _hTrace{ 0 }; 70 | EVENT_TRACE_PROPERTIES* _properties; 71 | std::unique_ptr _propertiesBuffer; 72 | EVENT_TRACE_LOGFILE _traceLog = { 0 }; 73 | wil::unique_handle _hProcessThread; 74 | EventCallback _callback; 75 | std::set _kernelEventTypes; 76 | std::set _kernelEventStacks; 77 | mutable std::shared_mutex _processesLock; 78 | std::unordered_map _processes; 79 | mutable std::unordered_map _kernelEventNames; 80 | std::vector _cleanupPids; 81 | std::shared_ptr _lastEvent; 82 | std::shared_ptr _lastExcluded; 83 | uint32_t _index{ 0 }; 84 | std::vector> _filters; 85 | std::atomic _filteredEvents{ 0 }; 86 | wil::unique_handle _hMemMap; 87 | bool _isTraceProcesses{ true }; 88 | bool _dumpUnnamedEvents{ true }; 89 | std::atomic _isPaused{ false }; 90 | }; 91 | 92 | -------------------------------------------------------------------------------- /ProcMonX/EventsDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "resource.h" 4 | 5 | class EventsConfiguration; 6 | 7 | class CEventsDlg : 8 | public CDialogImpl, 9 | public CDialogResize { 10 | public: 11 | enum { IDD = IDD_EVENTS }; 12 | 13 | CEventsDlg(EventsConfiguration& config); 14 | 15 | BEGIN_MSG_MAP(CEventsDlg) 16 | NOTIFY_CODE_HANDLER(TVN_ITEMCHANGED, OnTreeItemChanged) 17 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 18 | MESSAGE_HANDLER(WM_GETMINMAXINFO, OnGetMinMaxInfo) 19 | COMMAND_HANDLER(IDC_BASIC, BN_CLICKED, OnBasicView) 20 | COMMAND_HANDLER(IDC_ADVANCED, BN_CLICKED, OnAdvancedView) 21 | COMMAND_ID_HANDLER(IDC_SAVE, OnSave) 22 | COMMAND_ID_HANDLER(IDC_LOAD, OnLoad) 23 | COMMAND_ID_HANDLER(IDC_EXPAND, OnExpandAll) 24 | COMMAND_ID_HANDLER(IDC_COLLAPSE, OnCollapseAll) 25 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd) 26 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) 27 | MESSAGE_HANDLER(WM_DESTROY, OnDestroy) 28 | CHAIN_MSG_MAP(CDialogResize) 29 | END_MSG_MAP() 30 | 31 | BEGIN_DLGRESIZE_MAP(CEventsDlg) 32 | DLGRESIZE_CONTROL(IDC_TREE, DLSZ_SIZE_Y) 33 | DLGRESIZE_CONTROL(IDOK, DLSZ_MOVE_Y) 34 | DLGRESIZE_CONTROL(IDCANCEL, DLSZ_MOVE_Y) 35 | END_DLGRESIZE_MAP() 36 | 37 | // Handler prototypes (uncomment arguments if needed): 38 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) 39 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 40 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) 41 | 42 | private: 43 | void BuildEventsTree(const EventsConfiguration& config); 44 | void CheckTreeChildren(HTREEITEM hParent, bool check); 45 | bool BuildConfigFromTree(EventsConfiguration& config); 46 | void SwitchToAdvancedView(bool advanced); 47 | 48 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 49 | LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 50 | LRESULT OnGetMinMaxInfo(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 51 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD id, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 52 | LRESULT OnTreeItemChanged(int /*idCtrl*/, LPNMHDR hdr, BOOL& /*bHandled*/); 53 | LRESULT OnSave(WORD /*wNotifyCode*/, WORD id, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 54 | LRESULT OnLoad(WORD /*wNotifyCode*/, WORD id, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 55 | LRESULT OnExpandAll(WORD /*wNotifyCode*/, WORD id, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 56 | LRESULT OnCollapseAll(WORD /*wNotifyCode*/, WORD id, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 57 | LRESULT OnBasicView(WORD /*wNotifyCode*/, WORD id, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 58 | LRESULT OnAdvancedView(WORD /*wNotifyCode*/, WORD id, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 59 | 60 | private: 61 | EventsConfiguration& m_Config; 62 | EventsConfiguration m_TempConfig; 63 | CTreeViewCtrlEx m_Tree; 64 | int m_Recurse{ 0 }; 65 | bool m_Init{ true }; 66 | inline static bool m_Advanced{ false }; 67 | }; 68 | 69 | -------------------------------------------------------------------------------- /ProcMonX/BinaryEventDataSerializer.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "BinaryEventDataSerializer.h" 3 | #include "CompoundFile.h" 4 | #include "CompoundFileReaderWriter.h" 5 | 6 | using namespace StructuredStorage; 7 | 8 | bool BinaryEventDataSerializer::Save(const std::vector>& events, const EventDataSerializerOptions& options, PCWSTR path) { 9 | auto file = CompoundFile::Create(path); 10 | if(file == nullptr) 11 | return false; 12 | 13 | uint32_t i = 0; 14 | CString text; 15 | WriteMetadata(file.get(), events); 16 | for(uint32_t i = 0; i < (uint32_t)events.size(); i++) { 17 | auto& evt = events[i]; 18 | text.Format(L"Event%u", i); 19 | ATLTRACE(L"Writing event %u\n", i); 20 | auto dir = file->CreateStructuredDirectory((PCWSTR)text); 21 | WriteEventData(dir.get(), evt.get()); 22 | } 23 | 24 | if(options.CompressOutput) { 25 | // compress output file 26 | 27 | } 28 | 29 | return true; 30 | } 31 | 32 | std::vector> BinaryEventDataSerializer::Load(PCWSTR path) { 33 | return std::vector>(); 34 | } 35 | 36 | void BinaryEventDataSerializer::WriteMetadata(CompoundFile* file, const std::vector>& events) { 37 | auto dir = file->CreateStructuredDirectory(L"Contents"); 38 | WriteSimpleData(dir.get(), L"EventCount", events.size()); 39 | } 40 | 41 | void BinaryEventDataSerializer::WriteEventData(StructuredDirectory* dir, const EventData* data) { 42 | auto file = dir->CreateStructuredFile(L"Basic"); 43 | CompoundFileReaderWriter writer(*file); 44 | writer.Write(data->GetEventDescriptor()); 45 | writer.Write(data->GetEventName()); 46 | writer.Write(data->GetTimeStamp()); 47 | writer.Write(data->GetIndex()); 48 | writer.Write(data->GetProcessId()); 49 | writer.Write(data->GetThreadId()); 50 | writer.Write(data->GetProviderId()); 51 | 52 | //WriteSimpleData(dir, L"EventDescriptor", &data->GetEventDescriptor(), sizeof(EVENT_DESCRIPTOR)); 53 | //WriteSimpleData(dir, L"EventName", data->GetEventName()); 54 | //WriteSimpleData(dir, L"Index", data->GetIndex()); 55 | //WriteSimpleData(dir, L"ProcessId", data->GetProcessId()); 56 | //WriteSimpleData(dir, L"ThreadId", data->GetThreadId()); 57 | //WriteSimpleData(dir, L"ProcessName", data->GetProcessName()); 58 | //WriteSimpleData(dir, L"ProviderId", data->GetProviderId()); 59 | //WriteSimpleData(dir, L"TimeStamp", data->GetTimeStamp()); 60 | auto props = data->GetProperties(); 61 | if(!props.empty()) { 62 | auto file = dir->CreateStructuredFile(L"Properties"); 63 | CompoundFileReaderWriter writer(*file); 64 | 65 | for(auto& prop : props) { 66 | writer.Write(prop.Name); 67 | writer.Write(prop.GetLength()); 68 | file->Write(prop.GetData(), prop.GetLength()); 69 | 70 | //WriteSimpleData(propDir.get(), prop.Name.c_str(), prop.GetData(), prop.GetLength()); 71 | } 72 | } 73 | auto stackData = data->GetStackEventData(); 74 | if(stackData) { 75 | auto stackDir = dir->CreateStructuredDirectory(L"Stack"); 76 | WriteEventData(stackDir.get(), stackData); 77 | } 78 | } 79 | 80 | void BinaryEventDataSerializer::WriteSimpleData(StructuredDirectory* dir, PCWSTR streamName, const void* data, int size) { 81 | auto file = dir->CreateStructuredFile(streamName); 82 | file->Write(data, size); 83 | } 84 | 85 | void BinaryEventDataSerializer::WriteSimpleData(StructuredStorage::StructuredDirectory* dir, PCWSTR streamName, const std::wstring& value) { 86 | auto file = dir->CreateStructuredFile(streamName); 87 | CompoundFileReaderWriter writer(*file); 88 | writer.Write(value); 89 | } 90 | -------------------------------------------------------------------------------- /EventTracing/EventParser.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "EventParser.h" 3 | 4 | 5 | EventParser::EventParser(PEVENT_RECORD record) : _record(record) { 6 | ULONG size = 0; 7 | auto error = ::TdhGetEventInformation(record, 0, nullptr, _info, &size); 8 | if (error == ERROR_INSUFFICIENT_BUFFER) { 9 | _buffer = std::make_unique(size); 10 | _info = reinterpret_cast(_buffer.get()); 11 | error = ::TdhGetEventInformation(record, 0, nullptr, _info, &size); 12 | } 13 | ::SetLastError(error); 14 | } 15 | 16 | PTRACE_EVENT_INFO EventParser::GetEventInfo() const { 17 | return _info; 18 | } 19 | 20 | PEVENT_RECORD EventParser::GetEventRecord() const { 21 | return _record; 22 | } 23 | 24 | const EVENT_HEADER& EventParser::GetEventHeader() const { 25 | return _record->EventHeader; 26 | } 27 | 28 | const std::vector& EventParser::GetProperties() const { 29 | if (!_properties.empty()) 30 | return _properties; 31 | 32 | _properties.reserve(_info->TopLevelPropertyCount); 33 | auto userDataLength = _record->UserDataLength; 34 | BYTE* data = (BYTE*)_record->UserData; 35 | 36 | for (ULONG i = 0; i < _info->TopLevelPropertyCount; i++) { 37 | auto& prop = _info->EventPropertyInfoArray[i]; 38 | EventProperty property(prop); 39 | property.Name.assign((WCHAR*)((BYTE*)_info + prop.NameOffset)); 40 | ULONG len = prop.length; 41 | if (len == 0) { 42 | PROPERTY_DATA_DESCRIPTOR desc; 43 | desc.PropertyName = (ULONGLONG)property.Name.c_str(); 44 | desc.ArrayIndex = ULONG_MAX; 45 | if (ERROR_SUCCESS == ::TdhGetPropertySize(_record, 0, nullptr, 1, &desc, &len)) { 46 | // property.Allocate(len); 47 | // ::TdhGetProperty(_record, 0, nullptr, 1, &desc, len, property.Data); 48 | } 49 | } 50 | property.Length = len; 51 | property.Data = data; 52 | data += len; 53 | userDataLength -= (USHORT)len; 54 | 55 | _properties.push_back(std::move(property)); 56 | } 57 | 58 | return _properties; 59 | } 60 | 61 | const EventProperty* EventParser::GetProperty(PCWSTR name) const { 62 | for (auto& prop : GetProperties()) 63 | if (prop.Name == name) 64 | return ∝ 65 | return nullptr; 66 | } 67 | 68 | DWORD EventParser::GetProcessId() const { 69 | return _record->EventHeader.ProcessId; 70 | } 71 | 72 | std::wstring EventParser::GetDosNameFromNtName(PCWSTR name) { 73 | static std::vector> deviceNames; 74 | static bool first = true; 75 | if (first) { 76 | auto drives = ::GetLogicalDrives(); 77 | int drive = 0; 78 | while (drives) { 79 | if (drives & 1) { 80 | // drive exists 81 | WCHAR driveName[] = L"X:"; 82 | driveName[0] = (WCHAR)(drive + 'A'); 83 | WCHAR path[MAX_PATH]; 84 | if (::QueryDosDevice(driveName, path, MAX_PATH)) { 85 | deviceNames.push_back({ path, driveName }); 86 | } 87 | } 88 | drive++; 89 | drives >>= 1; 90 | } 91 | first = false; 92 | } 93 | 94 | for (auto& [ntName, dosName] : deviceNames) { 95 | if (::_wcsnicmp(name, ntName.c_str(), ntName.size()) == 0) 96 | return dosName + (name + ntName.size()); 97 | } 98 | return L""; 99 | } 100 | 101 | EventProperty::EventProperty(EVENT_PROPERTY_INFO& info) : Info(info) { 102 | } 103 | 104 | EventProperty::~EventProperty() { 105 | if (_allocated) 106 | ::free(Data); 107 | } 108 | 109 | void EventProperty::Allocate(ULONG size) { 110 | Data = (BYTE*)malloc(size); 111 | _allocated = true; 112 | } 113 | 114 | PCWSTR EventProperty::GetUnicodeString() const { 115 | return (PCWSTR)Data; 116 | } 117 | 118 | PCSTR EventProperty::GetAnsiString() const { 119 | return (PCSTR)Data; 120 | } 121 | -------------------------------------------------------------------------------- /ProcMonX.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30404.54 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProcMonX", "ProcMonX\ProcMonX.vcxproj", "{87B2E77F-E722-4830-B4CB-80D8179BEAA3}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EventTracing", "EventTracing\EventTracing.vcxproj", "{68987F0E-6F47-4D9E-9503-B93F5AD5983A}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ProcMonC", "ProcMonC\ProcMonC.vcxproj", "{96F3160E-965F-434D-9096-F54715AB906B}" 11 | EndProject 12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Utils", "Utils\Utils.vcxproj", "{CE7D8382-82CA-4139-8712-14FE68CACF16}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|x64 = Debug|x64 17 | Debug|x86 = Debug|x86 18 | Release|x64 = Release|x64 19 | Release|x86 = Release|x86 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {87B2E77F-E722-4830-B4CB-80D8179BEAA3}.Debug|x64.ActiveCfg = Debug|x64 23 | {87B2E77F-E722-4830-B4CB-80D8179BEAA3}.Debug|x64.Build.0 = Debug|x64 24 | {87B2E77F-E722-4830-B4CB-80D8179BEAA3}.Debug|x86.ActiveCfg = Debug|Win32 25 | {87B2E77F-E722-4830-B4CB-80D8179BEAA3}.Debug|x86.Build.0 = Debug|Win32 26 | {87B2E77F-E722-4830-B4CB-80D8179BEAA3}.Release|x64.ActiveCfg = Release|x64 27 | {87B2E77F-E722-4830-B4CB-80D8179BEAA3}.Release|x64.Build.0 = Release|x64 28 | {87B2E77F-E722-4830-B4CB-80D8179BEAA3}.Release|x86.ActiveCfg = Release|Win32 29 | {87B2E77F-E722-4830-B4CB-80D8179BEAA3}.Release|x86.Build.0 = Release|Win32 30 | {68987F0E-6F47-4D9E-9503-B93F5AD5983A}.Debug|x64.ActiveCfg = Debug|x64 31 | {68987F0E-6F47-4D9E-9503-B93F5AD5983A}.Debug|x64.Build.0 = Debug|x64 32 | {68987F0E-6F47-4D9E-9503-B93F5AD5983A}.Debug|x86.ActiveCfg = Debug|Win32 33 | {68987F0E-6F47-4D9E-9503-B93F5AD5983A}.Debug|x86.Build.0 = Debug|Win32 34 | {68987F0E-6F47-4D9E-9503-B93F5AD5983A}.Release|x64.ActiveCfg = Release|x64 35 | {68987F0E-6F47-4D9E-9503-B93F5AD5983A}.Release|x64.Build.0 = Release|x64 36 | {68987F0E-6F47-4D9E-9503-B93F5AD5983A}.Release|x86.ActiveCfg = Release|Win32 37 | {68987F0E-6F47-4D9E-9503-B93F5AD5983A}.Release|x86.Build.0 = Release|Win32 38 | {96F3160E-965F-434D-9096-F54715AB906B}.Debug|x64.ActiveCfg = Debug|x64 39 | {96F3160E-965F-434D-9096-F54715AB906B}.Debug|x64.Build.0 = Debug|x64 40 | {96F3160E-965F-434D-9096-F54715AB906B}.Debug|x86.ActiveCfg = Debug|Win32 41 | {96F3160E-965F-434D-9096-F54715AB906B}.Debug|x86.Build.0 = Debug|Win32 42 | {96F3160E-965F-434D-9096-F54715AB906B}.Release|x64.ActiveCfg = Release|x64 43 | {96F3160E-965F-434D-9096-F54715AB906B}.Release|x64.Build.0 = Release|x64 44 | {96F3160E-965F-434D-9096-F54715AB906B}.Release|x86.ActiveCfg = Release|Win32 45 | {96F3160E-965F-434D-9096-F54715AB906B}.Release|x86.Build.0 = Release|Win32 46 | {CE7D8382-82CA-4139-8712-14FE68CACF16}.Debug|x64.ActiveCfg = Debug|x64 47 | {CE7D8382-82CA-4139-8712-14FE68CACF16}.Debug|x64.Build.0 = Debug|x64 48 | {CE7D8382-82CA-4139-8712-14FE68CACF16}.Debug|x86.ActiveCfg = Debug|Win32 49 | {CE7D8382-82CA-4139-8712-14FE68CACF16}.Debug|x86.Build.0 = Debug|Win32 50 | {CE7D8382-82CA-4139-8712-14FE68CACF16}.Release|x64.ActiveCfg = Release|x64 51 | {CE7D8382-82CA-4139-8712-14FE68CACF16}.Release|x64.Build.0 = Release|x64 52 | {CE7D8382-82CA-4139-8712-14FE68CACF16}.Release|x86.ActiveCfg = Release|Win32 53 | {CE7D8382-82CA-4139-8712-14FE68CACF16}.Release|x86.Build.0 = Release|Win32 54 | EndGlobalSection 55 | GlobalSection(SolutionProperties) = preSolution 56 | HideSolutionNode = FALSE 57 | EndGlobalSection 58 | GlobalSection(ExtensibilityGlobals) = postSolution 59 | SolutionGuid = {0DB5B935-1572-49B2-8C7F-209F5870CEFA} 60 | EndGlobalSection 61 | EndGlobal 62 | -------------------------------------------------------------------------------- /ProcMonX/EventPropertiesDlg.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "EventPropertiesDlg.h" 3 | #include "EventData.h" 4 | #include "DialogHelper.h" 5 | #include "SortHelper.h" 6 | #include "ClipboardHelper.h" 7 | #include "CallStackDlg.h" 8 | #include "FormatHelper.h" 9 | 10 | CEventPropertiesDlg::CEventPropertiesDlg(EventData* data) : m_pData(data) { 11 | } 12 | 13 | int CEventPropertiesDlg::InsertItem(PCWSTR name, PCWSTR value) { 14 | int n = m_List.InsertItem(m_List.GetItemCount(), name); 15 | m_List.SetItemText(n, 1, value); 16 | m_List.SetItemData(n, (DWORD_PTR)name); 17 | 18 | return n; 19 | } 20 | 21 | LRESULT CEventPropertiesDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { 22 | m_List.Attach(GetDlgItem(IDC_LIST)); 23 | m_List.SetExtendedListViewStyle(LVS_EX_DOUBLEBUFFER | LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP | LVS_EX_INFOTIP); 24 | 25 | DialogHelper::AdjustOKCancelButtons(this); 26 | DialogHelper::SetDialogIcon(this, IDI_PROPERTIES); 27 | DialogHelper::AddIconToButton(this, IDC_COPY, IDI_COPY); 28 | DialogHelper::AddIconToButton(this, IDC_STACK, IDI_STACK); 29 | GetDlgItem(IDC_STACK).EnableWindow(m_pData->GetStackEventData() != nullptr); 30 | 31 | DlgResize_Init(true); 32 | 33 | CString text; 34 | text.Format(L"Event #%u (%s)", m_pData->GetIndex(), m_pData->GetEventName().c_str()); 35 | SetWindowText(text); 36 | 37 | m_List.InsertColumn(0, L"Name", LVCFMT_LEFT, 120); 38 | m_List.InsertColumn(1, L"Value", LVCFMT_LEFT, 300); 39 | 40 | auto ts = m_pData->GetTimeStamp(); 41 | text.Format(L".%06u", (ts / 10) % 1000000); 42 | 43 | auto& desc = m_pData->GetEventDescriptor(); 44 | InsertItem(L"Time Stamp", CTime(*(FILETIME*)&ts).Format(L"%x %X") + text); 45 | InsertItem(L"Event Name", m_pData->GetEventName().c_str()); 46 | ::StringFromGUID2(m_pData->GetProviderId(), (PWSTR)text.GetBufferSetLength(64), 64); 47 | InsertItem(L"Provider Id", text); 48 | text.Format(L"%d (0x%X)", desc.Opcode, desc.Opcode); 49 | InsertItem(L"Opcode", text); 50 | 51 | auto pid = m_pData->GetProcessId(); 52 | if (pid != (DWORD)-1 && pid != 0) { 53 | text.Format(L"%u (0x%X)", pid, pid); 54 | InsertItem(L"Process Id", text); 55 | InsertItem(L"Process Name", m_pData->GetProcessName().c_str()); 56 | } 57 | auto tid = m_pData->GetThreadId(); 58 | if (tid != (DWORD)-1 && tid != 0) { 59 | text.Format(L"%u (0x%X)", tid, tid); 60 | InsertItem(L"Thread Id", text); 61 | } 62 | 63 | for (auto& prop : m_pData->GetProperties()) { 64 | if (prop.Name.substr(0, 8) == L"Reserved") 65 | continue; 66 | auto value = FormatHelper::FormatProperty(m_pData, prop); 67 | if (value.empty()) 68 | value = m_pData->FormatProperty(prop); 69 | InsertItem(prop.Name.c_str(), value.c_str()); 70 | } 71 | 72 | return 0; 73 | } 74 | 75 | LRESULT CEventPropertiesDlg::OnCloseCmd(WORD, WORD wID, HWND, BOOL&) { 76 | EndDialog(wID); 77 | return 0; 78 | } 79 | 80 | LRESULT CEventPropertiesDlg::OnCopy(WORD, WORD wID, HWND, BOOL&) { 81 | CString text, item; 82 | for (int i = 0; i < m_List.GetItemCount(); i++) { 83 | for (int c = 0; c < 2; c++) { 84 | m_List.GetItemText(i, c, item); 85 | text += item += L","; 86 | } 87 | text = text.Left(text.GetLength() - 1) + L"\n"; 88 | } 89 | ClipboardHelper::CopyText(*this, text); 90 | return 0; 91 | } 92 | 93 | LRESULT CEventPropertiesDlg::OnColumnClick(int, LPNMHDR hdr, BOOL&) { 94 | auto lv = (NMLISTVIEW*)hdr; 95 | if (lv->iSubItem == 0) { 96 | m_Ascending = !m_Ascending; 97 | m_List.SortItems([](auto p1, auto p2, auto asc) { 98 | return SortHelper::SortStrings((PCWSTR)p1, (PCWSTR)p2, (bool)asc) ? -1 : 1; 99 | }, (LPARAM)m_Ascending); 100 | } 101 | return 0; 102 | } 103 | 104 | LRESULT CEventPropertiesDlg::OnCallStack(WORD, WORD wID, HWND, BOOL&) { 105 | CCallStackDlg dlg(m_pData); 106 | dlg.DoModal(); 107 | return 0; 108 | } 109 | -------------------------------------------------------------------------------- /Utils/CompoundFile.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "CompoundFile.h" 3 | 4 | using namespace std; 5 | using namespace StructuredStorage; 6 | 7 | unique_ptr CompoundFile::Create(const std::wstring & path, PSECURITY_DESCRIPTOR securityDescriptor) { 8 | CComPtr spStg; 9 | auto hr = ::StgCreateStorageEx(path.c_str(), STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 10 | STGFMT_STORAGE, 0, nullptr, securityDescriptor, __uuidof(IStorage), reinterpret_cast(&spStg)); 11 | if (FAILED(hr)) 12 | return nullptr; 13 | 14 | return unique_ptr(new CompoundFile(spStg)); 15 | } 16 | 17 | unique_ptr CompoundFile::Open(const std::wstring & path, CompoundFileMode mode) { 18 | CComPtr spStg; 19 | auto hr = ::StgOpenStorageEx(path.c_str(), (mode == CompoundFileMode::Read ? STGM_READ : STGM_READWRITE) | STGM_SHARE_EXCLUSIVE, 20 | STGFMT_STORAGE, 0, nullptr, nullptr, __uuidof(IStorage), reinterpret_cast(&spStg)); 21 | if (FAILED(hr)) 22 | return nullptr; 23 | 24 | return unique_ptr(new CompoundFile(spStg, mode)); 25 | } 26 | 27 | unique_ptr StructuredDirectory::CreateStructuredDirectory(const std::wstring & name) { 28 | CheckNameLength(name); 29 | 30 | CComPtr spStg; 31 | auto hr = GetStorage()->CreateStorage(name.c_str(), STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &spStg); 32 | if (FAILED(hr)) 33 | return nullptr; 34 | 35 | return unique_ptr(new StructuredDirectory(spStg)); 36 | } 37 | 38 | unique_ptr StructuredDirectory::CreateStructuredFile(const std::wstring & name) { 39 | CheckNameLength(name); 40 | 41 | CComPtr spStm; 42 | auto hr = GetStorage()->CreateStream(name.c_str(), STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &spStm); 43 | if (FAILED(hr)) 44 | return nullptr; 45 | 46 | return unique_ptr(new StructuredFile(spStm)); 47 | } 48 | 49 | unique_ptr StructuredDirectory::OpenStructuredFile(const std::wstring & name) { 50 | CheckNameLength(name); 51 | 52 | CComPtr spStm; 53 | auto hr = GetStorage()->OpenStream(name.c_str(), nullptr, 54 | (GetMode() == CompoundFileMode::Read ? STGM_READ : STGM_READWRITE) | STGM_SHARE_EXCLUSIVE, 0, &spStm); 55 | if (FAILED(hr)) 56 | return nullptr; 57 | 58 | return unique_ptr(new StructuredFile(spStm)); 59 | } 60 | 61 | unique_ptr StructuredDirectory::OpenStructuredDirectory(const std::wstring & name) { 62 | CheckNameLength(name); 63 | 64 | CComPtr spStg; 65 | auto hr = GetStorage()->OpenStorage(name.c_str(), nullptr, 66 | (GetMode() == CompoundFileMode::Read ? STGM_READ : STGM_READWRITE) | STGM_SHARE_EXCLUSIVE, 0, 0, &spStg); 67 | if (FAILED(hr)) 68 | return nullptr; 69 | 70 | return unique_ptr(new StructuredDirectory(spStg, GetMode())); 71 | } 72 | 73 | void StructuredDirectory::Close() { 74 | m_spStorage = nullptr; 75 | } 76 | 77 | void StructuredDirectory::CheckNameLength(const std::wstring & name) const { 78 | if (name.size() > 31) 79 | throw exception("structured directory and file names must be less than 32 characters"); 80 | } 81 | 82 | void StructuredFile::Write(const void * buffer, uint32_t count) { 83 | auto hr = m_spStream->Write(buffer, count, nullptr); 84 | if (FAILED(hr)) 85 | throw ComException(hr); 86 | } 87 | 88 | void StructuredFile::Read(void * buffer, uint32_t count) { 89 | auto hr = m_spStream->Read(buffer, count, nullptr); 90 | if (FAILED(hr)) 91 | throw ComException(hr); 92 | } 93 | 94 | uint32_t StructuredFile::Seek(uint32_t offset, SeekMode mode) { 95 | LARGE_INTEGER li; 96 | li.QuadPart = offset; 97 | ULARGE_INTEGER newOffset; 98 | auto hr = m_spStream->Seek(li, static_cast(mode), &newOffset); 99 | if (FAILED(hr)) 100 | throw ComException(hr); 101 | 102 | return newOffset.LowPart; 103 | } 104 | 105 | uint32_t StructuredFile::GetSize() const { 106 | STATSTG stat = { 0 }; 107 | m_spStream->Stat(&stat, STATFLAG_NONAME); 108 | return stat.cbSize.LowPart; 109 | } 110 | 111 | void StructuredFile::Close() { 112 | m_spStream = nullptr; 113 | } 114 | -------------------------------------------------------------------------------- /ProcMonX/CallStackDlg.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "CallStackDlg.h" 3 | #include "EventData.h" 4 | #include "SymbolManager.h" 5 | #include "ClipboardHelper.h" 6 | #include "DialogHelper.h" 7 | 8 | CCallStackDlg::CCallStackDlg(EventData* data) : m_pData(data) { 9 | ATLASSERT(data); 10 | } 11 | 12 | DWORD CCallStackDlg::LoadSymbolsThread() { 13 | auto stack = m_pData->GetStackEventData(); 14 | auto& symbols = SymbolManager::Get(); 15 | auto pid = stack->GetProperty(L"StackProcess")->GetValue(); 16 | 17 | CString num; 18 | for (int i = 1; i <= 192; i++) { 19 | if (m_ExitSymbolThread) 20 | break; 21 | 22 | num.Format(L"Stack%d", i); 23 | auto prop = stack->GetProperty(num); 24 | if (prop == nullptr) 25 | break; 26 | 27 | DWORD64 address; 28 | if (prop->GetLength() == 4) 29 | address = prop->GetValue(); 30 | else 31 | address = prop->GetValue(); 32 | DWORD64 offset = 0; 33 | auto symbol = symbols.GetSymbolFromAddress(pid, address, &offset); 34 | if (symbol) { 35 | auto sym = symbol->GetSymbolInfo(); 36 | CStringA text; 37 | text.Format("%s!%s+0x%X", symbol->ModuleInfo.ModuleName, sym->Name, (DWORD)offset); 38 | SendMessage(WM_USER + 100, i, (LPARAM)(PCSTR)text); 39 | } 40 | } 41 | SendMessage(WM_USER + 100, 0, 0); 42 | 43 | return 0; 44 | } 45 | 46 | LRESULT CCallStackDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { 47 | m_List.Attach(GetDlgItem(IDC_LIST)); 48 | 49 | DialogHelper::SetDialogIcon(this, IDI_STACK); 50 | DialogHelper::AddIconToButton(this, IDC_COPY, IDI_COPY); 51 | 52 | CString num; 53 | num.Format(L"Call Stack (Event #%u)", m_pData->GetIndex()); 54 | SetWindowText(num); 55 | 56 | DlgResize_Init(true); 57 | 58 | auto stack = m_pData->GetStackEventData(); 59 | ATLASSERT(stack); 60 | if (stack == nullptr) { 61 | EndDialog(IDCANCEL); 62 | return 0; 63 | } 64 | 65 | auto& symbols = SymbolManager::Get(); 66 | auto pid = stack->GetProperty(L"StackProcess")->GetValue(); 67 | auto tid = stack->GetProperty(L"StackThread")->GetValue(); 68 | SetDlgItemInt(IDC_PROCESS, pid); 69 | SetDlgItemInt(IDC_THREAD, tid); 70 | 71 | m_List.InsertColumn(0, L"#", LVCFMT_LEFT, 45); 72 | m_List.InsertColumn(1, L"Address", LVCFMT_RIGHT, 140); 73 | m_List.InsertColumn(2, L"Symbol", LVCFMT_LEFT, 280); 74 | m_List.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP); 75 | 76 | CImageList images; 77 | images.Create(16, 16, ILC_COLOR32, 2, 0); 78 | images.AddIcon(AtlLoadIconImage(IDI_K, 0, 16, 16)); 79 | images.AddIcon(AtlLoadIconImage(IDI_U, 0, 16, 16)); 80 | m_List.SetImageList(images, LVSIL_SMALL); 81 | 82 | SetDlgItemText(IDC_MESSAGE, L"Loading symbols..."); 83 | 84 | for (int i = 1; i <= 192; i++) { 85 | num.Format(L"Stack%d", i); 86 | auto prop = stack->GetProperty(num); 87 | if (prop == nullptr) 88 | break; 89 | 90 | DWORD64 address; 91 | if (prop->GetLength() == 4) 92 | address = prop->GetValue(); 93 | else 94 | address = prop->GetValue(); 95 | num.Format(L"%2d", i); 96 | int n = m_List.InsertItem(i - 1, num, (int64_t)address < 0 ? 0 : 1); 97 | num.Format(L"0x%p", (PVOID)address); 98 | m_List.SetItemText(n, 1, num); 99 | } 100 | 101 | // create thread to load symbols 102 | m_hThread.reset(::CreateThread(nullptr, 0, [](auto param) { 103 | return ((CCallStackDlg*)param)->LoadSymbolsThread(); 104 | }, this, 0, nullptr)); 105 | ::SetThreadPriority(m_hThread.get(), THREAD_PRIORITY_LOWEST); 106 | 107 | return 0; 108 | } 109 | 110 | LRESULT CCallStackDlg::OnSymbolLoaded(UINT, WPARAM wp, LPARAM lp, BOOL&) { 111 | if (lp) 112 | m_List.SetItemText((int)wp - 1, 2, CString((PCSTR)lp)); 113 | else 114 | SetDlgItemText(IDC_MESSAGE, L""); 115 | 116 | return 0; 117 | } 118 | 119 | LRESULT CCallStackDlg::OnCloseCmd(WORD, WORD wID, HWND, BOOL&) { 120 | m_ExitSymbolThread = true; 121 | if (WAIT_TIMEOUT == ::WaitForSingleObject(m_hThread.get(), 1500)) { 122 | ::TerminateThread(m_hThread.get(), 1); 123 | } 124 | EndDialog(wID); 125 | return 0; 126 | } 127 | 128 | LRESULT CCallStackDlg::OnCopy(WORD, WORD wID, HWND, BOOL&) { 129 | CString text, item; 130 | for (int i = 0; i < m_List.GetItemCount(); i++) { 131 | for (int c = 0; c < 3; c++) { 132 | m_List.GetItemText(i, c, item); 133 | text += item += L","; 134 | } 135 | text = text.Left(text.GetLength() - 1) + L"\n"; 136 | } 137 | ClipboardHelper::CopyText(*this, text); 138 | return 0; 139 | } 140 | -------------------------------------------------------------------------------- /ProcMonX/MainFrm.h: -------------------------------------------------------------------------------- 1 | // MainFrm.h : interface of the CMainFrame class 2 | // 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #pragma once 6 | 7 | #include "resource.h" 8 | #include "Interfaces.h" 9 | #include "TraceManager.h" 10 | #include "View.h" 11 | #include 12 | 13 | class CQuickFindDlg; 14 | 15 | class CMainFrame : 16 | public CFrameWindowImpl, 17 | public CAutoUpdateUI, 18 | public CMessageFilter, 19 | public CIdleHandler, 20 | public IMainFrame, 21 | public IQuickFind { 22 | public: 23 | DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME) 24 | 25 | CMainFrame(); 26 | 27 | virtual BOOL PreTranslateMessage(MSG* pMsg); 28 | virtual BOOL OnIdle(); 29 | 30 | // Inherited via IQuickFind 31 | void DoFind(PCWSTR text, const QuickFindOptions& options) override; 32 | void WindowClosed() override; 33 | 34 | // Inherited via IMainFrame 35 | BOOL TrackPopupMenu(HMENU hMenu, HWND hWnd, POINT* pt = nullptr, UINT flags = 0) override; 36 | HFONT GetMonoFont() override; 37 | void ViewDestroyed(void*) override; 38 | TraceManager& GetTraceManager() override; 39 | BOOL SetPaneText(int index, PCWSTR text) override; 40 | BOOL SetPaneIcon(int index, HICON hIcon) override; 41 | CUpdateUIBase* GetUpdateUI() override; 42 | 43 | BEGIN_MSG_MAP(CMainFrame) 44 | MESSAGE_HANDLER(WM_TIMER, OnTimer) 45 | COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit) 46 | COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew) 47 | COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar) 48 | COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout) 49 | COMMAND_ID_HANDLER(ID_WINDOW_CLOSE, OnWindowClose) 50 | COMMAND_ID_HANDLER(ID_WINDOW_CLOSE_ALL, OnWindowCloseAll) 51 | COMMAND_ID_HANDLER(ID_MONITOR_START, OnMonitorStart) 52 | COMMAND_ID_HANDLER(ID_MONITOR_STOP, OnMonitorStop) 53 | COMMAND_ID_HANDLER(ID_MONITOR_PAUSE, OnMonitorPause) 54 | COMMAND_ID_HANDLER(ID_SEARCH_QUICKFIND, OnQuickFind) 55 | COMMAND_ID_HANDLER(ID_OPTIONS_ALWAYSONTOP, OnAlwaysOnTop) 56 | COMMAND_RANGE_HANDLER(ID_WINDOW_TABFIRST, ID_WINDOW_TABLAST, OnWindowActivate) 57 | MESSAGE_HANDLER(WM_CREATE, OnCreate) 58 | MESSAGE_HANDLER(WM_CLOSE, OnClose) 59 | MESSAGE_HANDLER(WM_DESTROY, OnDestroy) 60 | NOTIFY_CODE_HANDLER(TBVN_PAGEACTIVATED, OnTabActivated) 61 | CHAIN_MSG_MAP(CAutoUpdateUI) 62 | CHAIN_MSG_MAP(CFrameWindowImpl) 63 | COMMAND_RANGE_HANDLER(0x8000, 0xefff, OnForwardToActiveTab) 64 | END_MSG_MAP() 65 | 66 | private: 67 | void InitCommandBar(); 68 | void InitToolBar(CToolBarCtrl&, int size = 24); 69 | static LONG WINAPI UnhandledExceptionFilter(EXCEPTION_POINTERS* ExceptionInfo); 70 | 71 | // Handler prototypes (uncomment arguments if needed): 72 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) 73 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 74 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) 75 | 76 | LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 77 | LRESULT OnTimer(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 78 | LRESULT OnClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 79 | LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled); 80 | LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 81 | LRESULT OnFileNew(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 82 | LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 83 | LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 84 | LRESULT OnWindowClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 85 | LRESULT OnWindowCloseAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 86 | LRESULT OnWindowActivate(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 87 | LRESULT OnAlwaysOnTop(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 88 | LRESULT OnMonitorStart(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 89 | LRESULT OnMonitorStop(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 90 | LRESULT OnMonitorPause(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 91 | LRESULT OnForwardToActiveTab(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 92 | LRESULT OnTabActivated(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/); 93 | LRESULT OnQuickFind(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 94 | 95 | private: 96 | CCommandBarCtrl m_CmdBar; 97 | CMultiPaneStatusBarCtrl m_StatusBar; 98 | CTabView m_view; 99 | CToolBarCtrl m_ToolBar; 100 | TraceManager m_tm; 101 | CFont m_MonoFont; 102 | CIcon m_RunIcon, m_StopIcon, m_PauseIcon; 103 | CView* m_pCurrentView{ nullptr }; 104 | CView* m_pMonitorView{ nullptr }; 105 | CQuickFindDlg* m_pQuickFindDlg{ nullptr }; 106 | }; 107 | -------------------------------------------------------------------------------- /ProcMonX/View.h: -------------------------------------------------------------------------------- 1 | // View.h : interface of the CView class 2 | // 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #pragma once 6 | 7 | #include "ViewBase.h" 8 | #include "VirtualListView.h" 9 | #include "Interfaces.h" 10 | #include "EventData.h" 11 | #include 12 | #include "EventConfiguration.h" 13 | #include "SymbolsHandler.h" 14 | #include "FilterConfiguration.h" 15 | 16 | class CView : 17 | public CViewBase, 18 | public CVirtualListView, 19 | public CCustomDraw { 20 | public: 21 | CView(IMainFrame* frame); 22 | 23 | DECLARE_WND_CLASS(NULL) 24 | 25 | void Activate(bool active); 26 | void AddEvent(std::shared_ptr data); 27 | void StartMonitoring(TraceManager& tm, bool start); 28 | CString GetColumnText(HWND, int row, int col) const; 29 | int GetRowImage(int row) const; 30 | PCWSTR GetColumnTextPointer(HWND, int row, int col) const; 31 | bool OnRightClickList(int row, int col, POINT& pt); 32 | bool OnDoubleClickList(int row, int col, POINT& pt); 33 | 34 | bool IsSortable(int col) const; 35 | void DoSort(const SortInfo* si); 36 | 37 | BOOL PreTranslateMessage(MSG* pMsg); 38 | 39 | // custom draw 40 | 41 | DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/); 42 | DWORD OnSubItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/); 43 | DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/); 44 | 45 | static CImageList GetEventImageList(); 46 | static int GetImageFromEventName(PCWSTR name); 47 | 48 | virtual void OnFinalMessage(HWND /*hWnd*/); 49 | 50 | BEGIN_MSG_MAP(CView) 51 | NOTIFY_CODE_HANDLER(LVN_ITEMCHANGED, OnItemChanged) 52 | // MESSAGE_HANDLER(WM_FORWARDMSG, OnForwardMsg) 53 | MESSAGE_HANDLER(WM_TIMER, OnTimer) 54 | MESSAGE_HANDLER(WM_CREATE, OnCreate) 55 | COMMAND_ID_HANDLER(ID_EVENT_CALLSTACK, OnCallStack) 56 | MESSAGE_HANDLER(WM_CLOSE, OnClose) 57 | COMMAND_ID_HANDLER(ID_MONITOR_CONFIGUREEVENTS, OnConfigureEvents) 58 | COMMAND_ID_HANDLER(ID_SEARCH_FINDNEXT, OnFindNext) 59 | COMMAND_ID_HANDLER(ID_MONITOR_CLEAR, OnClear) 60 | COMMAND_ID_HANDLER(ID_EDIT_COPY, OnCopy) 61 | COMMAND_ID_HANDLER(ID_FILE_SAVE, OnSave) 62 | COMMAND_ID_HANDLER(ID_EDIT_COPYALL, OnCopyAll) 63 | COMMAND_ID_HANDLER(ID_VIEW_AUTOSCROLL, OnAutoScroll) 64 | MESSAGE_HANDLER(WM_DESTROY, OnDestroy) 65 | COMMAND_ID_HANDLER(ID_EVENT_PROPERTIES, OnEventProperties) 66 | COMMAND_ID_HANDLER(ID_MONITOR_FILTERS, OnConfigFilters) 67 | CHAIN_MSG_MAP(CVirtualListView) 68 | CHAIN_MSG_MAP(CCustomDraw) 69 | CHAIN_MSG_MAP(CViewBase) 70 | END_MSG_MAP() 71 | 72 | private: 73 | std::wstring ProcessSpecialEvent(EventData* data) const; 74 | std::wstring GetEventDetails(EventData* data) const; 75 | void UpdateEventStatus(); 76 | void UpdateUI(); 77 | void ApplyFilters(const FilterConfiguration& config); 78 | 79 | // Handler prototypes (uncomment arguments if needed): 80 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) 81 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 82 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) 83 | 84 | LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 85 | LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 86 | LRESULT OnForwardMsg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 87 | LRESULT OnTimer(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 88 | LRESULT OnClear(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 89 | LRESULT OnCallStack(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 90 | LRESULT OnEventProperties(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 91 | LRESULT OnClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 92 | LRESULT OnConfigureEvents(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 93 | LRESULT OnCopy(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 94 | LRESULT OnSave(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 95 | LRESULT OnCopyAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 96 | LRESULT OnAutoScroll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 97 | LRESULT OnConfigFilters(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 98 | LRESULT OnItemChanged(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/); 99 | LRESULT OnFindNext(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 100 | 101 | private: 102 | CListViewCtrl m_List; 103 | inline static CImageList s_Images; 104 | inline static std::unordered_map s_IconsMap; 105 | std::vector> m_Events; 106 | std::vector> m_OrgEvents; 107 | std::vector> m_TempEvents; 108 | std::mutex m_EventsLock; 109 | EventsConfiguration m_EventsConfig; 110 | FilterConfiguration m_FilterConfig; 111 | HFONT m_hFont; 112 | bool m_IsMonitoring{ false }; 113 | bool m_IsDraining{ false }; 114 | bool m_AutoScroll{ false }; 115 | bool m_IsActive{ false }; 116 | }; 117 | -------------------------------------------------------------------------------- /ProcMonX/SymbolsHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SymbolsHandler.h" 3 | 4 | #pragma comment(lib, "dbghelp") 5 | #pragma comment(lib, "ntdll") 6 | 7 | enum SYSTEM_INFORMATION_CLASS { 8 | SystemModuleInformation = 11 9 | }; 10 | 11 | typedef struct _RTL_PROCESS_MODULE_INFORMATION { 12 | HANDLE Section; 13 | PVOID MappedBase; 14 | PVOID ImageBase; 15 | ULONG ImageSize; 16 | ULONG Flags; 17 | USHORT LoadOrderIndex; 18 | USHORT InitOrderIndex; 19 | USHORT LoadCount; 20 | USHORT OffsetToFileName; 21 | UCHAR FullPathName[256]; 22 | } RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION; 23 | 24 | typedef struct _RTL_PROCESS_MODULES { 25 | ULONG NumberOfModules; 26 | RTL_PROCESS_MODULE_INFORMATION Modules[1]; 27 | } RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES; 28 | 29 | extern "C" NTSTATUS NTAPI NtQuerySystemInformation( 30 | _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, 31 | _Out_writes_bytes_opt_(SystemInformationLength) PVOID SystemInformation, 32 | _In_ ULONG SystemInformationLength, 33 | _Out_opt_ PULONG ReturnLength 34 | ); 35 | 36 | SymbolInfo::SymbolInfo() { 37 | auto size = sizeof(SYMBOL_INFO) + MAX_SYM_NAME; 38 | m_Symbol = static_cast(malloc(size)); 39 | ::memset(m_Symbol, 0, size); 40 | m_Symbol->SizeOfStruct = sizeof(SYMBOL_INFO); 41 | m_Symbol->MaxNameLen = MAX_SYM_NAME; 42 | } 43 | 44 | SymbolInfo::~SymbolInfo() { 45 | ::free(m_Symbol); 46 | } 47 | 48 | 49 | SymbolsHandler::SymbolsHandler(HANDLE hProcess, PCSTR searchPath, DWORD symOptions) { 50 | m_hProcess = hProcess; 51 | ::SymSetOptions(symOptions); 52 | ATLVERIFY(::SymInitialize(m_hProcess, searchPath, TRUE)); 53 | } 54 | 55 | std::unique_ptr SymbolsHandler::CreateForProcess(DWORD pid, PCSTR searchPath) { 56 | auto hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, pid); 57 | if (!hProcess) 58 | return nullptr; 59 | return std::make_unique(hProcess, searchPath); 60 | } 61 | 62 | 63 | SymbolsHandler::~SymbolsHandler() { 64 | ::SymCleanup(m_hProcess); 65 | if (m_hProcess != ::GetCurrentProcess()) 66 | ::CloseHandle(m_hProcess); 67 | } 68 | 69 | HANDLE SymbolsHandler::GetHandle() const { 70 | return m_hProcess; 71 | } 72 | 73 | ULONG64 SymbolsHandler::LoadSymbolsForModule(PCSTR moduleName, DWORD64 baseAddress) { 74 | auto address = ::SymLoadModuleEx(m_hProcess, nullptr, moduleName, nullptr, baseAddress, 0, nullptr, 0); 75 | return address; 76 | } 77 | 78 | std::unique_ptr SymbolsHandler::GetSymbolFromName(PCSTR name) { 79 | auto symbol = std::make_unique(); 80 | if (::SymFromName(m_hProcess, name, symbol->GetSymbolInfo())) 81 | return symbol; 82 | return nullptr; 83 | } 84 | 85 | std::unique_ptr SymbolsHandler::GetSymbolFromAddress(DWORD64 address, PDWORD64 offset) { 86 | auto symbol = std::make_unique(); 87 | if (::SymFromAddr(m_hProcess, address, offset, symbol->GetSymbolInfo())) { 88 | symbol->ModuleInfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); 89 | ::SymGetModuleInfo64(m_hProcess, address, &symbol->ModuleInfo); 90 | return symbol; 91 | } 92 | return nullptr; 93 | } 94 | 95 | IMAGEHLP_MODULE64 SymbolsHandler::GetModuleInfo(DWORD64 address) const { 96 | IMAGEHLP_MODULE64 info = { sizeof(info) }; 97 | ::SymGetModuleInfo64(m_hProcess, address, &info); 98 | return info; 99 | } 100 | 101 | bool SymbolsHandler::LoadDefaultModules() { 102 | // load kernel modules 103 | PVOID base[1024]; 104 | DWORD needed; 105 | CHAR path[MAX_PATH]; 106 | ::EnumDeviceDrivers(base, sizeof(base), &needed); 107 | auto count = min(sizeof(base), needed) / sizeof(PVOID); 108 | for (int i = 0; i < count; i++) { 109 | if (::GetDeviceDriverFileNameA(base[i], path, _countof(path))) { 110 | CStringA fullpath(path); 111 | fullpath.Replace("\\SystemRoot\\", "%SystemRoot%\\"); 112 | if (fullpath.Mid(1, 2) == "??") 113 | fullpath = fullpath.Mid(4); 114 | auto address = LoadSymbolsForModule(fullpath, (DWORD64)base[i]); 115 | ATLASSERT(address); 116 | } 117 | } 118 | 119 | // load common user modules 120 | //HMODULE hModule[1024]; 121 | //::EnumProcessModules(::GetCurrentProcess(), hModule, sizeof(hModule), &needed); 122 | //count = min(sizeof(base), needed) / sizeof(PVOID); 123 | //for (int i = 0; i < count; i++) { 124 | // if (::GetModuleFileNameA(hModule[i], path, _countof(path))) { 125 | // ATLVERIFY(LoadSymbolsForModule(path, (DWORD64)hModule[i])); 126 | // } 127 | //} 128 | 129 | return true; 130 | } 131 | 132 | DWORD64 SymbolsHandler::LoadKernelModule(DWORD64 address) { 133 | auto size = 1 << 20; 134 | auto buffer = std::make_unique(size); 135 | if (0 != ::NtQuerySystemInformation(SystemModuleInformation, buffer.get(), size, nullptr)) 136 | return 0; 137 | 138 | auto p = (RTL_PROCESS_MODULES*)buffer.get(); 139 | auto count = p->NumberOfModules; 140 | for (ULONG i = 0; i < count; i++) { 141 | auto& module = p->Modules[i]; 142 | if ((DWORD64)module.ImageBase <= address && (DWORD64)module.ImageBase + module.ImageSize > address) { 143 | // found the module 144 | ATLTRACE(L"Kernel module for address 0x%p found: %s\n", address, CString(module.FullPathName)); 145 | CStringA fullpath(module.FullPathName); 146 | fullpath.Replace("\\SystemRoot\\", "%SystemRoot%\\"); 147 | if (fullpath.Mid(1, 2) == "??") 148 | fullpath = fullpath.Mid(4); 149 | return LoadSymbolsForModule(fullpath, (DWORD64)module.ImageBase); 150 | } 151 | } 152 | ATLTRACE(L"Kernel module for address 0x%p not found\n", address); 153 | 154 | return 0; 155 | } 156 | 157 | BOOL SymbolsHandler::Callback(ULONG code, ULONG64 data) { 158 | MSG msg; 159 | while (::PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) 160 | ::DispatchMessage(&msg); 161 | 162 | return 0; 163 | } 164 | -------------------------------------------------------------------------------- /ProcMonX/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by ProcMonX.rc 4 | // 5 | #define IDD_ABOUTBOX 100 6 | #define IDR_MAINFRAME 128 7 | #define IDS_TITLE 129 8 | #define IDI_CANCEL 202 9 | #define IDI_DRIVER 203 10 | #define IDI_FILTER 204 11 | #define IDI_FILTER_ADD 205 12 | #define IDI_FILTER_DELETE 206 13 | #define IDI_FIND 207 14 | #define IDI_MEMORY 208 15 | #define IDI_DLL 209 16 | #define IDI_NETWORK 210 17 | #define IDI_OK 211 18 | #define IDI_PLAY 212 19 | #define IDI_PROCESSES 213 20 | #define IDI_REGISTRY 214 21 | #define IDI_STOP 215 22 | #define IDI_THREAD 216 23 | #define IDI_TOOLS 217 24 | #define IDD_STACK 218 25 | #define IDI_EVENT 220 26 | #define IDI_SAVE 221 27 | #define IDI_SAVE_AS 222 28 | #define IDD_EVENTS 224 29 | #define IDI_EVENT2 226 30 | #define IDI_PROPERTIES 228 31 | #define IDI_STACK 229 32 | #define IDI_GENERIC 230 33 | #define IDI_GEAR 231 34 | #define IDI_FILE 233 35 | #define IDI_HANDLE 234 36 | #define IDI_OBJECT 235 37 | #define IDI_DISK 238 38 | #define IDI_HEAP 240 39 | #define IDI_HEAP2 241 40 | #define IDI_K 242 41 | #define IDI_U 243 42 | #define IDI_COPY 244 43 | #define IDR_CONTEXT 245 44 | #define IDD_EVENT_PROPS 246 45 | #define IDI_PROCESS_DELETE 248 46 | #define IDI_PROCESS_NEW 249 47 | #define IDI_DLL_LOAD 250 48 | #define IDI_DLL_UNLOAD 251 49 | #define IDI_THREAD_DELETE 252 50 | #define IDI_THREAD_NEW 253 51 | #define IDD_FILTERS 254 52 | #define IDI_DOWN_ARROW 256 53 | #define IDI_UP_ARROW 257 54 | #define IDI_OPEN 258 55 | #define IDI_ADD 259 56 | #define IDI_FILTER_EDIT 260 57 | #define IDI_CANCEL2 261 58 | #define IDI_OK2 262 59 | #define IDI_PAUSE 263 60 | #define IDI_ICON1 264 61 | #define IDI_SCROLL 264 62 | #define IDI_SEARCH 265 63 | #define IDD_FIND 266 64 | #define IDC_LIST 1000 65 | #define IDC_TREE 1002 66 | #define IDC_SAVE 1003 67 | #define IDC_LOAD 1004 68 | #define IDC_RESET 1005 69 | #define IDC_DEFAULTS 1006 70 | #define IDC_EXPAND 1007 71 | #define IDC_COLLAPSE 1008 72 | #define IDC_MESSAGE 1009 73 | #define IDC_PROCESS 1011 74 | #define IDC_THREAD 1012 75 | #define IDC_COPY 1013 76 | #define IDC_UP 1017 77 | #define IDC_DOWN 1018 78 | #define IDC_DELETE 1019 79 | #define IDC_NAMES 1020 80 | #define IDC_COMPARE 1021 81 | #define IDC_INC_EXC 1023 82 | #define IDC_ADD 1024 83 | #define IDC_VALUE 1025 84 | #define IDC_EDIT 1026 85 | #define IDC_BASIC 1026 86 | #define IDC_ADVANCED 1027 87 | #define IDC_STACK 1031 88 | #define IDC_RESOLVE_SYM 1032 89 | #define IDC_SYSLINK1 1033 90 | #define IDC_TEXT 1034 91 | #define IDC_PROCESSES 1035 92 | #define IDC_EVENT 1036 93 | #define IDC_DETAILS 1037 94 | #define IDC_CASESENSITIVE 1040 95 | #define IDC_FINDNEXT 1042 96 | #define ID_WINDOW_CLOSE 32772 97 | #define ID_WINDOW_CLOSE_ALL 32773 98 | #define ID_OPTIONS_ALWAYSONTOP 32775 99 | #define ID_MONITOR_START 32776 100 | #define ID_MONITOR_STOP 32777 101 | #define ID_VIEW_COLUMNS 32778 102 | #define ID_MONITOR_CLEAR 32780 103 | #define ID_EVENT_PROPERTIES 32781 104 | #define ID_EVENT_CALLSTACK 32782 105 | #define ID_MONITOR_CONFIGUREEVENTS 32783 106 | #define ID_MONITOR_FILTERS 32784 107 | #define ID_OPTIONS_SYMBOLS 32785 108 | #define ID_FILE_NEWTAB 32786 109 | #define ID_VIEW_AUTOSCROLL 32787 110 | #define ID_MONITOR_PAUSE 32788 111 | #define ID_EDIT_COPYALL 32789 112 | #define ID_SEARCH_QUICKFIND 32790 113 | #define ID_SEARCH_FINDALL 32791 114 | #define ID_SEARCH_FINDNEXT 32795 115 | 116 | // Next default values for new objects 117 | // 118 | #ifdef APSTUDIO_INVOKED 119 | #ifndef APSTUDIO_READONLY_SYMBOLS 120 | #define _APS_NEXT_RESOURCE_VALUE 268 121 | #define _APS_NEXT_COMMAND_VALUE 32797 122 | #define _APS_NEXT_CONTROL_VALUE 1043 123 | #define _APS_NEXT_SYMED_VALUE 101 124 | #endif 125 | #endif 126 | -------------------------------------------------------------------------------- /ProcMonX/ColumnManager.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ColumnManager.h" 3 | 4 | 5 | class ListCtrlHelper { 6 | public: 7 | template 8 | static T FindColumn(CHeaderCtrl header, int id) { 9 | auto count = header.GetItemCount(); 10 | HDITEM hdi; 11 | hdi.mask = HDI_LPARAM; 12 | for (int i = 0; i < count; i++) { 13 | header.GetItem(i, &hdi); 14 | if (hdi.lParam == id) 15 | return static_cast(i); 16 | } 17 | return static_cast(-1); 18 | } 19 | 20 | template 21 | static T FindColumn(CListViewCtrl list, int id) { 22 | return FindColumn(list.GetHeader().m_hWnd, id); 23 | } 24 | 25 | template 26 | static T GetRealColumn(CListViewCtrl& list, int index) { 27 | return static_cast(GetRealColumn(list.GetHeader(), index)); 28 | } 29 | 30 | template 31 | static T GetRealColumn(CHeaderCtrl header, int index) { 32 | HDITEM hdi; 33 | hdi.mask = HDI_LPARAM; 34 | header.GetItem(index, &hdi); 35 | return static_cast(hdi.lParam); 36 | } 37 | }; 38 | 39 | ColumnManager::~ColumnManager() = default; 40 | 41 | bool ColumnManager::CopyTo(ColumnManager & other) const { 42 | if (other.GetCount() != GetCount()) 43 | return false; 44 | 45 | int i = 0; 46 | for (const auto& column : m_Columns) { 47 | other.SetColumn(i, column); 48 | i++; 49 | } 50 | return true; 51 | } 52 | 53 | void ColumnManager::AddFromControl(HWND hWnd) { 54 | CHeaderCtrl header(hWnd == nullptr ? m_ListView.GetHeader() : CListViewCtrl(hWnd).GetHeader()); 55 | ATLASSERT(header); 56 | auto count = header.GetItemCount(); 57 | HDITEM item; 58 | WCHAR text[64]; 59 | item.pszText = text; 60 | item.cchTextMax = _countof(text); 61 | item.mask = HDI_FORMAT | HDI_WIDTH | HDI_TEXT; 62 | for (int i = 0; i < count; i++) { 63 | ATLVERIFY(header.GetItem(i, &item)); 64 | ColumnInfo info; 65 | info.DefaultWidth = item.cxy; 66 | info.Flags = (info.DefaultWidth <= 1 && ((item.fmt & HDF_FIXEDWIDTH) > 0) ? ColumnFlags::Visible : ColumnFlags::None); 67 | info.Name = item.pszText; 68 | m_Columns.push_back(info); 69 | } 70 | } 71 | 72 | void ColumnManager::SetVisible(int column, bool visible) { 73 | m_Columns[column].SetVisible(visible); 74 | } 75 | 76 | bool ColumnManager::IsVisible(int column) const { 77 | ATLASSERT(column >= 0 && column < GetCount()); 78 | return (m_Columns[column].Flags & ColumnFlags::Visible) == ColumnFlags::Visible; 79 | } 80 | 81 | bool ColumnManager::IsModified(int column) const { 82 | return (GetColumn(column).Flags & ColumnFlags::Modified) == ColumnFlags::Modified; 83 | } 84 | 85 | void ColumnManager::SetModified(int column, bool modified) { 86 | auto& col = m_Columns[column]; 87 | if (modified) 88 | col.Flags |= ColumnFlags::Modified; 89 | else 90 | col.Flags &= ~ColumnFlags::Modified; 91 | } 92 | 93 | bool ColumnManager::IsConst(int column) const { 94 | return (m_Columns[column].Flags & ColumnFlags::Const) == ColumnFlags::Const; 95 | } 96 | 97 | int ColumnManager::AddColumn(PCWSTR name, int format, int width, ColumnFlags flags) { 98 | auto category = ::wcschr(name, L'\\'); 99 | CString categoryName; 100 | if (category) { 101 | categoryName = CString(name, static_cast(category - name)); 102 | name = category + 1; 103 | } 104 | else { 105 | categoryName = L"General"; 106 | } 107 | ColumnInfo info; 108 | info.Format = format; 109 | info.DefaultWidth = width; 110 | info.Flags = flags; 111 | info.Name = name; 112 | info.Category = categoryName; 113 | 114 | if (m_ListView && ((flags & ColumnFlags::Visible) == ColumnFlags::Visible)) { 115 | auto header = m_ListView.GetHeader(); 116 | int i = m_ListView.InsertColumn(header.GetItemCount(), name, format, width); 117 | HDITEM hdi; 118 | hdi.mask = HDI_LPARAM; 119 | hdi.lParam = m_Columns.size(); 120 | header.SetItem(i, &hdi); 121 | } 122 | 123 | m_Columns.push_back(info); 124 | if (!categoryName.IsEmpty()) { 125 | if (std::find(m_Categories.begin(), m_Categories.end(), categoryName) == m_Categories.end()) 126 | m_Categories.push_back(categoryName); 127 | m_ColumnsByCategory[categoryName].push_back(static_cast(m_Columns.size() - 1)); 128 | } 129 | 130 | return static_cast(m_Columns.size()); 131 | } 132 | 133 | void ColumnManager::UpdateColumns() { 134 | auto header = m_ListView.GetHeader(); 135 | HDITEM hdi; 136 | hdi.mask = HDI_LPARAM; 137 | for (int i = 0; i < GetCount(); i++) { 138 | if (IsModified(i)) { 139 | if (IsVisible(i)) { 140 | auto& info = GetColumn(i); 141 | // make visible - add column 142 | int c = m_ListView.InsertColumn(header.GetItemCount(), info.Name, info.Format, info.DefaultWidth); 143 | hdi.lParam = i; 144 | header.SetItem(c, &hdi); 145 | } 146 | else { 147 | int c = ListCtrlHelper::FindColumn(header, i); 148 | ATLASSERT(c >= 0); 149 | m_ListView.DeleteColumn(c); 150 | } 151 | SetModified(i, false); 152 | } 153 | } 154 | } 155 | 156 | const ColumnManager::ColumnInfo& ColumnManager::GetColumn(int index) const { 157 | return m_Columns[index]; 158 | } 159 | 160 | const std::vector& ColumnManager::GetColumnsByCategory(PCWSTR category) const { 161 | return m_ColumnsByCategory.at(category); 162 | } 163 | 164 | const std::vector& ColumnManager::GetCategories() const { 165 | return m_Categories; 166 | } 167 | 168 | void ColumnManager::SetColumn(int i, const ColumnInfo & info) { 169 | ATLASSERT(i >= 0 && i < GetCount()); 170 | if ((info.Flags & ColumnFlags::Visible) != (m_Columns[i].Flags & ColumnFlags::Visible)) { 171 | SetVisible(i, (info.Flags & ColumnFlags::Visible) == ColumnFlags::Visible); 172 | } 173 | } 174 | 175 | int ColumnManager::GetRealColumn(int index) const { 176 | HDITEM hdi; 177 | hdi.mask = HDI_LPARAM; 178 | m_ListView.GetHeader().GetItem(index, &hdi); 179 | return static_cast(hdi.lParam); 180 | } 181 | -------------------------------------------------------------------------------- /EventTracing/EventData.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "EventData.h" 3 | #include 4 | 5 | // EventProperty 6 | 7 | EventProperty::EventProperty(EVENT_PROPERTY_INFO& info) : Info(info) { 8 | } 9 | 10 | void* EventProperty::Allocate(ULONG size) { 11 | Data.resize(size); 12 | return Data.data(); 13 | } 14 | 15 | PCWSTR EventProperty::GetUnicodeString() const { 16 | return (PCWSTR)Data.data(); 17 | } 18 | 19 | PCSTR EventProperty::GetAnsiString() const { 20 | return (PCSTR)Data.data(); 21 | } 22 | 23 | // EventData 24 | 25 | EventData::EventData(PEVENT_RECORD rec, std::wstring processName, const std::wstring& eventName, uint32_t index) : _record(rec), 26 | _processName(std::move(processName)), _eventName(std::move(eventName)), _index(index) { 27 | auto& header = rec->EventHeader; 28 | _headerFlags = header.Flags; 29 | _processId = header.ProcessId; 30 | _threadId = header.ThreadId; 31 | _providerId = header.ProviderId; 32 | _timeStamp = header.TimeStamp.QuadPart; 33 | _eventDescriptor = header.EventDescriptor; 34 | 35 | // parse event specific data 36 | 37 | ULONG size = 0; 38 | auto error = ::TdhGetEventInformation(rec, 0, nullptr, nullptr, &size); 39 | if (error == ERROR_INSUFFICIENT_BUFFER) { 40 | _buffer = std::make_unique(size); 41 | auto info = reinterpret_cast(_buffer.get()); 42 | error = ::TdhGetEventInformation(rec, 0, nullptr, info, &size); 43 | } 44 | ::SetLastError(error); 45 | } 46 | 47 | void* EventData::operator new(size_t size) { 48 | if (InterlockedIncrement(&s_Count) == 1) { 49 | InitializeCriticalSection(&s_HeapLock); 50 | s_hHeap = ::HeapCreate(HEAP_NO_SERIALIZE, 1 << 24, 0); 51 | assert(s_hHeap); 52 | } 53 | 54 | EnterCriticalSection(&s_HeapLock); 55 | 56 | const LPVOID p = ::HeapAlloc(s_hHeap, 0, size); 57 | 58 | LeaveCriticalSection(&s_HeapLock); 59 | 60 | return p; 61 | } 62 | 63 | void EventData::operator delete(void* p) { 64 | 65 | EnterCriticalSection(&s_HeapLock); 66 | 67 | ::HeapFree(s_hHeap, 0, p); 68 | 69 | LeaveCriticalSection(&s_HeapLock); 70 | 71 | if (InterlockedDecrement(&s_Count) == 0) { 72 | if (s_hHeap) { 73 | ::HeapDestroy(s_hHeap); 74 | } 75 | } 76 | } 77 | 78 | DWORD EventData::GetProcessId() const { 79 | return _processId; 80 | } 81 | 82 | const std::wstring& EventData::GetProcessName() const { 83 | return _processName; 84 | } 85 | 86 | const std::wstring& EventData::GetEventName() const { 87 | return _eventName; 88 | } 89 | 90 | DWORD EventData::GetThreadId() const { 91 | return _threadId; 92 | } 93 | 94 | ULONGLONG EventData::GetTimeStamp() const { 95 | return _timeStamp; 96 | } 97 | 98 | const GUID& EventData::GetProviderId() const { 99 | return _providerId; 100 | } 101 | 102 | const EVENT_DESCRIPTOR& EventData::GetEventDescriptor() const { 103 | return _eventDescriptor; 104 | } 105 | 106 | const std::vector& EventData::GetProperties() const { 107 | if (!_properties.empty() || _buffer == nullptr) 108 | return _properties; 109 | 110 | auto info = reinterpret_cast(_buffer.get()); 111 | _properties.reserve(info->TopLevelPropertyCount); 112 | auto userDataLength = _record->UserDataLength; 113 | auto data = (BYTE*)_record->UserData; 114 | 115 | for (ULONG i = 0; i < info->TopLevelPropertyCount && userDataLength > 0; i++) { 116 | auto& prop = info->EventPropertyInfoArray[i]; 117 | EventProperty property(prop); 118 | property.Name.assign((WCHAR*)((BYTE*)info + prop.NameOffset)); 119 | ULONG len = prop.length; 120 | if (len == 0) { 121 | PROPERTY_DATA_DESCRIPTOR desc; 122 | desc.PropertyName = (ULONGLONG)property.Name.c_str(); 123 | desc.ArrayIndex = ULONG_MAX; 124 | ::TdhGetPropertySize(_record, 0, nullptr, 1, &desc, &len); 125 | } 126 | if (len) { 127 | auto d = property.Allocate(len); 128 | if (d) { 129 | ::memcpy(d, data, len); 130 | } 131 | data += len; 132 | if (userDataLength < len) 133 | break; 134 | userDataLength -= (USHORT)len; 135 | } 136 | _properties.push_back(std::move(property)); 137 | } 138 | if (_properties.empty()) { 139 | _buffer.release(); 140 | } 141 | return _properties; 142 | } 143 | 144 | const EventProperty* EventData::GetProperty(PCWSTR name) const { 145 | for (auto& prop : GetProperties()) 146 | if (prop.Name == name) 147 | return ∝ 148 | return nullptr; 149 | } 150 | 151 | const EventData* EventData::GetStackEventData() const { 152 | return _stackData.get(); 153 | } 154 | 155 | uint32_t EventData::GetIndex() const { 156 | return _index; 157 | } 158 | 159 | std::wstring EventData::FormatProperty(const EventProperty& property) const { 160 | ULONG size = 0; 161 | PEVENT_MAP_INFO eventMap = nullptr; 162 | std::unique_ptr mapBuffer; 163 | auto& prop = property.Info; 164 | WCHAR buffer[1024]; 165 | auto info = reinterpret_cast(_buffer.get()); 166 | if (prop.nonStructType.MapNameOffset) { 167 | auto mapName = (PWSTR)((PBYTE)info + prop.nonStructType.MapNameOffset); 168 | if(ERROR_INSUFFICIENT_BUFFER == ::TdhGetEventMapInformation(_record, mapName, nullptr, &size)) { 169 | mapBuffer = std::make_unique(size); 170 | eventMap = reinterpret_cast(mapBuffer.get()); 171 | if(ERROR_SUCCESS != ::TdhGetEventMapInformation(_record, mapName, eventMap, &size)) 172 | eventMap = nullptr; 173 | } 174 | } 175 | size = sizeof(buffer); 176 | 177 | // length special case for IPV6 178 | auto len = prop.length; 179 | if (prop.nonStructType.InType == TDH_INTYPE_BINARY && prop.nonStructType.OutType == TDH_OUTTYPE_IPV6) 180 | len = sizeof(IN6_ADDR); 181 | 182 | USHORT consumed; 183 | auto status = ::TdhFormatProperty(info, eventMap, (_headerFlags & EVENT_HEADER_FLAG_32_BIT_HEADER) ? 4 : 8, 184 | prop.nonStructType.InType, prop.nonStructType.OutType, len, (USHORT)property.GetLength(), (PBYTE)property.GetData(), 185 | &size, buffer, &consumed); 186 | if (status == STATUS_SUCCESS) 187 | return std::wstring(buffer); 188 | 189 | return L""; 190 | } 191 | 192 | uint64_t EventData::GetEventKey() const { 193 | return _providerId.Data1 ^ _eventDescriptor.Opcode; 194 | } 195 | 196 | void EventData::SetStackEventData(std::shared_ptr data) { 197 | _stackData = std::move(data); 198 | } 199 | 200 | void EventData::SetProcessName(std::wstring name) { 201 | _processName = std::move(name); 202 | } 203 | 204 | -------------------------------------------------------------------------------- /ProcMonX/EventsDlg.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "EventConfiguration.h" 3 | #include "EventsDlg.h" 4 | #include "KernelEvents.h" 5 | #include "View.h" 6 | #include "DialogHelper.h" 7 | 8 | CEventsDlg::CEventsDlg(EventsConfiguration& config) : m_Config(config) { 9 | } 10 | 11 | void CEventsDlg::BuildEventsTree(const EventsConfiguration& config) { 12 | m_Tree.LockWindowUpdate(TRUE); 13 | 14 | m_Tree.DeleteAllItems(); 15 | for (auto& category : KernelEventCategory::GetAllCategories()) { 16 | if (category.Advanced == m_Advanced) { 17 | int image = CView::GetImageFromEventName(category.Name.c_str()); 18 | auto item = m_Tree.InsertItem(category.Name.c_str(), image, image, TVI_ROOT, TVI_LAST); 19 | if (m_Advanced && !category.Advanced) 20 | item.SetState(TVIS_BOLD, TVIS_BOLD); 21 | 22 | item.SetData((DWORD_PTR)&category); 23 | auto cat = config.GetCategory(category.Name.c_str()); 24 | for (auto& evt : category.Events) { 25 | image = CView::GetImageFromEventName(evt.Name.c_str()); 26 | auto child = item.InsertAfter(evt.Name.c_str(), TVI_LAST, image); 27 | child.SetData((DWORD_PTR)&evt); 28 | if (cat && cat->Contains(evt.Opcode)) 29 | m_Tree.SetCheckState(child, TRUE); 30 | } 31 | if (cat) { 32 | if (cat->Opcodes.empty()) { 33 | // all events must be checked 34 | CheckTreeChildren(item, TRUE); 35 | m_Tree.SetCheckState(item, TRUE); 36 | } 37 | else { 38 | item.Expand(TVE_EXPAND); 39 | } 40 | } 41 | item.SortChildren(FALSE); 42 | } 43 | } 44 | m_Tree.SortChildren(TVI_ROOT, FALSE); 45 | m_Tree.LockWindowUpdate(FALSE); 46 | } 47 | 48 | LRESULT CEventsDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { 49 | DlgResize_Init(true); 50 | m_Tree.Attach(GetDlgItem(IDC_TREE)); 51 | DialogHelper::SetDialogIcon(this, IDI_TOOLS); 52 | CheckRadioButton(IDC_BASIC, IDC_ADVANCED, m_Advanced ? IDC_ADVANCED : IDC_BASIC); 53 | 54 | m_Tree.ModifyStyle(0, TVS_CHECKBOXES); 55 | ATLASSERT(m_Tree.GetStyle() & TVS_CHECKBOXES); 56 | m_Tree.SetExtendedStyle(TVS_EX_DIMMEDCHECKBOXES | TVS_EX_DOUBLEBUFFER, TVS_EX_DIMMEDCHECKBOXES); 57 | 58 | auto images = CView::GetEventImageList(); 59 | m_Tree.SetImageList(images, TVSIL_NORMAL); 60 | m_Tree.SetItemHeight(18); 61 | m_Tree.SetIndent(4); 62 | 63 | m_TempConfig = m_Config; 64 | 65 | BuildEventsTree(m_Config); 66 | m_Init = false; 67 | 68 | return 0; 69 | } 70 | 71 | LRESULT CEventsDlg::OnDestroy(UINT, WPARAM, LPARAM, BOOL& handled) { 72 | handled = FALSE; 73 | m_Tree.SetImageList(nullptr, TVSIL_NORMAL); 74 | 75 | return 0; 76 | } 77 | 78 | LRESULT CEventsDlg::OnGetMinMaxInfo(UINT, WPARAM, LPARAM lParam, BOOL& handled) { 79 | auto pMMI = (PMINMAXINFO)lParam; 80 | pMMI->ptMaxTrackSize.x = m_ptMinTrackSize.x; 81 | handled = FALSE; 82 | 83 | return 0; 84 | } 85 | 86 | void CEventsDlg::CheckTreeChildren(HTREEITEM hParent, bool check) { 87 | auto hChild = m_Tree.GetChildItem(hParent); 88 | while (hChild) { 89 | m_Tree.SetCheckState(hChild, check); 90 | hChild = hChild.GetNextSibling(); 91 | } 92 | } 93 | 94 | bool CEventsDlg::BuildConfigFromTree(EventsConfiguration& config) { 95 | auto item = m_Tree.GetRootItem(); 96 | CString text; 97 | while (item) { 98 | item.GetText(text); 99 | EventConfigCategory category; 100 | category.Name = text; 101 | if (m_Tree.GetCheckState(item)) { 102 | // entire category selected 103 | config.AddCategory(category); 104 | } 105 | else { 106 | auto child = item.GetChild(); 107 | while (child) { 108 | if (m_Tree.GetCheckState(child)) { 109 | auto evt = (KernelEvent*)child.GetData(); 110 | category.Opcodes.push_back(evt->Opcode); 111 | } 112 | child = child.GetNextSibling(); 113 | } 114 | if(!category.Opcodes.empty()) 115 | config.AddCategory(category); 116 | } 117 | item = item.GetNextSibling(); 118 | } 119 | 120 | return true; 121 | } 122 | 123 | void CEventsDlg::SwitchToAdvancedView(bool advanced) { 124 | m_Init = true; 125 | m_TempConfig.RemoveAdvanced(!advanced); 126 | BuildConfigFromTree(m_TempConfig); 127 | BuildEventsTree(m_TempConfig); 128 | m_Init = false; 129 | } 130 | 131 | LRESULT CEventsDlg::OnTreeItemChanged(int, LPNMHDR hdr, BOOL&) { 132 | if (m_Init || m_Recurse > 0) 133 | return 0; 134 | 135 | auto tv = (NMTVITEMCHANGE*)hdr; 136 | if (((tv->uStateNew ^ tv->uStateOld) & TVIS_STATEIMAGEMASK) == 0) 137 | return 0; 138 | 139 | auto hItem = tv->hItem; 140 | auto checked = m_Tree.GetCheckState(hItem); 141 | auto child = m_Tree.GetChildItem(hItem); 142 | if (child) { 143 | m_Recurse++; 144 | CheckTreeChildren(hItem, checked); 145 | m_Recurse--; 146 | } 147 | else if (!checked) { 148 | m_Recurse++; 149 | m_Tree.SetCheckState(m_Tree.GetParentItem(hItem), FALSE); 150 | m_Recurse--; 151 | } 152 | 153 | m_Tree.SelectItem(hItem); 154 | return 0; 155 | } 156 | 157 | LRESULT CEventsDlg::OnSave(WORD, WORD id, HWND, BOOL&) { 158 | CSimpleFileDialog dlg(FALSE, L"ini", nullptr, OFN_EXPLORER | OFN_ENABLESIZING | OFN_OVERWRITEPROMPT, 159 | SaveLoadIniFilter, *this); 160 | if (dlg.DoModal() == IDOK) { 161 | EventsConfiguration config; 162 | BuildConfigFromTree(config); 163 | config.Save(dlg.m_szFileName); 164 | } 165 | 166 | return 0; 167 | } 168 | 169 | LRESULT CEventsDlg::OnLoad(WORD, WORD id, HWND, BOOL&) { 170 | CSimpleFileDialog dlg(TRUE, L"ini", nullptr, OFN_EXPLORER | OFN_ENABLESIZING | OFN_FILEMUSTEXIST, 171 | SaveLoadIniFilter, *this); 172 | if (dlg.DoModal() == IDOK) { 173 | EventsConfiguration config; 174 | if (config.Load(dlg.m_szFileName)) { 175 | BuildEventsTree(config); 176 | } 177 | } 178 | return 0; 179 | } 180 | 181 | LRESULT CEventsDlg::OnExpandAll(WORD, WORD id, HWND, BOOL&) { 182 | auto item = m_Tree.GetRootItem(); 183 | while (item) { 184 | m_Tree.Expand(item, TVE_EXPAND); 185 | item = item.GetNextSibling(); 186 | } 187 | 188 | return 0; 189 | } 190 | 191 | LRESULT CEventsDlg::OnCollapseAll(WORD, WORD id, HWND, BOOL&) { 192 | auto item = m_Tree.GetRootItem(); 193 | while (item) { 194 | m_Tree.Expand(item, TVE_COLLAPSE); 195 | item = item.GetNextSibling(); 196 | } 197 | 198 | return 0; 199 | } 200 | 201 | LRESULT CEventsDlg::OnBasicView(WORD, WORD id, HWND, BOOL&) { 202 | if (m_Advanced) { 203 | m_Advanced = false; 204 | SwitchToAdvancedView(false); 205 | } 206 | return 0; 207 | } 208 | 209 | LRESULT CEventsDlg::OnAdvancedView(WORD, WORD id, HWND, BOOL&) { 210 | if (!m_Advanced) { 211 | m_Advanced = true; 212 | SwitchToAdvancedView(true); 213 | } 214 | return 0; 215 | } 216 | 217 | LRESULT CEventsDlg::OnCloseCmd(WORD, WORD id, HWND, BOOL&) { 218 | if (id == IDOK) { 219 | m_TempConfig.RemoveAdvanced(m_Advanced); 220 | BuildConfigFromTree(m_TempConfig); 221 | m_Config = m_TempConfig; 222 | } 223 | EndDialog(id); 224 | return 0; 225 | } 226 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | [Aa][Rr][Mm]/ 24 | [Aa][Rr][Mm]64/ 25 | bld/ 26 | [Bb]in/ 27 | [Oo]bj/ 28 | [Ll]og/ 29 | 30 | # Visual Studio 2015/2017 cache/options directory 31 | .vs/ 32 | # Uncomment if you have tasks that create the project's static files in wwwroot 33 | #wwwroot/ 34 | 35 | # Visual Studio 2017 auto generated files 36 | Generated\ Files/ 37 | 38 | # MSTest test Results 39 | [Tt]est[Rr]esult*/ 40 | [Bb]uild[Ll]og.* 41 | 42 | # NUNIT 43 | *.VisualState.xml 44 | TestResult.xml 45 | 46 | # Build Results of an ATL Project 47 | [Dd]ebugPS/ 48 | [Rr]eleasePS/ 49 | dlldata.c 50 | 51 | # Benchmark Results 52 | BenchmarkDotNet.Artifacts/ 53 | 54 | # .NET Core 55 | project.lock.json 56 | project.fragment.lock.json 57 | artifacts/ 58 | 59 | # StyleCop 60 | StyleCopReport.xml 61 | 62 | # Files built by Visual Studio 63 | *_i.c 64 | *_p.c 65 | *_h.h 66 | *.ilk 67 | *.meta 68 | *.obj 69 | *.iobj 70 | *.pch 71 | *.pdb 72 | *.ipdb 73 | *.pgc 74 | *.pgd 75 | *.rsp 76 | *.sbr 77 | *.tlb 78 | *.tli 79 | *.tlh 80 | *.tmp 81 | *.tmp_proj 82 | *_wpftmp.csproj 83 | *.log 84 | *.vspscc 85 | *.vssscc 86 | .builds 87 | *.pidb 88 | *.svclog 89 | *.scc 90 | 91 | # Chutzpah Test files 92 | _Chutzpah* 93 | 94 | # Visual C++ cache files 95 | ipch/ 96 | *.aps 97 | *.ncb 98 | *.opendb 99 | *.opensdf 100 | *.sdf 101 | *.cachefile 102 | *.VC.db 103 | *.VC.VC.opendb 104 | 105 | # Visual Studio profiler 106 | *.psess 107 | *.vsp 108 | *.vspx 109 | *.sap 110 | 111 | # Visual Studio Trace Files 112 | *.e2e 113 | 114 | # TFS 2012 Local Workspace 115 | $tf/ 116 | 117 | # Guidance Automation Toolkit 118 | *.gpState 119 | 120 | # ReSharper is a .NET coding add-in 121 | _ReSharper*/ 122 | *.[Rr]e[Ss]harper 123 | *.DotSettings.user 124 | 125 | # JustCode is a .NET coding add-in 126 | .JustCode 127 | 128 | # TeamCity is a build add-in 129 | _TeamCity* 130 | 131 | # DotCover is a Code Coverage Tool 132 | *.dotCover 133 | 134 | # AxoCover is a Code Coverage Tool 135 | .axoCover/* 136 | !.axoCover/settings.json 137 | 138 | # Visual Studio code coverage results 139 | *.coverage 140 | *.coveragexml 141 | 142 | # NCrunch 143 | _NCrunch_* 144 | .*crunch*.local.xml 145 | nCrunchTemp_* 146 | 147 | # MightyMoose 148 | *.mm.* 149 | AutoTest.Net/ 150 | 151 | # Web workbench (sass) 152 | .sass-cache/ 153 | 154 | # Installshield output folder 155 | [Ee]xpress/ 156 | 157 | # DocProject is a documentation generator add-in 158 | DocProject/buildhelp/ 159 | DocProject/Help/*.HxT 160 | DocProject/Help/*.HxC 161 | DocProject/Help/*.hhc 162 | DocProject/Help/*.hhk 163 | DocProject/Help/*.hhp 164 | DocProject/Help/Html2 165 | DocProject/Help/html 166 | 167 | # Click-Once directory 168 | publish/ 169 | 170 | # Publish Web Output 171 | *.[Pp]ublish.xml 172 | *.azurePubxml 173 | # Note: Comment the next line if you want to checkin your web deploy settings, 174 | # but database connection strings (with potential passwords) will be unencrypted 175 | *.pubxml 176 | *.publishproj 177 | 178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 179 | # checkin your Azure Web App publish settings, but sensitive information contained 180 | # in these scripts will be unencrypted 181 | PublishScripts/ 182 | 183 | # NuGet Packages 184 | *.nupkg 185 | # The packages folder can be ignored because of Package Restore 186 | **/[Pp]ackages/* 187 | # except build/, which is used as an MSBuild target. 188 | !**/[Pp]ackages/build/ 189 | # Uncomment if necessary however generally it will be regenerated when needed 190 | #!**/[Pp]ackages/repositories.config 191 | # NuGet v3's project.json files produces more ignorable files 192 | *.nuget.props 193 | *.nuget.targets 194 | 195 | # Microsoft Azure Build Output 196 | csx/ 197 | *.build.csdef 198 | 199 | # Microsoft Azure Emulator 200 | ecf/ 201 | rcf/ 202 | 203 | # Windows Store app package directories and files 204 | AppPackages/ 205 | BundleArtifacts/ 206 | Package.StoreAssociation.xml 207 | _pkginfo.txt 208 | *.appx 209 | 210 | # Visual Studio cache files 211 | # files ending in .cache can be ignored 212 | *.[Cc]ache 213 | # but keep track of directories ending in .cache 214 | !?*.[Cc]ache/ 215 | 216 | # Others 217 | ClientBin/ 218 | ~$* 219 | *~ 220 | *.dbmdl 221 | *.dbproj.schemaview 222 | *.jfm 223 | *.pfx 224 | *.publishsettings 225 | orleans.codegen.cs 226 | 227 | # Including strong name files can present a security risk 228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 229 | #*.snk 230 | 231 | # Since there are multiple workflows, uncomment next line to ignore bower_components 232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 233 | #bower_components/ 234 | 235 | # RIA/Silverlight projects 236 | Generated_Code/ 237 | 238 | # Backup & report files from converting an old project file 239 | # to a newer Visual Studio version. Backup files are not needed, 240 | # because we have git ;-) 241 | _UpgradeReport_Files/ 242 | Backup*/ 243 | UpgradeLog*.XML 244 | UpgradeLog*.htm 245 | ServiceFabricBackup/ 246 | *.rptproj.bak 247 | 248 | # SQL Server files 249 | *.mdf 250 | *.ldf 251 | *.ndf 252 | 253 | # Business Intelligence projects 254 | *.rdl.data 255 | *.bim.layout 256 | *.bim_*.settings 257 | *.rptproj.rsuser 258 | *- Backup*.rdl 259 | 260 | # Microsoft Fakes 261 | FakesAssemblies/ 262 | 263 | # GhostDoc plugin setting file 264 | *.GhostDoc.xml 265 | 266 | # Node.js Tools for Visual Studio 267 | .ntvs_analysis.dat 268 | node_modules/ 269 | 270 | # Visual Studio 6 build log 271 | *.plg 272 | 273 | # Visual Studio 6 workspace options file 274 | *.opt 275 | 276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 277 | *.vbw 278 | 279 | # Visual Studio LightSwitch build output 280 | **/*.HTMLClient/GeneratedArtifacts 281 | **/*.DesktopClient/GeneratedArtifacts 282 | **/*.DesktopClient/ModelManifest.xml 283 | **/*.Server/GeneratedArtifacts 284 | **/*.Server/ModelManifest.xml 285 | _Pvt_Extensions 286 | 287 | # Paket dependency manager 288 | .paket/paket.exe 289 | paket-files/ 290 | 291 | # FAKE - F# Make 292 | .fake/ 293 | 294 | # JetBrains Rider 295 | .idea/ 296 | *.sln.iml 297 | 298 | # CodeRush personal settings 299 | .cr/personal 300 | 301 | # Python Tools for Visual Studio (PTVS) 302 | __pycache__/ 303 | *.pyc 304 | 305 | # Cake - Uncomment if you are using it 306 | # tools/** 307 | # !tools/packages.config 308 | 309 | # Tabs Studio 310 | *.tss 311 | 312 | # Telerik's JustMock configuration file 313 | *.jmconfig 314 | 315 | # BizTalk build output 316 | *.btp.cs 317 | *.btm.cs 318 | *.odx.cs 319 | *.xsd.cs 320 | 321 | # OpenCover UI analysis results 322 | OpenCover/ 323 | 324 | # Azure Stream Analytics local run output 325 | ASALocalRun/ 326 | 327 | # MSBuild Binary and Structured Log 328 | *.binlog 329 | 330 | # NVidia Nsight GPU debugger configuration file 331 | *.nvuser 332 | 333 | # MFractors (Xamarin productivity tool) working folder 334 | .mfractor/ 335 | 336 | # Local History for Visual Studio 337 | .localhistory/ 338 | 339 | # BeatPulse healthcheck temp database 340 | healthchecksdb -------------------------------------------------------------------------------- /Utils/Utils.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {ce7d8382-82ca-4139-8712-14fe68cacf16} 25 | Utils 26 | 10.0 27 | 28 | 29 | 30 | StaticLibrary 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | StaticLibrary 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | StaticLibrary 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | StaticLibrary 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 90 | true 91 | Use 92 | pch.h 93 | MultiThreadedDebug 94 | 95 | 96 | 97 | 98 | true 99 | 100 | 101 | 102 | 103 | Level3 104 | true 105 | true 106 | true 107 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 108 | true 109 | Use 110 | pch.h 111 | MultiThreaded 112 | 113 | 114 | 115 | 116 | true 117 | true 118 | true 119 | 120 | 121 | 122 | 123 | Level3 124 | true 125 | _DEBUG;_LIB;%(PreprocessorDefinitions) 126 | true 127 | Use 128 | pch.h 129 | MultiThreadedDebug 130 | 131 | 132 | 133 | 134 | true 135 | 136 | 137 | 138 | 139 | Level3 140 | true 141 | true 142 | true 143 | NDEBUG;_LIB;%(PreprocessorDefinitions) 144 | true 145 | Use 146 | pch.h 147 | MultiThreaded 148 | 149 | 150 | 151 | 152 | true 153 | true 154 | true 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | Create 167 | Create 168 | Create 169 | Create 170 | 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /ProcMonX/FiltersDlg.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "FiltersDlg.h" 3 | #include "DialogHelper.h" 4 | #include "FilterFactory.h" 5 | 6 | CFiltersDlg::CFiltersDlg(FilterConfiguration& fc) : m_Config(fc) { 7 | } 8 | 9 | CString CFiltersDlg::CompareTypeToString(CompareType compare) { 10 | static PCWSTR types[] = { 11 | L"Equals", 12 | L"Not Equal", 13 | L"Contains", 14 | L"Does Not Contain", 15 | L"Greater Than", 16 | L"Less Than", 17 | }; 18 | return types[(int)compare]; 19 | } 20 | 21 | CString CFiltersDlg::GetComboText(CComboBox& cb) { 22 | CString text; 23 | cb.GetWindowText(text); 24 | return text; 25 | } 26 | 27 | bool CFiltersDlg::SwapItems(CListViewCtrl& lv, int i1, int i2) { 28 | if (i1 < 0 || i2 < 0) 29 | return false; 30 | 31 | LVITEM item1, item2; 32 | WCHAR text1[128], text2[128]; 33 | item1.pszText = text1; 34 | item2.pszText = text2; 35 | item1.cchTextMax = item2.cchTextMax = _countof(text1); 36 | auto mask = LVIF_TEXT | LVIF_IMAGE | LVIF_INDENT | LVIF_PARAM | LVIF_STATE; 37 | item1.mask = mask; 38 | item1.iItem = i1; 39 | item2.mask = mask; 40 | item2.iItem = i2; 41 | lv.GetItem(&item1); 42 | lv.GetItem(&item2); 43 | item1.iItem = i2; 44 | item2.iItem = i1; 45 | lv.SetItem(&item1); 46 | lv.SetItem(&item2); 47 | 48 | for (int c = 1;; c++) { 49 | if (!lv.GetItemText(i1, c, text1, _countof(text1))) 50 | break; 51 | lv.GetItemText(i2, c, text2, _countof(text2)); 52 | lv.SetItemText(i1, c, text2); 53 | lv.SetItemText(i2, c, text1); 54 | } 55 | 56 | return true; 57 | } 58 | 59 | void CFiltersDlg::InitList(const FilterConfiguration& config) { 60 | m_List.DeleteAllItems(); 61 | 62 | for (int i = 0; i < config.GetFilterCount(); ++i) { 63 | auto filter = config.GetFilter(i); 64 | int n = m_List.InsertItem(m_List.GetItemCount(), filter->Name.c_str(), filter->Action == FilterAction::Include ? 0 : 1); 65 | m_List.SetItemText(n, 3, filter->Action == FilterAction::Include ? L"Include" : L"Exclude"); 66 | m_List.SetItemText(n, 2, filter->Parameters.c_str()); 67 | m_List.SetItemText(n, 1, CompareTypeToString(filter->Compare)); 68 | m_List.SetCheckState(n, filter->Enabled); 69 | } 70 | } 71 | 72 | void CFiltersDlg::UpdateUI() { 73 | int selected = m_List.GetSelectedIndex(); 74 | int count = m_List.GetItemCount(); 75 | 76 | GetDlgItem(IDC_UP).EnableWindow(selected > 0); 77 | GetDlgItem(IDC_DOWN).EnableWindow(selected >= 0 && selected < m_List.GetItemCount() - 1); 78 | GetDlgItem(IDC_SAVE).EnableWindow(count > 0); 79 | GetDlgItem(IDC_DELETE).EnableWindow(selected >= 0); 80 | GetDlgItem(IDC_ADD).EnableWindow(m_Text.GetWindowTextLength() > 0); 81 | GetDlgItem(IDC_EDIT).EnableWindow(selected >= 0); 82 | } 83 | 84 | void CFiltersDlg::UpdateConfig(FilterConfiguration& config) { 85 | config.Clear(); 86 | FilterDescription desc; 87 | CString text; 88 | for (int i = 0; i < m_List.GetItemCount(); i++) { 89 | m_List.GetItemText(i, 0, text); 90 | desc.Name = text; 91 | desc.Enabled = m_List.GetCheckState(i) ? true : false; 92 | m_List.GetItemText(i, 1, text); 93 | m_CompareTypes.SelectString(-1, text); 94 | desc.Compare = (CompareType)m_CompareTypes.GetItemData(m_CompareTypes.GetCurSel()); 95 | m_List.GetItemText(i, 2, text); 96 | desc.Parameters = text; 97 | m_List.GetItemText(i, 3, text); 98 | m_IncExc.SelectString(-1, text); 99 | desc.Action = (FilterAction)m_IncExc.GetItemData(m_IncExc.GetCurSel()); 100 | config.AddFilter(desc); 101 | } 102 | } 103 | 104 | LRESULT CFiltersDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { 105 | DialogHelper::AdjustOKCancelButtons(this); 106 | 107 | SetIcon(AtlLoadIconImage(IDI_FILTER, 0, 16, 16), FALSE); 108 | SetIcon(AtlLoadIconImage(IDI_FILTER, 0, 32, 32), TRUE); 109 | 110 | m_List.Attach(GetDlgItem(IDC_LIST)); 111 | m_List.SetExtendedListViewStyle(LVS_EX_CHECKBOXES | LVS_EX_DOUBLEBUFFER | LVS_EX_FULLROWSELECT); 112 | CImageList images; 113 | images.Create(16, 16, ILC_COLOR32, 2, 2); 114 | images.AddIcon(AtlLoadIconImage(IDI_OK2, 0, 16, 16)); 115 | images.AddIcon(AtlLoadIconImage(IDI_CANCEL2, 0, 16, 16)); 116 | m_List.SetImageList(images, LVSIL_SMALL); 117 | 118 | struct { 119 | UINT button, icon; 120 | } buttons[] = { 121 | { IDC_UP, IDI_UP_ARROW }, 122 | { IDC_DOWN, IDI_DOWN_ARROW }, 123 | { IDC_SAVE, IDI_FILE }, 124 | { IDC_LOAD, IDI_OPEN }, 125 | { IDC_DELETE, IDI_FILTER_DELETE }, 126 | { IDC_ADD, IDI_FILTER_ADD }, 127 | { IDC_EDIT, IDI_FILTER_EDIT }, 128 | }; 129 | 130 | for (auto& b : buttons) { 131 | ((CButton)GetDlgItem(b.button)).SetIcon(AtlLoadIconImage(b.icon, 0, 24, 24)); 132 | } 133 | 134 | m_List.InsertColumn(0, L"Name", LVCFMT_LEFT, 130); 135 | m_List.InsertColumn(1, L"Compare Type", LVCFMT_LEFT, 100); 136 | m_List.InsertColumn(2, L"Parameters", LVCFMT_LEFT, 150); 137 | m_List.InsertColumn(3, L"Action", LVCFMT_LEFT, 80); 138 | 139 | // populate combos 140 | 141 | m_Text.Attach(GetDlgItem(IDC_VALUE)); 142 | 143 | m_FilterNames.Attach(GetDlgItem(IDC_NAMES)); 144 | for (auto name : FilterFactory::GetFilterNames()) { 145 | m_FilterNames.AddString(name); 146 | } 147 | m_FilterNames.SetCurSel(0); 148 | 149 | // compare types combo 150 | 151 | struct { 152 | PCWSTR text; 153 | CompareType type; 154 | } compare[] = { 155 | { L"Equals", CompareType::Equals }, 156 | { L"Not Equals", CompareType::NotEqual }, 157 | { L"Contains", CompareType::Contains }, 158 | { L"Does Not Contain", CompareType::NotContains }, 159 | }; 160 | 161 | m_CompareTypes.Attach(GetDlgItem(IDC_COMPARE)); 162 | for (auto& c : compare) { 163 | auto n = m_CompareTypes.AddString(c.text); 164 | m_CompareTypes.SetItemData(n, (DWORD_PTR)c.type); 165 | } 166 | m_CompareTypes.SetCurSel(0); 167 | 168 | // include / exclude combo 169 | 170 | m_IncExc.Attach(GetDlgItem(IDC_INC_EXC)); 171 | auto n = m_IncExc.AddString(L"Include"); 172 | m_IncExc.SetItemData(n, (DWORD_PTR)FilterAction::Include); 173 | n = m_IncExc.AddString(L"Exclude"); 174 | m_IncExc.SetItemData(n, (DWORD_PTR)FilterAction::Exclude); 175 | m_IncExc.SetCurSel(0); 176 | 177 | InitList(m_Config); 178 | 179 | UpdateUI(); 180 | 181 | return 0; 182 | } 183 | 184 | LRESULT CFiltersDlg::OnCloseCmd(WORD, WORD wID, HWND, BOOL&) { 185 | if (wID == IDOK) { 186 | UpdateConfig(m_Config); 187 | } 188 | 189 | EndDialog(wID); 190 | return 0; 191 | } 192 | 193 | LRESULT CFiltersDlg::OnAdd(WORD, WORD wID, HWND, BOOL&) { 194 | auto incexc = GetComboText(m_IncExc); 195 | int n = m_List.InsertItem(m_List.GetItemCount(), GetComboText(m_FilterNames), incexc == L"Include" ? 0 : 1); 196 | m_List.SetItemText(n, 1, GetComboText(m_CompareTypes)); 197 | m_List.SetItemText(n, 2, GetComboText(m_Text)); 198 | m_List.SetItemText(n, 3, incexc); 199 | m_List.SetCheckState(n, TRUE); 200 | m_Text.SetWindowText(L""); 201 | UpdateUI(); 202 | 203 | return 0; 204 | } 205 | 206 | LRESULT CFiltersDlg::OnSave(WORD, WORD wID, HWND, BOOL&) { 207 | CSimpleFileDialog dlg(FALSE, L"ini", nullptr, OFN_EXPLORER | OFN_OVERWRITEPROMPT | OFN_ENABLESIZING, SaveLoadIniFilter, *this); 208 | if (dlg.DoModal() == IDOK) { 209 | FilterConfiguration config; 210 | UpdateConfig(config); 211 | config.Save(dlg.m_szFileName); 212 | } 213 | return 0; 214 | } 215 | 216 | LRESULT CFiltersDlg::OnLoad(WORD, WORD wID, HWND, BOOL&) { 217 | CSimpleFileDialog dlg(TRUE, L"ini", nullptr, OFN_EXPLORER | OFN_OVERWRITEPROMPT | OFN_FILEMUSTEXIST, SaveLoadIniFilter, *this); 218 | if (dlg.DoModal() == IDOK) { 219 | FilterConfiguration config; 220 | config.Load(dlg.m_szFileName); 221 | InitList(config); 222 | UpdateUI(); 223 | } 224 | return 0; 225 | } 226 | 227 | LRESULT CFiltersDlg::OnEdit(WORD, WORD wID, HWND, BOOL&) { 228 | auto selected = m_List.GetSelectedIndex(); 229 | ATLASSERT(selected >= 0); 230 | CString text; 231 | m_List.GetItemText(selected, 0, text); 232 | m_FilterNames.SelectString(-1, text); 233 | 234 | m_List.GetItemText(selected, 1, text); 235 | m_CompareTypes.SelectString(-1, text); 236 | 237 | m_List.GetItemText(selected, 2, text); 238 | m_Text.SetWindowText(text); 239 | 240 | m_List.GetItemText(selected, 3, text); 241 | m_IncExc.SelectString(-1, text); 242 | 243 | m_List.DeleteItem(selected); 244 | 245 | return 0; 246 | } 247 | 248 | LRESULT CFiltersDlg::OnMoveUp(WORD, WORD wID, HWND, BOOL&) { 249 | auto selected = m_List.GetSelectedIndex(); 250 | ATLASSERT(selected > 0); 251 | SwapItems(m_List, selected, selected - 1); 252 | m_List.SelectItem(selected - 1); 253 | 254 | return 0; 255 | } 256 | 257 | LRESULT CFiltersDlg::OnMoveDown(WORD, WORD wID, HWND, BOOL&) { 258 | auto selected = m_List.GetSelectedIndex(); 259 | ATLASSERT(selected < m_List.GetItemCount() - 1); 260 | SwapItems(m_List, selected, selected + 1); 261 | m_List.SelectItem(selected + 1); 262 | 263 | return 0; 264 | } 265 | 266 | LRESULT CFiltersDlg::OnDelete(WORD, WORD wID, HWND, BOOL&) { 267 | auto selected = m_List.GetSelectedIndex(); 268 | ATLASSERT(selected >= 0); 269 | m_List.DeleteItem(selected); 270 | 271 | return 0; 272 | } 273 | 274 | LRESULT CFiltersDlg::OnValueChanged(WORD, WORD wID, HWND, BOOL&) { 275 | ((CButton)GetDlgItem(IDC_ADD)).EnableWindow(m_Text.GetWindowTextLength() > 0); 276 | 277 | return 0; 278 | } 279 | 280 | LRESULT CFiltersDlg::OnItemChanged(int, LPNMHDR, BOOL&) { 281 | UpdateUI(); 282 | return 0; 283 | } 284 | -------------------------------------------------------------------------------- /EventTracing/KernelEvents.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "KernelEvents.h" 3 | #include 4 | 5 | const std::vector KernelEvents { 6 | { L"Process", KernelEventTypes::Process, &ProcessGuid, 7 | { 8 | { L"Start", 1 }, 9 | { L"End", 2 }, 10 | { L"Terminate", 11 }, 11 | { L"DC Start", 3 }, 12 | { L"DC Stop", 4 }, 13 | { L"Defunct", 39 }, 14 | { L"Perf Counter", 32 }, 15 | { L"Perf Counter Rundown", 33 }, 16 | } 17 | }, 18 | 19 | { L"ALPC", KernelEventTypes::ALPC, &ALPCGuid, 20 | { 21 | { L"Send Message", 0x21 }, 22 | { L"Receive Message", 0x22 }, 23 | { L"Wait For Reply", 0x23 }, 24 | { L"Wait For New Message", 0x24 }, 25 | { L"Unwait", 0x25 }, 26 | { L"Connect Request", 0x26 }, 27 | { L"Connect Success", 0x27 }, 28 | { L"Connect Fail", 0x28 }, 29 | { L"Close Port", 0x29 }, 30 | }, true 31 | }, 32 | 33 | { L"Thread", KernelEventTypes::Thread, &ThreadGuid, 34 | { 35 | { L"Start", 1 }, 36 | { L"End", 2 }, 37 | { L"Set Name", 72 }, 38 | } 39 | }, 40 | 41 | { L"Image", KernelEventTypes::ImageLoad, &ImageLoadGuid, 42 | { 43 | { L"Load", 10 }, 44 | { L"Unload", 2 }, 45 | //{ L"DC Start", 3 }, 46 | //{ L"DC Stop", 4 }, 47 | { L"Relocation", 0x20 }, 48 | { L"Kernel Base", 0x21 }, 49 | { L"Hypercall Page", 0x22 }, 50 | } 51 | }, 52 | 53 | { L"File", KernelEventTypes::FileIO, &FileIoGuid, 54 | { 55 | { L"Name", 0 }, 56 | { L"File Create", 32 }, 57 | { L"File Delete", 35 }, 58 | { L"File Rundown", 36 }, 59 | { L"Create", 64 }, 60 | { L"Dir Enum", 72 }, 61 | { L"Dir Notify", 77 }, 62 | { L"Set Info", 69 }, 63 | { L"Delete", 70 }, 64 | { L"Rename", 71 }, 65 | { L"Query Info", 74 }, 66 | { L"FS Control", 75 }, 67 | { L"Operation End", 76 }, 68 | { L"Read", 67 }, 69 | { L"Write", 68 }, 70 | { L"Cleanup", 65 }, 71 | { L"Close", 66 }, 72 | { L"Flush", 73 }, 73 | } 74 | }, 75 | 76 | { L"Registry", KernelEventTypes::Registry, &RegistryGuid, 77 | { 78 | { L"Create Key", EVENT_TRACE_TYPE_REGCREATE }, 79 | { L"Open Key", EVENT_TRACE_TYPE_REGOPEN }, 80 | { L"Delete Key", EVENT_TRACE_TYPE_REGDELETE }, 81 | { L"Query Key", EVENT_TRACE_TYPE_REGQUERY }, 82 | { L"Set Value", EVENT_TRACE_TYPE_REGSETVALUE }, 83 | { L"Delete Value", EVENT_TRACE_TYPE_REGDELETEVALUE }, 84 | { L"Query Value", EVENT_TRACE_TYPE_REGQUERYVALUE }, 85 | { L"Enum Key", EVENT_TRACE_TYPE_REGENUMERATEKEY }, 86 | { L"Enum Value", EVENT_TRACE_TYPE_REGENUMERATEVALUEKEY }, 87 | { L"Query Multiple Values", EVENT_TRACE_TYPE_REGQUERYMULTIPLEVALUE }, 88 | { L"Set Key Information", EVENT_TRACE_TYPE_REGSETINFORMATION }, 89 | { L"Flush Key", EVENT_TRACE_TYPE_REGFLUSH }, 90 | { L"KCB Create", EVENT_TRACE_TYPE_REGKCBCREATE }, 91 | { L"KCB Delete", EVENT_TRACE_TYPE_REGKCBDELETE }, 92 | { L"KCB Rundown Begin", EVENT_TRACE_TYPE_REGKCBRUNDOWNBEGIN }, 93 | { L"KCB Rundown End", EVENT_TRACE_TYPE_REGKCBRUNDOWNEND }, 94 | { L"Virtualize Key", EVENT_TRACE_TYPE_REGVIRTUALIZE }, 95 | { L"Close Key", EVENT_TRACE_TYPE_REGCLOSE }, 96 | { L"Set Security Descriptor", EVENT_TRACE_TYPE_REGSETSECURITY }, 97 | { L"Query Security Descriptor", EVENT_TRACE_TYPE_REGQUERYSECURITY }, 98 | { L"Commit Tx", EVENT_TRACE_TYPE_REGCOMMIT }, 99 | { L"Prepare Tx", EVENT_TRACE_TYPE_REGPREPARE }, 100 | { L"Rollback Tx", EVENT_TRACE_TYPE_REGROLLBACK }, 101 | { L"Load Key", EVENT_TRACE_TYPE_REGMOUNTHIVE }, 102 | } 103 | }, 104 | 105 | { L"TCP", KernelEventTypes::Network, &TcpIpGuid, 106 | { 107 | { L"TCP Send IPv4", EVENT_TRACE_TYPE_SEND }, 108 | { L"TCP Receive IPv4", EVENT_TRACE_TYPE_RECEIVE }, 109 | { L"TCP Connect IPv4", EVENT_TRACE_TYPE_CONNECT }, 110 | { L"TCP Disconnect IPv4", EVENT_TRACE_TYPE_DISCONNECT }, 111 | { L"TCP Retransmit IPv4", EVENT_TRACE_TYPE_RETRANSMIT }, 112 | { L"TCP Accept IPv4", EVENT_TRACE_TYPE_ACCEPT }, 113 | { L"TCP Reconnect IPv4", EVENT_TRACE_TYPE_RECONNECT }, 114 | { L"TCP Fail", EVENT_TRACE_TYPE_CONNFAIL }, 115 | { L"TCP Copy IPv4", 18 }, 116 | { L"TCP Send IPv6", 26 }, 117 | { L"TCP Receive IPv6", 27 }, 118 | { L"TCP Disconnect IPv6", 29 }, 119 | { L"TCP Retransmit IPv6", 30 }, 120 | { L"TCP Reconnect IPv6", 32 }, 121 | { L"TCP Copy IPv6", 34 }, 122 | { L"TCP Connect IPv6", 28 }, 123 | { L"TCP Accept IPv6", 31 }, 124 | { L"Copy ARP", EVENT_TRACE_TYPE_COPY_ARP }, 125 | { L"Full Ack", EVENT_TRACE_TYPE_ACKFULL }, 126 | { L"Partial Ack", EVENT_TRACE_TYPE_ACKPART }, 127 | { L"Duplicate Ack", EVENT_TRACE_TYPE_ACKDUP }, 128 | } 129 | }, 130 | 131 | { L"UDP", KernelEventTypes::Network, &UdpIpGuid, 132 | { 133 | { L"UDP Send IPv4", 10 }, 134 | { L"UDP Receive IPv4", 11 }, 135 | { L"UDP Send IPv6", 26 }, 136 | { L"UDP Receive IPv6", 27 }, 137 | { L"UDP Send IPv4", 10 }, 138 | { L"UDP Receive IPv4", 11 }, 139 | { L"UDP Send IPv6", 26 }, 140 | { L"UDP Receive IPv6", 27 }, 141 | } 142 | }, 143 | 144 | { L"Handles", KernelEventTypes::PerfHandles, &ObjectGuid, 145 | { 146 | { L"Create Handle", 32 }, 147 | { L"Close Handle", 33 }, 148 | { L"Duplicate Handle", 34 }, 149 | }, true 150 | }, 151 | 152 | { L"Objects", KernelEventTypes::PerfObjects, &ObjectGuid, 153 | { 154 | { L"Create Object", 48 }, 155 | { L"Delete Object", 49 }, 156 | { L"Reference Object", 50 }, 157 | { L"Dereference Object", 51 }, 158 | }, true 159 | }, 160 | 161 | { L"Kernel Pool", KernelEventTypes::PerfPool, &PoolGuid, 162 | { 163 | { L"Pool Alloc", 0x20 }, 164 | { L"Pool Session Alloc", 0x21 }, 165 | { L"Pool Free", 0x22 }, 166 | { L"Pool (Session) Free", 0x23 }, 167 | { L"Add Pool Page", 0x24 }, 168 | { L"Add Session Pool Page", 0x25 }, 169 | { L"Big Pool Page", 0x26 }, 170 | { L"Big Session Pool Page", 0x27 }, 171 | }, true 172 | }, 173 | 174 | { L"Disk I/O", KernelEventTypes::DiskIO, &DiskIoGuid, 175 | { 176 | { L"Read", 10 }, 177 | { L"Write", 11 }, 178 | { L"Read Init", 12 }, 179 | { L"Write Init", 13 }, 180 | { L"Flush Init", 15 }, 181 | { L"Flush Buffers", 14 }, 182 | } 183 | }, 184 | 185 | { L"Virtual Memory", KernelEventTypes::VirtualMemory, &PageFaultGuid, 186 | { 187 | { L"Virtual Alloc", 98 }, 188 | { L"Virtual Free", 99 }, 189 | } 190 | }, 191 | 192 | { L"Page Fault", KernelEventTypes::PageFaults, &PageFaultGuid, 193 | { 194 | { L"Hard Fault", 0x20 }, 195 | { L"Transition Fault", 10 }, 196 | { L"Demand Zero Fault", 11 }, 197 | { L"Copy on Write", 12 }, 198 | { L"Guard Page Fault", 13 }, 199 | { L"Hard Page Fault", 14 }, 200 | { L"Access Violation", 15 }, 201 | { L"Image Load Backed", 105 }, 202 | }, true 203 | }, 204 | 205 | { L"Debug", KernelEventTypes::DebugPrint, &GUID_NULL, 206 | { 207 | { L"Debug Print", 0x20 }, 208 | }, true 209 | }, 210 | 211 | { L"Heap", KernelEventTypes::PerfHeap, &HeapGuid, 212 | { 213 | { L"Heap Create", 0x20 }, 214 | { L"Heap Alloc", 0x21 }, 215 | { L"Heap ReAlloc", 0x22 }, 216 | { L"Heap Destroy", 0x22 }, 217 | { L"Heap Free", 0x24 }, 218 | { L"Heap Extend", 0x25 }, 219 | { L"Heap Snapshot", 0x26 }, 220 | { L"Heap Create Snapshot", 0x27 }, 221 | { L"Heap Destroy Snapshot", 0x28 }, 222 | { L"Heap Extend Snapshot", 0x29 }, 223 | { L"Heap Contract", 0x2a }, 224 | { L"Heap Lock", 0x2b }, 225 | { L"Heap Unlock", 0x2c }, 226 | { L"Heap Validate", 0x2d }, 227 | { L"Heap Walk", 0x2e }, 228 | }, true 229 | }, 230 | 231 | { L"Job", KernelEventTypes::Job, &JobGuid, 232 | { 233 | { L"Create", 0x20 }, 234 | { L"Terminate", 0x21 }, 235 | { L"Open", 0x22 }, 236 | { L"Assign Process", 0x23 }, 237 | { L"Remove Process", 0x24 }, 238 | { L"Set", 0x25 }, 239 | { L"Query", 0x26 }, 240 | }, true 241 | }, 242 | 243 | { L"Driver", KernelEventTypes::Driver, &DiskIoGuid, 244 | { 245 | { L"Init", 0x20 }, 246 | { L"Init Complete", 0x21 }, 247 | { L"Major Function Call", 0x22 }, 248 | { L"Major Function Return", 0x23 }, 249 | { L"Completion Routine Call", 0x24 }, 250 | { L"Completion Routine Return", 0x25 }, 251 | { L"Device Call", 0x26 }, 252 | { L"Device Return", 0x27 }, 253 | { L"Start I/O Call", 0x28 }, 254 | { L"Start I/O Return", 0x29 }, 255 | }, true 256 | }, 257 | 258 | { L"Kernel Thread Pool", KernelEventTypes::WorkerThread, &ThreadGuid, 259 | { 260 | { L"Create", 1 }, 261 | { L"Delete", 2 }, 262 | }, true 263 | }, 264 | 265 | { L"File System Filter", KernelEventTypes::PerfFlt, &FileIoGuid, 266 | { 267 | { L"Pre Operation Init", 0x60 }, 268 | { L"Post Operation Init", 0x61 }, 269 | { L"Pre Operation Completion", 0x62 }, 270 | { L"Post Operation Completion", 0x63 }, 271 | { L"Pre Operation Failure", 0x64 }, 272 | { L"Post Operation Failure", 0x65 }, 273 | }, true 274 | }, 275 | 276 | //{ L"Experimental", KernelEventTypes::PerfHeap, &HeapGuid, 277 | // { 278 | // { L"Create", 1 }, 279 | // { L"Delete", 2 }, 280 | // }, true 281 | //}, 282 | 283 | }; 284 | 285 | const std::vector& KernelEventCategory::GetAllCategories() { 286 | return KernelEvents; 287 | } 288 | 289 | const KernelEventCategory* KernelEventCategory::GetCategory(PCWSTR name) { 290 | for (auto& cat : GetAllCategories()) 291 | if (cat.Name == name) 292 | return &cat; 293 | return nullptr; 294 | } 295 | -------------------------------------------------------------------------------- /ProcMonX/FormatHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "FormatHelper.h" 3 | #include "TraceManager.h" 4 | #include 5 | 6 | #pragma comment(lib, "ntdll") 7 | 8 | typedef enum _OBJECT_INFORMATION_CLASS { 9 | ObjectBasicInformation, // OBJECT_BASIC_INFORMATION 10 | ObjectNameInformation, // OBJECT_NAME_INFORMATION 11 | ObjectTypeInformation, // OBJECT_TYPE_INFORMATION 12 | ObjectTypesInformation, // OBJECT_TYPES_INFORMATION 13 | ObjectHandleFlagInformation, // OBJECT_HANDLE_FLAG_INFORMATION 14 | ObjectSessionInformation, 15 | ObjectSessionObjectInformation, 16 | MaxObjectInfoClass 17 | } OBJECT_INFORMATION_CLASS; 18 | 19 | typedef struct _UNICODE_STRING { 20 | USHORT Length; 21 | USHORT MaximumLength; 22 | PWSTR Buffer; 23 | } UNICODE_STRING; 24 | typedef UNICODE_STRING* PUNICODE_STRING; 25 | typedef const UNICODE_STRING* PCUNICODE_STRING; 26 | 27 | extern "C" NTSTATUS NTAPI NtQueryObject( 28 | _In_opt_ HANDLE Handle, 29 | _In_ OBJECT_INFORMATION_CLASS ObjectInformationClass, 30 | _Out_writes_bytes_opt_(ObjectInformationLength) PVOID ObjectInformation, 31 | _In_ ULONG ObjectInformationLength, 32 | _Out_opt_ PULONG ReturnLength); 33 | 34 | typedef struct _OBJECT_TYPE_INFORMATION { 35 | UNICODE_STRING TypeName; 36 | ULONG TotalNumberOfObjects; 37 | ULONG TotalNumberOfHandles; 38 | ULONG TotalPagedPoolUsage; 39 | ULONG TotalNonPagedPoolUsage; 40 | ULONG TotalNamePoolUsage; 41 | ULONG TotalHandleTableUsage; 42 | ULONG HighWaterNumberOfObjects; 43 | ULONG HighWaterNumberOfHandles; 44 | ULONG HighWaterPagedPoolUsage; 45 | ULONG HighWaterNonPagedPoolUsage; 46 | ULONG HighWaterNamePoolUsage; 47 | ULONG HighWaterHandleTableUsage; 48 | ULONG InvalidAttributes; 49 | GENERIC_MAPPING GenericMapping; 50 | ULONG ValidAccessMask; 51 | BOOLEAN SecurityRequired; 52 | BOOLEAN MaintainHandleCount; 53 | UCHAR TypeIndex; // since WINBLUE 54 | CHAR ReservedByte; 55 | ULONG PoolType; 56 | ULONG DefaultPagedPoolCharge; 57 | ULONG DefaultNonPagedPoolCharge; 58 | } OBJECT_TYPE_INFORMATION, * POBJECT_TYPE_INFORMATION; 59 | 60 | typedef struct _OBJECT_TYPES_INFORMATION { 61 | ULONG NumberOfTypes; 62 | OBJECT_TYPE_INFORMATION TypeInformation[1]; 63 | } OBJECT_TYPES_INFORMATION, * POBJECT_TYPES_INFORMATION; 64 | 65 | typedef struct _SYSTEM_TIMEOFDAY_INFORMATION { 66 | LARGE_INTEGER BootTime; 67 | LARGE_INTEGER CurrentTime; 68 | LARGE_INTEGER TimeZoneBias; 69 | ULONG TimeZoneId; 70 | ULONG Reserved; 71 | ULONGLONG BootTimeBias; 72 | ULONGLONG SleepTimeBias; 73 | } SYSTEM_TIMEOFDAY_INFORMATION, * PSYSTEM_TIMEOFDAY_INFORMATION; 74 | 75 | enum SYSTEM_INFORMATION_CLASS { 76 | SystemTimeOfDayInformation = 3 77 | }; 78 | 79 | extern "C" NTSTATUS NTAPI NtQuerySystemInformation( 80 | _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, 81 | _Out_writes_bytes_opt_(SystemInformationLength) PVOID SystemInformation, 82 | _In_ ULONG SystemInformationLength, 83 | _Out_opt_ PULONG ReturnLength); 84 | 85 | uint64_t GetBootTime() { 86 | static int64_t time = 0; 87 | if (time == 0) { 88 | SYSTEM_TIMEOFDAY_INFORMATION info; 89 | if (0 == ::NtQuerySystemInformation(SystemTimeOfDayInformation, &info, sizeof(info), nullptr)) 90 | time = info.BootTime.QuadPart; 91 | } 92 | 93 | return time; 94 | } 95 | 96 | std::wstring FormatHelper::FormatProperty(const EventData* data, const EventProperty& prop) { 97 | static const auto statusFunction = [](auto, auto& p) { 98 | CString result; 99 | ATLASSERT(p.GetLength() == sizeof(DWORD)); 100 | result.Format(L"0x%08X", p.GetValue()); 101 | return (PCWSTR)result; 102 | }; 103 | 104 | static const auto int64ToHex = [](auto, auto& p) -> std::wstring { 105 | ATLASSERT(p.GetLength() == sizeof(LONGLONG)); 106 | CString text; 107 | text.Format(L"0x%llX", p.GetValue()); 108 | return (PCWSTR)text; 109 | }; 110 | 111 | static const auto initialTimeToString = [](auto, auto& p) -> std::wstring { 112 | ATLASSERT(p.GetLength() == sizeof(LONGLONG)); 113 | auto time = p.GetValue(); 114 | auto initTime = GetBootTime() + time; 115 | return std::wstring(FormatTime(initTime)); 116 | }; 117 | 118 | static const std::unordered_map> functions{ 119 | { L"Status", statusFunction }, 120 | { L"NtStatus", statusFunction }, 121 | { L"InitialTime", initialTimeToString }, 122 | { L"TimeDateStamp", statusFunction }, 123 | { L"PageFault/VirtualAlloc;Flags", [](auto, auto& p) -> std::wstring { 124 | ATLASSERT(p.GetLength() == sizeof(DWORD)); 125 | return (PCWSTR)VirtualAllocFlagsToString(p.GetValue(), true); 126 | } }, 127 | { L"MajorFunction", [](auto, auto& p) -> std::wstring { 128 | ATLASSERT(p.GetLength() == sizeof(DWORD)); 129 | return (PCWSTR)MajorFunctionToString((UCHAR)p.GetValue()); 130 | } }, 131 | { L"FileName", [](auto data, auto& p) -> std::wstring { 132 | auto value = data->FormatProperty(p); 133 | if (value[0] == L'\\') 134 | value = TraceManager::GetDosNameFromNtName(value.c_str()); 135 | return value; 136 | } }, 137 | { L"ObjectType", [](auto, auto& p) -> std::wstring { 138 | ATLASSERT(p.GetLength() == sizeof(USHORT)); 139 | auto type = p.GetValue(); 140 | return std::to_wstring(type) + L" (" + ObjectTypeToString(type) + L")"; 141 | } }, 142 | { L"Tag", [](auto data, auto& p) -> std::wstring { 143 | if (p.GetLength() != sizeof(DWORD)) 144 | return data->FormatProperty(p); 145 | auto tag = p.GetValue(); 146 | auto chars = (const char*)&tag; 147 | CStringA str(chars[0]); 148 | ((str += chars[1]) += chars[2]) += chars[3]; 149 | CStringA text; 150 | text.Format("%s (0x%X)", str, tag); 151 | return std::wstring(CString(text)); 152 | } }, 153 | }; 154 | 155 | auto it = functions.find(data->GetEventName() + L";" + prop.Name); 156 | if (it == functions.end()) 157 | it = functions.find(prop.Name); 158 | if (it == functions.end()) 159 | return L""; 160 | 161 | return (it->second)(data, prop); 162 | } 163 | 164 | CString FormatHelper::FormatTime(LONGLONG ts) { 165 | CString text; 166 | text.Format(L".%06u", (ts / 10) % 1000000); 167 | return CTime(*(FILETIME*)&ts).Format(L"%x %X") + text; 168 | } 169 | 170 | CString FormatHelper::VirtualAllocFlagsToString(DWORD flags, bool withNumeric) { 171 | CString text; 172 | if (flags & MEM_COMMIT) 173 | text += L"MEM_COMMIT | "; 174 | if (flags & MEM_RESERVE) 175 | text += L"MEM_RESERVE | "; 176 | 177 | if (!text.IsEmpty()) 178 | text = text.Left(text.GetLength() - 3); 179 | 180 | if (withNumeric) 181 | text.Format(L"%s (0x%X)", text, flags); 182 | 183 | return text; 184 | } 185 | 186 | CString FormatHelper::MajorFunctionToString(UCHAR mf) { 187 | static PCWSTR major[] = { 188 | L"CREATE", 189 | L"CREATE_NAMED_PIPE", 190 | L"CLOSE", 191 | L"READ", 192 | L"WRITE", 193 | L"QUERY_INFORMATION", 194 | L"SET_INFORMATION", 195 | L"QUERY_EA", 196 | L"SET_EA", 197 | L"FLUSH_BUFFERS", 198 | L"QUERY_VOLUME_INFORMATION", 199 | L"SET_VOLUME_INFORMATION", 200 | L"DIRECTORY_CONTROL", 201 | L"FILE_SYSTEM_CONTROL", 202 | L"DEVICE_CONTROL", 203 | L"INTERNAL_DEVICE_CONTROL", 204 | L"SHUTDOWN", 205 | L"LOCK_CONTROL", 206 | L"CLEANUP", 207 | L"CREATE_MAILSLOT", 208 | L"QUERY_SECURITY", 209 | L"SET_SECURITY", 210 | L"POWER", 211 | L"SYSTEM_CONTROL", 212 | L"DEVICE_CHANGE", 213 | L"QUERY_QUOTA", 214 | L"SET_QUOTA", 215 | L"PNP" 216 | }; 217 | 218 | static PCWSTR major_flt[] = { 219 | L"ACQUIRE_FOR_SECTION_SYNCHRONIZATION", 220 | L"RELEASE_FOR_SECTION_SYNCHRONIZATION", 221 | L"ACQUIRE_FOR_MOD_WRITE", 222 | L"RELEASE_FOR_MOD_WRITE", 223 | L"ACQUIRE_FOR_CC_FLUSH", 224 | L"RELEASE_FOR_CC_FLUSH", 225 | L"QUERY_OPEN", 226 | }; 227 | 228 | static PCWSTR major_flt2[] = { 229 | L"FAST_IO_CHECK_IF_POSSIBLE", 230 | L"NETWORK_QUERY_OPEN", 231 | L"MDL_READ", 232 | L"MDL_READ_COMPLETE", 233 | L"PREPARE_MDL_WRITE", 234 | L"MDL_WRITE_COMPLETE", 235 | L"VOLUME_MOUNT", 236 | L"VOLUME_DISMOUNT" 237 | }; 238 | 239 | CString text; 240 | if (mf < _countof(major)) 241 | text.Format(L"IRP_MJ_%s (%d)", major[mf], (int)mf); 242 | else if (mf >= 255 - 7) 243 | text.Format(L"IRP_MJ_%s (%d)", major_flt[255 - mf - 1], (int)mf); 244 | else if (mf >= 255 - 20) 245 | text.Format(L"IRP_MJ_%s (%d)", major_flt2[255 - mf - 7], (int)mf); 246 | else 247 | text.Format(L"%d", (int)mf); 248 | return text; 249 | } 250 | 251 | PCWSTR FormatHelper::ObjectTypeToString(int type) { 252 | static std::unordered_map types; 253 | if (types.empty()) { 254 | const ULONG len = 1 << 14; 255 | BYTE buffer[len]; 256 | if (0 != ::NtQueryObject(nullptr, ObjectTypesInformation, buffer, len, nullptr)) 257 | return L""; 258 | 259 | auto p = reinterpret_cast(buffer); 260 | auto count = p->NumberOfTypes; 261 | types.reserve(count); 262 | 263 | auto raw = &p->TypeInformation[0]; 264 | for (ULONG i = 0; i < count; i++) { 265 | types.insert({ raw->TypeIndex, std::wstring(raw->TypeName.Buffer, raw->TypeName.Length / sizeof(WCHAR)) }); 266 | 267 | auto temp = (BYTE*)raw + sizeof(OBJECT_TYPE_INFORMATION) + raw->TypeName.MaximumLength; 268 | temp += sizeof(PVOID) - 1; 269 | raw = reinterpret_cast((ULONG_PTR)temp / sizeof(PVOID) * sizeof(PVOID)); 270 | } 271 | } 272 | return types.empty() ? L"" : types[type].c_str(); 273 | } 274 | -------------------------------------------------------------------------------- /EventTracing/KernelEvents.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | enum class KernelEventTypes : uint64_t { 9 | None = 0, 10 | 11 | Process = EVENT_TRACE_FLAG_PROCESS, 12 | Thread = EVENT_TRACE_FLAG_THREAD, 13 | ImageLoad = EVENT_TRACE_FLAG_IMAGE_LOAD, 14 | Registry = EVENT_TRACE_FLAG_REGISTRY, 15 | DiskIO = EVENT_TRACE_FLAG_DISK_IO, 16 | DiskFileIO = DiskIO | EVENT_TRACE_FLAG_DISK_FILE_IO, 17 | PageFaults = EVENT_TRACE_FLAG_MEMORY_PAGE_FAULTS, 18 | HardPageFaults = EVENT_TRACE_FLAG_MEMORY_HARD_FAULTS, 19 | Network = EVENT_TRACE_FLAG_NETWORK_TCPIP, 20 | DebugPrint = EVENT_TRACE_FLAG_DBGPRINT, 21 | 22 | ProcessCounters = EVENT_TRACE_FLAG_PROCESS_COUNTERS, 23 | ContextSwitch = EVENT_TRACE_FLAG_CSWITCH, 24 | DPC = EVENT_TRACE_FLAG_DPC, 25 | Interrupt = EVENT_TRACE_FLAG_INTERRUPT, 26 | SystemCall = EVENT_TRACE_FLAG_SYSTEMCALL, 27 | DiskIoInit = EVENT_TRACE_FLAG_DISK_IO_INIT, 28 | ALPC = EVENT_TRACE_FLAG_ALPC, 29 | SplitIO = EVENT_TRACE_FLAG_SPLIT_IO, 30 | Driver = EVENT_TRACE_FLAG_DRIVER, 31 | Profile = EVENT_TRACE_FLAG_PROFILE, 32 | FileIO = EVENT_TRACE_FLAG_FILE_IO | EVENT_TRACE_FLAG_FILE_IO_INIT, 33 | FileIOInit = EVENT_TRACE_FLAG_FILE_IO_INIT, 34 | 35 | Dispatcher = EVENT_TRACE_FLAG_DISPATCHER, 36 | VirtualAlloc = EVENT_TRACE_FLAG_VIRTUAL_ALLOC, 37 | VAMap = EVENT_TRACE_FLAG_VAMAP, 38 | VirtualMemory = VirtualAlloc | VAMap, 39 | NoSysConfig = EVENT_TRACE_FLAG_NO_SYSCONFIG, 40 | 41 | Job = EVENT_TRACE_FLAG_JOB, 42 | Debug = EVENT_TRACE_FLAG_DEBUG_EVENTS, 43 | 44 | // Mask[1] 45 | PerfMemory = 0x20000001 | (1LL << 32), 46 | PerfProfile = 0x20000002 | (1LL << 32), 47 | PerfContextSwitch = 0x20000004 | (1LL << 32), 48 | PerfDrivers = 0x20000010 | (1LL << 32), 49 | PerfPool = 0x20000040 | (1LL << 32), 50 | PerfSyncObjects = 0x20020000 | (1LL << 32), 51 | PerfVirtualAlloc = 0x20008000 | (1LL << 32), 52 | PerfSession = 0x20400000 | (1LL << 32), 53 | PerfMemInfo = 0x20080000 | (1LL << 32), 54 | 55 | // Mask[2] 56 | PerfHeap = 0x40000020 | (2LL << 32), 57 | PerfSysCalls = 0x40000040 | (2LL << 32), 58 | WorkerThread = 0x48000000 | (2LL << 32), 59 | ProcessFreeze = 0x40000002 | (2LL << 32), 60 | PerfEvents = 0x40000800 | (2LL << 32), 61 | PerfWSDetail = 0x40000008 | (2LL << 32), 62 | PerfTimer = 0x40020000 | (2LL << 32), 63 | PerfIPI = 0x40400000 | (2LL << 32), 64 | PerfClockIntr = 0x40040000 | (2LL << 32), 65 | Mask2All = 0x4fffffff | (2LL << 32), 66 | 67 | // Mask[4] 68 | PerfHandles = 0x80000040 | (4LL << 32), 69 | PerfObjects = 0x80000080 | (4LL << 32), 70 | PerfDebugger = 0x80000800 | (4LL << 32), 71 | PerfPower = 0x80008000 | (4LL << 32), 72 | PerfDllInfo = 0x80000008 | (4LL << 32), 73 | PerfFltIoInit = 0x80080000 | (4LL << 32), 74 | PerfFltIO = 0x80100000 | (4LL << 32), 75 | PerfFltFastIO = 0x80200000 | (4LL << 32), 76 | PerfFltFail = 0x80400000 | (4LL << 32), 77 | PerfFlt = PerfFltIO | PerfFltIoInit | PerfFltFastIO | PerfFltFail, 78 | PerfHvProfile = 0x80800000 | (4LL << 32), 79 | Mask4All = 0x8fffffff | (2LL << 32), 80 | 81 | // Mask[6] 82 | PerfConfigSystem = 0xC0000001 | (6LL << 32), 83 | PerfConfigGraphics = 0xC0000002 | (6LL << 32), 84 | }; 85 | DEFINE_ENUM_FLAG_OPERATORS(KernelEventTypes); 86 | 87 | DEFINE_GUID( /* 54849625-5478-4994-a5ba-3e3b0328c30d */ 88 | SecurityProviderGuid, 89 | 0x54849625, 90 | 0x5478, 91 | 0x4994, 92 | 0xa5, 0xba, 0x3e, 0x3b, 0x03, 0x28, 0xc3, 0x0d 93 | ); 94 | 95 | DEFINE_GUID( /* 3d6fa8d0-fe05-11d0-9dda-00c04fd7ba7c */ 96 | ProcessGuid, 97 | 0x3d6fa8d0, 98 | 0xfe05, 99 | 0x11d0, 100 | 0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c 101 | ); 102 | 103 | DEFINE_GUID( /* 45d8cccd-539f-4b72-a8b7-5c683142609a */ 104 | ALPCGuid, 105 | 0x45d8cccd, 106 | 0x539f, 107 | 0x4b72, 108 | 0xa8, 0xb7, 0x5c, 0x68, 0x31, 0x42, 0x60, 0x9a 109 | ); 110 | 111 | DEFINE_GUID( /* 3d6fa8d4-fe05-11d0-9dda-00c04fd7ba7c */ 112 | DiskIoGuid, 113 | 0x3d6fa8d4, 114 | 0xfe05, 115 | 0x11d0, 116 | 0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c 117 | ); 118 | 119 | DEFINE_GUID( /* 90cbdc39-4a3e-11d1-84f4-0000f80464e3 */ 120 | FileIoGuid, 121 | 0x90cbdc39, 122 | 0x4a3e, 123 | 0x11d1, 124 | 0x84, 0xf4, 0x00, 0x00, 0xf8, 0x04, 0x64, 0xe3 125 | ); 126 | 127 | DEFINE_GUID( /* 2cb15d1d-5fc1-11d2-abe1-00a0c911f518 */ 128 | ImageLoadGuid, 129 | 0x2cb15d1d, 130 | 0x5fc1, 131 | 0x11d2, 132 | 0xab, 0xe1, 0x00, 0xa0, 0xc9, 0x11, 0xf5, 0x18 133 | ); 134 | 135 | DEFINE_GUID( /* 3d6fa8d3-fe05-11d0-9dda-00c04fd7ba7c */ 136 | PageFaultGuid, 137 | 0x3d6fa8d3, 138 | 0xfe05, 139 | 0x11d0, 140 | 0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c 141 | ); 142 | 143 | DEFINE_GUID( /* ce1dbfb4-137e-4da6-87b0-3f59aa102cbc */ 144 | PerfInfoGuid, 145 | 0xce1dbfb4, 146 | 0x137e, 147 | 0x4da6, 148 | 0x87, 0xb0, 0x3f, 0x59, 0xaa, 0x10, 0x2c, 0xbc 149 | ); 150 | 151 | DEFINE_GUID( /* AE53722E-C863-11d2-8659-00C04FA321A1 */ 152 | RegistryGuid, 153 | 0xae53722e, 154 | 0xc863, 155 | 0x11d2, 156 | 0x86, 0x59, 0x0, 0xc0, 0x4f, 0xa3, 0x21, 0xa1 157 | ); 158 | 159 | DEFINE_GUID( /* 9a280ac0-c8e0-11d1-84e2-00c04fb998a2 */ 160 | TcpIpGuid, 161 | 0x9a280ac0, 162 | 0xc8e0, 163 | 0x11d1, 164 | 0x84, 0xe2, 0x00, 0xc0, 0x4f, 0xb9, 0x98, 0xa2 165 | ); 166 | 167 | DEFINE_GUID( /* 3d6fa8d1-fe05-11d0-9dda-00c04fd7ba7c */ 168 | ThreadGuid, 169 | 0x3d6fa8d1, 170 | 0xfe05, 171 | 0x11d0, 172 | 0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c 173 | ); 174 | 175 | DEFINE_GUID( /* bf3a50c5-a9c9-4988-a005-2df0b7c80f80 */ 176 | UdpIpGuid, 177 | 0xbf3a50c5, 178 | 0xa9c9, 179 | 0x4988, 180 | 0xa0, 0x05, 0x2d, 0xf0, 0xb7, 0xc8, 0x0f, 0x80 181 | ); 182 | 183 | DEFINE_GUID( /* DEF2FE46-7BD6-4b80-bd94-F57FE20D0CE3 */ 184 | StackWalkGuid, 185 | 0xdef2fe46, 186 | 0x7bd6, 187 | 0x4b80, 188 | 0xbd, 0x94, 0xf5, 0x7f, 0xe2, 0xd, 0xc, 0xe3 189 | ); 190 | 191 | DEFINE_GUID( /* 89497f50-effe-4440-8cf2-ce6b1cdcaca7 */ 192 | ObjectGuid, 193 | 0x89497f50, 194 | 0xeffe, 195 | 0x4440, 196 | 0x8c, 0xf2, 0xce, 0x6b, 0x1c, 0xdc, 0xac, 0xa7 197 | ); 198 | 199 | DEFINE_GUID( /* E43445E0-0903-48c3-B878-FF0FCCEBDD04 */ 200 | PowerGuid, 201 | 0xe43445e0, 202 | 0x903, 203 | 0x48c3, 204 | 0xb8, 0x78, 0xff, 0xf, 0xcc, 0xeb, 0xdd, 0x4 205 | ); 206 | 207 | DEFINE_GUID( /* F8F10121-B617-4A56-868B-9dF1B27FE32C */ 208 | MmcssGuid, 209 | 0xf8f10121, 210 | 0xb617, 211 | 0x4a56, 212 | 0x86, 0x8b, 0x9d, 0xf1, 0xb2, 0x7f, 0xe3, 0x2c 213 | ); 214 | 215 | DEFINE_GUID( /* b2d14872-7c5b-463d-8419-ee9bf7d23e04 */ 216 | DpcGuid, 217 | 0xb2d14872, 218 | 0x7c5b, 219 | 0x463d, 220 | 0x84, 0x19, 0xee, 0x9b, 0xf7, 0xd2, 0x3e, 0x04 221 | ); 222 | 223 | DEFINE_GUID( /* d837ca92-12b9-44a5-ad6a-3a65b3578aa8 */ 224 | SplitIoGuid, 225 | 0xd837ca92, 226 | 0x12b9, 227 | 0x44a5, 228 | 0xad, 0x6a, 0x3a, 0x65, 0xb3, 0x57, 0x8a, 0xa8 229 | ); 230 | 231 | DEFINE_GUID( /* c861d0e2-a2c1-4d36-9f9c-970bab943a12 */ 232 | ThreadPoolGuid, 233 | 0xc861d0e2, 234 | 0xa2c1, 235 | 0x4d36, 236 | 0x9f, 0x9c, 0x97, 0x0b, 0xab, 0x94, 0x3a, 0x12 237 | ); 238 | 239 | DEFINE_GUID( /* 0268a8b6-74fd-4302-9dd0-6e8f1795c0cf */ 240 | PoolGuid, 241 | 0x0268a8b6, 242 | 0x74fd, 243 | 0x4302, 244 | 0x9d, 0xd0, 0x6e, 0x8f, 0x17, 0x95, 0xc0, 0xcf 245 | ); 246 | 247 | DEFINE_GUID( /* 222962ab-6180-4b88-a825-346b75f2a24a */ 248 | HeapGuid, 249 | 0x222962ab, 250 | 0x6180, 251 | 0x4b88, 252 | 0xa8, 0x25, 0x34, 0x6b, 0x75, 0xf2, 0xa2, 0x4a 253 | ); 254 | 255 | DEFINE_GUID( /* d781ca11-61c0-4387-b83d-af52d3d2dd6a */ 256 | HeapRangeGuid, 257 | 0xd781ca11, 258 | 0x61c0, 259 | 0x4387, 260 | 0xb8, 0x3d, 0xaf, 0x52, 0xd3, 0xd2, 0xdd, 0x6a 261 | ); 262 | 263 | DEFINE_GUID( /* 05867806-c246-43ef-a147-e17d2bdb1496 */ 264 | HeapSummaryGuid, 265 | 0x05867806, 266 | 0xc246, 267 | 0x43ef, 268 | 0xa1, 0x47, 0xe1, 0x7d, 0x2b, 0xdb, 0x14, 0x96 269 | ); 270 | 271 | DEFINE_GUID( /* 3AC66736-CC59-4cff-8115-8DF50E39816B */ 272 | CritSecGuid, 273 | 0x3ac66736, 274 | 0xcc59, 275 | 0x4cff, 276 | 0x81, 0x15, 0x8d, 0xf5, 0xe, 0x39, 0x81, 0x6b 277 | ); 278 | 279 | DEFINE_GUID( /* 13976D09-A327-438c-950B-7F03192815C7 */ 280 | DbgPrintGuid, 281 | 0x13976d09, 282 | 0xa327, 283 | 0x438c, 284 | 0x95, 0xb, 0x7f, 0x3, 0x19, 0x28, 0x15, 0xc7 285 | ); 286 | 287 | DEFINE_GUID( /* D56CA431-61BF-4904-A621-00E0381E4DDE */ 288 | DriverVerifierGuid, 289 | 0xd56ca431, 290 | 0x61bf, 291 | 0x4904, 292 | 0xa6, 0x21, 0x0, 0xe0, 0x38, 0x1e, 0x4d, 0xde 293 | ); 294 | 295 | 296 | DEFINE_GUID( /* E21D2142-DF90-4d93-BBD9-30E63D5A4AD6 */ 297 | NtdllTraceGuid, 298 | 0xe21d2142, 299 | 0xdf90, 300 | 0x4d93, 301 | 0xbb, 0xd9, 0x30, 0xe6, 0x3d, 0x5a, 0x4a, 0xd6 302 | ); 303 | 304 | DEFINE_GUID( /* d3de60b2-a663-45d5-9826-a0a5949d2cb0 */ 305 | LoadMUIDllGuid, 306 | 0xd3de60b2, 307 | 0xa663, 308 | 0x45d5, 309 | 0x98, 0x26, 0xa0, 0xa5, 0x94, 0x9d, 0x2c, 0xb0 310 | ); 311 | 312 | DEFINE_GUID( /* 3282fc76-feed-498e-8aa7-e70f459d430e */ 313 | JobGuid, 314 | 0x3282fc76, 315 | 0xfeed, 316 | 0x498e, 317 | 0x8a, 0xa7, 0xe7, 0x0f, 0x45, 0x9d, 0x43, 0x0e 318 | ); 319 | 320 | struct KernelEvent { 321 | std::wstring Name; 322 | uint32_t Opcode; 323 | }; 324 | 325 | struct KernelEventCategory { 326 | std::wstring Name; 327 | KernelEventTypes EnableFlag; 328 | const GUID* Guid; 329 | std::vector Events; 330 | bool Advanced{ false }; 331 | 332 | static const std::vector& GetAllCategories(); 333 | static const KernelEventCategory* GetCategory(PCWSTR name); 334 | }; 335 | 336 | --------------------------------------------------------------------------------