├── DbgPrint ├── DbgPrint.h ├── AppSettings.cpp ├── DbgPrint.rc ├── res │ ├── app.ico │ ├── ok.ico │ ├── Play.ico │ ├── Stop.ico │ ├── app0.ico │ ├── atom.ico │ ├── copy.ico │ ├── erase.ico │ ├── find.ico │ ├── gear.ico │ ├── open.ico │ ├── save.ico │ ├── DbgPrint.ico │ ├── FindNext.ico │ ├── bookmark.ico │ ├── cancel.ico │ ├── comment.ico │ ├── filter.ico │ ├── letter-k.ico │ ├── letter-u.ico │ ├── save_as.ico │ ├── script.ico │ ├── autoscroll.ico │ ├── script-new.ico │ ├── script-run.ico │ ├── bookmark-next.ico │ ├── bookmark-prev.ico │ └── file_script.ico ├── pch.cpp ├── SecurityHelper.h ├── Interfaces.cpp ├── Helpers.h ├── DebugOutputBase.cpp ├── UserModeDebugOutput.h ├── ImageIconCache.h ├── KernelModeDebugOutput.h ├── CommentDlg.cpp ├── DebugLogPersist.h ├── Interfaces.h ├── AboutDlg.h ├── DebugOutputBase.h ├── AboutDlg.cpp ├── manifest.xml ├── CommentDlg.h ├── DbgPrint.cpp ├── ProcessManager.h ├── SecurityHelper.cpp ├── PropertiesDlg.h ├── ImageIconCache.cpp ├── AppSettings.h ├── HighlightDlg.h ├── pch.h ├── PropertiesDlg.cpp ├── HighlightDlg.cpp ├── UserModeDebugOutput.cpp ├── KernelModeDebugOutput.cpp ├── Helpers.cpp ├── ProcessManager.cpp ├── resource.h ├── DebugLogPersist.cpp ├── DebugView.h ├── MainFrm.h ├── DbgPrint.vcxproj.filters ├── MainFrm.cpp ├── DebugView.cpp └── DbgPrint.vcxproj ├── dbgprint.png ├── .gitmodules ├── README.md ├── LICENSE ├── .gitattributes ├── DbgPrint.sln └── .gitignore /DbgPrint/DbgPrint.h: -------------------------------------------------------------------------------- 1 | // DbgPrint.h 2 | -------------------------------------------------------------------------------- /DbgPrint/AppSettings.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "AppSettings.h" 3 | -------------------------------------------------------------------------------- /dbgprint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/dbgprint.png -------------------------------------------------------------------------------- /DbgPrint/DbgPrint.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/DbgPrint.rc -------------------------------------------------------------------------------- /DbgPrint/res/app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/app.ico -------------------------------------------------------------------------------- /DbgPrint/res/ok.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/ok.ico -------------------------------------------------------------------------------- /DbgPrint/res/Play.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/Play.ico -------------------------------------------------------------------------------- /DbgPrint/res/Stop.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/Stop.ico -------------------------------------------------------------------------------- /DbgPrint/res/app0.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/app0.ico -------------------------------------------------------------------------------- /DbgPrint/res/atom.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/atom.ico -------------------------------------------------------------------------------- /DbgPrint/res/copy.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/copy.ico -------------------------------------------------------------------------------- /DbgPrint/res/erase.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/erase.ico -------------------------------------------------------------------------------- /DbgPrint/res/find.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/find.ico -------------------------------------------------------------------------------- /DbgPrint/res/gear.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/gear.ico -------------------------------------------------------------------------------- /DbgPrint/res/open.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/open.ico -------------------------------------------------------------------------------- /DbgPrint/res/save.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/save.ico -------------------------------------------------------------------------------- /DbgPrint/res/DbgPrint.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/DbgPrint.ico -------------------------------------------------------------------------------- /DbgPrint/res/FindNext.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/FindNext.ico -------------------------------------------------------------------------------- /DbgPrint/res/bookmark.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/bookmark.ico -------------------------------------------------------------------------------- /DbgPrint/res/cancel.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/cancel.ico -------------------------------------------------------------------------------- /DbgPrint/res/comment.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/comment.ico -------------------------------------------------------------------------------- /DbgPrint/res/filter.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/filter.ico -------------------------------------------------------------------------------- /DbgPrint/res/letter-k.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/letter-k.ico -------------------------------------------------------------------------------- /DbgPrint/res/letter-u.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/letter-u.ico -------------------------------------------------------------------------------- /DbgPrint/res/save_as.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/save_as.ico -------------------------------------------------------------------------------- /DbgPrint/res/script.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/script.ico -------------------------------------------------------------------------------- /DbgPrint/res/autoscroll.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/autoscroll.ico -------------------------------------------------------------------------------- /DbgPrint/res/script-new.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/script-new.ico -------------------------------------------------------------------------------- /DbgPrint/res/script-run.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/script-run.ico -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "WTLHelper"] 2 | path = WTLHelper 3 | url = https://github.com/zodiacon/WTLHelper 4 | -------------------------------------------------------------------------------- /DbgPrint/res/bookmark-next.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/bookmark-next.ico -------------------------------------------------------------------------------- /DbgPrint/res/bookmark-prev.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/bookmark-prev.ico -------------------------------------------------------------------------------- /DbgPrint/res/file_script.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zodiacon/DbgPrint/HEAD/DbgPrint/res/file_script.ico -------------------------------------------------------------------------------- /DbgPrint/pch.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // DbgPrint.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "pch.h" 6 | -------------------------------------------------------------------------------- /DbgPrint/SecurityHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct SecurityHelper abstract final { 4 | static bool IsRunningElevated(); 5 | static bool RunElevated(); 6 | static bool EnablePrivilege(PCWSTR privName, bool enable = true); 7 | }; 8 | -------------------------------------------------------------------------------- /DbgPrint/Interfaces.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Interfaces.h" 3 | 4 | std::wostream& operator<<(std::wostream& out, ProcessKey const& key) { 5 | out << key.ProcessId << L":" << *(uint64_t*)&key.StartTime; 6 | return out; 7 | } 8 | -------------------------------------------------------------------------------- /DbgPrint/Helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct Helpers { 4 | static void ReportError(PCWSTR text, DWORD error = ::GetLastError()); 5 | static bool EnableAllkernelOutput(bool enable); 6 | static int GetKernelComponentNames(PCWSTR*& names); 7 | }; 8 | 9 | -------------------------------------------------------------------------------- /DbgPrint/DebugOutputBase.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "DebugOutputBase.h" 3 | 4 | HANDLE g_hHeap = ::HeapCreate(0, 1 << 20, 0); 5 | 6 | void* DebugItem::operator new(size_t size) { 7 | ATLASSERT(g_hHeap); 8 | return ::HeapAlloc(g_hHeap, 0, size); 9 | } 10 | 11 | void DebugItem::operator delete(void* p) { 12 | ::HeapFree(g_hHeap, 0, p); 13 | } 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DbgPrint 2 | 3 | Debug Print viewer (user and kernel) 4 | 5 | View `OutputDebugString` output (.NET `Debug.Write*`, `Trace.Write*`, etc.). 6 | 7 | View kernel mode output (`DbgPrint`/`Ex`), no driver required. Use the *Kernel* / *Enable All Components* to see all kernel components output without the need to modify the Registry or restart. 8 | 9 | ![](https://github.com/zodiacon/DbgPrint/blob/master/dbgprint.png) 10 | -------------------------------------------------------------------------------- /DbgPrint/UserModeDebugOutput.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DebugOutputBase.h" 4 | #include 5 | 6 | class UserModeDebugOutput : public DebugOutputBase { 7 | public: 8 | UserModeDebugOutput(PCWSTR prefix = L"Local"); 9 | ~UserModeDebugOutput(); 10 | 11 | bool Run(IDebugOutput* callback) override; 12 | bool Stop() override; 13 | bool IsRunning() const override; 14 | 15 | private: 16 | DWORD DebugListen(); 17 | 18 | wil::unique_handle m_hDataReady, m_hMemFile, m_hBufferReady, m_hThread, m_hStop; 19 | PBYTE m_buffer{ nullptr }; 20 | CString m_prefix; 21 | IDebugOutput* m_sink; 22 | }; 23 | 24 | -------------------------------------------------------------------------------- /DbgPrint/ImageIconCache.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class ImageIconCache { 6 | public: 7 | ImageIconCache(); 8 | ImageIconCache(const ImageIconCache&) = delete; 9 | ImageIconCache& operator=(const ImageIconCache&) = delete; 10 | 11 | HIMAGELIST GetImageList() const; 12 | int GetIcon(std::wstring_view path, HICON* phIcon = nullptr) const; 13 | 14 | using Map = std::unordered_map; 15 | Map::const_iterator begin() const; 16 | Map::const_iterator end() const; 17 | 18 | private: 19 | mutable CImageList m_images; 20 | mutable Map m_icons; 21 | mutable std::shared_mutex m_lock; 22 | }; 23 | -------------------------------------------------------------------------------- /DbgPrint/KernelModeDebugOutput.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DebugOutputBase.h" 4 | #include 5 | 6 | class KernelModeDebugOutput : public DebugOutputBase { 7 | public: 8 | // Inherited via DebugOutputBase 9 | bool Run(IDebugOutput* sink) override; 10 | bool Stop() override; 11 | bool IsRunning() const override; 12 | 13 | protected: 14 | DWORD Process(); 15 | 16 | private: 17 | IDebugOutput* m_sink; 18 | TRACEHANDLE m_handle{ 0 }; 19 | TRACEHANDLE m_hTrace{ 0 }; 20 | EVENT_TRACE_PROPERTIES* m_properties; 21 | std::unique_ptr m_propertiesBuffer; 22 | EVENT_TRACE_LOGFILE m_traceLog = { 0 }; 23 | wil::unique_handle m_hThread, m_hStop; 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /DbgPrint/CommentDlg.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "resource.h" 3 | #include "CommentDlg.h" 4 | 5 | LRESULT CCommentDlg::OnInitDialog(UINT, WPARAM, LPARAM lp, BOOL&) { 6 | InitDynamicLayout(); 7 | AdjustOKCancelButtons(IDI_OK, IDI_CANCEL); 8 | 9 | m_Edit.Attach(GetDlgItem(IDC_COMMENT)); 10 | 11 | auto hIcon = reinterpret_cast(lp); 12 | if (hIcon) 13 | SetDialogIcon(hIcon); 14 | 15 | m_Edit.SetWindowTextW(m_Comment.c_str()); 16 | 17 | return 0; 18 | } 19 | 20 | LRESULT CCommentDlg::OnCloseCmd(WORD, WORD wID, HWND, BOOL&) { 21 | if (wID == IDOK) { 22 | CString comment; 23 | GetDlgItemText(IDC_COMMENT, comment); 24 | m_Comment = comment; 25 | } 26 | EndDialog(wID); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /DbgPrint/DebugLogPersist.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct DebugItem; 6 | class ImageIconCache; 7 | class ProcessManager; 8 | 9 | enum class PersistFormat { 10 | Native, 11 | CSV, 12 | }; 13 | 14 | class DebugLogPersist abstract final { 15 | public: 16 | static bool Save(PersistFormat format, std::vector> const& items, ImageIconCache const& iconCache, ProcessManager const& pm, std::wstring_view path); 17 | static bool Load(std::wstring_view path, std::vector>& items, ProcessManager& pm); 18 | 19 | private: 20 | static bool SaveCSV(std::vector> const& items, std::wstring_view path); 21 | static bool SaveNative(std::vector> const& items, ImageIconCache const& iconCache, ProcessManager const& pm, std::wstring_view path); 22 | }; 23 | 24 | -------------------------------------------------------------------------------- /DbgPrint/Interfaces.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct ProcessKey { 6 | DWORD ProcessId; 7 | FILETIME StartTime{}; 8 | bool operator==(const ProcessKey& other) const { 9 | return other.ProcessId == ProcessId && 10 | other.StartTime.dwLowDateTime == StartTime.dwLowDateTime && 11 | other.StartTime.dwHighDateTime == StartTime.dwHighDateTime; 12 | } 13 | }; 14 | 15 | std::wostream& operator<<(std::wostream& out, ProcessKey const& key); 16 | 17 | template<> 18 | struct std::hash { 19 | size_t operator()(ProcessKey const& key) const { 20 | return (key.ProcessId << 16LL) ^ key.StartTime.dwLowDateTime ^ (key.StartTime.dwHighDateTime << 16LL); 21 | } 22 | }; 23 | 24 | struct HighlightItem { 25 | COLORREF Light; 26 | COLORREF Dark; 27 | std::wstring Text; 28 | }; 29 | 30 | struct IMainFrame { 31 | virtual BOOL TrackPopupMenu(HMENU hMenu, DWORD flags, int x, int y, HWND hWnd = nullptr) = 0; 32 | virtual CFindReplaceDialog* GetFindDlg() = 0; 33 | virtual CString& GetSearchString() = 0; 34 | }; 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 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 | -------------------------------------------------------------------------------- /DbgPrint/AboutDlg.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | #include "DialogHelper.h" 5 | 6 | class CAboutDlg : 7 | public CDialogImpl, 8 | public CDialogHelper { 9 | public: 10 | enum { IDD = IDD_ABOUTBOX }; 11 | 12 | BEGIN_MSG_MAP(CAboutDlg) 13 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 14 | NOTIFY_CODE_HANDLER(NM_CLICK, OnClickSyslink) 15 | NOTIFY_CODE_HANDLER(NM_RETURN, OnClickSyslink) 16 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd) 17 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) 18 | END_MSG_MAP() 19 | 20 | // Handler prototypes (uncomment arguments if needed): 21 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) 22 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 23 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) 24 | 25 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 26 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 27 | LRESULT OnClickSyslink(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) const; 28 | }; 29 | -------------------------------------------------------------------------------- /DbgPrint/DebugOutputBase.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Interfaces.h" 4 | 5 | enum class DebugOutputFlags { 6 | None = 0, 7 | Kernel = 0x100, 8 | Bookmark = 0x200, 9 | Highlight = 0x400, 10 | }; 11 | DEFINE_ENUM_FLAG_OPERATORS(DebugOutputFlags); 12 | 13 | struct IDebugOutput { 14 | virtual void DebugOutput(DWORD pid, PCSTR text, FILETIME const&, DebugOutputFlags flags = DebugOutputFlags::None) = 0; 15 | }; 16 | 17 | struct DebugOutputBase abstract { 18 | virtual bool Run(IDebugOutput* sink) = 0; 19 | virtual bool Stop() = 0; 20 | virtual bool IsRunning() const = 0; 21 | }; 22 | 23 | enum class ViewType { 24 | RealTimeLog, 25 | FileLog, 26 | }; 27 | 28 | struct IViewBase abstract { 29 | virtual BOOL ProcessWindowMessage(_In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM wParam, 30 | _In_ LPARAM lParam, _Inout_ LRESULT& lResult, _In_ DWORD dwMsgMapID = 0) = 0; 31 | 32 | }; 33 | 34 | struct DebugItem { 35 | void* operator new(size_t size); 36 | void operator delete(void* p); 37 | 38 | ProcessKey Process; 39 | std::wstring Text; 40 | FILETIME SystemTime; 41 | mutable CString LocalTimeAsString; 42 | std::wstring ProcessName; 43 | DWORD Index; 44 | DebugOutputFlags Flags; 45 | std::wstring Comment; 46 | int Image{ -1 }; 47 | }; 48 | -------------------------------------------------------------------------------- /DbgPrint/AboutDlg.cpp: -------------------------------------------------------------------------------- 1 | // aboutdlg.cpp : implementation of the CAboutDlg class 2 | // 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #include "pch.h" 6 | #include "resource.h" 7 | #include "AboutDlg.h" 8 | #include 9 | 10 | LRESULT CAboutDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { 11 | CenterWindow(GetParent()); 12 | SetDialogIcon(IDR_MAINFRAME); 13 | AdjustOKCancelButtons(IDI_OK, IDI_CANCEL); 14 | 15 | VersionResourceHelper vh; 16 | auto version = vh.GetValue(L"ProductVersion"); 17 | SetDlgItemText(IDC_VERSION, vh.GetValue(L"ProductName") + L" v" + version); 18 | SetDlgItemText(IDC_COPYRIGHT, vh.GetValue(L"LegalCopyright")); 19 | 20 | return TRUE; 21 | } 22 | 23 | LRESULT CAboutDlg::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 24 | EndDialog(wID); 25 | return 0; 26 | } 27 | 28 | LRESULT CAboutDlg::OnClickSyslink(int, LPNMHDR hdr, BOOL&) const { 29 | CString text; 30 | GetDlgItem((UINT)hdr->idFrom).GetWindowText(text); 31 | text.Replace(L"", L""); 32 | text.Replace(L"", L""); 33 | ::ShellExecute(nullptr, L"open", text, nullptr, nullptr, SW_SHOWDEFAULT); 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /DbgPrint/manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | true 22 | PerMonitorV2, system 23 | true 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /DbgPrint/CommentDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DialogHelper.h" 4 | 5 | struct CCommentDlg : 6 | public CDialogImpl, 7 | public CDynamicDialogLayout, 8 | public CDialogHelper { 9 | public: 10 | enum { IDD = IDD_COMMENT }; 11 | 12 | CCommentDlg(std::wstring const& comment) : m_Comment(comment) {} 13 | 14 | std::wstring const& GetComment() const { 15 | return m_Comment; 16 | } 17 | 18 | protected: 19 | BEGIN_MSG_MAP(CCommentDlg) 20 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 21 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd) 22 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) 23 | CHAIN_MSG_MAP(CDynamicDialogLayout) 24 | END_MSG_MAP() 25 | 26 | // Handler prototypes (uncomment arguments if needed): 27 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) 28 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 29 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) 30 | 31 | private: 32 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 33 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 34 | 35 | std::wstring m_Comment; 36 | CEdit m_Edit; 37 | }; 38 | -------------------------------------------------------------------------------- /DbgPrint/DbgPrint.cpp: -------------------------------------------------------------------------------- 1 | // DbgPrint.cpp : main source file for DbgPrint.exe 2 | // 3 | 4 | #include "pch.h" 5 | #include "resource.h" 6 | #include "MainFrm.h" 7 | #include "AppSettings.h" 8 | #include "SecurityHelper.h" 9 | #include 10 | 11 | CAppModule _Module; 12 | AppSettings _Settings; 13 | 14 | int Run(LPTSTR /*lpstrCmdLine*/ = nullptr, int nCmdShow = SW_SHOWDEFAULT) { 15 | CMessageLoop theLoop; 16 | _Module.AddMessageLoop(&theLoop); 17 | 18 | CMainFrame wndMain; 19 | 20 | if (wndMain.CreateEx() == nullptr) { 21 | ATLTRACE(_T("Main window creation failed!\n")); 22 | return 0; 23 | } 24 | 25 | wndMain.ShowWindow(nCmdShow); 26 | 27 | int nRet = theLoop.Run(); 28 | 29 | _Module.RemoveMessageLoop(); 30 | return nRet; 31 | } 32 | 33 | int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow) { 34 | HRESULT hRes = ::CoInitialize(nullptr); 35 | ATLASSERT(SUCCEEDED(hRes)); 36 | 37 | AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES | ICC_LISTVIEW_CLASSES); 38 | 39 | hRes = _Module.Init(nullptr, hInstance); 40 | ATLASSERT(SUCCEEDED(hRes)); 41 | 42 | if (SecurityHelper::IsRunningElevated()) 43 | SecurityHelper::EnablePrivilege(SE_DEBUG_NAME); 44 | 45 | ThemeHelper::Init(); 46 | int nRet = Run(lpstrCmdLine, nCmdShow); 47 | 48 | _Module.Term(); 49 | ::CoUninitialize(); 50 | 51 | return nRet; 52 | } 53 | -------------------------------------------------------------------------------- /DbgPrint/ProcessManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "Interfaces.h" 6 | #include 7 | 8 | enum class ProcessInfoFlags { 9 | None = 0, 10 | FromFile = 1, 11 | }; 12 | DEFINE_ENUM_FLAG_OPERATORS(ProcessInfoFlags); 13 | 14 | struct StaticProcessInfo : ProcessKey { 15 | std::wstring FullPath; 16 | std::wstring CommandLine; 17 | std::wstring Name; 18 | wil::unique_handle hProcess; 19 | DWORD SessionId; 20 | ProcessInfoFlags Flags{ ProcessInfoFlags::None }; 21 | }; 22 | 23 | class ProcessManager { 24 | public: 25 | ProcessManager(); 26 | std::wstring GetProcessName(DWORD pid) const; 27 | PCWSTR GetFullImagePath(DWORD pid) const; 28 | ProcessKey GetProcessKey(DWORD pid) const; 29 | StaticProcessInfo* const GetProcessInfo(ProcessKey const&) const; 30 | 31 | std::vector GetRuntimeProcesses() const; 32 | 33 | void AddProcessesNoLock(std::span> const& processes); 34 | 35 | private: 36 | void AddProcess(std::shared_ptr& pi) const; 37 | bool AddProcess(DWORD pid, PCWSTR path = nullptr) const; 38 | void Init(); 39 | void AddProcessIfNotExist(DWORD pid) const; 40 | 41 | mutable std::unordered_map> _processesByKey; 42 | mutable std::unordered_map> _processes; 43 | mutable std::shared_mutex _lock; 44 | }; 45 | 46 | -------------------------------------------------------------------------------- /DbgPrint/SecurityHelper.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "SecurityHelper.h" 3 | #include 4 | 5 | bool SecurityHelper::IsRunningElevated() { 6 | static bool runningElevated = false; 7 | static bool runningElevatedCheck = false; 8 | if (runningElevatedCheck) 9 | return runningElevated; 10 | 11 | runningElevatedCheck = true; 12 | wil::unique_handle hToken; 13 | if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, hToken.addressof())) 14 | return false; 15 | 16 | TOKEN_ELEVATION te; 17 | DWORD len; 18 | if (::GetTokenInformation(hToken.get(), TokenElevation, &te, sizeof(te), &len)) { 19 | runningElevated = te.TokenIsElevated ? true : false; 20 | } 21 | return runningElevated; 22 | } 23 | 24 | bool SecurityHelper::RunElevated() { 25 | WCHAR path[MAX_PATH]; 26 | ::GetModuleFileName(nullptr, path, _countof(path)); 27 | return (INT_PTR)::ShellExecute(nullptr, L"runas", path, nullptr, nullptr, SW_SHOWDEFAULT) > 31; 28 | } 29 | 30 | bool SecurityHelper::EnablePrivilege(PCWSTR privName, bool enable) { 31 | wil::unique_handle hToken; 32 | if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, hToken.addressof())) 33 | return false; 34 | 35 | bool result = false; 36 | TOKEN_PRIVILEGES tp; 37 | tp.PrivilegeCount = 1; 38 | tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; 39 | if (::LookupPrivilegeValue(nullptr, privName, 40 | &tp.Privileges[0].Luid)) { 41 | if (::AdjustTokenPrivileges(hToken.get(), FALSE, &tp, sizeof(tp), 42 | nullptr, nullptr)) 43 | result = ::GetLastError() == ERROR_SUCCESS; 44 | } 45 | return result; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /DbgPrint/PropertiesDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DialogHelper.h" 4 | 5 | struct DebugItem; 6 | class ImageIconCache; 7 | class ProcessManager; 8 | 9 | class CPropertiesDlg : 10 | public CDialogImpl, 11 | public CDialogHelper, 12 | public CDynamicDialogLayout { 13 | public: 14 | enum { IDD = IDD_PROPERTIES }; 15 | 16 | CPropertiesDlg(DebugItem const& item, ImageIconCache const& iconCache, ProcessManager const& pm); 17 | 18 | CString const& GetComment() const { 19 | return m_Comment; 20 | } 21 | 22 | CString const& GetText() const { 23 | return m_Text; 24 | } 25 | 26 | protected: 27 | BEGIN_MSG_MAP(CPropertiesDlg) 28 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 29 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd) 30 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) 31 | CHAIN_MSG_MAP(CDynamicDialogLayout) 32 | END_MSG_MAP() 33 | 34 | // Handler prototypes (uncomment arguments if needed): 35 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) 36 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 37 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) 38 | 39 | private: 40 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 41 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 42 | 43 | DebugItem const& m_Item; 44 | CString m_Comment, m_Text; 45 | ImageIconCache const& m_IconCache; 46 | ProcessManager const& m_pm; 47 | }; 48 | -------------------------------------------------------------------------------- /DbgPrint/ImageIconCache.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ImageIconCache.h" 3 | #include "resource.h" 4 | 5 | int ImageIconCache::GetIcon(std::wstring_view path, HICON* phIcon) const { 6 | if (path.empty() || path.find(L'\\') != std::wstring::npos) 7 | return 0; 8 | 9 | std::wstring wspath(path); 10 | { 11 | std::shared_lock locker(m_lock); 12 | auto it = m_icons.find(wspath); 13 | if (it != m_icons.end()) { 14 | int index = it->second; 15 | if (phIcon) 16 | *phIcon = m_images.GetIcon(index); 17 | return index; 18 | } 19 | } 20 | WORD index = 0; 21 | CString spath(path.data()); 22 | auto hIcon = ::ExtractAssociatedIcon(_Module.GetModuleInstance(), spath.GetBufferSetLength(MAX_PATH), &index); 23 | 24 | if (hIcon) { 25 | std::lock_guard locker(m_lock); 26 | int index = m_images.AddIcon(hIcon); 27 | if (phIcon) 28 | *phIcon = hIcon; 29 | m_icons.insert({ wspath, index }); 30 | return index; 31 | } 32 | return 0; 33 | } 34 | 35 | ImageIconCache::Map::const_iterator ImageIconCache::begin() const { 36 | return m_icons.begin(); 37 | } 38 | 39 | ImageIconCache::Map::const_iterator ImageIconCache::end() const { 40 | return m_icons.end(); 41 | } 42 | 43 | ImageIconCache::ImageIconCache() { 44 | m_images.Create(16, 16, ILC_COLOR32 | ILC_COLOR | ILC_MASK, 16, 16); 45 | m_images.AddIcon(AtlLoadSysIcon(IDI_APPLICATION)); 46 | m_images.AddIcon(AtlLoadIconImage(IDI_KERNEL, 0, 16, 16)); 47 | m_images.AddIcon(AtlLoadIconImage(IDI_USERMODE, 0, 16, 16)); 48 | m_images.AddIcon(AtlLoadIconImage(IDI_BOOKMARK, 0, 16, 16)); 49 | } 50 | 51 | HIMAGELIST ImageIconCache::GetImageList() const { 52 | return m_images; 53 | } 54 | 55 | 56 | -------------------------------------------------------------------------------- /DbgPrint/AppSettings.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Interfaces.h" 5 | 6 | static std::vector DefaultHighlightColors { 7 | { RGB(0, 255, 0), RGB(0, 128, 0) }, 8 | { RGB(0, 0, 255), RGB(0, 0, 128) }, 9 | { RGB(255, 128, 0), RGB(128, 0, 0) }, 10 | }; 11 | 12 | struct AppSettings : Settings { 13 | BEGIN_SETTINGS(AppSettings) 14 | SETTING(MainWindowPlacement, WINDOWPLACEMENT{}, SettingType::Binary); 15 | SETTING(Font, LOGFONT{}, SettingType::Binary); 16 | SETTING(MenuFont, LOGFONT{}, SettingType::Binary); 17 | SETTING(ViewToolBar, 1, SettingType::Bool); 18 | SETTING(ViewStatusBar, 1, SettingType::Bool); 19 | SETTING(SingleInstance, 0, SettingType::Bool); 20 | SETTING(DarkMode, 0, SettingType::Bool); 21 | SETTING(AlwaysOnTop, 0, SettingType::Bool); 22 | SETTING(Capture, 1, SettingType::Bool); 23 | SETTING(ConfirmErase, 0, SettingType::Bool); 24 | SETTING(CaptureUserMode, 1, SettingType::Bool); 25 | SETTING(CaptureSession0, 0, SettingType::Bool); 26 | SETTING(CaptureKernel, 0, SettingType::Bool); 27 | SETTING(AutoScroll, 0, SettingType::Bool); 28 | SETTING(BookmarkColor, RGB(0, 255, 0), SettingType::Int32); 29 | SETTING(HightlightItems, DefaultHighlightColors, SettingType::Binary); 30 | END_SETTINGS 31 | 32 | DEF_SETTING(AlwaysOnTop, int) 33 | DEF_SETTING(Font, LOGFONT) 34 | DEF_SETTING(ViewToolBar, int) 35 | DEF_SETTING(ViewStatusBar, int) 36 | DEF_SETTING(SingleInstance, int) 37 | DEF_SETTING(DarkMode, int) 38 | DEF_SETTING(Capture, int) 39 | DEF_SETTING(CaptureUserMode, int) 40 | DEF_SETTING(CaptureSession0, int) 41 | DEF_SETTING(CaptureKernel, int) 42 | DEF_SETTING(AutoScroll, int) 43 | DEF_SETTING(HighlightItems, std::vector) 44 | DEF_SETTING(ConfirmErase, bool); 45 | }; 46 | 47 | -------------------------------------------------------------------------------- /DbgPrint/HighlightDlg.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "DialogHelper.h" 4 | #include "VirtualListView.h" 5 | #include "Interfaces.h" 6 | 7 | struct CHighlightDlg : 8 | public CDialogImpl, 9 | public CDynamicDialogLayout, 10 | public CVirtualListView, 11 | public CCustomDraw, 12 | public CDialogHelper { 13 | public: 14 | enum { IDD = IDD_HIGHLIGHT }; 15 | 16 | explicit CHighlightDlg(std::vector items); 17 | 18 | std::vector const& GetItems() const; 19 | 20 | CString GetColumnText(HWND, int row, int col) const; 21 | 22 | int OnPrePaint(int, LPNMCUSTOMDRAW cd); 23 | int OnItemPrePaint(int, LPNMCUSTOMDRAW cd); 24 | int OnSubItemPrePaint(int, LPNMCUSTOMDRAW cd); 25 | 26 | protected: 27 | BEGIN_MSG_MAP(CHighlightDlg) 28 | COMMAND_ID_HANDLER(IDOK, OnCloseCmd) 29 | COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd) 30 | CHAIN_MSG_MAP(CCustomDraw) 31 | CHAIN_MSG_MAP(CVirtualListView) 32 | CHAIN_MSG_MAP(CDynamicDialogLayout) 33 | MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) 34 | END_MSG_MAP() 35 | 36 | private: 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 | LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 43 | LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD id, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 44 | 45 | std::vector m_Items; 46 | CListViewCtrl m_List; 47 | }; 48 | -------------------------------------------------------------------------------- /DbgPrint/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 | 14 | #include 15 | #include 16 | 17 | extern CAppModule _Module; 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #define INITGUID 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #if defined _M_IX86 39 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") 40 | #elif defined _M_IA64 41 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") 42 | #elif defined _M_X64 43 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") 44 | #else 45 | #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 46 | #endif 47 | -------------------------------------------------------------------------------- /DbgPrint/PropertiesDlg.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "resource.h" 3 | #include "PropertiesDlg.h" 4 | #include "DebugOutputBase.h" 5 | #include "ImageIconCache.h" 6 | #include "ProcessManager.h" 7 | #include "AppSettings.h" 8 | 9 | CPropertiesDlg::CPropertiesDlg(DebugItem const& item, ImageIconCache const& iconCache, ProcessManager const& pm) 10 | : m_Item(item), m_IconCache(iconCache), m_pm(pm) { 11 | } 12 | 13 | LRESULT CPropertiesDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { 14 | InitDynamicLayout(); 15 | AdjustOKCancelButtons(IDI_OK, IDI_CANCEL); 16 | 17 | AppSettings::Get().LoadWindowPosition(m_hWnd, L"PropertiesDlg"); 18 | 19 | CImageList images(m_IconCache.GetImageList()); 20 | SetDialogIcon(images.GetIcon(m_Item.Image)); 21 | 22 | SetDlgItemInt(IDC_PID, m_Item.Process.ProcessId, FALSE); 23 | SetDlgItemInt(IDC_INDEX, m_Item.Index, FALSE); 24 | SetDlgItemText(IDC_TIME, m_Item.LocalTimeAsString); 25 | SetDlgItemText(IDC_NAME, m_Item.ProcessName.c_str()); 26 | auto pi = m_pm.GetProcessInfo(m_Item.Process); 27 | SetDlgItemText(IDC_PATH, pi->FullPath.c_str()); 28 | SetDlgItemText(IDC_CMDLINE, pi->CommandLine.c_str()); 29 | 30 | int start = 0; 31 | CString text = m_Item.Text.c_str(); 32 | while ((start = text.Find(L"\n", start)) >= 0) { 33 | if(text[start + 1] != L'\r') 34 | text = text.Left(start) + L"\r\n" + text.Mid(start + 1); 35 | start += 2; 36 | } 37 | 38 | SetDlgItemText(IDC_TEXT, text); 39 | SetDlgItemText(IDC_COMMENT, m_Item.Comment.c_str()); 40 | 41 | return 0; 42 | } 43 | 44 | LRESULT CPropertiesDlg::OnCloseCmd(WORD, WORD wID, HWND, BOOL&) { 45 | AppSettings::Get().SaveWindowPosition(m_hWnd, L"PropertiesDlg"); 46 | 47 | if (wID == IDOK) { 48 | GetDlgItemText(IDC_COMMENT, m_Comment); 49 | GetDlgItemText(IDC_TEXT, m_Text); 50 | } 51 | EndDialog(wID); 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /DbgPrint/HighlightDlg.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "resource.h" 3 | #include "HighlightDlg.h" 4 | #include "AppSettings.h" 5 | 6 | CHighlightDlg::CHighlightDlg(std::vector items) : m_Items(items) { 7 | } 8 | 9 | std::vector const& CHighlightDlg::GetItems() const { 10 | return m_Items; 11 | } 12 | 13 | CString CHighlightDlg::GetColumnText(HWND, int row, int col) const { 14 | auto& item = m_Items[row]; 15 | switch (col) { 16 | case 1: return item.Text.c_str(); 17 | } 18 | return L""; 19 | } 20 | 21 | int CHighlightDlg::OnPrePaint(int, LPNMCUSTOMDRAW cd) { 22 | if (cd->hdr.hwndFrom != m_List) { 23 | SetMsgHandled(FALSE); 24 | return 0; 25 | } 26 | 27 | return CDRF_NOTIFYITEMDRAW; 28 | } 29 | 30 | int CHighlightDlg::OnItemPrePaint(int, LPNMCUSTOMDRAW cd) { 31 | if (cd->hdr.hwndFrom != m_List) { 32 | SetMsgHandled(FALSE); 33 | return 0; 34 | } 35 | return CDRF_NOTIFYSUBITEMDRAW; 36 | } 37 | 38 | int CHighlightDlg::OnSubItemPrePaint(int, LPNMCUSTOMDRAW cd) { 39 | auto lv = (NMLVCUSTOMDRAW*)cd; 40 | if (lv->iSubItem == 0) { 41 | auto& item = m_Items[cd->dwItemSpec]; 42 | CRect rc(cd->rc); 43 | CDCHandle dc(cd->hdc); 44 | rc.DeflateRect(2, 2); 45 | dc.FillSolidRect(&rc, AppSettings::Get().DarkMode() ? item.Dark : item.Light); 46 | } 47 | return CDRF_SKIPPOSTPAINT; 48 | } 49 | 50 | LRESULT CHighlightDlg::OnInitDialog(UINT, WPARAM, LPARAM, BOOL&) { 51 | InitDynamicLayout(); 52 | m_List.Attach(GetDlgItem(IDC_LIST)); 53 | m_List.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP); 54 | 55 | auto cm = GetColumnManager(m_List); 56 | cm->AddColumn(L"Color", 0, 80); 57 | cm->AddColumn(L"Text", 0, 200); 58 | cm->UpdateColumns(); 59 | 60 | m_List.SetItemCount((int)m_Items.size()); 61 | 62 | return 0; 63 | } 64 | 65 | LRESULT CHighlightDlg::OnCloseCmd(WORD, WORD id, HWND, BOOL&) { 66 | EndDialog(id); 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /DbgPrint/UserModeDebugOutput.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "UserModeDebugOutput.h" 3 | 4 | UserModeDebugOutput::UserModeDebugOutput(PCWSTR prefix) : m_prefix(prefix) { 5 | } 6 | 7 | UserModeDebugOutput::~UserModeDebugOutput() { 8 | Stop(); 9 | } 10 | 11 | bool UserModeDebugOutput::Run(IDebugOutput* sink) { 12 | m_sink = sink; 13 | m_hStop.reset(::CreateEvent(nullptr, TRUE, FALSE, nullptr)); 14 | if (!m_hStop) 15 | return false; 16 | 17 | if (!m_hBufferReady) { 18 | m_hBufferReady.reset(::CreateEvent(nullptr, FALSE, FALSE, m_prefix + L"\\DBWIN_BUFFER_READY")); 19 | if (!m_hBufferReady) 20 | return false; 21 | } 22 | 23 | if (!m_hDataReady) { 24 | m_hDataReady.reset(::CreateEvent(nullptr, FALSE, FALSE, m_prefix + L"\\DBWIN_DATA_READY")); 25 | if (!m_hDataReady) 26 | return false; 27 | } 28 | 29 | DWORD size = 1 << 12; // 4KB 30 | if (!m_hMemFile) { 31 | m_hMemFile.reset(::CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, size, m_prefix + L"\\DBWIN_BUFFER")); 32 | if (m_hMemFile == nullptr) 33 | return false; 34 | } 35 | 36 | if (!m_buffer) { 37 | m_buffer = (PBYTE)::MapViewOfFile(m_hMemFile.get(), FILE_MAP_READ, 0, 0, 0); 38 | if (m_buffer == nullptr) 39 | return false; 40 | } 41 | 42 | m_hThread.reset(::CreateThread(nullptr, 0, [](auto p) { 43 | return ((UserModeDebugOutput*)p)->DebugListen(); 44 | }, this, 0, nullptr)); 45 | return m_hThread != nullptr; 46 | } 47 | 48 | bool UserModeDebugOutput::Stop() { 49 | if (!m_hStop) 50 | return false; 51 | 52 | if (m_hThread == nullptr) 53 | return true; 54 | 55 | auto rv = ::SignalObjectAndWait(m_hStop.get(), m_hThread.get(), 2000, FALSE); 56 | m_hThread.reset(); 57 | 58 | return rv == WAIT_OBJECT_0; 59 | } 60 | 61 | bool UserModeDebugOutput::IsRunning() const { 62 | return ::WaitForSingleObject(m_hThread.get(), 0) == WAIT_TIMEOUT; 63 | } 64 | 65 | DWORD UserModeDebugOutput::DebugListen() { 66 | ::CoInitializeEx(nullptr, COINIT_MULTITHREADED); 67 | HANDLE h[] = { m_hStop.get(), m_hDataReady.get() }; 68 | 69 | while (true) { 70 | ::SetEvent(m_hBufferReady.get()); 71 | auto rv = ::WaitForMultipleObjects(_countof(h), h, FALSE, INFINITE); 72 | if (rv == WAIT_OBJECT_0) 73 | break; 74 | 75 | ATLASSERT(rv == WAIT_OBJECT_0 + 1); 76 | 77 | FILETIME st; 78 | ::GetSystemTimeAsFileTime(&st); 79 | DWORD pid = *(DWORD*)m_buffer; 80 | m_sink->DebugOutput(pid, (PCSTR)(m_buffer + sizeof(DWORD)), st); 81 | } 82 | 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /DbgPrint/KernelModeDebugOutput.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "KernelModeDebugOutput.h" 3 | 4 | #pragma comment(lib, "tdh") 5 | 6 | bool KernelModeDebugOutput::Run(IDebugOutput* sink) { 7 | m_sink = sink; 8 | 9 | if (m_handle || m_hTrace) 10 | return true; 11 | 12 | auto sessionName = KERNEL_LOGGER_NAME; 13 | 14 | // {6990501B-4484-4EF0-8793-84159B8D4728} 15 | static const GUID dummyGuid = 16 | { 0x6990501b, 0x4484, 0x4ef0, { 0x87, 0x93, 0x84, 0x15, 0x9b, 0x8d, 0x47, 0x28 } }; 17 | 18 | auto size = sizeof(EVENT_TRACE_PROPERTIES) + sizeof(KERNEL_LOGGER_NAME); 19 | m_propertiesBuffer = std::make_unique(size); 20 | bool isWin8Plus = ::IsWindows8OrGreater(); 21 | ULONG error; 22 | 23 | for (;;) { 24 | ::memset(m_propertiesBuffer.get(), 0, size); 25 | 26 | m_properties = reinterpret_cast(m_propertiesBuffer.get()); 27 | m_properties->EnableFlags = EVENT_TRACE_FLAG_DBGPRINT; 28 | m_properties->Wnode.BufferSize = (ULONG)size; 29 | m_properties->Wnode.Guid = isWin8Plus ? dummyGuid : SystemTraceControlGuid; 30 | m_properties->Wnode.Flags = WNODE_FLAG_TRACED_GUID; 31 | m_properties->Wnode.ClientContext = 1; 32 | m_properties->FlushTimer = 1; 33 | m_properties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE | EVENT_TRACE_USE_LOCAL_SEQUENCE | EVENT_TRACE_SYSTEM_LOGGER_MODE; 34 | m_properties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES); 35 | 36 | error = ::StartTrace(&m_handle, sessionName, m_properties); 37 | if (error == ERROR_ALREADY_EXISTS) { 38 | error = ::ControlTrace(m_hTrace, KERNEL_LOGGER_NAME, m_properties, EVENT_TRACE_CONTROL_STOP); 39 | if (error != ERROR_SUCCESS) 40 | return false; 41 | continue; 42 | } 43 | break; 44 | } 45 | if (error != ERROR_SUCCESS) 46 | return false; 47 | 48 | m_traceLog.Context = this; 49 | m_traceLog.LoggerName = (PWSTR)KERNEL_LOGGER_NAME; 50 | m_traceLog.ProcessTraceMode = PROCESS_TRACE_MODE_EVENT_RECORD | PROCESS_TRACE_MODE_REAL_TIME; 51 | m_traceLog.EventRecordCallback = [](PEVENT_RECORD record) { 52 | if (record->EventHeader.ProcessId != 0xffffffff) { 53 | auto text((PCSTR)((BYTE*)record->UserData + sizeof(ULONG) * 2)); 54 | ATLASSERT(text); 55 | ((KernelModeDebugOutput*)record->UserContext)->m_sink->DebugOutput( 56 | record->EventHeader.ProcessId, 57 | text, 58 | (FILETIME&)record->EventHeader.TimeStamp.QuadPart, 59 | DebugOutputFlags::Kernel); 60 | } 61 | }; 62 | m_hTrace = ::OpenTrace(&m_traceLog); 63 | if (!m_hTrace) 64 | return false; 65 | 66 | // create a dedicated thread to process the trace 67 | m_hThread.reset(::CreateThread(nullptr, 0, [](auto param) { 68 | return ((KernelModeDebugOutput*)param)->Process(); 69 | }, this, 0, nullptr)); 70 | ::SetThreadPriority(m_hThread.get(), THREAD_PRIORITY_HIGHEST); 71 | return true; 72 | } 73 | 74 | bool KernelModeDebugOutput::Stop() { 75 | if (m_handle) { 76 | ::ControlTrace(m_hTrace, KERNEL_LOGGER_NAME, m_properties, EVENT_TRACE_CONTROL_STOP); 77 | m_handle = 0; 78 | } 79 | if (m_hTrace) { 80 | ::CloseTrace(m_hTrace); 81 | m_hTrace = 0; 82 | } 83 | if (WAIT_TIMEOUT == ::WaitForSingleObject(m_hThread.get(), 1000)) 84 | DebugBreak(); 85 | m_hThread.reset(); 86 | return true; 87 | } 88 | 89 | bool KernelModeDebugOutput::IsRunning() const { 90 | return m_hTrace != 0; 91 | } 92 | 93 | DWORD KernelModeDebugOutput::Process() { 94 | FILETIME now; 95 | ::GetSystemTimeAsFileTime(&now); 96 | ::ProcessTrace(&m_hTrace, 1, &now, nullptr); 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /DbgPrint/Helpers.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "Helpers.h" 3 | #include "resource.h" 4 | #include 5 | #include 6 | 7 | #pragma comment(lib, "ntdll") 8 | 9 | static PCWSTR components[] = { 10 | L"SYSTEM", 11 | L"SMSS", 12 | L"SETUP", 13 | L"NTFS", 14 | L"FSTUB", 15 | L"CRASHDUMP", 16 | L"CDAUDIO", 17 | L"CDROM", 18 | L"CLASSPNP", 19 | L"DISK", 20 | L"REDBOOK", 21 | L"STORPROP", 22 | L"SCSIPORT", 23 | L"SCSIMINIPORT", 24 | L"CONFIG", 25 | L"I8042PRT", 26 | L"SERMOUSE", 27 | L"LSERMOUS", 28 | L"KBDHID", 29 | L"MOUHID", 30 | L"KBDCLASS", 31 | L"MOUCLASS", 32 | L"TWOTRACK", 33 | L"WMILIB", 34 | L"ACPI", 35 | L"AMLI", 36 | L"HALIA64", 37 | L"VIDEO", 38 | L"SVCHOST", 39 | L"VIDEOPRT", 40 | L"TCPIP", 41 | L"DMSYNTH", 42 | L"NTOSPNP", 43 | L"FASTFAT", 44 | L"SAMSS", 45 | L"PNPMGR", 46 | L"NETAPI", 47 | L"SCSERVER", 48 | L"SCCLIENT", 49 | L"SERIAL", 50 | L"SERENUM", 51 | L"UHCD", 52 | L"RPCPROXY", 53 | L"AUTOCHK", 54 | L"DCOMSS", 55 | L"UNIMODEM", 56 | L"SIS", 57 | L"FLTMGR", 58 | L"WMICORE", 59 | L"BURNENG", 60 | L"IMAPI", 61 | L"SXS", 62 | L"FUSION", 63 | L"IDLETASK", 64 | L"SOFTPCI", 65 | L"TAPE", 66 | L"MCHGR", 67 | L"IDEP", 68 | L"PCIIDE", 69 | L"FLOPPY", 70 | L"FDC", 71 | L"TERMSRV", 72 | L"W32TIME", 73 | L"PREFETCHER", 74 | L"RSFILTER", 75 | L"FCPORT", 76 | L"PCI", 77 | L"DMIO", 78 | L"DMCONFIG", 79 | L"DMADMIN", 80 | L"WSOCKTRANSPORT", 81 | L"VSS", 82 | L"PNPMEM", 83 | L"PROCESSOR", 84 | L"DMSERVER", 85 | L"SR", 86 | L"INFINIBAND", 87 | L"IHVDRIVER", 88 | L"IHVVIDEO", 89 | L"IHVAUDIO", 90 | L"IHVNETWORK", 91 | L"IHVSTREAMING", 92 | L"IHVBUS", 93 | L"HPS", 94 | L"RTLTHREADPOOL", 95 | L"LDR", 96 | L"TCPIP6", 97 | L"ISAPNP", 98 | L"SHPC", 99 | L"STORPORT", 100 | L"STORMINIPORT", 101 | L"PRINTSPOOLER", 102 | L"VSSDYNDISK", 103 | L"VERIFIER", 104 | L"VDS", 105 | L"VDSBAS", 106 | L"VDSDYN", 107 | L"VDSDYNDR", 108 | L"VDSLDR", 109 | L"VDSUTIL", 110 | L"DFRGIFC", 111 | L"DEFAULT", 112 | L"MM", 113 | L"DFSC", 114 | L"WOW64", 115 | L"ALPC", 116 | L"WDI", 117 | L"PERFLIB", 118 | L"KTM", 119 | L"IOSTRESS", 120 | L"HEAP", 121 | L"WHEA", 122 | L"USERGDI", 123 | L"MMCSS", 124 | L"TPM", 125 | L"THREADORDER", 126 | L"ENVIRON", 127 | L"EMS", 128 | L"WDT", 129 | L"FVEVOL", 130 | L"NDIS", 131 | L"NVCTRACE", 132 | L"LUAFV", 133 | L"APPCOMPAT", 134 | L"USBSTOR", 135 | L"SBP2PORT", 136 | L"COVERAGE", 137 | L"CACHEMGR", 138 | L"MOUNTMGR", 139 | L"CFR", 140 | L"TXF", 141 | L"KSECDD", 142 | L"FLTREGRESS", 143 | L"MPIO", 144 | L"MSDSM", 145 | L"UDFS", 146 | L"PSHED", 147 | L"STORVSP", 148 | L"LSASS", 149 | L"SSPICLI", 150 | L"CNG", 151 | L"EXFAT", 152 | L"FILETRACE", 153 | L"XSAVE", 154 | L"SE", 155 | L"DRIVEEXTENDER", 156 | L"POWER", 157 | L"CRASHDUMPXHCI", 158 | L"GPIO", 159 | L"REFS", 160 | L"WER", 161 | L"CAPIMG", 162 | L"VPCI", 163 | L"STORAGECLASSMEMORY", 164 | L"FSLIB", 165 | }; 166 | 167 | extern "C" NTSTATUS WINAPI NtSetDebugFilterState( 168 | ULONG ComponentId, 169 | ULONG Level, 170 | BOOLEAN State); 171 | 172 | extern "C" ULONG WINAPI NtQueryDebugFilterState( 173 | __in ULONG ComponentId, 174 | __in ULONG Level); 175 | 176 | void Helpers::ReportError(PCWSTR text, DWORD error) { 177 | PWSTR buffer; 178 | CString msg; 179 | if (::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 180 | nullptr, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buffer, 0, nullptr)) { 181 | msg = buffer; 182 | ::LocalFree(buffer); 183 | msg.Trim(L"\n\r"); 184 | } 185 | AtlMessageBox(nullptr, (PCWSTR)(text + msg), IDS_TITLE, MB_ICONERROR); 186 | } 187 | 188 | bool Helpers::EnableAllkernelOutput(bool enable) { 189 | for (int i = 0; i < _countof(components); i++) { 190 | auto status = NtSetDebugFilterState(i, 0xffffffff, enable); 191 | if (!NT_SUCCESS(status)) 192 | return false; 193 | } 194 | return true; 195 | } 196 | 197 | int Helpers::GetKernelComponentNames(PCWSTR*& names) { 198 | names = components; 199 | return _countof(components); 200 | } 201 | -------------------------------------------------------------------------------- /DbgPrint.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.31815.197 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DbgPrint", "DbgPrint\DbgPrint.vcxproj", "{06BA589B-5714-4A56-8CC2-B2D550CF4F3A}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WTLHelper", "WTLHelper\WTLHelper\WTLHelper.vcxproj", "{AE53419F-A769-4548-8E15-E311904DF7DF}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|ARM64 = Debug|ARM64 13 | Debug|x64 = Debug|x64 14 | Debug|x86 = Debug|x86 15 | Release|ARM64 = Release|ARM64 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | ReleaseSigned|ARM64 = ReleaseSigned|ARM64 19 | ReleaseSigned|x64 = ReleaseSigned|x64 20 | ReleaseSigned|x86 = ReleaseSigned|x86 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A}.Debug|ARM64.ActiveCfg = Debug|ARM64 24 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A}.Debug|ARM64.Build.0 = Debug|ARM64 25 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A}.Debug|x64.ActiveCfg = Debug|x64 26 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A}.Debug|x64.Build.0 = Debug|x64 27 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A}.Debug|x86.ActiveCfg = Debug|Win32 28 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A}.Debug|x86.Build.0 = Debug|Win32 29 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A}.Release|ARM64.ActiveCfg = Release|ARM64 30 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A}.Release|ARM64.Build.0 = Release|ARM64 31 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A}.Release|x64.ActiveCfg = Release|x64 32 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A}.Release|x64.Build.0 = Release|x64 33 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A}.Release|x86.ActiveCfg = Release|Win32 34 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A}.Release|x86.Build.0 = Release|Win32 35 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A}.ReleaseSigned|ARM64.ActiveCfg = ReleaseSigned|ARM64 36 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A}.ReleaseSigned|ARM64.Build.0 = ReleaseSigned|ARM64 37 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A}.ReleaseSigned|x64.ActiveCfg = ReleaseSigned|x64 38 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A}.ReleaseSigned|x64.Build.0 = ReleaseSigned|x64 39 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A}.ReleaseSigned|x86.ActiveCfg = ReleaseSigned|Win32 40 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A}.ReleaseSigned|x86.Build.0 = ReleaseSigned|Win32 41 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|ARM64.ActiveCfg = Debug|ARM64 42 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|ARM64.Build.0 = Debug|ARM64 43 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|x64.ActiveCfg = Debug|x64 44 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|x64.Build.0 = Debug|x64 45 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|x86.ActiveCfg = Debug|Win32 46 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Debug|x86.Build.0 = Debug|Win32 47 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|ARM64.ActiveCfg = Release|ARM64 48 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|ARM64.Build.0 = Release|ARM64 49 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|x64.ActiveCfg = Release|x64 50 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|x64.Build.0 = Release|x64 51 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|x86.ActiveCfg = Release|Win32 52 | {AE53419F-A769-4548-8E15-E311904DF7DF}.Release|x86.Build.0 = Release|Win32 53 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|ARM64.ActiveCfg = ReleaseSigned|ARM64 54 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|ARM64.Build.0 = ReleaseSigned|ARM64 55 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|x64.ActiveCfg = ReleaseSigned|x64 56 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|x64.Build.0 = ReleaseSigned|x64 57 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|x86.ActiveCfg = ReleaseSigned|Win32 58 | {AE53419F-A769-4548-8E15-E311904DF7DF}.ReleaseSigned|x86.Build.0 = ReleaseSigned|Win32 59 | EndGlobalSection 60 | GlobalSection(SolutionProperties) = preSolution 61 | HideSolutionNode = FALSE 62 | EndGlobalSection 63 | GlobalSection(ExtensibilityGlobals) = postSolution 64 | SolutionGuid = {EFD105FE-D212-42BD-8DD7-2FD145A59860} 65 | EndGlobalSection 66 | EndGlobal 67 | -------------------------------------------------------------------------------- /DbgPrint/ProcessManager.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "ProcessManager.h" 3 | #include 4 | #include 5 | 6 | PCWSTR ProcessManager::GetFullImagePath(DWORD pid) const { 7 | AddProcessIfNotExist(pid); 8 | { 9 | std::shared_lock locker(_lock); 10 | if (auto it = _processes.find(pid); it != _processes.end()) { 11 | auto& pi = it->second; 12 | return pi->FullPath.c_str(); 13 | } 14 | } 15 | return L""; 16 | } 17 | 18 | ProcessKey ProcessManager::GetProcessKey(DWORD pid) const { 19 | std::shared_lock locker(_lock); 20 | if (auto it = _processes.find(pid); it != _processes.end()) { 21 | return *it->second; 22 | } 23 | return ProcessKey{ pid }; 24 | } 25 | 26 | StaticProcessInfo* const ProcessManager::GetProcessInfo(ProcessKey const& key) const { 27 | std::shared_lock locker(_lock); 28 | if (auto it = _processesByKey.find(key); it != _processesByKey.end()) { 29 | return it->second.get(); 30 | } 31 | return nullptr; 32 | } 33 | 34 | std::vector ProcessManager::GetRuntimeProcesses() const { 35 | std::vector processes; 36 | processes.reserve(64); 37 | 38 | std::shared_lock locker(_lock); 39 | for (auto& [key, pi] : _processesByKey) { 40 | if ((pi->Flags & ProcessInfoFlags::FromFile) == ProcessInfoFlags::None) 41 | processes.push_back(pi.get()); 42 | } 43 | return processes; 44 | } 45 | 46 | std::wstring ProcessManager::GetProcessName(DWORD pid) const { 47 | AddProcessIfNotExist(pid); 48 | { 49 | std::shared_lock locker(_lock); 50 | if (auto it = _processes.find(pid); it != _processes.end()) { 51 | auto pi = it->second; 52 | return pi->Name; 53 | } 54 | } 55 | 56 | return L""; 57 | } 58 | 59 | ProcessManager::ProcessManager() { 60 | Init(); 61 | } 62 | 63 | bool ProcessManager::AddProcess(DWORD pid, PCWSTR name) const { 64 | auto info = std::make_shared(); 65 | auto hProcess = ::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | SYNCHRONIZE, FALSE, pid); 66 | WCHAR full[MAX_PATH]; 67 | if (hProcess) { 68 | DWORD len = _countof(full); 69 | if (::QueryFullProcessImageName(hProcess, 0, full, &len)) { 70 | info->FullPath = full; 71 | } 72 | FILETIME dummy; 73 | ::GetProcessTimes(hProcess, &info->StartTime, &dummy, &dummy, &dummy); 74 | info->hProcess.reset(hProcess); 75 | enum { 76 | ProcessCommandLineInformation = 60 77 | }; 78 | BYTE buffer[2048]; 79 | if (STATUS_SUCCESS == ::NtQueryInformationProcess(hProcess, (PROCESSINFOCLASS)ProcessCommandLineInformation, buffer, sizeof(buffer), nullptr)) { 80 | auto us = (UNICODE_STRING*)buffer; 81 | info->CommandLine = std::wstring(us->Buffer, us->Length / sizeof(WCHAR)); 82 | } 83 | } 84 | 85 | if (name == nullptr) { 86 | auto bs = info->FullPath.rfind(L'\\'); 87 | info->Name = bs == std::wstring::npos ? info->FullPath : info->FullPath.substr(bs + 1); 88 | } 89 | else { 90 | info->Name = name; 91 | } 92 | info->ProcessId = pid; 93 | { 94 | ProcessKey key{ pid, info->StartTime }; 95 | std::lock_guard locker(_lock); 96 | _processes.insert({ pid, info }); 97 | _processesByKey.insert({ key, std::move(info) }); 98 | } 99 | return hProcess != nullptr; 100 | } 101 | 102 | void ProcessManager::Init() { 103 | _processes.clear(); 104 | 105 | auto hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 106 | ATLASSERT(hSnapshot != INVALID_HANDLE_VALUE); 107 | if (hSnapshot == INVALID_HANDLE_VALUE) 108 | return; 109 | 110 | PROCESSENTRY32 pe; 111 | pe.dwSize = sizeof(pe); 112 | 113 | ::Process32First(hSnapshot, &pe); 114 | while (::Process32Next(hSnapshot, &pe)) { 115 | AddProcess(pe.th32ProcessID, pe.szExeFile); 116 | } 117 | ::CloseHandle(hSnapshot); 118 | } 119 | 120 | void ProcessManager::AddProcessIfNotExist(DWORD pid) const { 121 | { 122 | std::shared_lock locker(_lock); 123 | if (auto it = _processes.find(pid); it != _processes.end()) { 124 | auto& pi = *it->second; 125 | if (pi.hProcess && ::WaitForSingleObject(pi.hProcess.get(), 0) == WAIT_TIMEOUT) 126 | return; 127 | locker.unlock(); 128 | std::lock_guard locker(_lock); 129 | _processes.erase(pid); 130 | } 131 | } 132 | AddProcess(pid); 133 | } 134 | 135 | void ProcessManager::AddProcess(std::shared_ptr& pi) const { 136 | std::lock_guard locker(_lock); 137 | _processesByKey.insert({ *pi, std::move(pi) }); 138 | } 139 | 140 | void ProcessManager::AddProcessesNoLock(std::span> const& processes) { 141 | for(auto& pi : processes) 142 | _processesByKey.insert({ *pi, std::move(pi) }); 143 | } 144 | -------------------------------------------------------------------------------- /DbgPrint/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by DbgPrint.rc 4 | // 5 | #define IDD_ABOUTBOX 100 6 | #define IDR_MAINFRAME 128 7 | #define IDS_TITLE 129 8 | #define IDI_AUTOSCROLL 201 9 | #define IDI_DELETE 202 10 | #define IDI_COPY 203 11 | #define IDI_FILTER 204 12 | #define IDI_FIND 205 13 | #define IDI_KERNEL 206 14 | #define IDI_OK 207 15 | #define IDI_PLAY 208 16 | #define IDI_SAVEAS 209 17 | #define IDI_STOP 210 18 | #define IDI_SCRIPT_FILE 211 19 | #define IDI_SCRIPT 212 20 | #define IDI_CANCEL 213 21 | #define IDI_OPEN 214 22 | #define IDI_USER 215 23 | #define IDI_USER0 216 24 | #define IDI_ATOM 217 25 | #define IDR_CONTEXT 218 26 | #define IDI_ERASE 219 27 | #define IDI_USERMODE 220 28 | #define IDD_PROPERTIES 221 29 | #define IDD_COMMENT 223 30 | #define IDI_COMMENT 225 31 | #define IDI_BOOKMARK 226 32 | #define IDI_BOOKMARK_NEXT 227 33 | #define IDI_BOOKMARK_PREV 228 34 | #define IDD_HIGHLIGHT 229 35 | #define IDI_ICON1 231 36 | #define IDI_FIND_NEXT 231 37 | #define IDC_PID 1000 38 | #define IDC_NAME 1001 39 | #define IDC_PATH 1002 40 | #define IDC_TEXT 1003 41 | #define IDC_COMMENT 1004 42 | #define IDC_INDEX 1005 43 | #define IDC_TIME 1006 44 | #define IDC_CMDLINE 1007 45 | #define IDC_LINK 1008 46 | #define IDC_VERSION 1009 47 | #define IDC_COPYRIGHT 1010 48 | #define IDC_LIST 1011 49 | #define IDC_COLOR 1013 50 | #define IDC_SAVE 1015 51 | #define IDC_LOAD 1016 52 | #define IDC_RESET 1017 53 | #define IDC_ADD 1018 54 | #define IDC_DELETE 1019 55 | #define ID_FILE_RUNASADMINISTRATOR 32775 56 | #define ID_OPTIONS_ALWAYSONTOP 32776 57 | #define ID_OPTIONS_FONTS 32777 58 | #define ID_CAPTURE_CAPTUREUSERMODE 32778 59 | #define ID_CAPTURE_CAPTUREKERNEL 32780 60 | #define ID_CAPTURE_CAPTURESESSION0 32781 61 | #define ID_CAPTURE_CAPTUREOUTPUT 32782 62 | #define ID_VIEW_AUTOSCROLL 32783 63 | #define ID_OPTIONS_DARKMODE 32784 64 | #define ID_EDIT_COMMENT 32786 65 | #define ID_VIEW_PROPERTIES 32787 66 | #define ID_FILE_SAVEASTEXT 32788 67 | #define ID_SEARCH_FIND 32789 68 | #define ID_SEARCH_QUICKFIND 32790 69 | #define ID_KERNEL_COMPONENTS 32791 70 | #define ID_KERNEL_ENABLEALLCOMPONENTS 32792 71 | #define ID_KERNEL_DISABLEALLCOMPONENTS 32793 72 | #define ID_WINDOWS_CLOSE 32794 73 | #define ID_WINDOWS_CLOSEALL 32795 74 | #define ID_EDIT_CLEARALL 32796 75 | #define ID_OPTIONS_CONFIRMDELETE 32797 76 | #define ID_EDIT_BOOKMARK 32801 77 | #define ID_OPTIONS_BOOKMARKCOLOR 32802 78 | #define ID_EDIT_DELETEALLBOOKMARKS 32803 79 | #define ID_VIEW_NEXTBOOKMARK 32804 80 | #define ID_VIEW_PREVIOUSBOOKMARK 32805 81 | #define ID_VIEW_FIRSTBOOKMARK 32806 82 | #define ID_VIEW_LASTBOOKMARK 32807 83 | #define ID_EDIT_HIGHLIGHT 32808 84 | #define ID_HIGHLIGHT_REMOVEHIGHLIGHT 32809 85 | #define ID_FILE_NEWREAL 32810 86 | #define ID_FILE_NEWREALTIME 32811 87 | #define ID_SEARCH_FILTER 32812 88 | #define ID_EDIT_HIGHLIGHT32813 32813 89 | #define ID_SEARCH_FINDNEXT 32816 90 | 91 | // Next default values for new objects 92 | // 93 | #ifdef APSTUDIO_INVOKED 94 | #ifndef APSTUDIO_READONLY_SYMBOLS 95 | #define _APS_NEXT_RESOURCE_VALUE 232 96 | #define _APS_NEXT_COMMAND_VALUE 32819 97 | #define _APS_NEXT_CONTROL_VALUE 1020 98 | #define _APS_NEXT_SYMED_VALUE 101 99 | #endif 100 | #endif 101 | -------------------------------------------------------------------------------- /DbgPrint/DebugLogPersist.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "DebugLogPersist.h" 3 | #include 4 | #include "DebugOutputBase.h" 5 | #include "Interfaces.h" 6 | #include 7 | #include 8 | #include "ProcessManager.h" 9 | #include "ImageIconCache.h" 10 | 11 | bool DebugLogPersist::Save(PersistFormat format, std::vector> const& items, ImageIconCache const& iconCache, ProcessManager const& pm, std::wstring_view path) { 12 | return format == PersistFormat::Native ? SaveNative(items, iconCache, pm, path) : SaveCSV(items, path); 13 | } 14 | 15 | bool DebugLogPersist::Load(std::wstring_view path, std::vector>& items, ProcessManager& pm) { 16 | using namespace StructuredStorage; 17 | 18 | auto file = CompoundFile::Open(path.data()); 19 | if (!file) 20 | return false; 21 | 22 | DWORD count; 23 | OpenFileAndRead(file, L"Count", count); 24 | items.reserve(count + items.size()); 25 | 26 | for (DWORD i = 0; i < count; i++) { 27 | auto dir = file.OpenStructuredDirectory(std::to_wstring(i)); 28 | if (!dir) 29 | break; 30 | 31 | auto item = std::make_shared(); 32 | if (!item) 33 | break; 34 | OpenFileAndRead(dir, L"Index", item->Index); 35 | OpenFileAndRead(dir, L"ProcessName", item->ProcessName); 36 | OpenFileAndRead(dir, L"ProcessKey", item->Process); 37 | OpenFileAndRead(dir, L"Time", item->SystemTime); 38 | OpenFileAndRead(dir, L"Text", item->Text); 39 | OpenFileAndRead(dir, L"Comment", item->Comment); 40 | OpenFileAndRead(dir, L"Flags", item->Flags); 41 | OpenFileAndRead(dir, L"Image", item->Image); 42 | 43 | items.push_back(item); 44 | } 45 | OpenFileAndRead(file, L"ProcessCount", count); 46 | auto pdir = file.OpenStructuredDirectory(L"Processes"); 47 | 48 | std::vector> processes; 49 | processes.reserve(count); 50 | for (DWORD i = 0; i < count; i++) { 51 | auto pidir = pdir.OpenStructuredDirectory(std::to_wstring(i)); 52 | auto pi = std::make_shared(); 53 | OpenFileAndRead(pidir, L"Name", pi->Name); 54 | OpenFileAndRead(pidir, L"FullPath", pi->FullPath); 55 | OpenFileAndRead(pidir, L"CommandLine", pi->CommandLine); 56 | OpenFileAndRead(pidir, L"Session", pi->SessionId); 57 | OpenFileAndRead(pidir, L"StartTime", pi->StartTime); 58 | OpenFileAndRead(pidir, L"ProcessId", pi->ProcessId); 59 | OpenFileAndRead(pidir, L"Flags", pi->Flags); 60 | processes.push_back(std::move(pi)); 61 | } 62 | pm.AddProcessesNoLock(processes); 63 | return true; 64 | } 65 | 66 | bool DebugLogPersist::SaveCSV(std::vector> const& items, std::wstring_view path) { 67 | std::wofstream stm; 68 | stm.open(path.data(), std::ios_base::out); 69 | if (!stm) 70 | return false; 71 | 72 | for (auto const& item : items) { 73 | stm << item->Index << "," << *(uint64_t*)&item->SystemTime << "," << (PCWSTR)item->LocalTimeAsString << "," 74 | << item->ProcessName << "," << item->Process << "," << (DWORD)item->Flags << "," 75 | << item->Text << "," << item->Text << "\n"; 76 | } 77 | return true; 78 | } 79 | 80 | bool DebugLogPersist::SaveNative(std::vector> const& items, ImageIconCache const& iconCache, ProcessManager const& pm, std::wstring_view path) { 81 | using namespace StructuredStorage; 82 | 83 | auto file = CompoundFile::Create(path.data()); 84 | if(!file) 85 | return false; 86 | 87 | CreateFileAndWrite(file, L"Count", (DWORD)items.size()); 88 | int i = 0; 89 | for (auto const& item : items) { 90 | auto dir = file.CreateStructuredDirectory(std::to_wstring(i++)); 91 | if (!dir) 92 | return false; 93 | 94 | CreateFileAndWrite(dir, L"Index", item->Index); 95 | CreateFileAndWrite(dir, L"ProcessName", item->ProcessName); 96 | CreateFileAndWrite(dir, L"ProcessKey", item->Process); 97 | CreateFileAndWrite(dir, L"Time", item->SystemTime); 98 | CreateFileAndWrite(dir, L"Text", item->Text); 99 | CreateFileAndWrite(dir, L"Image", item->Image); 100 | CreateFileAndWrite(dir, L"Comment", item->Comment); 101 | CreateFileAndWrite(dir, L"Flags", item->Flags); 102 | } 103 | 104 | auto images = file.CreateStructuredFile(L"ImageList"); 105 | CImageList il(iconCache.GetImageList()); 106 | il.Write(images); 107 | 108 | // 109 | // save process information 110 | // 111 | auto dir = file.CreateStructuredDirectory(L"Processes"); 112 | 113 | i = 0; 114 | auto processes = pm.GetRuntimeProcesses(); 115 | CreateFileAndWrite(dir, L"ProcessCount", (ULONG)processes.size()); 116 | 117 | for (auto& pi : processes) { 118 | auto pdir = dir.CreateStructuredDirectory(std::to_wstring(i++)); 119 | CreateFileAndWrite(pdir, L"Name", pi->Name); 120 | CreateFileAndWrite(pdir, L"FullPath", pi->FullPath); 121 | CreateFileAndWrite(pdir, L"CommandLine", pi->CommandLine); 122 | CreateFileAndWrite(pdir, L"Session", pi->SessionId); 123 | CreateFileAndWrite(pdir, L"StartTime", pi->StartTime); 124 | CreateFileAndWrite(pdir, L"ProcessId", pi->ProcessId); 125 | CreateFileAndWrite(pdir, L"Flags", pi->Flags); 126 | } 127 | 128 | return true; 129 | } 130 | -------------------------------------------------------------------------------- /DbgPrint/DebugView.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "VirtualListView.h" 4 | #include "UserModeDebugOutput.h" 5 | #include "KernelModeDebugOutput.h" 6 | #include "resource.h" 7 | #include 8 | #include "Interfaces.h" 9 | #include "ImageIconCache.h" 10 | #include "ProcessManager.h" 11 | #include 12 | 13 | class CDebugView : 14 | public CFrameWindowImpl, 15 | public IDebugOutput, 16 | public CVirtualListView, 17 | public CCustomDraw { 18 | public: 19 | using BaseFrame = CFrameWindowImpl; 20 | 21 | CDebugView(IMainFrame* frame, bool realTime = true); 22 | 23 | CString GetColumnText(HWND, int row, int col) const; 24 | PCWSTR GetExistingColumnText(HWND, int row, int col) const; 25 | bool IsSortable(HWND, int col) const; 26 | BOOL OnDoubleClickList(HWND, int row, int col, POINT const& pt); 27 | BOOL OnRightClickList(HWND, int row, int col, POINT const&); 28 | DWORD OnPrePaint(DWORD, LPNMCUSTOMDRAW cd); 29 | DWORD OnItemPrePaint(DWORD, LPNMCUSTOMDRAW cd); 30 | 31 | bool CanClose(); 32 | bool IsRealTime() const; 33 | bool IsEmpty() const; 34 | 35 | int GetRowImage(HWND, int row, int col) const; 36 | void DoSort(SortInfo const*); 37 | void Capture(bool capture); 38 | void CaptureKernel(bool capture); 39 | void CaptureUser(bool capture); 40 | void CaptureSession0(bool capture); 41 | 42 | void UpdateUI(CUpdateUIBase* ui); 43 | 44 | void DebugOutput(DWORD pid, PCSTR text, FILETIME const&, DebugOutputFlags flags) override; 45 | 46 | protected: 47 | BEGIN_MSG_MAP(CDebugView) 48 | MESSAGE_HANDLER(WM_TIMER, OnTimer) 49 | NOTIFY_CODE_HANDLER(LVN_ITEMCHANGED, OnItemChanged) 50 | MESSAGE_HANDLER(WM_CREATE, OnCreate) 51 | MESSAGE_HANDLER(CFindReplaceDialog::GetFindReplaceMsg(), OnFind) 52 | MESSAGE_HANDLER(WM_DESTROY, OnDestroy) 53 | MESSAGE_HANDLER(WM_SETFONT, OnSetFont) 54 | CHAIN_MSG_MAP(CVirtualListView) 55 | CHAIN_MSG_MAP(CCustomDraw) 56 | CHAIN_MSG_MAP(BaseFrame) 57 | ALT_MSG_MAP(1) 58 | COMMAND_ID_HANDLER(ID_SEARCH_FINDNEXT, OnFindNext) 59 | COMMAND_ID_HANDLER(ID_EDIT_COPY, OnEditCopy) 60 | COMMAND_ID_HANDLER(ID_VIEW_PROPERTIES, OnProperties) 61 | COMMAND_ID_HANDLER(ID_EDIT_DELETE, OnEditDelete) 62 | COMMAND_ID_HANDLER(ID_EDIT_COMMENT, OnEditComment) 63 | COMMAND_ID_HANDLER(ID_EDIT_CLEAR_ALL, OnEditClearAll) 64 | COMMAND_ID_HANDLER(ID_EDIT_BOOKMARK, OnToggleBookmark) 65 | COMMAND_ID_HANDLER(ID_VIEW_NEXTBOOKMARK, OnNextBookmark) 66 | COMMAND_ID_HANDLER(ID_VIEW_PREVIOUSBOOKMARK, OnPrevBookmark) 67 | COMMAND_ID_HANDLER(ID_EDIT_DELETEALLBOOKMARKS, OnDeleteAllBookmarks) 68 | COMMAND_ID_HANDLER(ID_FILE_SAVEASTEXT, OnSaveAsText) 69 | COMMAND_ID_HANDLER(ID_FILE_SAVE, OnSave) 70 | COMMAND_ID_HANDLER(ID_EDIT_HIGHLIGHT, OnHighlight) 71 | END_MSG_MAP() 72 | 73 | enum class ColumnType { 74 | ProcessId, Time, Index, Text, ProcessName, Comment 75 | }; 76 | 77 | private: 78 | void UpdateList(); 79 | void ShowProperties(int row); 80 | 81 | LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 82 | LRESULT OnTimer(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 83 | LRESULT OnFind(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 84 | LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 85 | LRESULT OnEditCopy(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 86 | LRESULT OnSetFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 87 | LRESULT OnSaveAsText(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 88 | LRESULT OnProperties(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 89 | LRESULT OnItemChanged(int /*idCtrl*/, LPNMHDR hdr, BOOL& /*bHandled*/); 90 | LRESULT OnEditDelete(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 91 | LRESULT OnEditComment(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 92 | LRESULT OnEditClearAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 93 | LRESULT OnToggleBookmark(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 94 | LRESULT OnNextBookmark(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 95 | LRESULT OnPrevBookmark(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 96 | LRESULT OnDeleteAllBookmarks(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 97 | LRESULT OnSave(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 98 | LRESULT OnHighlight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 99 | LRESULT OnFindNext(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 100 | 101 | CListViewCtrl m_List; 102 | SortedFilteredVector> m_Items, m_TempItems; 103 | std::mutex m_Lock; 104 | UserModeDebugOutput m_UserMode; 105 | UserModeDebugOutput m_UserModeSession0{ L"Global" }; 106 | KernelModeDebugOutput m_KernelMode; 107 | inline static ULONG s_Index; 108 | CUpdateUIBase* m_ui{ nullptr }; 109 | IMainFrame* m_pFrame; 110 | std::atomic m_Running{ false }; 111 | ImageIconCache m_IconCache; 112 | ProcessManager m_pm; 113 | std::vector m_Highlights; 114 | bool m_RealTime; 115 | }; 116 | 117 | -------------------------------------------------------------------------------- /DbgPrint/MainFrm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "OwnerDrawnMenu.h" 4 | #include "DebugView.h" 5 | #include "Interfaces.h" 6 | #include 7 | #include 8 | 9 | class CMainFrame : 10 | public CFrameWindowImpl, 11 | public COwnerDrawnMenu, 12 | public CAutoUpdateUI, 13 | public IMainFrame, 14 | public CMessageFilter, 15 | public CIdleHandler 16 | { 17 | public: 18 | DECLARE_FRAME_WND_CLASS(L"DebugPrintMainWindowClass", IDR_MAINFRAME) 19 | 20 | virtual BOOL PreTranslateMessage(MSG* pMsg); 21 | virtual BOOL OnIdle(); 22 | 23 | BOOL TrackPopupMenu(HMENU hMenu, DWORD flags, int x, int y, HWND hWnd) override; 24 | CFindReplaceDialog* GetFindDlg() override; 25 | CString& GetSearchString() override; 26 | 27 | protected: 28 | BEGIN_MSG_MAP(CMainFrame) 29 | if (uMsg == WM_COMMAND && m_Tabs.GetPageCount() > 0) { 30 | int page = m_Tabs.GetActivePage(); 31 | if (page >= 0) { 32 | auto view = (CDebugView*)m_Tabs.GetPageData(page); 33 | if (view->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, 1)) 34 | break; 35 | } 36 | } 37 | NOTIFY_CODE_HANDLER(TBVN_PAGEACTIVATED, OnPageActivated) 38 | //NOTIFY_CODE_HANDLER(TBVN_CONTEXTMENU, OnPageActivated) 39 | COMMAND_ID_HANDLER(ID_FILE_RUNASADMINISTRATOR, OnRunAsAdmin) 40 | COMMAND_ID_HANDLER(ID_OPTIONS_ALWAYSONTOP, OnAlwaysOnTop) 41 | COMMAND_ID_HANDLER(ID_CAPTURE_CAPTUREOUTPUT, OnCapture) 42 | COMMAND_ID_HANDLER(ID_CAPTURE_CAPTUREUSERMODE, OnCaptureUser) 43 | COMMAND_ID_HANDLER(ID_CAPTURE_CAPTURESESSION0, OnCaptureUserSession0) 44 | COMMAND_ID_HANDLER(ID_CAPTURE_CAPTUREKERNEL, OnCaptureKernel) 45 | COMMAND_ID_HANDLER(ID_VIEW_AUTOSCROLL, OnAutoScroll) 46 | MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect) 47 | MESSAGE_HANDLER(CFindReplaceDialog::GetFindReplaceMsg(), OnFind) 48 | COMMAND_ID_HANDLER(ID_KERNEL_ENABLEALLCOMPONENTS, OnEnableKernelComponents) 49 | COMMAND_ID_HANDLER(ID_KERNEL_DISABLEALLCOMPONENTS, OnEnableKernelComponents) 50 | COMMAND_ID_HANDLER(ID_WINDOWS_CLOSE, OnTabClose) 51 | COMMAND_ID_HANDLER(ID_WINDOWS_CLOSEALL, OnTabCloseAll) 52 | COMMAND_ID_HANDLER(ID_SEARCH_FIND, OnSearchFind) 53 | COMMAND_ID_HANDLER(ID_OPTIONS_DARKMODE, OnDarkMode) 54 | COMMAND_ID_HANDLER(ID_FILE_NEWREALTIME, OnNewRealTimeLog) 55 | COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit) 56 | COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar) 57 | COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar) 58 | COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout) 59 | COMMAND_ID_HANDLER(ID_OPTIONS_CONFIRMDELETE, OnConfirmErase) 60 | MESSAGE_HANDLER(WM_CREATE, OnCreate) 61 | MESSAGE_HANDLER(WM_DESTROY, OnDestroy) 62 | CHAIN_MSG_MAP(CAutoUpdateUI) 63 | CHAIN_MSG_MAP(CFrameWindowImpl) 64 | CHAIN_MSG_MAP(COwnerDrawnMenu) 65 | REFLECT_NOTIFICATIONS_EX() 66 | END_MSG_MAP() 67 | 68 | private: 69 | void SetAlwaysOnTop(bool alwaysOnTop); 70 | void InitMenu(); 71 | void InitToolBar(CToolBarCtrl& tb) const; 72 | void UpdateUI(); 73 | CDebugView* CreateDebugOutputView(PCWSTR name); 74 | void InitDarkTheme(); 75 | void SetDarkMode(bool dark); 76 | 77 | // Handler prototypes (uncomment arguments if needed): 78 | // LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) 79 | // LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) 80 | // LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) 81 | 82 | LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 83 | LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled); 84 | LRESULT OnMenuSelect(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) const; 85 | LRESULT OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 86 | LRESULT OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 87 | LRESULT OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 88 | LRESULT OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) const; 89 | LRESULT OnAlwaysOnTop(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 90 | LRESULT OnFileSave(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 91 | LRESULT OnEditFind(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 92 | LRESULT OnViewHighlight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 93 | LRESULT OnCapture(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 94 | LRESULT OnCaptureUser(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 95 | LRESULT OnCaptureUserSession0(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 96 | LRESULT OnCaptureKernel(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 97 | LRESULT OnRunAsAdmin(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 98 | LRESULT OnPageActivated(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/); 99 | LRESULT OnAutoScroll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 100 | LRESULT OnEnableKernelComponents(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 101 | LRESULT OnTabClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 102 | LRESULT OnTabCloseAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 103 | LRESULT OnDarkMode(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 104 | LRESULT OnConfirmErase(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 105 | LRESULT OnNewRealTimeLog(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 106 | LRESULT OnSearchFind(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/); 107 | LRESULT OnFind(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/); 108 | 109 | CCustomTabView m_Tabs; 110 | CDebugView* m_pActiveView; 111 | CFont m_Font; 112 | Theme m_DarkTheme, m_DefaultTheme{ true }; 113 | CFindReplaceDialog* m_pFindDlg{ nullptr }; 114 | CString m_SearchText; 115 | }; 116 | -------------------------------------------------------------------------------- /.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 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Oo]ut/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio LightSwitch build output 298 | **/*.HTMLClient/GeneratedArtifacts 299 | **/*.DesktopClient/GeneratedArtifacts 300 | **/*.DesktopClient/ModelManifest.xml 301 | **/*.Server/GeneratedArtifacts 302 | **/*.Server/ModelManifest.xml 303 | _Pvt_Extensions 304 | 305 | # Paket dependency manager 306 | .paket/paket.exe 307 | paket-files/ 308 | 309 | # FAKE - F# Make 310 | .fake/ 311 | 312 | # CodeRush personal settings 313 | .cr/personal 314 | 315 | # Python Tools for Visual Studio (PTVS) 316 | __pycache__/ 317 | *.pyc 318 | 319 | # Cake - Uncomment if you are using it 320 | # tools/** 321 | # !tools/packages.config 322 | 323 | # Tabs Studio 324 | *.tss 325 | 326 | # Telerik's JustMock configuration file 327 | *.jmconfig 328 | 329 | # BizTalk build output 330 | *.btp.cs 331 | *.btm.cs 332 | *.odx.cs 333 | *.xsd.cs 334 | 335 | # OpenCover UI analysis results 336 | OpenCover/ 337 | 338 | # Azure Stream Analytics local run output 339 | ASALocalRun/ 340 | 341 | # MSBuild Binary and Structured Log 342 | *.binlog 343 | 344 | # NVidia Nsight GPU debugger configuration file 345 | *.nvuser 346 | 347 | # MFractors (Xamarin productivity tool) working folder 348 | .mfractor/ 349 | 350 | # Local History for Visual Studio 351 | .localhistory/ 352 | 353 | # BeatPulse healthcheck temp database 354 | healthchecksdb 355 | 356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 357 | MigrationBackup/ 358 | 359 | # Ionide (cross platform F# VS Code tools) working folder 360 | .ionide/ 361 | 362 | # Fody - auto-generated XML schema 363 | FodyWeavers.xsd -------------------------------------------------------------------------------- /DbgPrint/DbgPrint.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {8e3f7268-3d41-49b9-a590-e87b3f8fdaa6} 6 | cpp;c;cxx;def;odl;idl;hpj;bat;asm 7 | 8 | 9 | {15a85e42-7a72-4732-83aa-5c0b223d7b64} 10 | h;hpp;hxx;hm;inl;inc 11 | 12 | 13 | {a8ca7910-aee7-40da-a9bf-2d9cac481452} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;jpg;jpeg;jpe;manifest 15 | 16 | 17 | {c6f711aa-1c14-4907-bc95-ac76007e4f70} 18 | 19 | 20 | {05fd5740-3db0-4db9-9320-60cfe26af4be} 21 | 22 | 23 | {1588d934-6c0c-413b-aed1-0e05d76865ae} 24 | 25 | 26 | {ee4c9a95-06fc-4baa-983a-da8286275dba} 27 | 28 | 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Helpers 47 | 48 | 49 | Source Files 50 | 51 | 52 | Source Files 53 | 54 | 55 | Helpers 56 | 57 | 58 | Helpers 59 | 60 | 61 | Source Files 62 | 63 | 64 | Dialogs 65 | 66 | 67 | Dialogs 68 | 69 | 70 | Dialogs 71 | 72 | 73 | Views 74 | 75 | 76 | Source Files 77 | 78 | 79 | Source Files 80 | 81 | 82 | Dialogs 83 | 84 | 85 | 86 | 87 | Header Files 88 | 89 | 90 | Header Files 91 | 92 | 93 | Header Files 94 | 95 | 96 | Header Files 97 | 98 | 99 | Header Files 100 | 101 | 102 | Resource Files 103 | 104 | 105 | Helpers 106 | 107 | 108 | Header Files 109 | 110 | 111 | Header Files 112 | 113 | 114 | Helpers 115 | 116 | 117 | Helpers 118 | 119 | 120 | Dialogs 121 | 122 | 123 | Dialogs 124 | 125 | 126 | Header Files 127 | 128 | 129 | Dialogs 130 | 131 | 132 | Views 133 | 134 | 135 | Header Files 136 | 137 | 138 | Dialogs 139 | 140 | 141 | 142 | 143 | Resource Files\Icons 144 | 145 | 146 | Resource Files\Icons 147 | 148 | 149 | Resource Files\Icons 150 | 151 | 152 | Resource Files\Icons 153 | 154 | 155 | Resource Files\Icons 156 | 157 | 158 | Resource Files\Icons 159 | 160 | 161 | Resource Files\Icons 162 | 163 | 164 | Resource Files\Icons 165 | 166 | 167 | Resource Files\Icons 168 | 169 | 170 | Resource Files\Icons 171 | 172 | 173 | Resource Files\Icons 174 | 175 | 176 | Resource Files\Icons 177 | 178 | 179 | Resource Files\Icons 180 | 181 | 182 | Resource Files\Icons 183 | 184 | 185 | Resource Files\Icons 186 | 187 | 188 | Resource Files\Icons 189 | 190 | 191 | Resource Files\Icons 192 | 193 | 194 | Resource Files\Icons 195 | 196 | 197 | Resource Files\Icons 198 | 199 | 200 | Resource Files\Icons 201 | 202 | 203 | Resource Files\Icons 204 | 205 | 206 | Resource Files\Icons 207 | 208 | 209 | Resource Files\Icons 210 | 211 | 212 | Resource Files\Icons 213 | 214 | 215 | 216 | 217 | Resource Files 218 | 219 | 220 | 221 | 222 | 223 | -------------------------------------------------------------------------------- /DbgPrint/MainFrm.cpp: -------------------------------------------------------------------------------- 1 | // MainFrm.cpp : implmentation of the CMainFrame class 2 | // 3 | ///////////////////////////////////////////////////////////////////////////// 4 | 5 | #include "pch.h" 6 | #include "resource.h" 7 | #include "AboutDlg.h" 8 | #include "MainFrm.h" 9 | #include "IconHelper.h" 10 | #include "SecurityHelper.h" 11 | #include "AppSettings.h" 12 | #include "Helpers.h" 13 | #include 14 | 15 | BOOL CMainFrame::PreTranslateMessage(MSG* pMsg) { 16 | if (m_pFindDlg && m_pFindDlg->IsDialogMessageW(pMsg)) 17 | return TRUE; 18 | 19 | return CFrameWindowImpl::PreTranslateMessage(pMsg); 20 | } 21 | 22 | BOOL CMainFrame::OnIdle() { 23 | UIUpdateToolBar(); 24 | return FALSE; 25 | } 26 | 27 | void CMainFrame::InitMenu() { 28 | AddMenu(GetMenu()); 29 | struct { 30 | UINT id, icon; 31 | HICON hIcon = nullptr; 32 | } cmds[] = { 33 | { ID_FILE_RUNASADMINISTRATOR, 0, IconHelper::GetShieldIcon() }, 34 | { ID_EDIT_COPY, IDI_COPY }, 35 | { ID_SEARCH_FIND, IDI_FIND }, 36 | { ID_CAPTURE_CAPTUREOUTPUT, IDI_PLAY }, 37 | { ID_CAPTURE_CAPTUREUSERMODE, IDI_USER }, 38 | { ID_CAPTURE_CAPTURESESSION0, IDI_USER0 }, 39 | { ID_CAPTURE_CAPTUREKERNEL, IDI_ATOM }, 40 | { ID_FILE_SAVE, IDI_SAVEAS }, 41 | { ID_FILE_OPEN, IDI_OPEN }, 42 | { ID_VIEW_AUTOSCROLL, IDI_AUTOSCROLL }, 43 | { ID_EDIT_DELETE, IDI_CANCEL }, 44 | { ID_EDIT_CLEAR_ALL, IDI_ERASE }, 45 | { ID_EDIT_COMMENT, IDI_COMMENT }, 46 | { ID_EDIT_BOOKMARK, IDI_BOOKMARK }, 47 | { ID_VIEW_NEXTBOOKMARK, IDI_BOOKMARK_NEXT }, 48 | { ID_VIEW_PREVIOUSBOOKMARK, IDI_BOOKMARK_PREV }, 49 | }; 50 | for (auto& cmd : cmds) { 51 | if (cmd.icon) 52 | AddCommand(cmd.id, cmd.icon); 53 | else 54 | AddCommand(cmd.id, cmd.hIcon); 55 | } 56 | } 57 | 58 | void CMainFrame::InitToolBar(CToolBarCtrl& tb) const { 59 | const int size = 24; 60 | CImageList tbImages; 61 | tbImages.Create(size, size, ILC_COLOR32, 8, 4); 62 | tb.SetImageList(tbImages); 63 | 64 | const struct { 65 | UINT id; 66 | int image; 67 | BYTE style = BTNS_BUTTON; 68 | PCWSTR text = nullptr; 69 | } buttons[] = { 70 | { ID_EDIT_COPY, IDI_COPY }, 71 | { 0 }, 72 | { ID_CAPTURE_CAPTUREOUTPUT, IDI_PLAY }, 73 | { ID_VIEW_AUTOSCROLL, IDI_AUTOSCROLL }, 74 | { 0 }, 75 | { ID_CAPTURE_CAPTUREUSERMODE, IDI_USER }, 76 | { ID_CAPTURE_CAPTURESESSION0, IDI_USER0 }, 77 | { 0 }, 78 | { ID_CAPTURE_CAPTUREKERNEL, IDI_ATOM }, 79 | { 0 }, 80 | { ID_EDIT_CLEAR_ALL, IDI_ERASE }, 81 | { 0 }, 82 | { ID_EDIT_BOOKMARK, IDI_BOOKMARK }, 83 | { ID_VIEW_PREVIOUSBOOKMARK, IDI_BOOKMARK_PREV }, 84 | { ID_VIEW_NEXTBOOKMARK, IDI_BOOKMARK_NEXT }, 85 | { 0 }, 86 | { ID_SEARCH_FIND, IDI_FIND }, 87 | { ID_SEARCH_FINDNEXT, IDI_FIND_NEXT }, 88 | }; 89 | for (auto& b : buttons) { 90 | if (b.id == 0) 91 | tb.AddSeparator(0); 92 | else { 93 | auto hIcon = AtlLoadIconImage(b.image, 0, size, size); 94 | ATLASSERT(hIcon); 95 | int image = tbImages.AddIcon(hIcon); 96 | tb.AddButton(b.id, b.style, TBSTATE_ENABLED, image, b.text, 0); 97 | } 98 | } 99 | } 100 | 101 | LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { 102 | InitDarkTheme(); 103 | if (SecurityHelper::IsRunningElevated()) { 104 | CMenuHandle menu(GetMenu()); 105 | menu.GetSubMenu(0).DeleteMenu(0, MF_BYPOSITION); 106 | menu.GetSubMenu(0).DeleteMenu(0, MF_BYPOSITION); 107 | } 108 | SetCheckIcon(AtlLoadIconImage(IDI_OK)); 109 | 110 | auto& settings = AppSettings::Get(); 111 | settings.LoadFromKey(L"Software\\ScorpioSoftware\\DbgPrint"); 112 | 113 | auto font = settings.Font(); 114 | if (font.lfHeight == 0) 115 | m_Font.CreatePointFont(100, L"Segoe UI"); 116 | else 117 | m_Font.CreateFontIndirect(&font); 118 | 119 | InitMenu(); 120 | UIAddMenu(GetMenu()); 121 | 122 | CToolBarCtrl tb; 123 | tb.Create(m_hWnd, nullptr, nullptr, ATL_SIMPLE_TOOLBAR_PANE_STYLE, 0, ATL_IDW_TOOLBAR); 124 | InitToolBar(tb); 125 | 126 | CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE); 127 | AddSimpleReBarBand(tb); 128 | 129 | CreateSimpleStatusBar(); 130 | 131 | UIAddToolBar(tb); 132 | 133 | UISetCheck(ID_VIEW_TOOLBAR, settings.ViewToolBar()); 134 | UISetCheck(ID_VIEW_STATUS_BAR, settings.ViewStatusBar()); 135 | 136 | m_Tabs.m_bTabCloseButton = false; 137 | m_hWndClient = m_Tabs.Create(m_hWnd, 0, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); 138 | m_Tabs.SetWindowMenu(CMenuHandle(GetMenu()).GetSubMenu(7)); 139 | 140 | CImageList images; 141 | images.Create(16, 16, ILC_COLOR32 | ILC_COLOR | ILC_MASK, 4, 4); 142 | images.AddIcon(AtlLoadIconImage(IDI_SCRIPT, 0, 16, 16)); 143 | images.AddIcon(AtlLoadIconImage(IDI_SCRIPT_FILE, 0, 16, 16)); 144 | m_Tabs.SetImageList(images); 145 | 146 | UISetCheck(ID_CAPTURE_CAPTUREOUTPUT, settings.Capture()); 147 | UISetCheck(ID_CAPTURE_CAPTUREUSERMODE, settings.CaptureUserMode()); 148 | UISetCheck(ID_CAPTURE_CAPTURESESSION0, settings.CaptureSession0()); 149 | UISetCheck(ID_CAPTURE_CAPTUREKERNEL, settings.CaptureKernel()); 150 | UISetCheck(ID_VIEW_AUTOSCROLL, settings.AutoScroll()); 151 | UISetCheck(ID_OPTIONS_CONFIRMDELETE, settings.ConfirmErase()); 152 | 153 | if (!SecurityHelper::IsRunningElevated()) { 154 | if (settings.CaptureSession0() || settings.CaptureKernel()) { 155 | AtlMessageBox(m_hWnd, L"Running with standard user rights. Session 0 and Kernel captures will not be available.", 156 | IDS_TITLE, MB_ICONWARNING); 157 | settings.CaptureKernel(false); 158 | settings.CaptureSession0(false); 159 | } 160 | UIEnable(ID_CAPTURE_CAPTURESESSION0, false); 161 | UIEnable(ID_CAPTURE_CAPTUREKERNEL, false); 162 | } 163 | 164 | CreateDebugOutputView(L"Real-time Log"); 165 | 166 | SetAlwaysOnTop(settings.AlwaysOnTop()); 167 | SetDarkMode(AppSettings::Get().DarkMode()); 168 | 169 | auto pLoop = _Module.GetMessageLoop(); 170 | ATLASSERT(pLoop != NULL); 171 | pLoop->AddMessageFilter(this); 172 | pLoop->AddIdleHandler(this); 173 | 174 | return 0; 175 | } 176 | 177 | LRESULT CMainFrame::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) { 178 | AppSettings::Get().SaveToKey(); 179 | 180 | auto pLoop = _Module.GetMessageLoop(); 181 | ATLASSERT(pLoop != NULL); 182 | pLoop->RemoveMessageFilter(this); 183 | pLoop->RemoveIdleHandler(this); 184 | 185 | bHandled = FALSE; 186 | return 1; 187 | } 188 | 189 | LRESULT CMainFrame::OnFileExit(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 190 | PostMessage(WM_CLOSE); 191 | return 0; 192 | } 193 | 194 | LRESULT CMainFrame::OnViewToolBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 195 | static bool bVisible = true; // initially visible 196 | bVisible = !bVisible; 197 | CReBarCtrl rebar = m_hWndToolBar; 198 | int nBandIndex = rebar.IdToIndex(ATL_IDW_BAND_FIRST); // toolbar is first 1st band 199 | rebar.ShowBand(nBandIndex, bVisible); 200 | UISetCheck(ID_VIEW_TOOLBAR, bVisible); 201 | UpdateLayout(); 202 | return 0; 203 | } 204 | 205 | LRESULT CMainFrame::OnViewStatusBar(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 206 | auto bVisible = !::IsWindowVisible(m_hWndStatusBar); 207 | ::ShowWindow(m_hWndStatusBar, bVisible ? SW_SHOWNOACTIVATE : SW_HIDE); 208 | UISetCheck(ID_VIEW_STATUS_BAR, bVisible); 209 | UpdateLayout(); 210 | return 0; 211 | } 212 | 213 | LRESULT CMainFrame::OnAppAbout(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) const { 214 | CAboutDlg dlg; 215 | dlg.DoModal(); 216 | return 0; 217 | } 218 | 219 | LRESULT CMainFrame::OnRunAsAdmin(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 220 | if (SecurityHelper::RunElevated()) 221 | SendMessage(WM_COMMAND, ID_APP_EXIT); 222 | return 0; 223 | } 224 | 225 | void CMainFrame::SetAlwaysOnTop(bool alwaysOnTop) { 226 | UISetCheck(ID_OPTIONS_ALWAYSONTOP, alwaysOnTop); 227 | SetWindowPos(alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); 228 | } 229 | 230 | LRESULT CMainFrame::OnAlwaysOnTop(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 231 | bool onTop = (GetExStyle() & WS_EX_TOPMOST) ? false : true; 232 | AppSettings::Get().AlwaysOnTop(onTop); 233 | SetAlwaysOnTop(onTop); 234 | return 0; 235 | } 236 | 237 | LRESULT CMainFrame::OnCapture(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 238 | bool capture; 239 | AppSettings::Get().Capture(capture = !AppSettings::Get().Capture()); 240 | UISetCheck(ID_CAPTURE_CAPTUREOUTPUT, capture); 241 | m_pActiveView->Capture(capture); 242 | return 0; 243 | } 244 | 245 | LRESULT CMainFrame::OnCaptureUser(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 246 | bool capture; 247 | AppSettings::Get().CaptureUserMode(capture = !AppSettings::Get().CaptureUserMode()); 248 | UISetCheck(ID_CAPTURE_CAPTUREUSERMODE, capture); 249 | if (AppSettings::Get().Capture()) 250 | m_pActiveView->CaptureUser(capture); 251 | return 0; 252 | } 253 | 254 | LRESULT CMainFrame::OnCaptureUserSession0(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 255 | bool capture; 256 | AppSettings::Get().CaptureSession0(capture = !AppSettings::Get().CaptureSession0()); 257 | UISetCheck(ID_CAPTURE_CAPTURESESSION0, capture); 258 | if (AppSettings::Get().Capture()) 259 | m_pActiveView->CaptureSession0(capture); 260 | return 0; 261 | } 262 | 263 | LRESULT CMainFrame::OnCaptureKernel(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 264 | bool capture; 265 | AppSettings::Get().CaptureKernel(capture = !AppSettings::Get().CaptureKernel()); 266 | UISetCheck(ID_CAPTURE_CAPTUREKERNEL, capture); 267 | if (AppSettings::Get().Capture()) 268 | m_pActiveView->CaptureKernel(capture); 269 | return 0; 270 | } 271 | 272 | LRESULT CMainFrame::OnAutoScroll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 273 | bool autoscroll = !AppSettings::Get().AutoScroll(); 274 | AppSettings::Get().AutoScroll(autoscroll); 275 | UISetCheck(ID_VIEW_AUTOSCROLL, autoscroll); 276 | 277 | return 0; 278 | } 279 | 280 | LRESULT CMainFrame::OnPageActivated(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/) { 281 | UpdateUI(); 282 | return 0; 283 | } 284 | 285 | void CMainFrame::UpdateUI() { 286 | auto active = m_Tabs && m_Tabs.GetPageCount() > 0 && m_Tabs.GetPageData(m_Tabs.GetActivePage()) == m_pActiveView; 287 | auto realTime = active && m_pActiveView->IsRealTime(); 288 | UIEnable(ID_WINDOWS_CLOSE, !realTime); 289 | UIEnable(ID_WINDOWS_CLOSEALL, m_Tabs.GetPageCount() > 1); 290 | UIEnable(ID_CAPTURE_CAPTUREOUTPUT, realTime); 291 | UIEnable(ID_CAPTURE_CAPTUREUSERMODE, realTime); 292 | UIEnable(ID_SEARCH_FIND, active); 293 | if (SecurityHelper::IsRunningElevated()) { 294 | UIEnable(ID_CAPTURE_CAPTUREKERNEL, realTime); 295 | UIEnable(ID_CAPTURE_CAPTURESESSION0, realTime); 296 | } 297 | if (active) 298 | m_pActiveView->UpdateUI(this); 299 | } 300 | 301 | LRESULT CMainFrame::OnMenuSelect(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) const { 302 | return 0; 303 | } 304 | 305 | BOOL CMainFrame::TrackPopupMenu(HMENU hMenu, DWORD flags, int x, int y, HWND hWnd) { 306 | return ShowContextMenu(hMenu, flags, x, y, hWnd); 307 | } 308 | 309 | LRESULT CMainFrame::OnEnableKernelComponents(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 310 | if (!SecurityHelper::IsRunningElevated()) { 311 | AtlMessageBox(m_hWnd, L"Changing kernel component levels requires running elevated.", 312 | IDS_TITLE, MB_ICONERROR); 313 | return 0; 314 | } 315 | 316 | if (!Helpers::EnableAllkernelOutput(wID == ID_KERNEL_ENABLEALLCOMPONENTS)) { 317 | AtlMessageBox(m_hWnd, L"Failed to change kernel component levels.", 318 | IDS_TITLE, MB_ICONERROR); 319 | } 320 | 321 | return 0; 322 | } 323 | 324 | LRESULT CMainFrame::OnTabClose(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 325 | int page = m_Tabs.GetActivePage(); 326 | ATLASSERT(page >= 0); 327 | if (page < 0) 328 | return 0; 329 | 330 | auto view = (CDebugView*)m_Tabs.GetPageData(page); 331 | if (view->CanClose()) 332 | m_Tabs.RemovePage(page); 333 | return 0; 334 | } 335 | 336 | LRESULT CMainFrame::OnTabCloseAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 337 | while (m_Tabs.GetPageCount() > 0) 338 | SendMessage(WM_COMMAND, ID_WINDOWS_CLOSE); 339 | return 0; 340 | } 341 | 342 | void CMainFrame::InitDarkTheme() { 343 | m_DarkTheme.BackColor = m_DarkTheme.SysColors[COLOR_WINDOW] = RGB(32, 32, 32); 344 | m_DarkTheme.TextColor = m_DarkTheme.SysColors[COLOR_WINDOWTEXT] = RGB(248, 248, 248); 345 | m_DarkTheme.SysColors[COLOR_HIGHLIGHT] = RGB(10, 10, 160); 346 | m_DarkTheme.SysColors[COLOR_HIGHLIGHTTEXT] = RGB(240, 240, 240); 347 | m_DarkTheme.SysColors[COLOR_MENUTEXT] = m_DarkTheme.TextColor; 348 | m_DarkTheme.SysColors[COLOR_CAPTIONTEXT] = m_DarkTheme.TextColor; 349 | m_DarkTheme.SysColors[COLOR_BTNFACE] = m_DarkTheme.BackColor; 350 | m_DarkTheme.SysColors[COLOR_BTNTEXT] = m_DarkTheme.TextColor; 351 | m_DarkTheme.SysColors[COLOR_3DLIGHT] = RGB(192, 192, 192); 352 | m_DarkTheme.SysColors[COLOR_BTNHIGHLIGHT] = RGB(192, 192, 192); 353 | m_DarkTheme.SysColors[COLOR_CAPTIONTEXT] = m_DarkTheme.TextColor; 354 | m_DarkTheme.SysColors[COLOR_3DSHADOW] = m_DarkTheme.TextColor; 355 | m_DarkTheme.SysColors[COLOR_SCROLLBAR] = m_DarkTheme.BackColor; 356 | m_DarkTheme.Name = L"Dark"; 357 | m_DarkTheme.Menu.BackColor = m_DarkTheme.BackColor; 358 | m_DarkTheme.Menu.TextColor = m_DarkTheme.TextColor; 359 | m_DarkTheme.StatusBar.BackColor = m_DarkTheme.BackColor; 360 | m_DarkTheme.StatusBar.TextColor = m_DarkTheme.TextColor; 361 | } 362 | 363 | LRESULT CMainFrame::OnDarkMode(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 364 | auto dark = !AppSettings::Get().DarkMode(); 365 | AppSettings::Get().DarkMode(dark); 366 | SetDarkMode(dark); 367 | return 0; 368 | } 369 | 370 | void CMainFrame::SetDarkMode(bool dark) { 371 | ThemeHelper::SetCurrentTheme(dark ? m_DarkTheme : m_DefaultTheme, m_hWnd); 372 | ThemeHelper::UpdateMenuColors(*this, dark); 373 | UpdateMenu(GetMenu(), true); 374 | DrawMenuBar(); 375 | 376 | UISetCheck(ID_OPTIONS_DARKMODE, dark); 377 | } 378 | 379 | LRESULT CMainFrame::OnConfirmErase(WORD /*wNotifyCode*/, WORD id, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 380 | auto confirm = !AppSettings::Get().ConfirmErase(); 381 | AppSettings::Get().ConfirmErase(confirm); 382 | UISetCheck(id, confirm); 383 | return 0; 384 | } 385 | 386 | LRESULT CMainFrame::OnNewRealTimeLog(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 387 | if (m_pActiveView) { 388 | m_pActiveView->Capture(false); 389 | CString name; 390 | name.Format(L"Real-time Log %d", m_Tabs.GetPageCount() + 1); 391 | m_pActiveView = CreateDebugOutputView(name); 392 | } 393 | return 0; 394 | } 395 | 396 | CDebugView* CMainFrame::CreateDebugOutputView(PCWSTR name) { 397 | auto view = new CDebugView(this); 398 | view->Create(m_Tabs, 0, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); 399 | view->SetFont(m_Font); 400 | m_pActiveView = view; 401 | view->Capture(AppSettings::Get().Capture()); 402 | m_Tabs.AddPage(view->m_hWnd, name, 0, view); 403 | return view; 404 | } 405 | 406 | LRESULT CMainFrame::OnSearchFind(WORD, WORD, HWND, BOOL&) { 407 | if (m_pFindDlg == nullptr) { 408 | m_pFindDlg = new CFindReplaceDialog; 409 | m_pFindDlg->Create(TRUE, m_SearchText, nullptr, FR_DOWN | FR_HIDEWHOLEWORD, m_hWnd); 410 | m_pFindDlg->ShowWindow(SW_SHOW); 411 | } 412 | return 0; 413 | } 414 | 415 | LRESULT CMainFrame::OnFind(UINT msg, WPARAM wp, LPARAM lp, BOOL&) { 416 | if (m_pFindDlg->IsTerminating()) { 417 | m_pFindDlg = nullptr; 418 | return 0; 419 | } 420 | 421 | m_SearchText = m_pFindDlg->GetFindString(); 422 | auto page = m_Tabs.GetActivePage(); 423 | if (page >= 0) 424 | ::SendMessage(m_Tabs.GetPageHWND(page), msg, wp, lp); 425 | 426 | return 0; 427 | } 428 | 429 | CFindReplaceDialog* CMainFrame::GetFindDlg() { 430 | return m_pFindDlg; 431 | } 432 | 433 | CString& CMainFrame::GetSearchString() { 434 | return m_SearchText; 435 | } 436 | 437 | -------------------------------------------------------------------------------- /DbgPrint/DebugView.cpp: -------------------------------------------------------------------------------- 1 | #include "pch.h" 2 | #include "DebugView.h" 3 | #include "SortHelper.h" 4 | #include "SecurityHelper.h" 5 | #include "ListViewhelper.h" 6 | #include "ClipboardHelper.h" 7 | #include "AppSettings.h" 8 | #include "Helpers.h" 9 | #include "PropertiesDlg.h" 10 | #include "CommentDlg.h" 11 | #include 12 | #include "resource.h" 13 | #include "DebugLogPersist.h" 14 | #include "HighlightDlg.h" 15 | 16 | CDebugView::CDebugView(IMainFrame* frame, bool realTime) : m_pFrame(frame), m_RealTime(realTime) { 17 | } 18 | 19 | void CDebugView::UpdateList() { 20 | m_List.SetItemCountEx((int)m_Items.size(), LVSICF_NOINVALIDATEALL | LVSICF_NOSCROLL); 21 | DoSort(GetSortInfo(m_List)); 22 | if (AppSettings::Get().AutoScroll()) 23 | m_List.EnsureVisible(m_List.GetItemCount() - 1, FALSE); 24 | m_List.RedrawItems(m_List.GetTopIndex(), m_List.GetTopIndex() + m_List.GetCountPerPage()); 25 | } 26 | 27 | LRESULT CDebugView::OnCreate(UINT, WPARAM, LPARAM, BOOL&) { 28 | m_hWndClient = m_List.Create(m_hWnd, 0, nullptr, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | 29 | LVS_OWNERDATA | LVS_REPORT); 30 | m_List.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER | LVS_EX_INFOTIP | LVS_EX_SUBITEMIMAGES); 31 | m_List.SetImageList(m_IconCache.GetImageList(), LVSIL_SMALL); 32 | 33 | auto cm = GetColumnManager(m_List); 34 | cm->AddColumn(L"", LVCFMT_RIGHT, 1); 35 | cm->AddColumn(L"#", LVCFMT_RIGHT, 70, ColumnType::Index); 36 | cm->AddColumn(L"Time", LVCFMT_RIGHT, 110, ColumnType::Time); 37 | cm->AddColumn(L"PID", LVCFMT_RIGHT, 80, ColumnType::ProcessId); 38 | cm->AddColumn(L"Process Name", LVCFMT_LEFT, 180, ColumnType::ProcessName); 39 | cm->AddColumn(L"Message", LVCFMT_LEFT, 500, ColumnType::Text); 40 | cm->AddColumn(L"Comment", LVCFMT_LEFT, 150, ColumnType::Comment); 41 | cm->UpdateColumns(); 42 | cm->DeleteColumn(0); 43 | 44 | m_Highlights = AppSettings::Get().HighlightItems(); 45 | if (m_Highlights.empty()) 46 | m_Highlights = DefaultHighlightColors; 47 | 48 | m_TempItems.reserve(256); 49 | m_Items.reserve(4096); 50 | 51 | SetTimer(1, 1000); 52 | 53 | return 0; 54 | } 55 | 56 | LRESULT CDebugView::OnTimer(UINT, WPARAM id, LPARAM, BOOL&) { 57 | if (id == 1) { 58 | { 59 | std::lock_guard locker(m_Lock); 60 | if (m_TempItems.empty()) 61 | return 0; 62 | 63 | m_Items.append(m_TempItems.begin(), m_TempItems.end()); 64 | m_TempItems.clear(); 65 | } 66 | UpdateList(); 67 | } 68 | return 0; 69 | } 70 | 71 | void CDebugView::ShowProperties(int selected) { 72 | auto& item = *m_Items[selected]; 73 | CPropertiesDlg dlg(item, m_IconCache, m_pm); 74 | if (IDOK == dlg.DoModal()) { 75 | // 76 | // update comment 77 | // 78 | item.Comment = dlg.GetComment(); 79 | item.Text = dlg.GetText(); 80 | m_List.RedrawItems(selected, selected); 81 | } 82 | } 83 | 84 | CString CDebugView::GetColumnText(HWND h, int row, int col) const { 85 | CString text; 86 | auto& item = *m_Items[row]; 87 | 88 | switch (GetColumnManager(h)->GetColumnTag(col)) { 89 | case ColumnType::Index: text.Format(L"%u", item.Index); break; 90 | case ColumnType::Time: 91 | if (item.LocalTimeAsString.IsEmpty()) { 92 | FILETIME ft; 93 | ::FileTimeToLocalFileTime(&item.SystemTime, &ft); 94 | SYSTEMTIME st; 95 | ::FileTimeToSystemTime(&ft, &st); 96 | item.LocalTimeAsString.Format(L"%02d:%02d:%02d.%03d%03d", 97 | st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, ft.dwLowDateTime * 10 % 1000); 98 | 99 | } 100 | return item.LocalTimeAsString; 101 | 102 | case ColumnType::ProcessId: text.Format(L"%u", item.Process.ProcessId); break; 103 | case ColumnType::ProcessName: return item.ProcessName.c_str(); 104 | case ColumnType::Comment: return item.Comment.c_str(); 105 | } 106 | return text; 107 | } 108 | 109 | PCWSTR CDebugView::GetExistingColumnText(HWND h, int row, int col) const { 110 | auto& item = m_Items[row]; 111 | if (GetColumnManager(h)->GetColumnTag(col) == ColumnType::Text) 112 | return item->Text.c_str(); 113 | 114 | return nullptr; 115 | } 116 | 117 | bool CDebugView::IsSortable(HWND, int col) const { 118 | return !AppSettings::Get().Capture(); 119 | } 120 | 121 | BOOL CDebugView::OnDoubleClickList(HWND, int row, int col, POINT const& pt) { 122 | if (row < 0) 123 | return FALSE; 124 | 125 | ShowProperties(row); 126 | return TRUE; 127 | } 128 | 129 | BOOL CDebugView::OnRightClickList(HWND, int row, int col, POINT const& pt) { 130 | if (row < 0) 131 | return FALSE; 132 | 133 | CMenu menu; 134 | menu.LoadMenu(IDR_CONTEXT); 135 | return m_pFrame->TrackPopupMenu(menu.GetSubMenu(0), 0, pt.x, pt.y); 136 | } 137 | 138 | DWORD CDebugView::OnPrePaint(DWORD, LPNMCUSTOMDRAW cd) { 139 | if (cd->hdr.hwndFrom == m_List) 140 | return CDRF_NOTIFYITEMDRAW; 141 | 142 | SetMsgHandled(FALSE); 143 | return 0; 144 | } 145 | 146 | DWORD CDebugView::OnItemPrePaint(DWORD, LPNMCUSTOMDRAW cd) { 147 | auto lvcd = (NMLVCUSTOMDRAW*)cd; 148 | auto& item = m_Items[(int)cd->dwItemSpec]; 149 | if ((item->Flags & DebugOutputFlags::Highlight) == DebugOutputFlags::Highlight) { 150 | 151 | } 152 | return CDRF_SKIPPOSTPAINT; 153 | } 154 | 155 | bool CDebugView::CanClose() { 156 | return !m_RealTime; 157 | } 158 | 159 | bool CDebugView::IsRealTime() const { 160 | return m_RealTime; 161 | } 162 | 163 | bool CDebugView::IsEmpty() const { 164 | return m_Items.empty(); 165 | } 166 | 167 | void CDebugView::DebugOutput(DWORD pid, PCSTR text, FILETIME const& time, DebugOutputFlags flags) { 168 | if (!m_Running) 169 | return; 170 | 171 | auto item = std::make_unique(); 172 | item->ProcessName = m_pm.GetProcessName(pid); 173 | item->Process = m_pm.GetProcessKey(pid); 174 | item->Text.assign(text, text + strlen(text) + 1); 175 | item->SystemTime = time; 176 | item->Flags = flags; 177 | item->Index = InterlockedIncrement(&s_Index); 178 | item->Image = pid <= 4 ? 0 : m_IconCache.GetIcon(m_pm.GetProcessInfo(item->Process)->FullPath); 179 | std::lock_guard locker(m_Lock); 180 | m_TempItems.push_back(std::move(item)); 181 | } 182 | 183 | void CDebugView::DoSort(SortInfo const* si) { 184 | if (si == nullptr) 185 | return; 186 | 187 | auto col = GetColumnManager(si->hWnd)->GetColumnTag(si->SortColumn); 188 | auto asc = si->SortAscending; 189 | auto compare = [&](auto const& item1, auto const& item2) { 190 | switch (col) { 191 | case ColumnType::Index: return SortHelper::Sort(item1->Index, item2->Index, asc); 192 | case ColumnType::ProcessId: return SortHelper::Sort(item1->Process.ProcessId, item2->Process.ProcessId, asc); 193 | case ColumnType::ProcessName: return SortHelper::Sort(item1->ProcessName, item2->ProcessName, asc); 194 | case ColumnType::Time: return SortHelper::Sort(*(LONG64*)&item1->SystemTime, *(LONG64*)&item2->SystemTime, asc); 195 | case ColumnType::Text: return SortHelper::Sort(item1->Text, item2->Text, asc); 196 | case ColumnType::Comment: return SortHelper::Sort(item1->Comment, item2->Comment, asc); 197 | }; 198 | return false; 199 | }; 200 | 201 | std::lock_guard locker(m_Lock); 202 | m_Items.Sort(compare); 203 | } 204 | 205 | void CDebugView::Capture(bool capture) { 206 | m_Running = capture; 207 | if (capture) { 208 | auto const& settings = AppSettings::Get(); 209 | if (settings.CaptureUserMode()) 210 | m_UserMode.Run(this); 211 | if (settings.CaptureSession0()) 212 | m_UserModeSession0.Run(this); 213 | if (settings.CaptureKernel()) 214 | m_KernelMode.Run(this); 215 | } 216 | else { 217 | m_UserMode.Stop(); 218 | m_UserModeSession0.Stop(); 219 | m_KernelMode.Stop(); 220 | } 221 | } 222 | 223 | void CDebugView::CaptureKernel(bool capture) { 224 | if (!m_Running) 225 | return; 226 | capture ? m_KernelMode.Run(this) : m_KernelMode.Stop(); 227 | } 228 | 229 | void CDebugView::CaptureUser(bool capture) { 230 | if (!m_Running) 231 | return; 232 | capture ? m_UserMode.Run(this) : m_UserMode.Stop(); 233 | } 234 | 235 | void CDebugView::CaptureSession0(bool capture) { 236 | if (!m_Running) 237 | return; 238 | capture ? m_UserModeSession0.Run(this) : m_UserModeSession0.Stop(); 239 | } 240 | 241 | void CDebugView::UpdateUI(CUpdateUIBase* ui) { 242 | if (m_ui == nullptr) 243 | m_ui = ui; 244 | 245 | auto selectedCount = m_List.GetSelectedCount(); 246 | ui->UIEnable(ID_VIEW_PROPERTIES, selectedCount == 1); 247 | ui->UIEnable(ID_EDIT_DELETE, selectedCount > 0); 248 | ui->UIEnable(ID_EDIT_COPY, selectedCount > 0); 249 | ui->UIEnable(ID_EDIT_COMMENT, selectedCount == 1); 250 | ui->UIEnable(ID_EDIT_BOOKMARK, selectedCount > 0); 251 | ui->UIEnable(ID_SEARCH_FIND, m_List.GetItemCount() > 0); 252 | ui->UIEnable(ID_SEARCH_FINDNEXT, !m_pFrame->GetSearchString().IsEmpty()); 253 | } 254 | 255 | int CDebugView::GetRowImage(HWND h, int row, int col) const { 256 | auto& item = m_Items[row]; 257 | if (col == 0) 258 | return ((item->Flags & DebugOutputFlags::Kernel) == DebugOutputFlags::Kernel) ? 1 : 2; 259 | 260 | auto type = GetColumnManager(h)->GetColumnTag(col); 261 | switch (type) { 262 | case ColumnType::ProcessName: 263 | if (item->Image >= 0) 264 | return item->Image; 265 | return item->Process.ProcessId ? 0 : 1; 266 | 267 | case ColumnType::Text: 268 | auto bookmark = (item->Flags & DebugOutputFlags::Bookmark) == DebugOutputFlags::Bookmark; 269 | if (bookmark) 270 | return 3; 271 | break; 272 | } 273 | return -1; 274 | } 275 | 276 | LRESULT CDebugView::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& handled) { 277 | KillTimer(1); 278 | m_UserMode.Stop(); 279 | m_UserModeSession0.Stop(); 280 | handled = FALSE; 281 | return 0; 282 | } 283 | 284 | LRESULT CDebugView::OnEditCopy(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 285 | ClipboardHelper::CopyText(m_hWnd, ListViewHelper::GetSelectedRowsAsString(m_List, L",")); 286 | return 0; 287 | } 288 | 289 | LRESULT CDebugView::OnSetFont(UINT, WPARAM wp, LPARAM, BOOL&) { 290 | m_List.SetFont((HFONT)wp); 291 | return 0; 292 | } 293 | 294 | LRESULT CDebugView::OnSaveAsText(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 295 | CSimpleFileDialog dlg(FALSE, L"txt", L"log", OFN_EXPLORER | OFN_ENABLESIZING | OFN_OVERWRITEPROMPT, 296 | L"Text Files (*.txt)\0*.txt\0All Files\0*.*\0", m_hWnd); 297 | ThemeHelper::Suspend(); 298 | auto ok = IDOK == dlg.DoModal(); 299 | ThemeHelper::Resume(); 300 | if(ok) { 301 | auto text = ListViewHelper::GetAllRowsAsString(m_List, L","); 302 | wil::unique_hfile hFile(::CreateFile(dlg.m_szFileName, GENERIC_WRITE, 0, nullptr, OPEN_ALWAYS, 0, nullptr)); 303 | if (!hFile) { 304 | Helpers::ReportError(L"Error: "); 305 | return 0; 306 | } 307 | if (DWORD bytes; !::WriteFile(hFile.get(), text.GetBuffer(), text.GetLength() * sizeof(WCHAR), &bytes, nullptr)) { 308 | Helpers::ReportError(L"Error: "); 309 | return 0; 310 | } 311 | AtlMessageBox(m_hWnd, L"Saved successfully.", IDS_TITLE, MB_ICONINFORMATION); 312 | } 313 | return 0; 314 | } 315 | 316 | LRESULT CDebugView::OnProperties(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 317 | auto selected = m_List.GetSelectionMark(); 318 | ATLASSERT(selected >= 0); 319 | if (selected < 0) 320 | return 0; 321 | 322 | ShowProperties(selected); 323 | 324 | return 0; 325 | } 326 | 327 | LRESULT CDebugView::OnItemChanged(int /*idCtrl*/, LPNMHDR hdr, BOOL& /*bHandled*/) { 328 | if (m_ui) { 329 | UpdateUI(m_ui); 330 | } 331 | return 0; 332 | } 333 | 334 | LRESULT CDebugView::OnEditDelete(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 335 | int n = -1; 336 | int offset = 0; 337 | { 338 | std::lock_guard locker(m_Lock); 339 | while ((n = m_List.GetNextItem(n, LVIS_SELECTED)) != -1) { 340 | m_Items.erase(n - offset); 341 | offset++; 342 | } 343 | } 344 | m_List.SelectAllItems(false); 345 | UpdateList(); 346 | return 0; 347 | } 348 | 349 | LRESULT CDebugView::OnEditComment(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 350 | ATLASSERT(m_List.GetSelectedCount() == 1); 351 | int selected = m_List.GetSelectionMark(); 352 | ATLASSERT(selected >= 0); 353 | 354 | auto& item = m_Items[selected]; 355 | CCommentDlg dlg(item->Comment); 356 | if (IDOK == dlg.DoModal(m_hWnd, reinterpret_cast(CImageList(m_IconCache.GetImageList()).GetIcon(item->Image)))) { 357 | item->Comment = dlg.GetComment(); 358 | m_List.RedrawItems(selected, selected); 359 | } 360 | return 0; 361 | } 362 | 363 | LRESULT CDebugView::OnEditClearAll(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 364 | if (AppSettings::Get().ConfirmErase()) { 365 | if (AtlMessageBox(m_hWnd, L"Erase log?", IDS_TITLE, MB_YESNO | MB_DEFBUTTON2 | MB_ICONWARNING) == IDNO) 366 | return 0; 367 | } 368 | { 369 | std::lock_guard locker(m_Lock); 370 | m_Items.clear(); 371 | } 372 | m_List.SetItemCount(0); 373 | return 0; 374 | } 375 | 376 | LRESULT CDebugView::OnFind(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { 377 | auto dlg = m_pFrame->GetFindDlg(); 378 | auto searchDown = dlg->SearchDown(); 379 | auto index = ListViewHelper::SearchItem(m_List, dlg->GetFindString(), searchDown, dlg->MatchCase()); 380 | 381 | if (index >= 0) { 382 | m_List.SelectItem(index); 383 | m_List.SetFocus(); 384 | } 385 | else { 386 | AtlMessageBox(m_hWnd, L"Finished searching.", IDR_MAINFRAME, MB_ICONINFORMATION); 387 | } 388 | return 0; 389 | } 390 | 391 | LRESULT CDebugView::OnToggleBookmark(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 392 | int count = m_List.GetSelectedCount(); 393 | ATLASSERT(count); 394 | 395 | for (auto i : SelectedItemsView(m_List)) { 396 | auto& item = m_Items[i]; 397 | item->Flags ^= DebugOutputFlags::Bookmark; 398 | } 399 | m_List.RedrawItems(m_List.GetTopIndex(), m_List.GetTopIndex() + m_List.GetCountPerPage()); 400 | return 0; 401 | } 402 | 403 | LRESULT CDebugView::OnNextBookmark(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 404 | int n = m_List.GetSelectionMark(); 405 | int count = m_List.GetItemCount(); 406 | int next = -1; 407 | for (int i = n + 1; i < count + n; i++) { 408 | if ((m_Items[i % count]->Flags & DebugOutputFlags::Bookmark) == DebugOutputFlags::Bookmark) { 409 | next = i % count; 410 | break; 411 | } 412 | } 413 | if (next >= 0) 414 | m_List.SelectItem(next); 415 | else 416 | ::MessageBeep(-1); 417 | return 0; 418 | } 419 | 420 | LRESULT CDebugView::OnPrevBookmark(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 421 | int n = m_List.GetSelectionMark(); 422 | int count = m_List.GetItemCount(); 423 | int next = -1; 424 | for (int i = n - 1 + count; i >= n; i--) { 425 | if ((m_Items[i % count]->Flags & DebugOutputFlags::Bookmark) == DebugOutputFlags::Bookmark) { 426 | next = i % count; 427 | break; 428 | } 429 | } 430 | if (next >= 0) 431 | m_List.SelectItem(next); 432 | else 433 | ::MessageBeep(-1); 434 | return 0; 435 | } 436 | 437 | LRESULT CDebugView::OnDeleteAllBookmarks(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 438 | for (auto& item : m_Items) 439 | item->Flags &= ~DebugOutputFlags::Bookmark; 440 | 441 | m_List.RedrawItems(m_List.GetTopIndex(), m_List.GetTopIndex() + m_List.GetCountPerPage()); 442 | return 0; 443 | } 444 | 445 | LRESULT CDebugView::OnSave(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 446 | CSimpleFileDialog dlg(FALSE, L"dbgp", L"log", OFN_EXPLORER | OFN_ENABLESIZING | OFN_OVERWRITEPROMPT, 447 | L"DebugPrint Native Files (*.dbgp)\0*.dbgp\0CSV Files (*.csv)\0*.csv\0", m_hWnd); 448 | ThemeHelper::Suspend(); 449 | auto ok = IDOK == dlg.DoModal(); 450 | ThemeHelper::Resume(); 451 | if (ok) { 452 | auto ext = wcsrchr(dlg.m_szFileTitle, L'.'); 453 | auto format = ext && _wcsicmp(ext, L".dbgp") == 0 ? PersistFormat::Native : PersistFormat::CSV; 454 | ok = DebugLogPersist::Save(format, m_Items.GetItems(), m_IconCache, m_pm, dlg.m_szFileName); 455 | if (ok) 456 | AtlMessageBox(m_hWnd, L"Saved successfully.", IDS_TITLE, MB_ICONINFORMATION); 457 | else 458 | AtlMessageBox(m_hWnd, L"Error saving log.", IDS_TITLE, MB_ICONERROR); 459 | } 460 | return 0; 461 | } 462 | 463 | LRESULT CDebugView::OnHighlight(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { 464 | CHighlightDlg dlg(m_Highlights); 465 | if (IDOK == dlg.DoModal()) { 466 | } 467 | return 0; 468 | } 469 | 470 | LRESULT CDebugView::OnFindNext(WORD, WORD, HWND, BOOL&) { 471 | return SendMessage(CFindReplaceDialog::GetFindReplaceMsg()); 472 | } 473 | 474 | 475 | -------------------------------------------------------------------------------- /DbgPrint/DbgPrint.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | ARM64 7 | 8 | 9 | Debug 10 | Win32 11 | 12 | 13 | ReleaseSigned 14 | ARM64 15 | 16 | 17 | ReleaseSigned 18 | Win32 19 | 20 | 21 | ReleaseSigned 22 | x64 23 | 24 | 25 | Release 26 | ARM64 27 | 28 | 29 | Release 30 | Win32 31 | 32 | 33 | Debug 34 | x64 35 | 36 | 37 | Release 38 | x64 39 | 40 | 41 | 42 | 16.0 43 | {06BA589B-5714-4A56-8CC2-B2D550CF4F3A} 44 | 10.0 45 | DbgPrint 46 | 47 | 48 | 49 | Application 50 | true 51 | v143 52 | Unicode 53 | 54 | 55 | Application 56 | false 57 | v143 58 | Unicode 59 | 60 | 61 | Application 62 | false 63 | v143 64 | Unicode 65 | 66 | 67 | Application 68 | true 69 | v143 70 | Unicode 71 | 72 | 73 | Application 74 | true 75 | v143 76 | Unicode 77 | 78 | 79 | Application 80 | false 81 | v143 82 | Unicode 83 | 84 | 85 | Application 86 | false 87 | v143 88 | Unicode 89 | 90 | 91 | Application 92 | false 93 | v143 94 | Unicode 95 | 96 | 97 | Application 98 | false 99 | v143 100 | Unicode 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | true 137 | 138 | 139 | true 140 | 141 | 142 | true 143 | 144 | 145 | false 146 | 147 | 148 | false 149 | 150 | 151 | false 152 | 153 | 154 | false 155 | 156 | 157 | false 158 | 159 | 160 | false 161 | 162 | 163 | 164 | Use 165 | Level3 166 | MultiThreadedDebug 167 | EditAndContinue 168 | EnableFastChecks 169 | Disabled 170 | WIN32;_WINDOWS;STRICT;_DEBUG;%(PreprocessorDefinitions) 171 | pch.h 172 | stdcpp20 173 | ..\wtlhelper\wtlhelper 174 | 175 | 176 | Windows 177 | true 178 | 179 | 180 | 0x0409 181 | $(IntDir);%(AdditionalIncludeDirectories) 182 | _DEBUG;%(PreprocessorDefinitions) 183 | 184 | 185 | false 186 | Win32 187 | _DEBUG;%(PreprocessorDefinitions) 188 | DbgPrint.h 189 | DbgPrint_i.c 190 | DbgPrint_p.c 191 | true 192 | $(IntDir)/DbgPrint.tlb 193 | 194 | 195 | 196 | manifest.xml 197 | 198 | 199 | 200 | 201 | Use 202 | Level3 203 | MultiThreadedDebug 204 | EditAndContinue 205 | EnableFastChecks 206 | Disabled 207 | _WINDOWS;STRICT;_DEBUG;%(PreprocessorDefinitions) 208 | pch.h 209 | stdcpp20 210 | ..\wtlhelper\wtlhelper 211 | 212 | 213 | Windows 214 | true 215 | 216 | 217 | 0x0409 218 | $(IntDir);%(AdditionalIncludeDirectories) 219 | _DEBUG;%(PreprocessorDefinitions) 220 | 221 | 222 | false 223 | _DEBUG;%(PreprocessorDefinitions) 224 | DbgPrint.h 225 | DbgPrint_i.c 226 | DbgPrint_p.c 227 | true 228 | $(IntDir)/DbgPrint.tlb 229 | 230 | 231 | 232 | manifest.xml 233 | 234 | 235 | 236 | 237 | Use 238 | Level3 239 | MultiThreadedDebug 240 | EditAndContinue 241 | EnableFastChecks 242 | Disabled 243 | _WINDOWS;STRICT;_DEBUG;%(PreprocessorDefinitions) 244 | pch.h 245 | stdcpp20 246 | ..\wtlhelper\wtlhelper 247 | 248 | 249 | Windows 250 | true 251 | 252 | 253 | 0x0409 254 | $(IntDir);%(AdditionalIncludeDirectories) 255 | _DEBUG;%(PreprocessorDefinitions) 256 | 257 | 258 | false 259 | _DEBUG;%(PreprocessorDefinitions) 260 | DbgPrint.h 261 | DbgPrint_i.c 262 | DbgPrint_p.c 263 | true 264 | $(IntDir)/DbgPrint.tlb 265 | 266 | 267 | 268 | 269 | manifest.xml 270 | 271 | 272 | 273 | 274 | Use 275 | Level3 276 | MultiThreaded 277 | Async 278 | 279 | WIN32;_WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions) 280 | pch.h 281 | stdcpp20 282 | ..\wtlhelper\wtlhelper 283 | 284 | 285 | Windows 286 | 287 | 288 | 0x0409 289 | $(IntDir);%(AdditionalIncludeDirectories) 290 | NDEBUG;%(PreprocessorDefinitions) 291 | 292 | 293 | false 294 | Win32 295 | NDEBUG;%(PreprocessorDefinitions) 296 | DbgPrint.h 297 | DbgPrint_i.c 298 | DbgPrint_p.c 299 | true 300 | $(IntDir)/DbgPrint.tlb 301 | 302 | 303 | 304 | manifest.xml 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | Use 314 | Level3 315 | MultiThreaded 316 | Async 317 | 318 | 319 | WIN32;_WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions) 320 | pch.h 321 | stdcpp20 322 | ..\wtlhelper\wtlhelper 323 | 324 | 325 | Windows 326 | 327 | 328 | 0x0409 329 | $(IntDir);%(AdditionalIncludeDirectories) 330 | NDEBUG;%(PreprocessorDefinitions) 331 | 332 | 333 | false 334 | Win32 335 | NDEBUG;%(PreprocessorDefinitions) 336 | DbgPrint.h 337 | DbgPrint_i.c 338 | DbgPrint_p.c 339 | true 340 | $(IntDir)/DbgPrint.tlb 341 | 342 | 343 | 344 | 345 | manifest.xml 346 | 347 | 348 | signtool sign /i DigiCert /fd sha256 $(TargetPath) 349 | 350 | 351 | 352 | 353 | Use 354 | Level3 355 | MultiThreaded 356 | Async 357 | 358 | _WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions) 359 | pch.h 360 | stdcpp20 361 | ..\wtlhelper\wtlhelper 362 | 363 | 364 | Windows 365 | 366 | 367 | 0x0409 368 | $(IntDir);%(AdditionalIncludeDirectories) 369 | NDEBUG;%(PreprocessorDefinitions) 370 | 371 | 372 | false 373 | NDEBUG;%(PreprocessorDefinitions) 374 | DbgPrint.h 375 | DbgPrint_i.c 376 | DbgPrint_p.c 377 | true 378 | $(IntDir)/DbgPrint.tlb 379 | 380 | 381 | 382 | manifest.xml 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | Use 392 | Level3 393 | MultiThreaded 394 | Async 395 | 396 | 397 | _WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions) 398 | pch.h 399 | stdcpp20 400 | ..\wtlhelper\wtlhelper 401 | 402 | 403 | Windows 404 | 405 | 406 | 0x0409 407 | $(IntDir);%(AdditionalIncludeDirectories) 408 | NDEBUG;%(PreprocessorDefinitions) 409 | 410 | 411 | false 412 | NDEBUG;%(PreprocessorDefinitions) 413 | DbgPrint.h 414 | DbgPrint_i.c 415 | DbgPrint_p.c 416 | true 417 | $(IntDir)/DbgPrint.tlb 418 | 419 | 420 | 421 | 422 | manifest.xml 423 | 424 | 425 | signtool sign /i DigiCert /fd sha256 $(TargetPath) 426 | 427 | 428 | 429 | 430 | Use 431 | Level3 432 | MultiThreaded 433 | Async 434 | 435 | 436 | _WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions) 437 | pch.h 438 | stdcpp20 439 | ..\wtlhelper\wtlhelper 440 | 441 | 442 | Windows 443 | 444 | 445 | 0x0409 446 | $(IntDir);%(AdditionalIncludeDirectories) 447 | NDEBUG;%(PreprocessorDefinitions) 448 | 449 | 450 | false 451 | NDEBUG;%(PreprocessorDefinitions) 452 | DbgPrint.h 453 | DbgPrint_i.c 454 | DbgPrint_p.c 455 | true 456 | $(IntDir)/DbgPrint.tlb 457 | 458 | 459 | 460 | 461 | manifest.xml 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | Use 471 | Level3 472 | MultiThreaded 473 | Async 474 | 475 | 476 | _WINDOWS;STRICT;NDEBUG;%(PreprocessorDefinitions) 477 | pch.h 478 | stdcpp20 479 | ..\wtlhelper\wtlhelper 480 | 481 | 482 | Windows 483 | 484 | 485 | 0x0409 486 | $(IntDir);%(AdditionalIncludeDirectories) 487 | NDEBUG;%(PreprocessorDefinitions) 488 | 489 | 490 | false 491 | NDEBUG;%(PreprocessorDefinitions) 492 | DbgPrint.h 493 | DbgPrint_i.c 494 | DbgPrint_p.c 495 | true 496 | $(IntDir)/DbgPrint.tlb 497 | 498 | 499 | 500 | 501 | manifest.xml 502 | 503 | 504 | signtool sign /i DigiCert /fd sha256 $(TargetPath) 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | Create 523 | Create 524 | Create 525 | Create 526 | Create 527 | Create 528 | Create 529 | Create 530 | Create 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | {ae53419f-a769-4548-8e15-e311904df7df} 592 | 593 | 594 | 595 | 596 | --------------------------------------------------------------------------------