├── .gitattributes ├── Hexer ├── stdafx.cpp ├── res │ ├── Hexer.rc2 │ ├── IDB_FILE.bmp │ ├── IDB_DEVICE.bmp │ ├── IDB_PROCESS.bmp │ ├── IDR_HEXER_FRAME.ico │ └── IDR_TOOLBAR_MAIN.bmp ├── stdafx.h ├── Hexer.sln ├── CHexerApp.h ├── CChildFrame.h ├── Dialogs │ ├── HexerPropGridCtrl.ixx │ ├── DlgNewFile.ixx │ ├── DlgLogger.ixx │ ├── DlgProcMemory.ixx │ ├── DlgDataInfo.ixx │ ├── HexerDockablePane.ixx │ └── DlgOpenProcess.ixx ├── CHexerDoc.h ├── CHexerView.h ├── CMainFrame.h ├── CChildFrame.cpp ├── resource.h ├── CHexerDoc.cpp ├── Hexer.vcxproj.filters ├── Utility.ixx ├── Hexer.vcxproj ├── CHexerApp.cpp ├── CHexerView.cpp └── Hexer.rc ├── docs └── img │ ├── Hexer_Main.jpg │ └── HexCtrl_Templates.jpg ├── .gitmodules ├── .github └── ISSUE_TEMPLATE │ ├── bug-report.md │ └── config.yml ├── LICENSE ├── .clang-tidy ├── .editorconfig ├── .gitignore └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.rc diff 2 | *.rc2 diff -------------------------------------------------------------------------------- /Hexer/stdafx.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" -------------------------------------------------------------------------------- /Hexer/res/Hexer.rc2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovibor/Hexer/HEAD/Hexer/res/Hexer.rc2 -------------------------------------------------------------------------------- /Hexer/res/IDB_FILE.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovibor/Hexer/HEAD/Hexer/res/IDB_FILE.bmp -------------------------------------------------------------------------------- /Hexer/res/IDB_DEVICE.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovibor/Hexer/HEAD/Hexer/res/IDB_DEVICE.bmp -------------------------------------------------------------------------------- /docs/img/Hexer_Main.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovibor/Hexer/HEAD/docs/img/Hexer_Main.jpg -------------------------------------------------------------------------------- /Hexer/res/IDB_PROCESS.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovibor/Hexer/HEAD/Hexer/res/IDB_PROCESS.bmp -------------------------------------------------------------------------------- /Hexer/res/IDR_HEXER_FRAME.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovibor/Hexer/HEAD/Hexer/res/IDR_HEXER_FRAME.ico -------------------------------------------------------------------------------- /Hexer/res/IDR_TOOLBAR_MAIN.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovibor/Hexer/HEAD/Hexer/res/IDR_TOOLBAR_MAIN.bmp -------------------------------------------------------------------------------- /docs/img/HexCtrl_Templates.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovibor/Hexer/HEAD/docs/img/HexCtrl_Templates.jpg -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Hexer/dep/HexCtrl"] 2 | path = Hexer/dep/HexCtrl 3 | url = https://github.com/jovibor/HexCtrl.git 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐞 Bug Report 3 | about: Please report any Hexer bugs here. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: ❓/🚀/💬 Ask a Question / Feature Request / General Chat 4 | url: https://github.com/jovibor/Hexer/discussions/new 5 | about: Everything but bug-reports please post here. -------------------------------------------------------------------------------- /Hexer/stdafx.h: -------------------------------------------------------------------------------- 1 | #ifndef VC_EXTRALEAN 2 | #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers 3 | #endif 4 | 5 | #include 6 | 7 | #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit 8 | 9 | // turns off MFC's hiding of some common and often safely ignored warning messages 10 | #define _AFX_ALL_WARNINGS 11 | 12 | #include 13 | #include 14 | 15 | //Setting the manifest for the ComCtl32.dll version 6. 16 | #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The Hexer License Version 1.0 2 | 3 | Software: Hexer, https://github.com/jovibor/Hexer 4 | 5 | Copyright (c) 2023 - Present, Jovibor, https://github.com/jovibor 6 | 7 | Permission is hereby granted, free of charge, for any use, excluding selling, 8 | of the Software and associated documentation files. 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | 21 | For all third party components incorporated into the Software, those 22 | components are licensed under the original license provided by the owner of the 23 | applicable component. -------------------------------------------------------------------------------- /Hexer/Hexer.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.6.33723.286 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Hexer", "Hexer.vcxproj", "{EFF1D88A-4FED-465E-860A-2A4D5622F76D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {EFF1D88A-4FED-465E-860A-2A4D5622F76D}.Debug|x64.ActiveCfg = Debug|x64 15 | {EFF1D88A-4FED-465E-860A-2A4D5622F76D}.Debug|x64.Build.0 = Debug|x64 16 | {EFF1D88A-4FED-465E-860A-2A4D5622F76D}.Release|x64.ActiveCfg = Release|x64 17 | {EFF1D88A-4FED-465E-860A-2A4D5622F76D}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {3FAA9778-9320-4128-8833-1191AA584984} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | Checks: '*, 2 | -cppcoreguidelines-*,-google-*,-fuchsia-*,-hicpp-*,-cert-*,-clang-*,-llvmlibc-*,-altera-*,-boost-*,-abseil-*, 3 | -bugprone-easily-swappable-parameters, 4 | -bugprone-implicit-widening-of-multiplication-result, 5 | -bugprone-narrowing-conversions, 6 | -bugprone-use-after-move, 7 | -llvm-header-guard, 8 | -llvm-include-order, 9 | -llvm-namespace-comment, 10 | -llvm-qualified-auto, 11 | -misc-include-cleaner, 12 | -misc-non-private-member-variables-in-classes, 13 | -misc-no-recursion, 14 | -misc-use-after-move, 15 | -misc-use-internal-linkage, 16 | -modernize-use-trailing-return-type, 17 | -modernize-avoid-c-arrays, 18 | -modernize-use-nodiscard, 19 | -modernize-use-ranges, 20 | -performance-no-int-to-ptr, 21 | -portability-simd-intrinsics, 22 | -readability-avoid-nested-conditional-operator, 23 | -readability-braces-around-statements, 24 | -readability-implicit-bool-conversion, 25 | -readability-magic-numbers, 26 | -readability-redundant-access-specifiers, 27 | -readability-isolate-declaration, 28 | -readability-qualified-auto, 29 | -readability-convert-member-functions-to-static, 30 | -readability-misleading-indentation, 31 | -readability-function-cognitive-complexity, 32 | -readability-identifier-length, 33 | -readability-named-parameter, 34 | google-readability-casting' 35 | 36 | HeaderFilterRegex: '' -------------------------------------------------------------------------------- /Hexer/CHexerApp.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright © 2023-present Jovibor https://github.com/jovibor/ * 3 | * Hexer is a Hexadecimal Editor for Windows platform. * 4 | * Official git repository: https://github.com/jovibor/Hexer/ * 5 | * This software is available under "The Hexer License", see the LICENSE file. * 6 | *******************************************************************************/ 7 | #pragma once 8 | #include 9 | #include "HexCtrl.h" 10 | 11 | import Utility; 12 | import AppSettings; 13 | 14 | class CHexerApp final : public CWinAppEx { 15 | public: 16 | void NotifyTabsOnSettingsChange(); 17 | afx_msg void OnFileOpenFile(); 18 | [[nodiscard]] auto GetAppSettings() -> CAppSettings&; 19 | [[nodiscard]] auto GetClassName()const->LPCWSTR; 20 | auto OpenDocumentCustom(LPCWSTR pwszPath, bool fDontLNK) -> CDocument*; 21 | auto OpenDocumentCustom(const ut::DATAOPEN& dos) -> CDocument*; 22 | auto OpenDocumentFile(LPCWSTR pwszPath) -> CDocument* override; 23 | private: 24 | BOOL InitInstance()override; 25 | int ExitInstance()override; 26 | afx_msg void OnAppAbout(); 27 | afx_msg void OnFileNewFile(); 28 | afx_msg void OnFileOpenDevice(); 29 | afx_msg void OnFileOpenProcess(); 30 | afx_msg void OnToolsSettings(); 31 | afx_msg void OnFileRFL(UINT uID); 32 | DECLARE_MESSAGE_MAP(); 33 | private: 34 | CAppSettings m_stAppSettings; 35 | bool m_fMainAppInSingleAppMode { false }; 36 | }; 37 | 38 | extern CHexerApp theApp; -------------------------------------------------------------------------------- /Hexer/CChildFrame.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright © 2023-present Jovibor https://github.com/jovibor/ * 3 | * Hexer is a Hexadecimal Editor for Windows platform. * 4 | * Official git repository: https://github.com/jovibor/Hexer/ * 5 | * This software is available under "The Hexer License", see the LICENSE file. * 6 | *******************************************************************************/ 7 | #pragma once 8 | 9 | class CMainFrame; //Forward declarations. 10 | class CHexerView; 11 | namespace HEXCTRL { class IHexCtrl; } 12 | class CChildFrame final : public CMDIChildWndEx { 13 | public: 14 | [[nodiscard]] auto GetHexerView()const->CHexerView*; 15 | [[nodiscard]] bool OnBeforeClose(); 16 | void SetHexerView(CHexerView* pView); 17 | private: 18 | auto GetFrameIcon()const->HICON override; 19 | [[nodiscard]] auto GetMainFrame()const->CMainFrame*; 20 | [[nodiscard]] auto GetHexCtrl()const->HEXCTRL::IHexCtrl*; 21 | afx_msg void OnClose(); 22 | BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)override; 23 | afx_msg void OnDestroy(); 24 | void OnFrameActivate(); 25 | void OnFrameDisactivate(); 26 | afx_msg void OnMDIActivate(BOOL bActivate, CWnd* pActivateWnd, CWnd* pDeactivateWnd); 27 | DECLARE_DYNCREATE(CChildFrame); 28 | DECLARE_MESSAGE_MAP(); 29 | private: 30 | CHexerView* m_pHexerView { }; 31 | std::vector m_vecWndHidden; //HWNDs that must be shown/hidden on tab activating/disactivating. 32 | int m_iMDIActivateCreation { 2 }; 33 | bool m_fClosing { false }; //Indicates that a child-frame is closing. 34 | bool m_fCreating { false }; //Indicates that a child-frame is creating. 35 | }; -------------------------------------------------------------------------------- /Hexer/Dialogs/HexerPropGridCtrl.ixx: -------------------------------------------------------------------------------- 1 | module; 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | export module HexerPropGridCtrl; 8 | 9 | //CHexerPropGridCtrl. 10 | export class CHexerPropGridCtrl final : public CMFCPropertyGridCtrl { 11 | private: 12 | void OnSize(UINT /*f*/, int /*cx*/, int /*cy*/) { 13 | EndEditItem(); 14 | AdjustLayout(); 15 | } 16 | DECLARE_MESSAGE_MAP(); 17 | }; 18 | 19 | BEGIN_MESSAGE_MAP(CHexerPropGridCtrl, CMFCPropertyGridCtrl) 20 | ON_WM_SIZE() 21 | END_MESSAGE_MAP() 22 | 23 | 24 | //CHexerPropGridProp 25 | export class CHexerPropGridProp final : public CMFCPropertyGridProperty { 26 | public: 27 | using CMFCPropertyGridProperty::CMFCPropertyGridProperty; //All base class ctors. 28 | BOOL AddOptionEx(LPCWSTR lpszOption, DWORD_PTR dwData); 29 | auto FormatProperty() -> CString override; 30 | void OnDrawValue(CDC* pDC, CRect rect)override; 31 | void SetValueColor(COLORREF clr); 32 | void SetValueFromData(DWORD_PTR dwData); 33 | private: 34 | void OnSelectCombo()override; 35 | private: 36 | std::unordered_map m_umapData; //Options->Data map. 37 | COLORREF m_clrValue { 0xFFFFFFFFUL }; //Value text color. 38 | }; 39 | 40 | BOOL CHexerPropGridProp::AddOptionEx(LPCWSTR lpszOption, DWORD_PTR dwData) 41 | { 42 | m_umapData[lpszOption] = dwData; 43 | return CMFCPropertyGridProperty::AddOption(lpszOption, TRUE); 44 | } 45 | 46 | auto CHexerPropGridProp::FormatProperty()->CString 47 | { 48 | //Formatting output string for floats and doubles. 49 | switch (GetValue().vt) { 50 | case VT_R4: //float. 51 | return std::format(L"{:.2f}", GetValue().fltVal).data(); 52 | case VT_R8: //double. 53 | return std::format(L"{:.2f}", GetValue().dblVal).data(); 54 | default: 55 | return CMFCPropertyGridProperty::FormatProperty(); 56 | } 57 | } 58 | 59 | 60 | void CHexerPropGridProp::OnDrawValue(CDC* pDC, CRect rect) 61 | { 62 | if (m_clrValue != 0xFFFFFFFFUL) { 63 | const auto clrOld = pDC->SetTextColor(m_clrValue); 64 | CMFCPropertyGridProperty::OnDrawValue(pDC, rect); 65 | pDC->SetTextColor(clrOld); 66 | } 67 | else { 68 | CMFCPropertyGridProperty::OnDrawValue(pDC, rect); 69 | } 70 | } 71 | 72 | void CHexerPropGridProp::SetValueColor(COLORREF clr) 73 | { 74 | m_clrValue = clr; 75 | } 76 | 77 | void CHexerPropGridProp::SetValueFromData(DWORD_PTR dwData) 78 | { 79 | for (const auto& [key, value] : m_umapData) { 80 | if (value == dwData) { 81 | SetValue(key.data()); 82 | SetData(dwData); 83 | } 84 | } 85 | } 86 | 87 | void CHexerPropGridProp::OnSelectCombo() 88 | { 89 | CMFCPropertyGridProperty::OnSelectCombo(); 90 | SetData(m_umapData[GetValue().bstrVal]); 91 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}] 4 | cpp_generate_documentation_comments = xml 5 | cpp_indent_braces = false 6 | cpp_indent_multi_line_relative_to = innermost_parenthesis 7 | cpp_indent_within_parentheses = indent 8 | cpp_indent_preserve_within_parentheses = true 9 | cpp_indent_case_contents = true 10 | cpp_indent_case_labels = false 11 | cpp_indent_case_contents_when_block = false 12 | cpp_indent_lambda_braces_when_parameter = true 13 | cpp_indent_goto_labels = one_left 14 | cpp_indent_preprocessor = one_left 15 | cpp_indent_access_specifiers = false 16 | cpp_indent_namespace_contents = true 17 | cpp_indent_preserve_comments = true 18 | cpp_new_line_before_open_brace_namespace = same_line 19 | cpp_new_line_before_open_brace_type = same_line 20 | cpp_new_line_before_open_brace_function = ignore 21 | cpp_new_line_before_open_brace_block = same_line 22 | cpp_new_line_before_open_brace_lambda = same_line 23 | cpp_new_line_scope_braces_on_separate_lines = false 24 | cpp_new_line_close_brace_same_line_empty_type = false 25 | cpp_new_line_close_brace_same_line_empty_function = false 26 | cpp_new_line_before_catch = true 27 | cpp_new_line_before_else = true 28 | cpp_new_line_before_while_in_do_while = false 29 | cpp_space_before_function_open_parenthesis = remove 30 | cpp_space_within_parameter_list_parentheses = false 31 | cpp_space_between_empty_parameter_list_parentheses = false 32 | cpp_space_after_keywords_in_control_flow_statements = true 33 | cpp_space_within_control_flow_statement_parentheses = false 34 | cpp_space_before_lambda_open_parenthesis = false 35 | cpp_space_within_cast_parentheses = false 36 | cpp_space_after_cast_close_parenthesis = false 37 | cpp_space_within_expression_parentheses = false 38 | cpp_space_before_block_open_brace = true 39 | cpp_space_between_empty_braces = true 40 | cpp_space_before_initializer_list_open_brace = true 41 | cpp_space_within_initializer_list_braces = true 42 | cpp_space_preserve_in_initializer_list = false 43 | cpp_space_before_open_square_bracket = false 44 | cpp_space_within_square_brackets = false 45 | cpp_space_before_empty_square_brackets = false 46 | cpp_space_between_empty_square_brackets = false 47 | cpp_space_group_square_brackets = true 48 | cpp_space_within_lambda_brackets = false 49 | cpp_space_between_empty_lambda_brackets = false 50 | cpp_space_before_comma = false 51 | cpp_space_after_comma = true 52 | cpp_space_remove_around_member_operators = true 53 | cpp_space_before_inheritance_colon = true 54 | cpp_space_before_constructor_colon = true 55 | cpp_space_remove_before_semicolon = true 56 | cpp_space_after_semicolon = true 57 | cpp_space_remove_around_unary_operator = true 58 | cpp_space_around_binary_operator = insert 59 | cpp_space_around_assignment_operator = insert 60 | cpp_space_pointer_reference_alignment = ignore 61 | cpp_space_around_ternary_operator = insert 62 | cpp_wrap_preserve_blocks = one_liners 63 | -------------------------------------------------------------------------------- /Hexer/CHexerDoc.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright © 2023-present Jovibor https://github.com/jovibor/ * 3 | * Hexer is a Hexadecimal Editor for Windows platform. * 4 | * Official git repository: https://github.com/jovibor/Hexer/ * 5 | * This software is available under "The Hexer License", see the LICENSE file. * 6 | *******************************************************************************/ 7 | #pragma once 8 | #include 9 | #include 10 | #include "HexCtrl.h" 11 | 12 | import DataLoader; 13 | import Utility; 14 | 15 | class CHexerDoc final : public CDocument { 16 | public: 17 | void ChangeDataAccessMode(ut::DATAACCESS stDAC); 18 | void ChangeDataIOMode(ut::EDataIOMode eDataIOMode); 19 | [[nodiscard]] auto GetCacheSize()const->DWORD; 20 | [[nodiscard]] auto GetDataAccessMode()const->ut::DATAACCESS; 21 | [[nodiscard]] auto GetDataIOMode()const->ut::EDataIOMode; 22 | [[nodiscard]] auto GetDataPath()const->const std::wstring&; 23 | [[nodiscard]] auto GetDataSize()const->std::uint64_t; 24 | [[nodiscard]] auto GetDocIcon()const->HICON; 25 | [[nodiscard]] auto GetFileMMAPData()const->std::byte*; 26 | [[nodiscard]] auto GetFileName()const->const std::wstring&; 27 | [[nodiscard]] auto GetFriendlyName()const->const std::wstring&; 28 | [[nodiscard]] auto GetMaxVirtOffset()const->std::uint64_t; 29 | [[nodiscard]] auto GetMemPageSize()const->DWORD; 30 | [[nodiscard]] auto GetOpenMode()const->ut::EOpenMode; 31 | [[nodiscard]] auto GetProcID()const->DWORD; 32 | [[nodiscard]] auto GetVecProcMemory()const->const std::vector&; 33 | [[nodiscard]] auto GetIHexVirtData() -> HEXCTRL::IHexVirtData*; 34 | [[nodiscard]] bool IsDataAccessRWINPLACE()const; 35 | [[nodiscard]] bool IsDataAccessRWSAFE()const; 36 | [[nodiscard]] bool IsDataAccessRO(); 37 | [[nodiscard]] bool IsDataAccessRW(); //Is data access currently set to RW or RO? 38 | [[nodiscard]] bool IsDataOKForDASAFE()const; 39 | [[nodiscard]] bool IsDataWritable()const; //Is data opened writable or read only? 40 | [[nodiscard]] bool IsDevice()const; 41 | [[nodiscard]] bool IsFile()const; 42 | [[nodiscard]] bool IsProcess()const; 43 | [[nodiscard]] bool OnOpenDocument(const ut::DATAOPEN& dos); 44 | void SaveDataToDisk(); 45 | static auto GetUniqueDocName(const ut::DATAOPEN& dos) -> std::wstring; 46 | static auto GetDocTitle(const ut::DATAOPEN& dos) -> std::wstring; 47 | private: 48 | [[nodiscard]] auto GetMainFrame()const->CMainFrame*; 49 | BOOL OnOpenDocument(LPCWSTR lpszPathName)override; 50 | void OnCloseDocument()override; 51 | DECLARE_DYNCREATE(CHexerDoc); 52 | DECLARE_MESSAGE_MAP(); 53 | private: 54 | CDataLoader m_stDataLoader; 55 | std::wstring m_wstrDataPath; 56 | std::wstring m_wstrFileName; 57 | std::wstring m_wstrFriendlyName; 58 | HICON m_hDocIcon { }; //Document icon. 59 | bool m_fOpened { false }; //Document was successfully opened or not. 60 | }; -------------------------------------------------------------------------------- /Hexer/CHexerView.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright © 2023-present Jovibor https://github.com/jovibor/ * 3 | * Hexer is a Hexadecimal Editor for Windows platform. * 4 | * Official git repository: https://github.com/jovibor/Hexer/ * 5 | * This software is available under "The Hexer License", see the LICENSE file. * 6 | *******************************************************************************/ 7 | #pragma once 8 | #include "HexCtrl.h" 9 | 10 | import Utility; 11 | import DlgProcMemory; 12 | 13 | class CMainFrame; 14 | class CChildFrame; 15 | class CHexerDoc; 16 | class CHexerView final : public CView { 17 | public: 18 | [[nodiscard]] auto GetDataInfo()const->ut::DATAINFO; 19 | [[nodiscard]] auto GetDlgProcMemory()const->HWND; 20 | [[nodiscard]] auto GetDocument()const->CHexerDoc*; 21 | [[nodiscard]] auto GetHexCtrl()const->HEXCTRL::IHexCtrl*; 22 | [[nodiscard]] auto GetHWNDForPane(UINT uPaneID) -> HWND; 23 | [[nodiscard]] bool OnBeforeClose(); 24 | private: 25 | void ChangeDataAccessMode(ut::DATAACCESS stDAC); 26 | void ChangeDataIOMode(ut::EDataIOMode eDataIOMode); 27 | [[nodiscard]] auto GetChildFrame()const->CChildFrame*; 28 | [[nodiscard]] auto GetMainFrame()const->CMainFrame*; 29 | void HexCtrlSetData(bool fAdjust = false); 30 | [[nodiscard]] bool IsPaneAlreadyLaunch(UINT uPaneID)const; 31 | void OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView)override; 32 | afx_msg void OnDataAccessRO(); 33 | afx_msg void OnDataAccessRWSAFE(); 34 | afx_msg void OnDataAccessRWINPLACE(); 35 | afx_msg void OnDataIOMMAP(); 36 | afx_msg void OnDataIOBuff(); 37 | afx_msg void OnDataIOImmediate(); 38 | void OnDraw(CDC* pDC)override; 39 | afx_msg void OnEditCopyHex(); 40 | afx_msg void OnEditPasteHex(); 41 | afx_msg void OnEditUndo(); 42 | afx_msg void OnEditRedo(); 43 | afx_msg void OnFilePrint(); 44 | afx_msg void OnFileSave(); 45 | afx_msg void OnHexCtrlDLG(NMHDR* pNMHDR, LRESULT* pResult); 46 | afx_msg void OnHexCtrlSetData(NMHDR* pNMHDR, LRESULT* pResult); 47 | afx_msg void OnHexCtrlSetFont(NMHDR* pNMHDR, LRESULT* pResult); 48 | void OnInitialUpdate()override; 49 | afx_msg void OnSize(UINT nType, int cx, int cy); 50 | void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)override; 51 | afx_msg void OnUpdateDataAccessMode(CCmdUI* pCmdUI); 52 | afx_msg void OnUpdateDataIOMode(CCmdUI* pCmdUI); 53 | afx_msg void OnUpdateFileSave(CCmdUI* pCmdUI); 54 | afx_msg void OnUpdateProcMemory(CCmdUI* pCmdUI); 55 | afx_msg void OnViewProcMemory(); 56 | void SetPaneAlreadyLaunch(UINT uPaneID); 57 | void SaveDataToDisk(); 58 | void UpdateDlgBkmMgr()const; 59 | void UpdateDlgDataInterp()const; 60 | void UpdateDlgModify()const; 61 | void UpdateDlgSearch()const; 62 | void UpdateDlgTemplMgr()const; 63 | void UpdateHexCtrlDlgData(UINT uPaneID)const; 64 | DECLARE_DYNCREATE(CHexerView); 65 | DECLARE_MESSAGE_MAP(); 66 | private: 67 | HEXCTRL::IHexCtrlPtr m_pHexCtrl { HEXCTRL::CreateHexCtrl() }; 68 | CDlgProcMemory m_dlgProcMem; 69 | bool m_fIsAlreadyLaunchDlgBkmMgr { false }; 70 | bool m_fIsAlreadyLaunchDlgTemplMgr { false }; 71 | bool m_fIsAlreadyLaunchDlgDataInterp { false }; 72 | bool m_fIsHexCtrlDataModified { false }; 73 | }; -------------------------------------------------------------------------------- /Hexer/Dialogs/DlgNewFile.ixx: -------------------------------------------------------------------------------- 1 | module; 2 | /******************************************************************************* 3 | * Copyright © 2023-present Jovibor https://github.com/jovibor/ * 4 | * Hexer is a Hexadecimal Editor for Windows platform. * 5 | * Official git repository: https://github.com/jovibor/Hexer/ * 6 | * This software is available under "The Hexer License", see the LICENSE file. * 7 | *******************************************************************************/ 8 | #include 9 | #include "resource.h" 10 | #include 11 | #include 12 | #include 13 | export module DlgNewFile; 14 | 15 | import Utility; 16 | 17 | export class CDlgNewFile final : public CDialogEx { 18 | public: 19 | CDlgNewFile(CWnd* pParent = nullptr) : CDialogEx(IDD_NEWFILE, pParent) { } 20 | [[nodiscard]] auto GetOpenData()const->const ut::DATAOPEN&; 21 | private: 22 | void DoDataExchange(CDataExchange* pDX)override; 23 | [[nodiscard]] bool IsOK()const; 24 | BOOL OnInitDialog()override; 25 | afx_msg void OnBtnBrowse(); 26 | afx_msg void OnChangeEditPathAndSize(); 27 | void OnOK()override; 28 | DECLARE_MESSAGE_MAP(); 29 | private: 30 | CComboBox m_stComboMeasure; 31 | CEdit m_stEditPath; 32 | CEdit m_stEditSize; 33 | ut::DATAOPEN m_stDOS; 34 | }; 35 | 36 | BEGIN_MESSAGE_MAP(CDlgNewFile, CDialogEx) 37 | ON_BN_CLICKED(IDC_NEWFILE_BTN_BROWSE, &CDlgNewFile::OnBtnBrowse) 38 | ON_EN_CHANGE(IDC_NEWFILE_EDIT_PATH, &CDlgNewFile::OnChangeEditPathAndSize) 39 | ON_EN_CHANGE(IDC_NEWFILE_EDIT_SIZE, &CDlgNewFile::OnChangeEditPathAndSize) 40 | END_MESSAGE_MAP() 41 | 42 | auto CDlgNewFile::GetOpenData()const->const ut::DATAOPEN& 43 | { 44 | return m_stDOS; 45 | } 46 | 47 | 48 | //Private methods. 49 | 50 | void CDlgNewFile::DoDataExchange(CDataExchange* pDX) 51 | { 52 | CDialogEx::DoDataExchange(pDX); 53 | DDX_Control(pDX, IDC_NEWFILE_EDIT_PATH, m_stEditPath); 54 | DDX_Control(pDX, IDC_NEWFILE_EDIT_SIZE, m_stEditSize); 55 | DDX_Control(pDX, IDC_NEWFILE_COMBO_MEASURE, m_stComboMeasure); 56 | } 57 | 58 | bool CDlgNewFile::IsOK()const 59 | { 60 | return (m_stEditPath.GetWindowTextLengthW() > 0) && (m_stEditSize.GetWindowTextLengthW() > 0); 61 | } 62 | 63 | BOOL CDlgNewFile::OnInitDialog() 64 | { 65 | CDialogEx::OnInitDialog(); 66 | 67 | auto iIndex = m_stComboMeasure.AddString(L"Bytes"); 68 | m_stComboMeasure.SetItemData(iIndex, 1); 69 | m_stComboMeasure.SetCurSel(iIndex); 70 | iIndex = m_stComboMeasure.AddString(L"KB (1024 Bytes)"); 71 | m_stComboMeasure.SetItemData(iIndex, 1024); 72 | iIndex = m_stComboMeasure.AddString(L"MB (1024 KB)"); 73 | m_stComboMeasure.SetItemData(iIndex, 1024 * 1024); 74 | iIndex = m_stComboMeasure.AddString(L"GB (1024 MB)"); 75 | m_stComboMeasure.SetItemData(iIndex, 1024 * 1024 * 1024); 76 | 77 | const auto hIcon = AfxGetApp()->LoadIconW(IDR_HEXER_FRAME); 78 | SetIcon(hIcon, TRUE); 79 | SetIcon(hIcon, FALSE); 80 | 81 | return TRUE; 82 | } 83 | 84 | void CDlgNewFile::OnBtnBrowse() 85 | { 86 | CFileDialog fd(FALSE, nullptr, nullptr, 87 | OFN_OVERWRITEPROMPT | OFN_EXPLORER | OFN_DONTADDTORECENT | OFN_ENABLESIZING | OFN_PATHMUSTEXIST); 88 | if (fd.DoModal() == IDOK) { 89 | m_stEditPath.SetWindowTextW(fd.GetPathName()); 90 | } 91 | } 92 | 93 | void CDlgNewFile::OnChangeEditPathAndSize() 94 | { 95 | GetDlgItem(IDOK)->EnableWindow(IsOK()); 96 | } 97 | 98 | void CDlgNewFile::OnOK() 99 | { 100 | CStringW cwstrSize; 101 | m_stEditSize.GetWindowTextW(cwstrSize); 102 | const auto optSize = stn::StrToUInt64(cwstrSize.GetString()); 103 | if (!optSize || *optSize == 0) { 104 | MessageBoxW(L"Enter correct file size.", L"Incorrect file size", MB_ICONERROR); 105 | return; 106 | } 107 | 108 | CStringW cwstrPath; 109 | m_stEditPath.GetWindowTextW(cwstrPath); 110 | m_stDOS.eOpenMode = ut::EOpenMode::NEW_FILE; 111 | m_stDOS.wstrDataPath = cwstrPath; 112 | m_stDOS.ullSizeNewFile = *optSize * m_stComboMeasure.GetItemData(m_stComboMeasure.GetCurSel()); 113 | 114 | CDialogEx::OnOK(); 115 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *stacktrace.* 6 | *.zip 7 | *.rar 8 | *.exe 9 | *.pydevproject 10 | .project 11 | .metadata 12 | bin/ 13 | tmp/ 14 | *.tmp 15 | *.bak 16 | *.swp 17 | *~.nib 18 | local.properties 19 | .classpath 20 | .settings/ 21 | .loadpath 22 | 23 | # External tool builders 24 | .externalToolBuilders/ 25 | 26 | # Locally stored "Eclipse launch configurations" 27 | *.launch 28 | 29 | # CDT-specific 30 | .cproject 31 | 32 | # PDT-specific 33 | .buildpath 34 | 35 | 36 | ################# 37 | ## Visual Studio 38 | ################# 39 | 40 | ## Ignore Visual Studio temporary files, build results, and 41 | ## files generated by popular Visual Studio add-ons. 42 | 43 | .vs/ 44 | 45 | # User-specific files 46 | *.suppress 47 | *.suo 48 | *.user 49 | *.sln.docstates 50 | *.opendb 51 | *solution_suppressions.cfg 52 | 53 | # Build results 54 | 55 | [Dd]ebug*/ 56 | [Rr]elease*/ 57 | x64/ 58 | build/ 59 | [Bb]in/ 60 | [Oo]bj/ 61 | 62 | # MSTest test Results 63 | [Tt]est[Rr]esult*/ 64 | [Bb]uild[Ll]og.* 65 | 66 | *_i.c 67 | *_p.c 68 | *.ilk 69 | *.meta 70 | *.obj 71 | *.pch 72 | *.pdb 73 | *.pgc 74 | *.pgd 75 | *.rsp 76 | *.sbr 77 | *.tlb 78 | *.tli 79 | *.tlh 80 | *.tmp 81 | *.tmp_proj 82 | *.log 83 | *.vspscc 84 | *.vssscc 85 | .builds 86 | *.pidb 87 | *.log 88 | *.scc 89 | 90 | # Visual C++ cache files 91 | ipch/ 92 | *.aps 93 | *.ncb 94 | *.opensdf 95 | *.sdf 96 | *.cachefile 97 | *.cd 98 | *.i-* 99 | 100 | # Visual Studio profiler 101 | *.psess 102 | *.vsp 103 | *.vspx 104 | 105 | # Guidance Automation Toolkit 106 | *.gpState 107 | 108 | # ReSharper is a .NET coding add-in 109 | _ReSharper*/ 110 | *.[Rr]e[Ss]harper 111 | 112 | # TeamCity is a build add-in 113 | _TeamCity* 114 | 115 | # DotCover is a Code Coverage Tool 116 | *.dotCover 117 | 118 | # NCrunch 119 | *.ncrunch* 120 | .*crunch*.local.xml 121 | 122 | # Installshield output folder 123 | [Ee]xpress/ 124 | 125 | # DocProject is a documentation generator add-in 126 | DocProject/buildhelp/ 127 | DocProject/Help/*.HxT 128 | DocProject/Help/*.HxC 129 | DocProject/Help/*.hhc 130 | DocProject/Help/*.hhk 131 | DocProject/Help/*.hhp 132 | DocProject/Help/Html2 133 | DocProject/Help/html 134 | 135 | # Click-Once directory 136 | publish/ 137 | 138 | # Publish Web Output 139 | *.Publish.xml 140 | *.pubxml 141 | *.publishproj 142 | 143 | # NuGet Packages Directory 144 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 145 | #packages/ 146 | 147 | # Windows Azure Build Output 148 | csx 149 | *.build.csdef 150 | 151 | # Windows Store app package directory 152 | AppPackages/ 153 | 154 | # Others 155 | sql/ 156 | *.Cache 157 | ClientBin/ 158 | [Ss]tyle[Cc]op.* 159 | ~$* 160 | *~ 161 | *.dbmdl 162 | *.[Pp]ublish.xml 163 | *.pfx 164 | *.publishsettings 165 | 166 | # RIA/Silverlight projects 167 | Generated_Code/ 168 | 169 | # Backup & report files from converting an old project file to a newer 170 | # Visual Studio version. Backup files are not needed, because we have git ;-) 171 | _UpgradeReport_Files/ 172 | Backup*/ 173 | UpgradeLog*.XML 174 | UpgradeLog*.htm 175 | 176 | # SQL Server files 177 | App_Data/*.mdf 178 | App_Data/*.ldf 179 | 180 | ############# 181 | ## Windows detritus 182 | ############# 183 | 184 | # Windows image file caches 185 | Thumbs.db 186 | ehthumbs.db 187 | 188 | # Folder config file 189 | Desktop.ini 190 | 191 | # Recycle Bin used on file shares 192 | $RECYCLE.BIN/ 193 | 194 | # Mac crap 195 | .DS_Store 196 | 197 | 198 | ############# 199 | ## Python 200 | ############# 201 | 202 | *.py[cod] 203 | 204 | # Packages 205 | *.egg 206 | *.egg-info 207 | dist/ 208 | build/ 209 | eggs/ 210 | parts/ 211 | var/ 212 | sdist/ 213 | develop-eggs/ 214 | .installed.cfg 215 | 216 | # Installer logs 217 | pip-log.txt 218 | 219 | # Unit test / coverage reports 220 | .coverage 221 | .tox 222 | 223 | #Translations 224 | *.mo 225 | 226 | #Mr Developer 227 | .mr.developer.cfg 228 | *.db 229 | *.db -------------------------------------------------------------------------------- /Hexer/CMainFrame.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright © 2023-present Jovibor https://github.com/jovibor/ * 3 | * Hexer is a Hexadecimal Editor for Windows platform. * 4 | * Official git repository: https://github.com/jovibor/Hexer/ * 5 | * This software is available under "The Hexer License", see the LICENSE file. * 6 | *******************************************************************************/ 7 | #pragma once 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | import DlgDataInfo; 16 | import DlgLogger; 17 | import HexerDockablePane; 18 | import Utility; 19 | 20 | class CHexerView; //Forward declarations. 21 | namespace HEXCTRL { class IHexCtrl; } 22 | class CMainFrame final : public CMDIFrameWndEx { 23 | public: 24 | void AddLogEntry(const ut::Log::LOGINFO& stData); 25 | [[nodiscard]] int& GetChildFramesCount(); 26 | [[nodiscard]] bool IsAppClosing()const; 27 | [[nodiscard]] bool IsPaneVisible(UINT uPaneID); //Is Pane visible even if pane's window itself is tabbed and hidden atm (not active). 28 | [[nodiscard]] bool IsPaneActive(UINT uPaneID); //Is Pane itself visible atm. 29 | BOOL LoadFrame(UINT nIDResource, DWORD dwDefaultStyle = WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, 30 | CWnd* pParentWnd = nullptr, CCreateContext* pContext = nullptr)override; 31 | void OnChildFrameActivate(); 32 | void OnChildFrameCloseLast(); //When the last child frame is closed. 33 | void OnChildFrameDisactivate(); 34 | void OnChildFrameOpenFirst(); //When the first child frame is opened. 35 | void ShowPane(UINT uPaneID, bool fShow, bool fActivate); 36 | void UpdatePaneFileInfo(); 37 | protected: 38 | [[nodiscard]] auto GetDlgDataBkmMgr() -> std::uint64_t; 39 | [[nodiscard]] auto GetDlgDataDataInterp() -> std::uint64_t; 40 | [[nodiscard]] auto GetDlgDataModify() -> std::uint64_t; 41 | [[nodiscard]] auto GetDlgDataSearch() -> std::uint64_t; 42 | [[nodiscard]] auto GetDlgDataTemplMgr() -> std::uint64_t; 43 | [[nodiscard]] auto GetHexCtrl() -> HEXCTRL::IHexCtrl*; 44 | [[nodiscard]] auto GetHexCtrlDlgData(HEXCTRL::EHexWnd eWnd) -> std::uint64_t; 45 | [[nodiscard]] auto GetHexerView() -> CHexerView*; 46 | [[nodiscard]] auto GetHWNDForPane(UINT uPaneID) -> HWND; 47 | [[nodiscard]] auto GetPanesMap() -> const std::unordered_map&; 48 | [[nodiscard]] auto GetPtrFromPaneID(UINT uPaneID) -> CHexerDockablePane*; 49 | [[nodiscard]] bool HasChildFrame(); 50 | void HideAllPanes(); 51 | afx_msg auto OnAddLogEntry(WPARAM wParam, LPARAM lParam) -> LRESULT; 52 | afx_msg auto OnAppSettingsChanged(WPARAM wParam, LPARAM lParam) -> LRESULT; 53 | [[nodiscard]] bool OnBeforeClose(); 54 | afx_msg void OnClose(); 55 | BOOL OnCloseDockingPane(CDockablePane* pPane)override; 56 | afx_msg BOOL OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCDS); 57 | afx_msg int OnCreate(LPCREATESTRUCT lpcs); 58 | BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)override; 59 | afx_msg BOOL OnEraseMDIClientBackground(CDC* pDC)override; 60 | auto OnGetTabTooltip(WPARAM wParam, LPARAM lParam) -> LRESULT; 61 | afx_msg void OnUpdateRangePanes(CCmdUI* pCmdUI); 62 | afx_msg void OnViewCustomize(); 63 | afx_msg void OnViewRangePanes(UINT uMenuID); 64 | BOOL PreCreateWindow(CREATESTRUCT& cs)override; 65 | BOOL PreTranslateMessage(MSG* pMsg)override; 66 | void SaveHexCtrlSettings(); 67 | void SavePaneData(UINT uPaneID); 68 | void SavePanesSettings(); 69 | DECLARE_DYNAMIC(CMainFrame); 70 | DECLARE_MESSAGE_MAP(); 71 | private: 72 | static auto MDIClientProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uID, DWORD_PTR dwData) -> LRESULT; 73 | static void MDIClientSize(HWND hWnd, WPARAM wParam, LPARAM lParam); 74 | inline static CFont m_fontMDIClient; 75 | CMFCToolBar m_wndToolBar; 76 | CWnd* m_pWndMBtnCurrDown { }; 77 | CHexerDockablePane m_paneDataInfo; 78 | CHexerDockablePane m_paneBkmMgr; 79 | CHexerDockablePane m_paneDataInterp; 80 | CHexerDockablePane m_paneTemplMgr; 81 | CHexerDockablePane m_paneLogInfo; 82 | CDlgDataInfo m_dlgDataInfo; 83 | CDlgLogger m_dlgLogInfo; 84 | int m_iChildFrames { }; //Amount of active child frames. 85 | bool m_fClosing { false }; //Indicates that the app is closing now. 86 | }; -------------------------------------------------------------------------------- /Hexer/CChildFrame.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright © 2023-present Jovibor https://github.com/jovibor/ * 3 | * Hexer is a Hexadecimal Editor for Windows platform. * 4 | * Official git repository: https://github.com/jovibor/Hexer/ * 5 | * This software is available under "The Hexer License", see the LICENSE file. * 6 | *******************************************************************************/ 7 | #include "stdafx.h" 8 | #include "CHexerApp.h" 9 | #include "CMainFrame.h" 10 | #include "CChildFrame.h" 11 | #include "CHexerDoc.h" 12 | #include "CHexerView.h" 13 | 14 | import Utility; 15 | 16 | #ifdef _DEBUG 17 | #define new DEBUG_NEW 18 | #endif 19 | 20 | IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWndEx) 21 | 22 | BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWndEx) 23 | ON_WM_CLOSE() 24 | ON_WM_DESTROY() 25 | ON_WM_MDIACTIVATE() 26 | END_MESSAGE_MAP() 27 | 28 | auto CChildFrame::GetHexerView()const->CHexerView* 29 | { 30 | return m_pHexerView; 31 | } 32 | 33 | bool CChildFrame::OnBeforeClose() 34 | { 35 | const auto pView = GetHexerView();; 36 | if (pView == nullptr) 37 | return true; 38 | 39 | return pView->OnBeforeClose(); 40 | } 41 | 42 | void CChildFrame::SetHexerView(CHexerView* pView) 43 | { 44 | m_pHexerView = pView; 45 | } 46 | 47 | 48 | //Private methods. 49 | 50 | auto CChildFrame::GetFrameIcon()const->HICON 51 | { 52 | const auto pView = GetHexerView(); 53 | if (pView == nullptr) { 54 | return { }; 55 | } 56 | 57 | return pView->GetDocument()->GetDocIcon(); 58 | } 59 | 60 | auto CChildFrame::GetMainFrame()const->CMainFrame* 61 | { 62 | return reinterpret_cast(AfxGetMainWnd()); 63 | } 64 | 65 | auto CChildFrame::GetHexCtrl()const->HEXCTRL::IHexCtrl* 66 | { 67 | if (const auto pView = GetHexerView(); pView != nullptr) { 68 | return pView->GetHexCtrl(); 69 | } 70 | 71 | return { }; 72 | } 73 | 74 | void CChildFrame::OnClose() 75 | { 76 | if (!OnBeforeClose()) { 77 | return; 78 | } 79 | 80 | m_fClosing = true; 81 | CMDIChildWndEx::OnClose(); 82 | } 83 | 84 | BOOL CChildFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) 85 | { 86 | m_fCreating = true; 87 | ++GetMainFrame()->GetChildFramesCount(); 88 | return CMDIChildWndEx::OnCreateClient(lpcs, pContext); 89 | } 90 | 91 | void CChildFrame::OnDestroy() 92 | { 93 | --GetMainFrame()->GetChildFramesCount(); 94 | CMDIChildWndEx::OnDestroy(); 95 | } 96 | 97 | void CChildFrame::OnFrameActivate() 98 | { 99 | for (const auto hWnd : m_vecWndHidden) { //Show all hidden dialogs. 100 | ::ShowWindow(hWnd, SW_SHOW); 101 | } 102 | m_vecWndHidden.clear(); 103 | 104 | GetMainFrame()->OnChildFrameActivate(); 105 | } 106 | 107 | void CChildFrame::OnFrameDisactivate() 108 | { 109 | //HexCtrl dialogs that is not in panes. They must be hidden/restored during tab switching. 110 | static constexpr HEXCTRL::EHexWnd arrHexDlg[] { HEXCTRL::EHexWnd::DLG_CODEPAGE, HEXCTRL::EHexWnd::DLG_GOTO, 111 | HEXCTRL::EHexWnd::DLG_MODIFY, HEXCTRL::EHexWnd::DLG_SEARCH }; 112 | 113 | for (const auto eWnd : arrHexDlg) { //Hide all active HexCtrl dialogs. 114 | if (const auto hWnd = GetHexCtrl()->GetWndHandle(eWnd, false); ::IsWindowVisible(hWnd)) { 115 | ::ShowWindow(hWnd, SW_HIDE); 116 | m_vecWndHidden.emplace_back(hWnd); 117 | } 118 | } 119 | 120 | if (const auto hWnd = GetHexerView()->GetDlgProcMemory(); ::IsWindowVisible(hWnd)) { //Hide DlgProcMemory. 121 | ::ShowWindow(hWnd, SW_HIDE); 122 | m_vecWndHidden.emplace_back(hWnd); 123 | } 124 | 125 | GetMainFrame()->OnChildFrameDisactivate(); 126 | } 127 | 128 | void CChildFrame::OnMDIActivate(BOOL bActivate, CWnd* pActivateWnd, CWnd* pDeactivateWnd) 129 | { 130 | CMDIChildWndEx::OnMDIActivate(bActivate, pActivateWnd, pDeactivateWnd); 131 | 132 | const auto pMainFrame = GetMainFrame(); 133 | 134 | if (m_fCreating) { 135 | if (pMainFrame->GetChildFramesCount() == 1) { //Indicates that the first tab is opening now. 136 | pMainFrame->OnChildFrameOpenFirst(); 137 | m_fCreating = false; 138 | return; 139 | } 140 | 141 | //Buggy MFC sends two WM_MDIACTIVATE messages to the child-frame, when second and subsequent tabs are created. 142 | //This count is to prevent unnecessary OnChildFrameActivate calls. 143 | if (--m_iMDIActivateCreation == 0) { 144 | pMainFrame->OnChildFrameActivate(); 145 | m_fCreating = false; 146 | } 147 | 148 | return; 149 | } 150 | 151 | if (m_fClosing) { 152 | if (pMainFrame->GetChildFramesCount() == 1) { //Indicates that the last tab is closing now. 153 | pMainFrame->OnChildFrameCloseLast(); 154 | } 155 | 156 | return; 157 | } 158 | 159 | bActivate ? OnFrameActivate() : OnFrameDisactivate(); 160 | } -------------------------------------------------------------------------------- /Hexer/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Hexer.rc 4 | // 5 | #define IDD_ABOUTBOX 100 6 | #define IDD_OPENDEVICE 101 7 | #define IDD_OPENDEVICE_DRIVE 102 8 | #define IDD_OPENDEVICE_VOLUME 103 9 | #define IDD_OPENDEVICE_PATH 104 10 | #define IDD_OPENPROCESS 105 11 | #define IDD_NEWFILE 106 12 | #define IDD_SETTINGS 107 13 | #define IDD_DATAINFO 108 14 | #define IDD_LOGGER 109 15 | #define IDD_SETTINGSHEXCTRL 110 16 | #define IDD_SETTINGSGENERAL 111 17 | #define IDD_PROCMEMORY 112 18 | #define IDR_MAINFRAME 200 19 | #define IDR_HEXER_FRAME 201 20 | #define IDR_TOOLBAR_MAIN 202 21 | #define IDB_FILE 203 22 | #define IDB_DEVICE 204 23 | #define IDB_PROCESS 205 24 | #define IDC_LINK_HEXER 300 25 | #define IDC_LINK_HEXCTRL 301 26 | #define IDC_STATIC_BUILDTIME 302 27 | #define IDC_NEWFILE_EDIT_SIZE 303 28 | #define IDC_NEWFILE_COMBO_MEASURE 304 29 | #define IDC_NEWFILE_EDIT_PATH 305 30 | #define IDC_NEWFILE_BTN_BROWSE 306 31 | #define IDC_OPENDEVICE_TAB 307 32 | #define IDC_OPENDEVICE_STATIC_INFO 308 33 | #define IDC_OPENDRIVE_LIST 309 34 | #define IDC_OPENVOLUME_LIST 310 35 | #define IDC_OPENPATH_COMBO_PATH 311 36 | #define IDC_PANE_DATAINFO 312 37 | #define IDC_PANE_BKMMGR 313 38 | #define IDC_PANE_DATAINTERP 314 39 | #define IDC_PANE_TEMPLMGR 315 40 | #define IDC_PANE_LOGGER 316 41 | #define IDC_HEXCTRL_MAIN 317 42 | #define IDC_SETTINGS_TAB 318 43 | #define IDC_FILEINFO_GRID 319 44 | #define IDC_LOGINFO_LIST 320 45 | #define IDC_SETTINGSHEXCTRL_GRID 321 46 | #define IDC_SETTINGS_DEFS 322 47 | #define IDC_SETTINGSGENERAL_GRID 323 48 | #define IDC_ABOUT_STATIC_VERSION 324 49 | #define IDC_OPENPROCESS_LIST_PROCS 325 50 | #define IDC_OPENPROCESS_LIST_MODULES 326 51 | #define IDC_OPENPROCESS_BTN_REFRESH 327 52 | #define IDC_OPENPROCESS_STAT_INFO 328 53 | #define IDC_PROCMEMORY_LIST 329 54 | #define IDC_SETTINGS_APPLY 330 55 | #define IDM_FILE_RFL00 32770 56 | #define IDM_FILE_RFL01 32771 57 | #define IDM_FILE_RFL02 32772 58 | #define IDM_FILE_RFL03 32773 59 | #define IDM_FILE_RFL04 32774 60 | #define IDM_FILE_RFL05 32775 61 | #define IDM_FILE_RFL06 32776 62 | #define IDM_FILE_RFL07 32777 63 | #define IDM_FILE_RFL08 32778 64 | #define IDM_FILE_RFL09 32779 65 | #define IDM_FILE_RFL10 32780 66 | #define IDM_FILE_RFL11 32781 67 | #define IDM_FILE_RFL12 32782 68 | #define IDM_FILE_RFL13 32783 69 | #define IDM_FILE_RFL14 32784 70 | #define IDM_FILE_RFL15 32785 71 | #define IDM_FILE_RFL16 32786 72 | #define IDM_FILE_RFL17 32787 73 | #define IDM_FILE_RFL18 32788 74 | #define IDM_FILE_RFL19 32789 75 | #define IDM_FILE_NEWFILE 32790 76 | #define IDM_FILE_OPENFILE 32791 77 | #define IDM_FILE_OPENDEVICE 32792 78 | #define IDM_FILE_OPENPROCESS 32793 79 | #define IDM_FILE_SAVE 32794 80 | #define IDM_FILE_PRINT 32795 81 | #define IDM_EDIT_UNDO 32796 82 | #define IDM_EDIT_REDO 32797 83 | #define IDM_EDIT_COPYHEX 32798 84 | #define IDM_EDIT_PASTEHEX 32799 85 | #define IDM_VIEW_DATAINFO 32800 86 | #define IDM_VIEW_BKMMGR 32801 87 | #define IDM_VIEW_DATAINTERP 32802 88 | #define IDM_VIEW_TEMPLMGR 32803 89 | #define IDM_VIEW_LOGGER 32804 90 | #define IDM_VIEW_PROCMEMORY 32805 91 | #define IDM_TOOLS_SETTINGS 32806 92 | #define IDM_TOOLBAR_CUSTOMIZE 32807 93 | #define IDM_DA_RO 32808 94 | #define IDM_DA_RWSAFE 32809 95 | #define IDM_DA_RWINPLACE 32810 96 | #define IDM_DA_DATAIO_MMAP 32811 97 | #define IDM_DA_DATAIO_IOBUFF 32812 98 | #define IDM_DA_DATAIO_IOIMMEDIATE 32813 99 | 100 | // Next default values for new objects 101 | // 102 | #ifdef APSTUDIO_INVOKED 103 | #ifndef APSTUDIO_READONLY_SYMBOLS 104 | #define _APS_NEXT_RESOURCE_VALUE 330 105 | #define _APS_NEXT_COMMAND_VALUE 32814 106 | #define _APS_NEXT_CONTROL_VALUE 331 107 | #define _APS_NEXT_SYMED_VALUE 330 108 | #endif 109 | #endif 110 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Hexer 2 | **Hexer** is a free, fast, multi-tab hex editor, based on the [HexCtrl](https://github.com/jovibor/HexCtrl), and developed with the MFC library. **Hexer** is mostly a hobby project developed in spare time. 3 | 4 | ![](docs/img/Hexer_Main.jpg) 5 | 6 | ## Features 7 | * View and edit Files, Disks, Partitions and Processes, up to **16EB** (exabyte) 8 | * Fully-featured **Bookmarks Manager** 9 | * Fully-featured **Search and Replace** 10 | * Many options to **Copy/Paste** to/from the clipboard 11 | * **Undo/Redo** 12 | * Modify data with **Filling** and many **Operations** options 13 | * Ability to visually divide data into pages 14 | * Powerful system of [Templates](#templates) 15 | * And many more... 16 | 17 | ## How To Build 18 | 1. Clone git repo with all submodules: 19 | `git clone https://github.com/jovibor/Hexer.git --recurse-submodules` 20 | 1. Open `Hexer\Hexer.sln` solution in the **Visual Studio 2022** or newer 21 | 22 | ## [](#)Templates 23 | ![](docs/img/HexCtrl_Templates.jpg) 24 | **Hexer**'s templates is a powerful system of a data structures' description with a simple `.json` file. 25 | ```json 26 | { 27 | "$schema": "https://raw.githubusercontent.com/jovibor/HexCtrl/master/docs/HexCtrl.Templates.Schema.json", 28 | "TemplateName": "SampleTemplate", 29 | "Data": { 30 | "endianness": "little", 31 | "clrBk": "#999999", 32 | "clrText": "#FFFFFF", 33 | "Fields": [ 34 | { 35 | "name": "MyCustomDataSingle", 36 | "type": "MyCustomType" 37 | }, 38 | { 39 | "name": "CustomComplexData", 40 | "type": "MyCustomComplexType" 41 | }, 42 | { 43 | "name": "ArrayOfDWORDs", 44 | "type": "DWORD", 45 | "array": 10 46 | }, 47 | { 48 | "name": "MyCustomDataArray", 49 | "type": "MyCustomType", 50 | "array": 4 51 | } 52 | ] 53 | }, 54 | "CustomTypes": [ 55 | { 56 | "TypeName": "MyCustomType", 57 | "Fields": [ 58 | { 59 | "name": "myCustomTypeField1", 60 | "type": "DWORD" 61 | }, 62 | { 63 | "name": "myCustomTypeField2", 64 | "type": "DWORD" 65 | } 66 | ] 67 | }, 68 | { 69 | "TypeName": "MyCustomComplexType", 70 | "Fields": [ 71 | { 72 | "name": "MyCustomTypeData1", 73 | "type": "MyCustomType" 74 | }, 75 | { 76 | "name": "MyCustomTypeData2", 77 | "type": "MyCustomType" 78 | } 79 | ] 80 | } 81 | ] 82 | } 83 | ``` 84 | Every such file contains the following properties: 85 | - **TemplateName** [mandatory, string] - the name of the template 86 | - **Data** [mandatory, object] - main object that contains all template field's information 87 | - **CustomTypes** [optional, array] - array of a user defined types, that can be then referenced in the **type** property of the **Fields** 88 | 89 | **CustomTypes** objects are the same as **Fields** objects, the only difference is the **TypeName** property which **Fields** objects don't have. 90 | 91 | Every **Data** or **CustomType** object contains **Fields** property with actual struct members. 92 | 93 | **Fields** [array] - is an array of objects where every object represents a struct data member. Any such object can have its own **Fields** sub-objects, which will represent nested structs. 94 | The **Fields**'s properties include: 95 | - **name** - [mandatory, string] - name of the field 96 | - **description** - [optional, string] - field description 97 | - **type** - [optional, string] - field type, such as: 98 | `bool`, `char`, `unsigned char`, `byte`, `short`, `unsigned short`, `WORD`, `long`, `unsigned long`, `int`, `unsigned int`, `DWORD`, `long long`, `unsigned long long`, `QWORD`, `float`, `double`, `time32_t`, `time64_t`, `FILETIME`, `SYSTEMTIME`, `GUID`, or any custom type defined in the **CustomTypes** section 99 | - **size** - [optional, int] - size of the field in bytes, if the **type** field is not provided 100 | - **array** - [optional, int] - size of the array, if the given field is an array of fields 101 | - **endianness** - [optional, string] - field endianness, "little" or "big". By default all fields are little-endian. 102 | - **clrBk** - [optional, string] - field background color 103 | - **clrText** - [optional, string] - field text color 104 | 105 | The **endianness**, **clrBk** and **clrText** properties that locate at the same level as the **Fields** property, would mean the default properties for all the **Fields** objects of that level and below the line, unless they explicitly redefined in the field itself. 106 | 107 | For the available templates check the `Templates` directory. 108 | 109 | ## License 110 | **Hexer** is available under **"The Hexer License"**, see the [LICENSE](https://github.com/jovibor/Hexer/blob/master/LICENSE) file. -------------------------------------------------------------------------------- /Hexer/Dialogs/DlgLogger.ixx: -------------------------------------------------------------------------------- 1 | module; 2 | /******************************************************************************* 3 | * Copyright © 2023-present Jovibor https://github.com/jovibor/ * 4 | * Hexer is a Hexadecimal Editor for Windows platform. * 5 | * Official git repository: https://github.com/jovibor/Hexer/ * 6 | * This software is available under "The Hexer License", see the LICENSE file. * 7 | *******************************************************************************/ 8 | #include 9 | #include "resource.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | export module DlgLogger; 16 | 17 | import Utility; 18 | 19 | export class CDlgLogger final : public CDialogEx { 20 | public: 21 | void AddLogEntry(const ut::Log::LOGINFO& stData); 22 | private: 23 | void ClearAll(); 24 | void DoDataExchange(CDataExchange* pDX)override; 25 | void OnCancel()override; 26 | BOOL OnCommand(WPARAM wParam, LPARAM lParam)override; 27 | afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct); 28 | BOOL OnInitDialog()override; 29 | afx_msg void OnListGetDispInfo(NMHDR* pNMHDR, LRESULT* pResult); 30 | afx_msg void OnListGetIcon(NMHDR* pNMHDR, LRESULT* pResult); 31 | afx_msg void OnListRClick(NMHDR* pNMHDR, LRESULT* pResult); 32 | afx_msg void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct); 33 | void OnOK()override; 34 | DECLARE_MESSAGE_MAP(); 35 | private: 36 | enum class EMenuID : std::uint16_t { 37 | IDM_LIST_CLEARALL = 0x8001 38 | }; 39 | struct LOGDATA { //Struct for storing log data. 40 | std::time_t time; 41 | std::wstring wstrMsg; 42 | ut::Log::EMsgType eType { }; 43 | }; 44 | lex::CListEx m_List; 45 | std::vector m_vecData; 46 | CImageList m_stImgList; 47 | CMenu m_menuList; 48 | }; 49 | 50 | BEGIN_MESSAGE_MAP(CDlgLogger, CDialogEx) 51 | ON_NOTIFY(LVN_GETDISPINFOW, IDC_LOGINFO_LIST, &CDlgLogger::OnListGetDispInfo) 52 | ON_NOTIFY(NM_RCLICK, IDC_LOGINFO_LIST, &CDlgLogger::OnListRClick) 53 | ON_NOTIFY(lex::LISTEX_MSG_GETICON, IDC_LOGINFO_LIST, &CDlgLogger::OnListGetIcon) 54 | ON_WM_DRAWITEM() 55 | ON_WM_MEASUREITEM() 56 | END_MESSAGE_MAP() 57 | 58 | void CDlgLogger::AddLogEntry(const ut::Log::LOGINFO& li) 59 | { 60 | m_vecData.emplace_back(li.time, std::wstring { li.wsvMsg }, li.eType); 61 | 62 | if (::IsWindow(m_hWnd)) { 63 | m_List.SetItemCountEx(static_cast(m_vecData.size()), LVSICF_NOINVALIDATEALL); 64 | m_List.EnsureVisible(m_List.GetItemCount() - 1, FALSE); 65 | } 66 | } 67 | 68 | 69 | //Private methods. 70 | 71 | void CDlgLogger::ClearAll() 72 | { 73 | m_vecData.clear(); 74 | m_List.SetItemCountEx(static_cast(m_vecData.size()), LVSICF_NOSCROLL); 75 | } 76 | 77 | void CDlgLogger::DoDataExchange(CDataExchange* pDX) 78 | { 79 | CDialogEx::DoDataExchange(pDX); 80 | } 81 | 82 | void CDlgLogger::OnCancel() 83 | { 84 | //Just an empty handler, to not close Dialog on Escape key. 85 | } 86 | 87 | BOOL CDlgLogger::OnCommand(WPARAM wParam, LPARAM lParam) 88 | { 89 | switch (static_cast(LOWORD(wParam))) { 90 | case EMenuID::IDM_LIST_CLEARALL: 91 | ClearAll(); 92 | return TRUE; 93 | default: 94 | break; 95 | } 96 | 97 | return CDialogEx::OnCommand(wParam, lParam); 98 | } 99 | 100 | void CDlgLogger::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) 101 | { 102 | if (nIDCtl == IDC_LOGINFO_LIST) { 103 | m_List.DrawItem(lpDrawItemStruct); 104 | return; 105 | } 106 | 107 | CDialogEx::OnDrawItem(nIDCtl, lpDrawItemStruct); 108 | } 109 | 110 | BOOL CDlgLogger::OnInitDialog() 111 | { 112 | CDialogEx::OnInitDialog(); 113 | 114 | m_List.CreateDialogCtrl(IDC_LOGINFO_LIST, m_hWnd); 115 | m_List.SetExtendedStyle(LVS_EX_HEADERDRAGDROP); 116 | m_List.InsertColumn(0, L"№", 0, 30); 117 | m_List.InsertColumn(1, L"Time", 0, 70); 118 | m_List.InsertColumn(2, L"Event", 0, 1000); 119 | 120 | m_menuList.CreatePopupMenu(); 121 | m_menuList.AppendMenuW(MF_STRING, static_cast(EMenuID::IDM_LIST_CLEARALL), L"Clear All"); 122 | 123 | const auto iIconSize = static_cast(16 * ut::GetHiDPIInfo().flDPIScale); 124 | m_stImgList.Create(iIconSize, iIconSize, ILC_COLOR32 | ILC_MASK, 3, 3); 125 | 126 | //Icons added in exact order: "msg_error, msg_warning, msg_info" as the enum values in the EMsgType. 127 | m_stImgList.Add(static_cast(LoadImageW(nullptr, IDI_ERROR, IMAGE_ICON, 0, 0, LR_SHARED))); 128 | m_stImgList.Add(static_cast(LoadImageW(nullptr, IDI_WARNING, IMAGE_ICON, 0, 0, LR_SHARED))); 129 | m_stImgList.Add(static_cast(LoadImageW(nullptr, IDI_INFORMATION, IMAGE_ICON, 0, 0, LR_SHARED))); 130 | m_List.SetImageList(m_stImgList, LVSIL_NORMAL); 131 | m_List.SetItemCountEx(static_cast(m_vecData.size()), LVSICF_NOSCROLL); //m_vecData can already have data. 132 | 133 | if (const auto pLayout = GetDynamicLayout()) { 134 | pLayout->SetMinSize({ 0, 0 }); 135 | } 136 | 137 | return TRUE; 138 | } 139 | 140 | void CDlgLogger::OnListGetDispInfo(NMHDR* pNMHDR, LRESULT* /*pResult*/) 141 | { 142 | const auto pDI = reinterpret_cast(pNMHDR); 143 | const auto pItem = &pDI->item; 144 | if ((pItem->mask & LVIF_TEXT) == 0) 145 | return; 146 | 147 | const auto iItem = pItem->iItem; 148 | const auto& refData = m_vecData[iItem]; 149 | switch (pItem->iSubItem) { 150 | case 0: //№. 151 | *std::format_to(pItem->pszText, L"{}", iItem + 1) = L'\0'; 152 | break; 153 | case 1: //Time. 154 | *std::format_to(pItem->pszText, L"{}", ut::TimetToWstr(refData.time)) = L'\0'; 155 | break; 156 | case 2: //Event. 157 | *std::format_to(pItem->pszText, L"{}", refData.wstrMsg) = L'\0'; 158 | break; 159 | default: 160 | break; 161 | } 162 | } 163 | 164 | void CDlgLogger::OnListGetIcon(NMHDR* pNMHDR, LRESULT* pResult) 165 | { 166 | const auto pLII = reinterpret_cast(pNMHDR); 167 | if (pLII->iItem < 0 || pLII->iSubItem != 2) //Event field. 168 | return; 169 | 170 | pLII->iIconIndex = std::to_underlying(m_vecData[pLII->iItem].eType); //Icon index in list's image list. 171 | *pResult = TRUE; 172 | } 173 | 174 | void CDlgLogger::OnListRClick(NMHDR* /*pNMHDR*/, LRESULT* /*pResult*/) 175 | { 176 | POINT pt; 177 | GetCursorPos(&pt); 178 | m_menuList.TrackPopupMenuEx(TPM_LEFTALIGN, pt.x, pt.y, this, nullptr); 179 | } 180 | 181 | void CDlgLogger::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct) 182 | { 183 | if (nIDCtl == IDC_LOGINFO_LIST) { 184 | m_List.MeasureItem(lpMeasureItemStruct); 185 | return; 186 | } 187 | 188 | CDialogEx::OnMeasureItem(nIDCtl, lpMeasureItemStruct); 189 | } 190 | 191 | void CDlgLogger::OnOK() 192 | { 193 | //Just an empty handler, to not close Dialog on Enter key. 194 | } -------------------------------------------------------------------------------- /Hexer/Dialogs/DlgProcMemory.ixx: -------------------------------------------------------------------------------- 1 | module; 2 | /******************************************************************************* 3 | * Copyright © 2023-present Jovibor https://github.com/jovibor/ * 4 | * Hexer is a Hexadecimal Editor for Windows platform. * 5 | * Official git repository: https://github.com/jovibor/Hexer/ * 6 | * This software is available under "The Hexer License", see the LICENSE file. * 7 | *******************************************************************************/ 8 | #include 9 | #include "resource.h" 10 | #include 11 | #include "HexCtrl.h" 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | export module DlgProcMemory; 18 | 19 | import Utility; 20 | 21 | export class CDlgProcMemory final : public CDialogEx { 22 | public: 23 | CDlgProcMemory(CWnd* pParent = nullptr) : CDialogEx(IDD_PROCMEMORY, pParent) { } 24 | void Init(HEXCTRL::IHexCtrl* pHexCtrl, const std::vector& vec); 25 | private: 26 | void DoDataExchange(CDataExchange* pDX)override; 27 | BOOL OnInitDialog()override; 28 | afx_msg void OnListProcMemoryColumnClick(NMHDR* pNMHDR, LRESULT* pResult); 29 | afx_msg void OnListProcMemoryGetColor(NMHDR* pNMHDR, LRESULT* pResult); 30 | afx_msg void OnListProcMemoryGetDispInfo(NMHDR* pNMHDR, LRESULT* pResult); 31 | afx_msg void OnListProcMemoryItemChanged(NMHDR* pNMHDR, LRESULT* pResult); 32 | BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)override; 33 | DECLARE_MESSAGE_MAP(); 34 | private: 35 | lex::CListEx m_pListProcMem; 36 | HEXCTRL::IHexCtrl* m_pHexCtrl { }; 37 | const std::vector* m_pVecProcMemory { }; 38 | }; 39 | 40 | BEGIN_MESSAGE_MAP(CDlgProcMemory, CDialogEx) 41 | ON_NOTIFY(LVN_GETDISPINFOW, IDC_PROCMEMORY_LIST, &CDlgProcMemory::OnListProcMemoryGetDispInfo) 42 | ON_NOTIFY(lex::LISTEX_MSG_GETCOLOR, IDC_PROCMEMORY_LIST, &CDlgProcMemory::OnListProcMemoryGetColor) 43 | ON_NOTIFY(LVN_ITEMCHANGED, IDC_PROCMEMORY_LIST, &CDlgProcMemory::OnListProcMemoryItemChanged) 44 | END_MESSAGE_MAP() 45 | 46 | void CDlgProcMemory::Init(HEXCTRL::IHexCtrl* pHexCtrl, const std::vector& vec) 47 | { 48 | m_pHexCtrl = pHexCtrl; 49 | m_pVecProcMemory = &vec; 50 | } 51 | 52 | void CDlgProcMemory::DoDataExchange(CDataExchange* pDX) 53 | { 54 | CDialogEx::DoDataExchange(pDX); 55 | } 56 | 57 | BOOL CDlgProcMemory::OnInitDialog() 58 | { 59 | CDialogEx::OnInitDialog(); 60 | 61 | assert(m_pVecProcMemory != nullptr); 62 | 63 | m_pListProcMem.CreateDialogCtrl(IDC_PROCMEMORY_LIST, m_hWnd); 64 | m_pListProcMem.InsertColumn(0, L"Address Range", LVCFMT_CENTER, 170); 65 | m_pListProcMem.InsertColumn(1, L"Size", LVCFMT_CENTER, 70, -1, LVCFMT_CENTER); 66 | m_pListProcMem.InsertColumn(2, L"Protection", LVCFMT_CENTER, 180); 67 | m_pListProcMem.InsertColumn(3, L"Type", LVCFMT_CENTER, 100); 68 | m_pListProcMem.SetItemCountEx(static_cast(m_pVecProcMemory->size())); 69 | 70 | const auto hIcon = AfxGetApp()->LoadIconW(IDR_HEXER_FRAME); 71 | SetIcon(hIcon, TRUE); 72 | SetIcon(hIcon, FALSE); 73 | 74 | return TRUE; 75 | } 76 | 77 | void CDlgProcMemory::OnListProcMemoryColumnClick(NMHDR* /*pNMHDR*/, LRESULT* /*pResult*/) 78 | { 79 | } 80 | 81 | void CDlgProcMemory::OnListProcMemoryItemChanged(NMHDR* pNMHDR, LRESULT* /*pResult*/) 82 | { 83 | const auto pNMI = reinterpret_cast(pNMHDR); 84 | const auto iItem = pNMI->iItem; 85 | const auto iSubItem = pNMI->iSubItem; 86 | if (iItem < 0 || iSubItem < 0 || !(pNMI->uNewState & LVIS_SELECTED)) 87 | return; 88 | 89 | const auto ullOffset = m_pHexCtrl->GetOffset(reinterpret_cast((*m_pVecProcMemory)[iItem].BaseAddress), false); 90 | m_pHexCtrl->SetCaretPos(ullOffset, true, false); 91 | m_pHexCtrl->GoToOffset(ullOffset, -1); 92 | } 93 | 94 | void CDlgProcMemory::OnListProcMemoryGetColor(NMHDR* pNMHDR, LRESULT* /*pResult*/) 95 | { 96 | const auto pLCI = reinterpret_cast(pNMHDR); 97 | if (pLCI->iSubItem == 2) { //Protection. 98 | constexpr DWORD dwWritable = PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY; 99 | if ((*m_pVecProcMemory)[pLCI->iItem].Protect & dwWritable) { 100 | pLCI->stClr = { RGB(80, 200, 80), RGB(250, 250, 250) }; 101 | } 102 | } 103 | } 104 | 105 | void CDlgProcMemory::OnListProcMemoryGetDispInfo(NMHDR* pNMHDR, LRESULT* /*pResult*/) 106 | { 107 | static const std::unordered_map umapMemProtect { 108 | { PAGE_NOACCESS, L"PAGE_NOACCESS" }, 109 | { PAGE_READONLY, L"PAGE_READONLY" }, 110 | { PAGE_READWRITE, L"PAGE_READWRITE" }, 111 | { PAGE_WRITECOPY, L"PAGE_WRITECOPY" }, 112 | { PAGE_EXECUTE, L"PAGE_EXECUTE" }, 113 | { PAGE_EXECUTE_READ, L"PAGE_EXECUTE_READ" }, 114 | { PAGE_EXECUTE_READWRITE, L"PAGE_EXECUTE_READWRITE" }, 115 | { PAGE_EXECUTE_WRITECOPY, L"PAGE_EXECUTE_WRITECOPY" }, 116 | { PAGE_GUARD, L"PAGE_GUARD" }, 117 | { PAGE_NOCACHE, L"PAGE_NOCACHE" }, 118 | { PAGE_WRITECOMBINE, L"PAGE_WRITECOMBINE" }, 119 | { PAGE_TARGETS_INVALID, L"PAGE_TARGETS_INVALID" }, 120 | { PAGE_ENCLAVE_DECOMMIT, L"PAGE_ENCLAVE_DECOMMIT" }, 121 | { PAGE_ENCLAVE_THREAD_CONTROL, L"PAGE_ENCLAVE_THREAD_CONTROL" }, 122 | { PAGE_ENCLAVE_UNVALIDATED, L"PAGE_ENCLAVE_UNVALIDATED" } 123 | }; 124 | static const std::unordered_map umapMemType { 125 | { MEM_IMAGE, L"MEM_IMAGE" }, { MEM_MAPPED, L"MEM_MAPPED" }, { MEM_PRIVATE, L"MEM_PRIVATE" } 126 | }; 127 | 128 | const auto pDI = reinterpret_cast(pNMHDR); 129 | const auto pItem = &pDI->item; 130 | if ((pItem->mask & LVIF_TEXT) == 0) 131 | return; 132 | 133 | const auto iItem = pItem->iItem; 134 | const auto iSubItem = pItem->iSubItem; 135 | assert(m_pVecProcMemory != nullptr); 136 | const auto& ref = (*m_pVecProcMemory)[iItem]; 137 | 138 | switch (iSubItem) { 139 | case 0: //Offset range. 140 | { 141 | const auto ullOffset = reinterpret_cast(ref.BaseAddress); 142 | *std::format_to(pItem->pszText, L"{:X}h-{:X}h", ullOffset, ullOffset + ref.RegionSize) = L'\0'; 143 | } 144 | break; 145 | case 1: //Size. 146 | *std::format_to(pItem->pszText, L"{:X}h", ref.RegionSize) = L'\0'; 147 | break; 148 | case 2: //Protection. 149 | { 150 | std::wstring wstrData; 151 | for (const auto& [dwFlag, pwszData] : umapMemProtect) { 152 | if (dwFlag & ref.Protect) { 153 | if (!wstrData.empty()) { 154 | wstrData += L" | "; 155 | } 156 | wstrData += pwszData; 157 | } 158 | } 159 | *std::format_to(pItem->pszText, L"{}", wstrData) = L'\0'; 160 | } 161 | break; 162 | case 3: //Type. 163 | if (const auto it = umapMemType.find(ref.Type); it != umapMemType.end()) { 164 | *std::format_to(pItem->pszText, L"{}", it->second) = L'\0'; 165 | } 166 | break; 167 | default: 168 | break; 169 | } 170 | } 171 | 172 | BOOL CDlgProcMemory::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT * pResult) 173 | { 174 | const auto* const pNMI = reinterpret_cast(lParam); 175 | 176 | if (pNMI->hdr.idFrom == IDC_PROCMEMORY_LIST) { 177 | if (pNMI->hdr.code == LVN_COLUMNCLICK) { 178 | OnListProcMemoryColumnClick(reinterpret_cast(lParam), pResult); 179 | return TRUE; 180 | } 181 | } 182 | 183 | return CDialogEx::OnNotify(wParam, lParam, pResult); 184 | } -------------------------------------------------------------------------------- /Hexer/Dialogs/DlgDataInfo.ixx: -------------------------------------------------------------------------------- 1 | module; 2 | /******************************************************************************* 3 | * Copyright © 2023-present Jovibor https://github.com/jovibor/ * 4 | * Hexer is a Hexadecimal Editor for Windows platform. * 5 | * Official git repository: https://github.com/jovibor/Hexer/ * 6 | * This software is available under "The Hexer License", see the LICENSE file. * 7 | *******************************************************************************/ 8 | #include 9 | #include "resource.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | export module DlgDataInfo; 17 | 18 | import Utility; 19 | import HexerPropGridCtrl; 20 | 21 | //CDlgDataInfo. 22 | export class CDlgDataInfo final : public CDialogEx { 23 | public: 24 | void SetDataInfo(const ut::DATAINFO& dis); 25 | private: 26 | void DoDataExchange(CDataExchange* pDX)override; 27 | BOOL OnInitDialog()override; 28 | void UpdateGridData(); 29 | DECLARE_MESSAGE_MAP(); 30 | private: 31 | enum class EPropName : std::uint8_t { 32 | DATA_PATH = 0x1, DATA_NAME, FRIENDLY_NAME, DATA_SIZE, PAGE_SIZE, ACCESS_MODE, IO_MODE 33 | }; 34 | CHexerPropGridCtrl m_gridDataInfo; 35 | std::vector m_vecPropsDataProps; 36 | CFont m_fntFilePropsGrid; 37 | ut::DATAINFO m_dis; 38 | }; 39 | 40 | BEGIN_MESSAGE_MAP(CDlgDataInfo, CDialogEx) 41 | END_MESSAGE_MAP() 42 | 43 | 44 | //Private methods. 45 | 46 | void CDlgDataInfo::SetDataInfo(const ut::DATAINFO& dis) 47 | { 48 | m_dis = dis; 49 | 50 | if (IsWindow(m_hWnd)) { 51 | UpdateGridData(); 52 | } 53 | } 54 | 55 | 56 | //Private methods. 57 | 58 | void CDlgDataInfo::DoDataExchange(CDataExchange* pDX) 59 | { 60 | CDialogEx::DoDataExchange(pDX); 61 | DDX_Control(pDX, IDC_FILEINFO_GRID, m_gridDataInfo); 62 | } 63 | 64 | BOOL CDlgDataInfo::OnInitDialog() 65 | { 66 | CDialogEx::OnInitDialog(); 67 | 68 | m_gridDataInfo.SetVSDotNetLook(); 69 | m_gridDataInfo.EnableHeaderCtrl(TRUE); 70 | HDITEMW hdPropGrid { .mask = HDI_WIDTH, .cxy = 100 }; 71 | m_gridDataInfo.GetHeaderCtrl().SetItem(0, &hdPropGrid); //Property grid left column width. 72 | 73 | //Set new bigger font to the property. 74 | const auto pFont = m_gridDataInfo.GetFont(); 75 | LOGFONTW lf { }; 76 | pFont->GetLogFont(&lf); 77 | constexpr wchar_t pwszFont[] { L"Microsoft Sans Serif" }; 78 | std::copy_n(pwszFont, std::size(pwszFont), lf.lfFaceName); 79 | const auto lFontSize = MulDiv(-lf.lfHeight, 72, ut::GetHiDPIInfo().iLOGPIXELSY) + 1; //Convert font Height to point size. 80 | lf.lfHeight = -MulDiv(lFontSize, ut::GetHiDPIInfo().iLOGPIXELSY, 72); //Convert point size to font Height. 81 | m_fntFilePropsGrid.CreateFontIndirectW(&lf); 82 | m_gridDataInfo.SetFont(&m_fntFilePropsGrid); 83 | 84 | using enum EPropName; 85 | const auto pDataPath = new CHexerPropGridProp(L"", L""); 86 | pDataPath->SetData(static_cast(DATA_PATH)); 87 | pDataPath->SetValueColor(RGB(0, 0, 250)); 88 | pDataPath->AllowEdit(FALSE); 89 | m_vecPropsDataProps.emplace_back(pDataPath); 90 | m_gridDataInfo.AddProperty(pDataPath); 91 | 92 | const auto pDataName = new CHexerPropGridProp(L"", L""); 93 | pDataName->SetData(static_cast(DATA_NAME)); 94 | pDataName->SetValueColor(RGB(0, 0, 250)); 95 | pDataName->AllowEdit(FALSE); 96 | m_vecPropsDataProps.emplace_back(pDataName); 97 | m_gridDataInfo.AddProperty(pDataName); 98 | 99 | const auto pFriendlyName = new CHexerPropGridProp(L"Friendly Name:", L""); 100 | pFriendlyName->SetData(static_cast(FRIENDLY_NAME)); 101 | pFriendlyName->SetValueColor(RGB(0, 0, 250)); 102 | pFriendlyName->AllowEdit(FALSE); 103 | m_vecPropsDataProps.emplace_back(pFriendlyName); 104 | m_gridDataInfo.AddProperty(pFriendlyName); 105 | 106 | const auto pDataSize = new CHexerPropGridProp(L"", L""); 107 | pDataSize->SetData(static_cast(DATA_SIZE)); 108 | pDataSize->SetValueColor(RGB(0, 0, 250)); 109 | pDataSize->AllowEdit(FALSE); 110 | m_vecPropsDataProps.emplace_back(pDataSize); 111 | m_gridDataInfo.AddProperty(pDataSize); 112 | 113 | const auto pPageSize = new CHexerPropGridProp(L"Page Size:", L""); 114 | pPageSize->SetData(static_cast(PAGE_SIZE)); 115 | pPageSize->SetValueColor(RGB(0, 0, 250)); 116 | pPageSize->AllowEdit(FALSE); 117 | m_vecPropsDataProps.emplace_back(pPageSize); 118 | m_gridDataInfo.AddProperty(pPageSize); 119 | 120 | const auto pAccessMode = new CHexerPropGridProp(L"Access Mode:", L""); 121 | pAccessMode->SetData(static_cast(ACCESS_MODE)); 122 | pAccessMode->AllowEdit(FALSE); 123 | m_vecPropsDataProps.emplace_back(pAccessMode); 124 | m_gridDataInfo.AddProperty(pAccessMode); 125 | 126 | const auto pDataIOMode = new CHexerPropGridProp(L"Data IO Mode:", L""); 127 | pDataIOMode->SetData(static_cast(IO_MODE)); 128 | pDataIOMode->SetValueColor(RGB(0, 0, 250)); 129 | pDataIOMode->AllowEdit(FALSE); 130 | m_vecPropsDataProps.emplace_back(pDataIOMode); 131 | m_gridDataInfo.AddProperty(pDataIOMode); 132 | 133 | UpdateGridData(); 134 | 135 | if (const auto pLayout = GetDynamicLayout()) { 136 | pLayout->SetMinSize({ 0, 0 }); 137 | } 138 | 139 | return TRUE; 140 | } 141 | 142 | void CDlgDataInfo::UpdateGridData() 143 | { 144 | const auto lmbSetValue = [&](CHexerPropGridProp* pProp) { 145 | using enum EPropName; 146 | auto wstr = std::wstring { ut::GetWstrEOpenMode(m_dis.eOpenMode) }; 147 | switch (static_cast(pProp->GetData())) { 148 | case DATA_PATH: 149 | pProp->SetName((wstr += L" Path:").data(), FALSE); 150 | pProp->SetValue(m_dis.wsvDataPath.data()); 151 | break; 152 | case DATA_NAME: 153 | pProp->SetName((wstr += L" Name:").data(), FALSE); 154 | pProp->SetValue(m_dis.wsvFileName.data()); 155 | break; 156 | case FRIENDLY_NAME: 157 | pProp->SetValue(m_dis.wsvFriendlyName.empty() ? L"—" : m_dis.wsvFriendlyName.data()); 158 | break; 159 | case DATA_SIZE: 160 | pProp->SetName((wstr += L" Size:").data(), FALSE); 161 | pProp->SetValue(std::format(std::locale("en_US.UTF-8"), L"{:L} bytes", m_dis.ullDataSize).data()); 162 | break; 163 | case PAGE_SIZE: 164 | pProp->SetValue(std::format(L"{}", m_dis.dwPageSize).data()); 165 | break; 166 | case ACCESS_MODE: 167 | pProp->SetValue(ut::GetWstrDATAACCESS(m_dis.stDAC)); 168 | COLORREF clr; 169 | if (!m_dis.stDAC.fMutable) { 170 | clr = RGB(128, 128, 128); 171 | } 172 | else { 173 | switch (m_dis.stDAC.eDataAccessMode) { 174 | case ACCESS_SAFE: 175 | clr = RGB(20, 200, 20); 176 | break; 177 | case ACCESS_INPLACE: 178 | clr = RGB(200, 20, 20); 179 | break; 180 | default: 181 | clr = 0xFFFFFFFFUL; 182 | break; 183 | } 184 | } 185 | pProp->SetValueColor(clr); 186 | break; 187 | case IO_MODE: 188 | if (m_dis.stDAC.fMutable && m_dis.stDAC.eDataAccessMode == ut::EDataAccessMode::ACCESS_INPLACE) { 189 | pProp->SetValue(ut::GetWstrEDataIOMode(m_dis.eDataIOMode)); 190 | } 191 | else { 192 | pProp->SetValue(L"—"); 193 | } 194 | break; 195 | default: 196 | break; 197 | } 198 | }; 199 | 200 | m_gridDataInfo.SetRedraw(false); 201 | std::ranges::for_each(m_vecPropsDataProps, lmbSetValue); 202 | m_gridDataInfo.SetRedraw(true); 203 | m_gridDataInfo.RedrawWindow(); 204 | } -------------------------------------------------------------------------------- /Hexer/CHexerDoc.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright © 2023-present Jovibor https://github.com/jovibor/ * 3 | * Hexer is a Hexadecimal Editor for Windows platform. * 4 | * Official git repository: https://github.com/jovibor/Hexer/ * 5 | * This software is available under "The Hexer License", see the LICENSE file. * 6 | *******************************************************************************/ 7 | #include "stdafx.h" 8 | #include "resource.h" 9 | #include "CHexerApp.h" 10 | #include "CMainFrame.h" 11 | #include "CChildFrame.h" 12 | #include "CHexerDoc.h" 13 | #include 14 | 15 | #ifdef _DEBUG 16 | #define new DEBUG_NEW 17 | #endif 18 | 19 | IMPLEMENT_DYNCREATE(CHexerDoc, CDocument) 20 | 21 | BEGIN_MESSAGE_MAP(CHexerDoc, CDocument) 22 | END_MESSAGE_MAP() 23 | 24 | void CHexerDoc::ChangeDataAccessMode(ut::DATAACCESS stDAC) 25 | { 26 | m_stDataLoader.ChangeDataAccessMode(stDAC); 27 | } 28 | 29 | void CHexerDoc::ChangeDataIOMode(ut::EDataIOMode eDataIOMode) 30 | { 31 | m_stDataLoader.ChangeDataIOMode(eDataIOMode); 32 | } 33 | 34 | auto CHexerDoc::GetCacheSize()const->DWORD 35 | { 36 | return m_stDataLoader.GetCacheSize(); 37 | } 38 | 39 | auto CHexerDoc::GetDataAccessMode()const->ut::DATAACCESS 40 | { 41 | return m_stDataLoader.GetDataAccessMode(); 42 | } 43 | 44 | auto CHexerDoc::GetDataIOMode()const->ut::EDataIOMode 45 | { 46 | return m_stDataLoader.GetDataIOMode(); 47 | } 48 | 49 | auto CHexerDoc::GetDataPath()const->const std::wstring& 50 | { 51 | return m_wstrDataPath; 52 | } 53 | 54 | auto CHexerDoc::GetDataSize()const->std::uint64_t 55 | { 56 | return m_stDataLoader.GetDataSize(); 57 | } 58 | 59 | auto CHexerDoc::GetDocIcon()const->HICON 60 | { 61 | return m_hDocIcon; 62 | } 63 | 64 | auto CHexerDoc::GetFileMMAPData()const->std::byte* 65 | { 66 | return m_stDataLoader.GetFileMMAPData(); 67 | } 68 | 69 | auto CHexerDoc::GetFileName()const->const std::wstring& 70 | { 71 | return m_wstrFileName; 72 | } 73 | 74 | auto CHexerDoc::GetFriendlyName()const->const std::wstring& 75 | { 76 | return m_wstrFriendlyName; 77 | } 78 | 79 | auto CHexerDoc::GetMaxVirtOffset()const->std::uint64_t 80 | { 81 | return m_stDataLoader.GetMaxVirtOffset(); 82 | } 83 | 84 | auto CHexerDoc::GetMemPageSize()const->DWORD 85 | { 86 | return m_stDataLoader.GetMemPageSize(); 87 | } 88 | 89 | auto CHexerDoc::GetOpenMode()const->ut::EOpenMode 90 | { 91 | return m_stDataLoader.GetOpenMode(); 92 | } 93 | 94 | auto CHexerDoc::GetProcID()const->DWORD 95 | { 96 | return m_stDataLoader.GetProcID(); 97 | } 98 | 99 | auto CHexerDoc::GetVecProcMemory()const->const std::vector& 100 | { 101 | return m_stDataLoader.GetVecProcMemory(); 102 | } 103 | 104 | auto CHexerDoc::GetIHexVirtData()->HEXCTRL::IHexVirtData* 105 | { 106 | return m_stDataLoader.GetIHexVirtData(); 107 | } 108 | 109 | bool CHexerDoc::IsDataAccessRWINPLACE() const 110 | { 111 | const auto stDAC = GetDataAccessMode(); 112 | return stDAC.fMutable && stDAC.eDataAccessMode == ut::EDataAccessMode::ACCESS_INPLACE; 113 | } 114 | 115 | bool CHexerDoc::IsDataAccessRWSAFE()const 116 | { 117 | const auto stDAC = GetDataAccessMode(); 118 | return stDAC.fMutable && stDAC.eDataAccessMode == ut::EDataAccessMode::ACCESS_SAFE; 119 | } 120 | 121 | bool CHexerDoc::IsDataAccessRO() 122 | { 123 | return !IsDataAccessRW(); 124 | } 125 | 126 | bool CHexerDoc::IsDataAccessRW() 127 | { 128 | return GetDataAccessMode().fMutable; 129 | } 130 | 131 | bool CHexerDoc::IsDataOKForDASAFE()const 132 | { 133 | return m_stDataLoader.IsDataOKForDASAFE(); 134 | } 135 | 136 | bool CHexerDoc::IsDataWritable()const 137 | { 138 | return m_stDataLoader.IsDataWritable(); 139 | } 140 | 141 | bool CHexerDoc::IsDevice()const 142 | { 143 | return m_stDataLoader.IsDevice(); 144 | } 145 | 146 | bool CHexerDoc::IsFile()const 147 | { 148 | return m_stDataLoader.IsFile(); 149 | } 150 | 151 | bool CHexerDoc::IsProcess()const 152 | { 153 | return m_stDataLoader.IsProcess(); 154 | } 155 | 156 | bool CHexerDoc::OnOpenDocument(const ut::DATAOPEN& dos) 157 | { 158 | m_wstrDataPath = dos.wstrDataPath; 159 | m_wstrFileName = m_wstrDataPath.substr(m_wstrDataPath.find_last_of(L'\\') + 1); //Doc name with the .extension. 160 | m_wstrFriendlyName = dos.wstrFriendlyName; 161 | auto& refSett = theApp.GetAppSettings(); 162 | if (const auto expOpen = m_stDataLoader.Open(dos, refSett.GetGeneralSettings().stDAC, 163 | refSett.GetGeneralSettings().eDataIOMode); !expOpen) { 164 | refSett.RFLRemoveFromList(dos); 165 | const auto wstrLog = std::format(L"{} open failed: {} \r\n{}", ut::GetWstrEOpenMode(GetOpenMode()), GetFileName(), 166 | ut::GetLastErrorWstr(expOpen.error())); 167 | MessageBoxW(AfxGetMainWnd()->m_hWnd, wstrLog.data(), L"Opening error", MB_ICONERROR); 168 | ut::Log::AddLogEntryError(wstrLog); 169 | 170 | return false; 171 | } 172 | 173 | refSett.RFLAddToList(dos); 174 | refSett.LOLAddToList(dos); 175 | m_strPathName = GetUniqueDocName(dos).data(); 176 | m_bEmbedded = FALSE; 177 | SetTitle(GetDocTitle(dos).data()); 178 | const auto iResID = [this]() { 179 | using enum ut::EOpenMode; 180 | switch (GetOpenMode()) { 181 | case OPEN_FILE: 182 | case NEW_FILE: 183 | return IDB_FILE; 184 | case OPEN_DRIVE: 185 | case OPEN_VOLUME: 186 | case OPEN_PATH: 187 | return IDB_DEVICE; 188 | case OPEN_PROC: 189 | return IDB_PROCESS; 190 | default: 191 | return 0; 192 | } 193 | }(); 194 | m_hDocIcon = ut::HICONfromHBITMAP(ut::GetHBITMAP(iResID)); 195 | const auto wstrLog = std::format(L"{} opened: {} ({})", ut::GetWstrEOpenMode(GetOpenMode()), GetFileName(), 196 | ut::GetWstrDATAACCESS(GetDataAccessMode())); 197 | ut::Log::AddLogEntryInfo(wstrLog); 198 | m_fOpened = true; 199 | 200 | return true; 201 | } 202 | 203 | void CHexerDoc::SaveDataToDisk() 204 | { 205 | m_stDataLoader.SaveDataToDisk(); 206 | } 207 | 208 | 209 | //Private methods. 210 | 211 | auto CHexerDoc::GetMainFrame()const->CMainFrame* 212 | { 213 | return static_cast(AfxGetMainWnd()); 214 | } 215 | 216 | BOOL CHexerDoc::OnOpenDocument(LPCWSTR lpszPathName) 217 | { 218 | return OnOpenDocument({ .wstrDataPath { lpszPathName }, .eOpenMode { ut::EOpenMode::OPEN_FILE } }); 219 | } 220 | 221 | void CHexerDoc::OnCloseDocument() 222 | { 223 | //Doing below only when closing an individual opened document, not the whole App. 224 | if (m_fOpened && !GetMainFrame()->IsAppClosing()) { 225 | std::wstring wstrInfo; 226 | if (IsProcess()) { 227 | wstrInfo = std::format(L"{} closed: {} (ID: {})", 228 | ut::GetWstrEOpenMode(GetOpenMode()), GetFileName(), GetProcID()); 229 | } 230 | else { 231 | (((wstrInfo += ut::GetWstrEOpenMode(GetOpenMode())) += L" closed: ") += GetFileName()); 232 | } 233 | 234 | ut::Log::AddLogEntryInfo(wstrInfo); 235 | theApp.GetAppSettings().LOLRemoveFromList({ .wstrDataPath { GetDataPath() }, .dwProcID { GetProcID() } }); 236 | } 237 | 238 | CDocument::OnCloseDocument(); 239 | } 240 | 241 | auto CHexerDoc::GetUniqueDocName(const ut::DATAOPEN& dos)->std::wstring 242 | { 243 | if (dos.eOpenMode == ut::EOpenMode::OPEN_PROC) { 244 | return std::format(L"Process: {} (ID: {})", dos.wstrDataPath, dos.dwProcID); 245 | } 246 | else { 247 | return dos.wstrDataPath; 248 | } 249 | } 250 | 251 | auto CHexerDoc::GetDocTitle(const ut::DATAOPEN& dos)->std::wstring 252 | { 253 | using enum ut::EOpenMode; 254 | if (dos.eOpenMode == OPEN_PROC) { 255 | return GetUniqueDocName(dos); 256 | } 257 | 258 | const auto nName = dos.wstrDataPath.find_last_of(L'\\'); 259 | assert(nName != std::wstring::npos); 260 | if (nName == std::wstring::npos) { 261 | return { }; 262 | } 263 | 264 | switch (dos.eOpenMode) { 265 | case OPEN_DRIVE: 266 | case OPEN_VOLUME: 267 | case OPEN_PATH: 268 | return std::format(L"{}: {}", ut::GetWstrEOpenMode(dos.eOpenMode), dos.wstrDataPath.substr(nName + 1)); 269 | default: 270 | return dos.wstrDataPath.substr(nName + 1); 271 | } 272 | } -------------------------------------------------------------------------------- /Hexer/Hexer.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {f36aad90-1098-4a42-b0b9-c32da156b6fd} 18 | 19 | 20 | {4bf47b7d-10f1-49ad-973f-9bd56d5ba40c} 21 | 22 | 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | HexCtrl 47 | 48 | 49 | HexCtrl 50 | 51 | 52 | 53 | 54 | Source Files 55 | 56 | 57 | Source Files 58 | 59 | 60 | Source Files 61 | 62 | 63 | Source Files 64 | 65 | 66 | Source Files 67 | 68 | 69 | Source Files 70 | 71 | 72 | Modules 73 | 74 | 75 | Modules 76 | 77 | 78 | Modules 79 | 80 | 81 | Modules 82 | 83 | 84 | Modules 85 | 86 | 87 | Modules 88 | 89 | 90 | Modules 91 | 92 | 93 | Modules 94 | 95 | 96 | HexCtrl 97 | 98 | 99 | HexCtrl 100 | 101 | 102 | HexCtrl 103 | 104 | 105 | Modules 106 | 107 | 108 | Modules 109 | 110 | 111 | Modules 112 | 113 | 114 | Modules 115 | 116 | 117 | HexCtrl 118 | 119 | 120 | HexCtrl 121 | 122 | 123 | HexCtrl 124 | 125 | 126 | HexCtrl 127 | 128 | 129 | HexCtrl 130 | 131 | 132 | HexCtrl 133 | 134 | 135 | HexCtrl 136 | 137 | 138 | HexCtrl 139 | 140 | 141 | HexCtrl 142 | 143 | 144 | HexCtrl 145 | 146 | 147 | HexCtrl 148 | 149 | 150 | 151 | 152 | Resource Files 153 | 154 | 155 | HexCtrl 156 | 157 | 158 | 159 | 160 | Resource Files 161 | 162 | 163 | Resource Files 164 | 165 | 166 | HexCtrl 167 | 168 | 169 | HexCtrl 170 | 171 | 172 | HexCtrl 173 | 174 | 175 | HexCtrl 176 | 177 | 178 | HexCtrl 179 | 180 | 181 | HexCtrl 182 | 183 | 184 | HexCtrl 185 | 186 | 187 | HexCtrl 188 | 189 | 190 | HexCtrl 191 | 192 | 193 | HexCtrl 194 | 195 | 196 | Resource Files 197 | 198 | 199 | Resource Files 200 | 201 | 202 | Resource Files 203 | 204 | 205 | 206 | 207 | Resource Files 208 | 209 | 210 | HexCtrl 211 | 212 | 213 | -------------------------------------------------------------------------------- /Hexer/Dialogs/HexerDockablePane.ixx: -------------------------------------------------------------------------------- 1 | module; 2 | /******************************************************************************* 3 | * Copyright © 2023-present Jovibor https://github.com/jovibor/ * 4 | * Hexer is a Hexadecimal Editor for Windows platform. * 5 | * Official git repository: https://github.com/jovibor/Hexer/ * 6 | * This software is available under "The Hexer License", see the LICENSE file. * 7 | *******************************************************************************/ 8 | #include 9 | #include 10 | #include 11 | export module HexerDockablePane; 12 | 13 | 14 | //CHexerPaneDivider. 15 | export class CHexerPaneDivider final : public CPaneDivider { 16 | afx_msg void OnMouseMove(UINT nFlags, CPoint pt); 17 | DECLARE_SERIAL(CHexerPaneDivider); 18 | DECLARE_MESSAGE_MAP(); 19 | }; 20 | 21 | IMPLEMENT_SERIAL(CHexerPaneDivider, CPaneDivider, 1) 22 | 23 | BEGIN_MESSAGE_MAP(CHexerPaneDivider, CPaneDivider) 24 | ON_WM_MOUSEMOVE() 25 | END_MESSAGE_MAP() 26 | 27 | void CHexerPaneDivider::OnMouseMove(UINT nFlags, CPoint pt) 28 | { 29 | CPaneDivider::OnMouseMove(nFlags, pt); 30 | 31 | //For some reason cursor doesn't turn into resizable on Windows 11. This is to circumvent. 32 | static const auto hCurHorz { static_cast(LoadImageW(nullptr, IDC_SIZEWE, IMAGE_CURSOR, 0, 0, LR_SHARED)) }; 33 | static const auto hCurVert { static_cast(LoadImageW(nullptr, IDC_SIZENS, IMAGE_CURSOR, 0, 0, LR_SHARED)) }; 34 | SetCursor(IsHorizontal() ? hCurVert : hCurHorz); 35 | 36 | //"Dirty" hack to enable dynamic pane resizing while dragging the divider. 37 | if (m_bCaptured) { 38 | StopTracking(TRUE); 39 | OnLButtonDown(nFlags, pt); 40 | } 41 | } 42 | 43 | 44 | //CHexerTabCtrl. 45 | //Tab Control class used within Panes. 46 | //Needed to override OnLButtonDblClk message. 47 | class CHexerTabCtrl final : public CMFCTabCtrl { 48 | afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); 49 | afx_msg void OnMouseMove(UINT nFlags, CPoint point); 50 | DECLARE_SERIAL(CHexerTabCtrl); 51 | DECLARE_MESSAGE_MAP(); 52 | }; 53 | 54 | IMPLEMENT_SERIAL(CHexerTabCtrl, CMFCTabCtrl, 1) 55 | 56 | BEGIN_MESSAGE_MAP(CHexerTabCtrl, CMFCTabCtrl) 57 | ON_WM_LBUTTONDBLCLK() 58 | ON_WM_MOUSEMOVE() 59 | END_MESSAGE_MAP() 60 | 61 | void CHexerTabCtrl::OnLButtonDblClk(UINT /*nFlags*/, CPoint /*point*/) 62 | { 63 | //Empty handler for tabs' doubleclicks. 64 | } 65 | 66 | void CHexerTabCtrl::OnMouseMove(UINT nFlags, CPoint point) 67 | { 68 | //This method is overriden to resolve the issue with tabs' dragging described here: 69 | //https://developercommunity.visualstudio.com/t/problem-dragging-mdi-tabs-in-a-mfc-application-com/478457 70 | 71 | CWnd::OnMouseMove(nFlags, point); 72 | 73 | const auto iPrevHighlighted = m_iHighlighted; 74 | 75 | const auto bTabCloseButtonHighlighted = m_bTabCloseButtonHighlighted; 76 | m_bTabCloseButtonHighlighted = m_rectCloseButton.PtInRect(point); 77 | 78 | if (bTabCloseButtonHighlighted != m_bTabCloseButtonHighlighted) { 79 | RedrawWindow(m_rectCloseButton); 80 | } 81 | 82 | if (m_iHighlighted >= 0 && m_iPressed < 0 && !m_bReadyToDetach) { 83 | CPoint pt = point; 84 | ClientToScreen(&pt); 85 | const auto pWnd = CWnd::WindowFromPoint(pt); 86 | if (pWnd != nullptr && pWnd->GetSafeHwnd() != GetSafeHwnd()) { 87 | ReleaseCapture(); 88 | m_iHighlighted = -1; 89 | InvalidateTab(iPrevHighlighted); 90 | return; 91 | } 92 | } 93 | 94 | m_iHighlighted = GetTabFromPoint(point); 95 | 96 | if (m_iPressed >= 0 && m_iHighlighted != m_iPressed) { 97 | m_iHighlighted = -1; 98 | } 99 | 100 | if (m_iHighlighted != iPrevHighlighted && (m_bHighLightTabs || IsActiveTabCloseButton())) { 101 | if (iPrevHighlighted < 0) { 102 | if (m_iHighlighted >= 0) { 103 | SetCapture(); 104 | } 105 | } 106 | else { 107 | if (m_iHighlighted < 0 && m_iPressed < 0) { 108 | m_bTabCloseButtonHighlighted = FALSE; 109 | m_bTabCloseButtonPressed = FALSE; 110 | 111 | if (!m_bReadyToDetach) { 112 | ReleaseCapture(); 113 | } 114 | } 115 | } 116 | 117 | InvalidateTab(m_iHighlighted); 118 | InvalidateTab(iPrevHighlighted); 119 | } 120 | 121 | if (m_bReadyToDetach) { 122 | const auto nNumTabs = m_iTabsNum; // how many tabs before detch 123 | 124 | // try to rearrange tabs if their number > 1 125 | if (IsPtInTabArea(point) && nNumTabs > 1 && m_bEnableTabSwap) { 126 | const auto nTabNum = GetTabFromPoint(point); 127 | 128 | if (nTabNum != m_iActiveTab && nTabNum != -1) { 129 | const auto nSecondTab = m_iActiveTab; 130 | SwapTabs(nTabNum, nSecondTab); 131 | RecalcLayout(); 132 | SetActiveTab(nTabNum); 133 | /* 134 | int nCurrTabNum = GetTabFromPoint(point); 135 | if (nCurrTabNum != nTabNum) { 136 | CRect rectTab; 137 | GetTabRect(nTabNum, rectTab); 138 | CPoint ptCursorNewPos = point; 139 | 140 | ptCursorNewPos.x = rectTab.left + m_nOffsetFromTabLeft; 141 | 142 | ClientToScreen(&ptCursorNewPos); 143 | SetCursorPos(ptCursorNewPos.x, ptCursorNewPos.y); 144 | } 145 | */ 146 | } 147 | return; 148 | } 149 | 150 | if (IsPtInTabArea(point)) { 151 | return; 152 | } 153 | 154 | const auto bDetachSucceeded = DetachTab(DM_MOUSE); 155 | 156 | if (bDetachSucceeded && nNumTabs <= 2) { 157 | // last tab was detached successfully - run out, because the control 158 | // has been destroyed 159 | return; 160 | } 161 | 162 | if (bDetachSucceeded) { 163 | m_bReadyToDetach = FALSE; 164 | } 165 | 166 | return; 167 | } 168 | } 169 | 170 | 171 | //CHexerTabbedPane. 172 | //This class is used in the SetTabbedPaneRTC. 173 | //Needed to set the m_pTabWndRTC (pointer to a Tab Control) 174 | //to our own overridden CHexerTabCtrl class. 175 | class CHexerTabbedPane final : public CTabbedPane { 176 | CHexerTabbedPane() { m_pTabWndRTC = RUNTIME_CLASS(CHexerTabCtrl); }; 177 | DECLARE_SERIAL(CHexerTabbedPane); 178 | }; 179 | 180 | IMPLEMENT_SERIAL(CHexerTabbedPane, CTabbedPane, 1) 181 | 182 | 183 | //CHexerDockablePane. 184 | export class CHexerDockablePane final : public CDockablePane { 185 | public: 186 | void SetNestedHWND(HWND hWnd); 187 | [[nodiscard]] auto GetNestedHWND()const->HWND; 188 | private: 189 | void AdjustLayout()override; 190 | afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); 191 | afx_msg void OnPaint(); 192 | afx_msg void OnSize(UINT nType, int cx, int cy); 193 | BOOL PreTranslateMessage(MSG* pMsg)override; 194 | DECLARE_MESSAGE_MAP(); 195 | private: 196 | HWND m_hWndNested { }; //Currently nested window. 197 | HWND m_hWndParentOrig { }; //Original parent of the m_hWndNested. 198 | LONG_PTR m_llStylesOrig { }; //Original styles of the m_hWndNested. 199 | }; 200 | 201 | BEGIN_MESSAGE_MAP(CHexerDockablePane, CDockablePane) 202 | ON_WM_CREATE() 203 | ON_WM_PAINT() 204 | ON_WM_SIZE() 205 | END_MESSAGE_MAP() 206 | 207 | void CHexerDockablePane::SetNestedHWND(HWND hWnd) 208 | { 209 | assert(hWnd != nullptr); 210 | if (hWnd == nullptr || hWnd == m_hWndNested) 211 | return; 212 | 213 | if (m_hWndNested != nullptr) { 214 | ::SetWindowLongPtrW(m_hWndNested, GWL_STYLE, m_llStylesOrig); //Restore original styles. 215 | ::SetParent(m_hWndNested, m_hWndParentOrig); //Restore original parent. 216 | ::ShowWindow(m_hWndNested, SW_HIDE); 217 | } 218 | 219 | m_llStylesOrig = ::GetWindowLongPtrW(hWnd, GWL_STYLE); 220 | //We preserve all original styles, removing only those responsible for border, 221 | //caption, and resizability. Some nested dialogs might be WS_CHILD, some not. 222 | const auto llStylesNew = m_llStylesOrig & ~(WS_BORDER | WS_DLGFRAME | WS_THICKFRAME); 223 | ::SetWindowLongPtrW(hWnd, GWL_STYLE, llStylesNew); 224 | m_hWndParentOrig = ::SetParent(hWnd, m_hWnd); 225 | m_hWndNested = hWnd; 226 | AdjustLayout(); 227 | } 228 | 229 | auto CHexerDockablePane::GetNestedHWND()const->HWND 230 | { 231 | return m_hWndNested; 232 | } 233 | 234 | 235 | //CHexerDockablePane Private methods. 236 | 237 | void CHexerDockablePane::AdjustLayout() 238 | { 239 | if (m_hWndNested == nullptr) { 240 | return; 241 | } 242 | 243 | CRect rcClient; 244 | GetClientRect(rcClient); 245 | //SWP_NOACTIVATE flag doesn't send WM_ACTIVATE message which is vital to dialogs like DataInterp. 246 | ::SetWindowPos(m_hWndNested, nullptr, 0, 0, rcClient.Width(), rcClient.Height(), SWP_NOZORDER | SWP_SHOWWINDOW); 247 | } 248 | 249 | int CHexerDockablePane::OnCreate(LPCREATESTRUCT lpCreateStruct) 250 | { 251 | if (CDockablePane::OnCreate(lpCreateStruct) == -1) 252 | return -1; 253 | 254 | SetTabbedPaneRTC(RUNTIME_CLASS(CHexerTabbedPane)); 255 | 256 | return 0; 257 | } 258 | 259 | void CHexerDockablePane::OnPaint() 260 | { 261 | CPaintDC dc(this); 262 | CRect rcClient; 263 | GetClientRect(rcClient); 264 | dc.FillSolidRect(rcClient, RGB(255, 255, 255)); //Default white bk. 265 | } 266 | 267 | void CHexerDockablePane::OnSize(UINT nType, int cx, int cy) 268 | { 269 | CDockablePane::OnSize(nType, cx, cy); 270 | AdjustLayout(); 271 | } 272 | 273 | BOOL CHexerDockablePane::PreTranslateMessage(MSG* pMsg) 274 | { 275 | if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) { 276 | return FALSE; //To prevent App hanging on pressing Esc on any Pane's title. 277 | } 278 | 279 | return CDockablePane::PreTranslateMessage(pMsg); 280 | } -------------------------------------------------------------------------------- /Hexer/Utility.ixx: -------------------------------------------------------------------------------- 1 | module; 2 | /******************************************************************************* 3 | * Copyright © 2023-present Jovibor https://github.com/jovibor/ * 4 | * Hexer is a Hexadecimal Editor for Windows platform. * 5 | * Official git repository: https://github.com/jovibor/Hexer/ * 6 | * This software is available under "The Hexer License", see the LICENSE file. * 7 | *******************************************************************************/ 8 | #include 9 | #include "resource.h" 10 | #include 11 | #include "HexCtrl.h" 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | export module Utility; 18 | 19 | export import StrToNum; 20 | export namespace stn = HEXCTRL::stn; 21 | export import ListEx; 22 | export namespace lex = HEXCTRL::LISTEX; 23 | HWND g_hWndMain { }; 24 | 25 | export namespace ut { 26 | constexpr auto HEXER_VERSION_MAJOR = 1; 27 | constexpr auto HEXER_VERSION_MINOR = 3; 28 | constexpr auto HEXER_VERSION_PATCH = 2; 29 | 30 | constexpr UINT g_arrPanes[] { IDC_PANE_DATAINFO, IDC_PANE_BKMMGR, IDC_PANE_DATAINTERP, IDC_PANE_TEMPLMGR, IDC_PANE_LOGGER }; 31 | 32 | [[nodiscard]] bool IsElevated() { //Checking if the app runs elevated. 33 | static const bool fElevated = [] { 34 | HANDLE hToken { }; 35 | ::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &hToken); 36 | TOKEN_ELEVATION te { }; 37 | DWORD cbSize { sizeof(te) }; 38 | ::GetTokenInformation(hToken, TokenElevation, &te, sizeof(te), &cbSize); 39 | ::CloseHandle(hToken); 40 | return te.TokenIsElevated > 0; 41 | }(); 42 | return fElevated; 43 | } 44 | 45 | //AfxGetMainWnd() doesn't return correct handle in some cases. 46 | //For instance, when open process and trying filling its whole memory with any data. 47 | void SetMainWnd(HWND hWnd) { 48 | g_hWndMain = hWnd; 49 | } 50 | 51 | [[nodiscard]] auto GetMainWnd() -> HWND { 52 | return g_hWndMain; 53 | } 54 | 55 | [[nodiscard]] auto GetAppName() -> const std::wstring& { 56 | static const std::wstring wstrAppName { [] { 57 | CStringW strw; 58 | strw.LoadStringW(IDR_HEXER_FRAME); 59 | return strw; }() }; 60 | return wstrAppName; 61 | } 62 | 63 | [[nodiscard]] constexpr auto GetEHexWndFromPaneID(UINT uPaneID) -> std::optional { 64 | switch (uPaneID) { 65 | case IDC_PANE_BKMMGR: 66 | return HEXCTRL::EHexWnd::DLG_BKMMGR; 67 | case IDC_PANE_DATAINTERP: 68 | return HEXCTRL::EHexWnd::DLG_DATAINTERP; 69 | case IDC_PANE_TEMPLMGR: 70 | return HEXCTRL::EHexWnd::DLG_TEMPLMGR; 71 | default: 72 | return std::nullopt; 73 | } 74 | } 75 | 76 | [[nodiscard]] constexpr auto GetPaneIDFromMenuID(UINT uMenuID) -> UINT { 77 | switch (uMenuID) { 78 | case IDM_VIEW_DATAINFO: 79 | return IDC_PANE_DATAINFO; 80 | case IDM_VIEW_BKMMGR: 81 | return IDC_PANE_BKMMGR; 82 | case IDM_VIEW_DATAINTERP: 83 | return IDC_PANE_DATAINTERP; 84 | case IDM_VIEW_TEMPLMGR: 85 | return IDC_PANE_TEMPLMGR; 86 | case IDM_VIEW_LOGGER: 87 | return IDC_PANE_LOGGER; 88 | default: 89 | return { }; 90 | }; 91 | } 92 | 93 | [[nodiscard]] auto GetLastErrorWstr(DWORD dwErr = 0) -> std::wstring { 94 | std::wstring wstr; 95 | wstr.resize_and_overwrite(MAX_PATH, [=](wchar_t* pData, std::size_t sSize)noexcept { 96 | return FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, 97 | dwErr > 0 ? dwErr : GetLastError(), 0, pData, static_cast(sSize), nullptr); 98 | }); 99 | return wstr; 100 | } 101 | 102 | void ShowLastError(DWORD dwErr = 0) { 103 | ::MessageBoxW(nullptr, ut::GetLastErrorWstr(dwErr).data(), nullptr, 0); 104 | } 105 | 106 | [[nodiscard]] auto GetDeviceSize(HANDLE hHandle) -> std::expected { 107 | DISK_GEOMETRY stDG { }; 108 | if (DeviceIoControl(hHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY, nullptr, 0, &stDG, sizeof(stDG), 109 | nullptr, nullptr) == FALSE) { 110 | return std::unexpected(GetLastError()); 111 | } 112 | 113 | switch (stDG.MediaType) { 114 | case MEDIA_TYPE::Unknown: 115 | case MEDIA_TYPE::RemovableMedia: 116 | case MEDIA_TYPE::FixedMedia: 117 | { 118 | GET_LENGTH_INFORMATION stLI { }; 119 | if (DeviceIoControl(hHandle, IOCTL_DISK_GET_LENGTH_INFO, nullptr, 0, &stLI, 120 | sizeof(stLI), nullptr, nullptr) == FALSE) { 121 | return std::unexpected(GetLastError()); 122 | } 123 | return stLI.Length.QuadPart; 124 | } 125 | default: 126 | return stDG.Cylinders.QuadPart * stDG.TracksPerCylinder * 127 | stDG.SectorsPerTrack * stDG.BytesPerSector; 128 | } 129 | } 130 | 131 | [[nodiscard]] auto GetDeviceSize(const wchar_t* pwszPath) -> std::expected { 132 | //The GENERIC_READ flag is mandatory for the IOCTL_DISK_GET_LENGTH_INFO to work. 133 | //The IOCTL_DISK_GET_LENGTH_INFO also requires elevation (Admin access) for some drives/volumes. 134 | const auto hHandle = CreateFileW(pwszPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 135 | nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); 136 | if (hHandle == INVALID_HANDLE_VALUE) { 137 | return std::unexpected(GetLastError()); 138 | } 139 | 140 | const auto u64Size = GetDeviceSize(hHandle); 141 | CloseHandle(hHandle); 142 | 143 | return u64Size; 144 | } 145 | 146 | struct HIDPIINFO { 147 | int iLOGPIXELSY { }; 148 | float flDPIScale { }; 149 | }; 150 | 151 | [[nodiscard]] auto GetHiDPIInfo() -> HIDPIINFO { 152 | static const HIDPIINFO ret { []()->HIDPIINFO { 153 | const auto hDC = ::GetDC(nullptr); 154 | const auto iLOGPIXELSY = GetDeviceCaps(hDC, LOGPIXELSY); 155 | const auto flScale = iLOGPIXELSY / 96.0F; 156 | ::ReleaseDC(nullptr, hDC); 157 | return { .iLOGPIXELSY { iLOGPIXELSY }, .flDPIScale { flScale } }; 158 | }() }; 159 | 160 | return ret; 161 | } 162 | 163 | enum class EOpenMode : std::uint8_t { 164 | OPEN_FILE = 0x1, OPEN_DRIVE, OPEN_VOLUME, OPEN_PATH, OPEN_PROC, NEW_FILE 165 | }; 166 | 167 | enum class EDataAccessMode : std::uint8_t { 168 | ACCESS_SAFE = 0x1, ACCESS_INPLACE = 0x2 169 | }; 170 | 171 | struct DATAACCESS { 172 | constexpr DATAACCESS() = default; 173 | constexpr DATAACCESS(DWORD dw) { 174 | switch (dw) { 175 | case 0: 176 | fMutable = false; 177 | break; 178 | case 1: 179 | fMutable = true; 180 | eDataAccessMode = EDataAccessMode::ACCESS_SAFE; 181 | break; 182 | case 2: 183 | fMutable = true; 184 | eDataAccessMode = EDataAccessMode::ACCESS_INPLACE; 185 | break; 186 | default: 187 | fMutable = false; 188 | break; 189 | } 190 | }; 191 | EDataAccessMode eDataAccessMode { }; 192 | bool fMutable { }; 193 | constexpr auto operator<=>(const DATAACCESS&)const = default; 194 | constexpr operator DWORD()const { return fMutable ? std::to_underlying(eDataAccessMode) : 0; }; 195 | }; 196 | 197 | enum class EDataIOMode : std::uint8_t { 198 | DATA_MMAP, DATA_IOBUFF, DATA_IOIMMEDIATE 199 | }; 200 | 201 | [[nodiscard]] constexpr auto GetWstrEOpenMode(EOpenMode eOpenMode) { 202 | using enum EOpenMode; 203 | switch (eOpenMode) { 204 | case OPEN_DRIVE: 205 | return L"Drive"; 206 | case OPEN_VOLUME: 207 | return L"Volume"; 208 | case OPEN_PATH: 209 | return L"Path"; 210 | case OPEN_PROC: 211 | return L"Process"; 212 | case OPEN_FILE: 213 | case NEW_FILE: 214 | return L"File"; 215 | default: 216 | return L""; 217 | }; 218 | } 219 | 220 | [[nodiscard]] constexpr auto GetEOpenModeWstr(std::wstring_view wsv) -> std::optional { 221 | using enum EOpenMode; 222 | if (wsv == L"Drive") 223 | return OPEN_DRIVE; 224 | if (wsv == L"Volume") 225 | return OPEN_VOLUME; 226 | if (wsv == L"Path") 227 | return OPEN_PATH; 228 | if (wsv == L"File") 229 | return OPEN_FILE; 230 | if (wsv == L"Process") 231 | return OPEN_PROC; 232 | 233 | return std::nullopt; 234 | } 235 | 236 | [[nodiscard]] constexpr auto GetWstrDATAACCESS(DATAACCESS stDAC) { 237 | using enum EDataAccessMode; 238 | if (!stDAC.fMutable) { 239 | return L"Read Only"; 240 | } 241 | 242 | switch (stDAC.eDataAccessMode) { 243 | case ACCESS_SAFE: 244 | return L"Read/Write Safe"; 245 | case ACCESS_INPLACE: 246 | return L"Read/Write In-Place"; 247 | default: 248 | return L""; 249 | } 250 | } 251 | 252 | [[nodiscard]] constexpr auto GetWstrEDataIOMode(EDataIOMode eDataIOMode) { 253 | using enum EDataIOMode; 254 | switch (eDataIOMode) { 255 | case DATA_MMAP: 256 | return L"Memory Mapped File"; 257 | case DATA_IOBUFF: 258 | return L"Data IO Buffered"; 259 | case DATA_IOIMMEDIATE: 260 | return L"Data IO Immediate"; 261 | default: 262 | return L""; 263 | } 264 | } 265 | 266 | [[nodiscard]] auto ResolveLNK(const wchar_t* pwszPath) -> std::wstring { 267 | const std::wstring_view wsv = pwszPath; 268 | if (!wsv.ends_with(L".lnk") && !wsv.ends_with(L".LNK")) { 269 | return pwszPath; 270 | } 271 | 272 | CComPtr pIShellLinkW; 273 | pIShellLinkW.CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER); 274 | CComPtr pIPersistFile; 275 | pIShellLinkW->QueryInterface(IID_PPV_ARGS(&pIPersistFile)); 276 | pIPersistFile->Load(pwszPath, STGM_READ); 277 | 278 | std::wstring wstrPath; 279 | wstrPath.resize_and_overwrite(MAX_PATH, [pIShellLinkW = pIShellLinkW](wchar_t* pData, std::size_t sSize)noexcept { 280 | pIShellLinkW->GetPath(pData, static_cast(sSize), nullptr, 0); 281 | return sSize; }); 282 | wstrPath.resize(wstrPath.find_first_of(L'\0')); //Resize to the actual data size. 283 | 284 | return wstrPath; 285 | }; 286 | 287 | [[nodiscard]] auto GetHBITMAP(int iResID) -> HBITMAP { 288 | const auto iSizeIcon = static_cast(16 * ut::GetHiDPIInfo().flDPIScale); 289 | return static_cast(LoadImageW(AfxGetInstanceHandle(), MAKEINTRESOURCEW(iResID), 290 | IMAGE_BITMAP, iSizeIcon, iSizeIcon, LR_CREATEDIBSECTION)); 291 | } 292 | 293 | [[nodiscard]] auto HICONfromHBITMAP(HBITMAP hbmp) -> HICON { 294 | BITMAP stBmp; 295 | if (!GetObjectW(hbmp, sizeof(BITMAP), &stBmp)) 296 | return { }; 297 | 298 | const auto hbmpMask = CreateCompatibleBitmap(::GetDC(nullptr), stBmp.bmWidth, stBmp.bmHeight); 299 | ICONINFO ii { .fIcon { TRUE }, .hbmMask { hbmpMask }, .hbmColor { hbmp } }; 300 | auto hICO = CreateIconIndirect(&ii); 301 | DeleteObject(hbmpMask); 302 | 303 | return hICO; 304 | } 305 | 306 | [[nodiscard]] auto TimetToWstr(std::time_t time) -> std::wstring { 307 | std::wstring wstr; 308 | wstr.resize_and_overwrite(32, [=](wchar_t* pData, std::size_t sSize)noexcept { 309 | std::tm tm; 310 | localtime_s(&tm, &time); 311 | return std::wcsftime(pData, sSize, L"%H:%M:%S", &tm); 312 | }); 313 | 314 | return wstr; 315 | } 316 | 317 | struct DATAOPEN { //Main data opening struct. 318 | std::wstring wstrDataPath; //Or Process name. 319 | std::wstring wstrFriendlyName; //Used mostly for devices' friendly name. 320 | std::uint64_t ullSizeNewFile { }; 321 | DWORD dwProcID { }; 322 | EOpenMode eOpenMode { EOpenMode::OPEN_FILE }; 323 | [[nodiscard]] bool operator==(const DATAOPEN& rhs)const { 324 | return wstrDataPath == rhs.wstrDataPath && dwProcID == rhs.dwProcID; 325 | }; 326 | }; 327 | 328 | struct DATAINFO { //Data for the CDlgLogger dialog. 329 | std::wstring_view wsvDataPath; 330 | std::wstring_view wsvFileName; 331 | std::wstring_view wsvFriendlyName; 332 | std::uint64_t ullDataSize { }; 333 | std::uint32_t dwPageSize { }; 334 | EOpenMode eOpenMode { }; 335 | DATAACCESS stDAC; 336 | EDataIOMode eDataIOMode { }; 337 | }; 338 | 339 | //Custom messages. 340 | constexpr auto WM_ADD_LOG_ENTRY { WM_APP + 1 }; 341 | constexpr auto WM_APP_SETTINGS_CHANGED { WM_APP + 2 }; 342 | 343 | //Flags for the HexCtrl internal dialogs. 344 | constexpr auto HEXCTRL_FLAG_TEMPLMGR_MIN { 0x1ULL }; //Template Manager. 345 | constexpr auto HEXCTRL_FLAG_TEMPLMGR_HEX { 0x2ULL }; 346 | constexpr auto HEXCTRL_FLAG_TEMPLMGR_TT { 0x4ULL }; 347 | constexpr auto HEXCTRL_FLAG_TEMPLMGR_HGL { 0x8ULL }; 348 | constexpr auto HEXCTRL_FLAG_TEMPLMGR_SWAP { 0x10ULL }; 349 | constexpr auto HEXCTRL_FLAG_DATAINTERP_HEX { 0x1ULL }; //Data Interpreter. 350 | constexpr auto HEXCTRL_FLAG_DATAINTERP_BE { 0x2ULL }; 351 | constexpr auto HEXCTRL_FLAG_BKMMGR_HEX { 0x1ULL }; //Bookmark Manager. 352 | 353 | 354 | namespace Log { 355 | enum class EMsgType :std::int8_t { //Enum id-number is the icon's index in the image list. 356 | Unknown = -1, msg_error = 0, msg_warning = 1, msg_info = 2 357 | }; 358 | 359 | struct LOGINFO { //Struct for providing and transferring log data. 360 | std::time_t time { std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) }; 361 | std::wstring_view wsvMsg; 362 | EMsgType eType { }; 363 | }; 364 | 365 | void AddLogEntry(const LOGINFO& li) { 366 | SendMessageW(GetMainWnd(), WM_ADD_LOG_ENTRY, 0, reinterpret_cast(&li)); 367 | } 368 | 369 | void AddLogEntryError(std::wstring_view wsvMsg) { 370 | AddLogEntry({ .wsvMsg = wsvMsg, .eType = EMsgType::msg_error }); 371 | } 372 | 373 | void AddLogEntryWarning(std::wstring_view wsvMsg) { 374 | AddLogEntry({ .wsvMsg = wsvMsg, .eType = EMsgType::msg_warning }); 375 | } 376 | 377 | void AddLogEntryInfo(std::wstring_view wsvMsg) { 378 | AddLogEntry({ .wsvMsg = wsvMsg, .eType = EMsgType::msg_info }); 379 | } 380 | } 381 | } -------------------------------------------------------------------------------- /Hexer/Hexer.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 17.0 15 | {EFF1D88A-4FED-465E-860A-2A4D5622F76D} 16 | MFCProj 17 | Hexer 18 | 10.0 19 | 20 | 21 | 22 | Application 23 | true 24 | v143 25 | Unicode 26 | Dynamic 27 | 28 | 29 | Application 30 | false 31 | v143 32 | true 33 | Unicode 34 | Dynamic 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | $(SolutionDir)bin\ 50 | $(SolutionDir)bin\obj\$(Platform)\$(Configuration)\$(ProjectName)\ 51 | $(ProjectName)d 52 | 53 | 54 | 55 | 56 | $(SolutionDir)bin\ 57 | $(SolutionDir)bin\obj\$(Platform)\$(Configuration)\$(ProjectName)\ 58 | 59 | 60 | 61 | 62 | 63 | Level4 64 | _WINDOWS;_DEBUG;%(PreprocessorDefinitions) 65 | true 66 | true 67 | stdcpplatest 68 | Use 69 | $(ProjectDir);dep\HexCtrl\HexCtrl\;dep\HexCtrl\HexCtrl\dep\ListEx 70 | /utf-8 %(AdditionalOptions) 71 | true 72 | 73 | 74 | Windows 75 | /NOCOFFGRPINFO /pdbaltpath:%_PDB% %(AdditionalOptions) 76 | DebugFastLink 77 | 78 | 79 | false 80 | true 81 | _DEBUG;%(PreprocessorDefinitions) 82 | 83 | 84 | 0x0409 85 | _DEBUG;%(PreprocessorDefinitions) 86 | $(IntDir);%(AdditionalIncludeDirectories) 87 | 88 | 89 | 90 | 91 | Level4 92 | true 93 | true 94 | _WINDOWS;NDEBUG;%(PreprocessorDefinitions) 95 | true 96 | Speed 97 | true 98 | stdcpplatest 99 | Use 100 | $(ProjectDir);dep\HexCtrl\HexCtrl\;dep\HexCtrl\HexCtrl\dep\ListEx 101 | /utf-8 %(AdditionalOptions) 102 | true 103 | 104 | 105 | Windows 106 | true 107 | true 108 | false 109 | /NOCOFFGRPINFO /pdbaltpath:%_PDB% %(AdditionalOptions) 110 | 111 | 112 | false 113 | true 114 | NDEBUG;%(PreprocessorDefinitions) 115 | 116 | 117 | 0x0409 118 | NDEBUG;%(PreprocessorDefinitions) 119 | $(IntDir);%(AdditionalIncludeDirectories) 120 | 121 | 122 | 123 | 124 | Document 125 | NotUsing 126 | NotUsing 127 | 128 | 129 | 130 | NotUsing 131 | NotUsing 132 | 133 | 134 | NotUsing 135 | NotUsing 136 | 137 | 138 | NotUsing 139 | NotUsing 140 | 141 | 142 | NotUsing 143 | NotUsing 144 | 145 | 146 | NotUsing 147 | NotUsing 148 | 149 | 150 | NotUsing 151 | NotUsing 152 | 153 | 154 | NotUsing 155 | NotUsing 156 | 157 | 158 | NotUsing 159 | NotUsing 160 | 161 | 162 | NotUsing 163 | NotUsing 164 | 165 | 166 | NotUsing 167 | NotUsing 168 | 169 | 170 | NotUsing 171 | NotUsing 172 | 173 | 174 | NotUsing 175 | NotUsing 176 | 177 | 178 | NotUsing 179 | NotUsing 180 | 181 | 182 | NotUsing 183 | NotUsing 184 | 185 | 186 | NotUsing 187 | NotUsing 188 | 189 | 190 | NotUsing 191 | NotUsing 192 | 193 | 194 | NotUsing 195 | NotUsing 196 | 197 | 198 | NotUsing 199 | NotUsing 200 | 201 | 202 | NotUsing 203 | NotUsing 204 | 205 | 206 | Document 207 | NotUsing 208 | NotUsing 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | Document 218 | NotUsing 219 | NotUsing 220 | 221 | 222 | Document 223 | NotUsing 224 | NotUsing 225 | 226 | 227 | Document 228 | NotUsing 229 | NotUsing 230 | 231 | 232 | Document 233 | NotUsing 234 | NotUsing 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | Create 247 | Create 248 | 249 | 250 | NotUsing 251 | NotUsing 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | -------------------------------------------------------------------------------- /Hexer/CHexerApp.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright © 2023-present Jovibor https://github.com/jovibor/ * 3 | * Hexer is a Hexadecimal Editor for Windows platform. * 4 | * Official git repository: https://github.com/jovibor/Hexer/ * 5 | * This software is available under "The Hexer License", see the LICENSE file. * 6 | *******************************************************************************/ 7 | #include "stdafx.h" 8 | #include "resource.h" 9 | #include "CHexerApp.h" 10 | #include "CMainFrame.h" 11 | #include "CChildFrame.h" 12 | #include "CHexerDoc.h" 13 | #include "CHexerView.h" 14 | #include 15 | #include 16 | 17 | import DlgOpenDevice; 18 | import DlgOpenProcess; 19 | import DlgNewFile; 20 | import DlgSettings; 21 | 22 | #ifdef _DEBUG 23 | #define new DEBUG_NEW 24 | #endif 25 | 26 | CHexerApp theApp; 27 | 28 | //CDlgAbout. 29 | class CDlgAbout final : public CDialogEx { 30 | public: 31 | explicit CDlgAbout()noexcept : CDialogEx(IDD_ABOUTBOX) { } 32 | private: 33 | BOOL OnInitDialog()override; 34 | DECLARE_MESSAGE_MAP(); 35 | }; 36 | 37 | BEGIN_MESSAGE_MAP(CDlgAbout, CDialogEx) 38 | END_MESSAGE_MAP() 39 | 40 | #define STR2WIDE(x) L##x 41 | #define STRWIDER(x) STR2WIDE(x) 42 | 43 | BOOL CDlgAbout::OnInitDialog() 44 | { 45 | CDialogEx::OnInitDialog(); 46 | 47 | const auto wstrDescr = std::format(L"Hexer v{}.{}.{}, based on the HexCtrl v{}.{}.{}\r\n" 48 | "Copyright © 2023-present Jovibor", 49 | ut::HEXER_VERSION_MAJOR, ut::HEXER_VERSION_MINOR, ut::HEXER_VERSION_PATCH, 50 | HEXCTRL::HEXCTRL_VERSION_MAJOR, HEXCTRL::HEXCTRL_VERSION_MINOR, HEXCTRL::HEXCTRL_VERSION_PATCH); 51 | GetDlgItem(IDC_ABOUT_STATIC_VERSION)->SetWindowTextW(wstrDescr.data()); 52 | GetDlgItem(IDC_STATIC_BUILDTIME)->SetWindowTextW(L"Built on: " STRWIDER(__DATE__) L" " STRWIDER(__TIME__)); 53 | 54 | return TRUE; 55 | } 56 | 57 | 58 | //CHexerMDTemplate. 59 | class CHexerMDTemplate final : public CMultiDocTemplate { 60 | public: 61 | CHexerMDTemplate(UINT nIDResource, CRuntimeClass* pDocClass, CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass) 62 | : CMultiDocTemplate(nIDResource, pDocClass, pFrameClass, pViewClass) { 63 | } 64 | [[nodiscard]] auto OpenDocumentFile(const ut::DATAOPEN& dos) -> CDocument*; 65 | }; 66 | 67 | auto CHexerMDTemplate::OpenDocumentFile(const ut::DATAOPEN& dos)->CDocument* 68 | { 69 | //This code is copy-pasted from the original CMultiDocTemplate::OpenDocumentFile. 70 | //And adapted to work with the DATAOPEN struct. 71 | 72 | auto pDocument = static_cast(CreateNewDocument()); 73 | if (pDocument == nullptr) { 74 | TRACE(traceAppMsg, 0, "CDocTemplate::CreateNewDocument returned NULL.\n"); 75 | AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC); 76 | return nullptr; 77 | } 78 | ASSERT_VALID(pDocument); 79 | 80 | const auto bAutoDelete = pDocument->m_bAutoDelete; 81 | pDocument->m_bAutoDelete = FALSE; // don't destroy if something goes wrong 82 | CFrameWnd* pFrame = CreateNewFrame(pDocument, nullptr); 83 | pDocument->m_bAutoDelete = bAutoDelete; 84 | if (pFrame == nullptr) { 85 | AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC); 86 | delete pDocument; // explicit delete on error 87 | return nullptr; 88 | } 89 | ASSERT_VALID(pFrame); 90 | 91 | const CWaitCursor wait; 92 | if (!pDocument->OnOpenDocument(dos)) { 93 | // user has be alerted to what failed in OnOpenDocument 94 | TRACE(traceAppMsg, 0, "CDocument::OnOpenDocument returned FALSE.\n"); 95 | pFrame->DestroyWindow(); 96 | return nullptr; 97 | } 98 | 99 | pDocument->OnDocumentEvent(CDocument::onAfterOpenDocument); 100 | InitialUpdateFrame(pFrame, pDocument, TRUE); 101 | return pDocument; 102 | } 103 | 104 | 105 | //CHexerDocMgr. 106 | class CHexerDocMgr final : public CDocManager { 107 | public: 108 | auto OpenDocumentCustom(LPCWSTR lpszFileName, bool fDontLNK) -> CDocument*; 109 | auto OpenDocumentCustom(const ut::DATAOPEN& dos) -> CDocument*; 110 | auto OpenDocumentFile(LPCWSTR lpszFileName, BOOL bAddToMRU = FALSE) -> CDocument* override; 111 | DECLARE_DYNCREATE(CHexerDocMgr); 112 | }; 113 | 114 | IMPLEMENT_DYNCREATE(CHexerDocMgr, CDocument) 115 | 116 | auto CHexerDocMgr::OpenDocumentCustom(LPCWSTR lpszFileName, bool fDontLNK)->CDocument* 117 | { 118 | return OpenDocumentCustom({ .wstrDataPath { fDontLNK ? lpszFileName : ut::ResolveLNK(lpszFileName) }, 119 | .eOpenMode { ut::EOpenMode::OPEN_FILE } }); 120 | } 121 | 122 | auto CHexerDocMgr::OpenDocumentCustom(const ut::DATAOPEN& dos)->CDocument* 123 | { 124 | //This code below is copy-pasted from the original CDocManager::OpenDocumentFile. 125 | //We need to override this method to remove calls to AtlStrLen, AfxFullPath, AfxResolveShortcut 126 | //functions from the original method, because these functions can't handle paths like "\\?\PhysicalDisk". 127 | //Also this method is adapted to work with the DATAOPEN struct. 128 | 129 | // find the highest confidence 130 | POSITION pos = m_templateList.GetHeadPosition(); 131 | CDocTemplate::Confidence bestMatch = CDocTemplate::noAttempt; 132 | CHexerMDTemplate* pBestTemplate = nullptr; 133 | CDocument* pOpenDocument = nullptr; 134 | 135 | while (pos != nullptr) { 136 | auto pTemplate = static_cast(m_templateList.GetNext(pos)); 137 | ASSERT_KINDOF(CDocTemplate, pTemplate); 138 | 139 | CDocTemplate::Confidence match; 140 | ASSERT(pOpenDocument == nullptr); 141 | const auto wstrUniqueDocName = CHexerDoc::GetUniqueDocName(dos); 142 | match = pTemplate->MatchDocType(wstrUniqueDocName.data(), pOpenDocument); 143 | if (match > bestMatch) { 144 | bestMatch = match; 145 | pBestTemplate = pTemplate; 146 | } 147 | if (match == CDocTemplate::yesAlreadyOpen) 148 | break; // stop here 149 | } 150 | 151 | if (pOpenDocument != nullptr) { 152 | auto posOpenDoc = pOpenDocument->GetFirstViewPosition(); 153 | if (posOpenDoc != nullptr) { 154 | const auto pView = pOpenDocument->GetNextView(posOpenDoc); // get first one 155 | ASSERT_VALID(pView); 156 | const auto pFrame = pView->GetParentFrame(); 157 | 158 | if (pFrame == nullptr) { 159 | TRACE(traceAppMsg, 0, "Error: Can not find a frame for document to activate.\n"); 160 | } 161 | else { 162 | pFrame->ActivateFrame(); 163 | 164 | if (pFrame->GetParent() != nullptr) { 165 | if (const auto pAppFrame = static_cast(AfxGetApp()->m_pMainWnd); pFrame != pAppFrame) { 166 | ASSERT_KINDOF(CFrameWnd, pAppFrame); 167 | pAppFrame->ActivateFrame(); 168 | } 169 | } 170 | } 171 | } 172 | else { 173 | TRACE(traceAppMsg, 0, "Error: Can not find a view for document to activate.\n"); 174 | } 175 | 176 | return pOpenDocument; 177 | } 178 | 179 | if (pBestTemplate == nullptr) { 180 | AfxMessageBox(AFX_IDP_FAILED_TO_OPEN_DOC); 181 | return nullptr; 182 | } 183 | 184 | return pBestTemplate->OpenDocumentFile(dos); 185 | } 186 | 187 | auto CHexerDocMgr::OpenDocumentFile(LPCWSTR lpszFileName, BOOL /*bAddToMRU*/)->CDocument* 188 | { 189 | //This method also takes a part in the HDROP. 190 | 191 | return OpenDocumentCustom({ .wstrDataPath { ut::ResolveLNK(lpszFileName) }, .eOpenMode { ut::EOpenMode::OPEN_FILE } }); 192 | } 193 | 194 | 195 | //CHexerApp. 196 | BEGIN_MESSAGE_MAP(CHexerApp, CWinAppEx) 197 | ON_COMMAND(IDM_FILE_NEWFILE, &CHexerApp::OnFileNewFile) 198 | ON_COMMAND(IDM_FILE_OPENFILE, &CHexerApp::OnFileOpenFile) 199 | ON_COMMAND(IDM_FILE_OPENDEVICE, &CHexerApp::OnFileOpenDevice) 200 | ON_COMMAND(IDM_FILE_OPENPROCESS, &CHexerApp::OnFileOpenProcess) 201 | ON_COMMAND(IDM_TOOLS_SETTINGS, &CHexerApp::OnToolsSettings) 202 | ON_COMMAND(ID_APP_ABOUT, &CHexerApp::OnAppAbout) 203 | ON_COMMAND_RANGE(IDM_FILE_RFL00, IDM_FILE_RFL19, &CHexerApp::OnFileRFL) 204 | END_MESSAGE_MAP() 205 | 206 | auto CHexerApp::GetAppSettings()->CAppSettings& 207 | { 208 | return m_stAppSettings; 209 | } 210 | 211 | auto CHexerApp::GetClassName()const->LPCWSTR 212 | { 213 | //Just a "unique" string for a Window Class name. 214 | return L"HexerClassUnique{78306c63-7865}"; 215 | } 216 | 217 | void CHexerApp::NotifyTabsOnSettingsChange() 218 | { 219 | auto posDocTempl = GetFirstDocTemplatePosition(); 220 | while (posDocTempl != nullptr) { 221 | const auto pDocTempl = GetNextDocTemplate(posDocTempl); 222 | auto posDoc = pDocTempl->GetFirstDocPosition(); 223 | while (posDoc != nullptr) { 224 | pDocTempl->GetNextDoc(posDoc)->UpdateAllViews(nullptr, ut::WM_APP_SETTINGS_CHANGED); 225 | } 226 | } 227 | } 228 | 229 | void CHexerApp::OnFileOpenFile() 230 | { 231 | const auto lmbFOD = [this]()->bool { 232 | CFileDialog fd(TRUE, nullptr, nullptr, OFN_EXPLORER | OFN_ALLOWMULTISELECT | OFN_DONTADDTORECENT 233 | | OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_NODEREFERENCELINKS, L"All files (*.*)|*.*||"); 234 | constexpr auto dwIDChkLNK = 1UL; 235 | fd.AddCheckButton(dwIDChkLNK, L"Don't resolve .lnk", FALSE); 236 | if (fd.DoModal() != IDOK) 237 | return true; 238 | 239 | BOOL iChecked; 240 | fd.GetCheckButtonState(dwIDChkLNK, iChecked); 241 | const auto fDontLNK = iChecked == TRUE; 242 | CComPtr pIFOD = fd.GetIFileOpenDialog(); 243 | CComPtr pResults; 244 | pIFOD->GetResults(&pResults); 245 | bool fOpened { false }; 246 | DWORD dwCount { }; 247 | pResults->GetCount(&dwCount); 248 | for (auto i = 0U; i < dwCount; ++i) { 249 | CComPtr pItem; 250 | pResults->GetItemAt(i, &pItem); 251 | CComHeapPtr pwstrPath; 252 | pItem->GetDisplayName(SIGDN_FILESYSPATH, &pwstrPath); 253 | const auto pDoc = OpenDocumentCustom(pwstrPath, fDontLNK); 254 | fOpened = !fOpened ? pDoc != nullptr : true; 255 | } 256 | return fOpened; 257 | }; 258 | 259 | while (!lmbFOD()) { }; //If no file has been opened (in multiple selection) show the "Open File Dialog" again. 260 | } 261 | 262 | auto CHexerApp::OpenDocumentCustom(LPCWSTR pwszPath, bool fDontLNK)->CDocument* 263 | { 264 | ENSURE_VALID(m_pDocManager); 265 | return static_cast(m_pDocManager)->OpenDocumentCustom(pwszPath, fDontLNK); 266 | } 267 | 268 | auto CHexerApp::OpenDocumentCustom(const ut::DATAOPEN& dos)->CDocument* 269 | { 270 | ENSURE_VALID(m_pDocManager); 271 | return static_cast(m_pDocManager)->OpenDocumentCustom(dos); 272 | } 273 | 274 | auto CHexerApp::OpenDocumentFile(LPCWSTR pwszPath)->CDocument* 275 | { 276 | ENSURE_VALID(m_pDocManager); 277 | return static_cast(m_pDocManager)->OpenDocumentFile(pwszPath); 278 | } 279 | 280 | 281 | //CHexerApp private methods. 282 | 283 | BOOL CHexerApp::InitInstance() 284 | { 285 | CWinAppEx::InitInstance(); 286 | 287 | CCommandLineInfo cmdInfo; 288 | ParseCommandLine(cmdInfo); 289 | if (cmdInfo.m_nShellCommand == CCommandLineInfo::FileNew) { 290 | cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing; 291 | } 292 | 293 | //If a file is being opened by dropping on the App's shortcut, or through Windows context menu. 294 | const auto fHDROP = cmdInfo.m_nShellCommand == CCommandLineInfo::FileOpen; 295 | HANDLE hMutex { }; 296 | 297 | GetAppSettings().LoadSettings(ut::GetAppName()); 298 | 299 | if (!GetAppSettings().GetGeneralSettings().fMultipleInst) { //Single. 300 | //Check for the already running app instance. 301 | //The WaitForSingleObject call is needed for cases when multiple files are opened simultaneously, 302 | //like dropping on app's shortcut. In such cases the first process must have some time-room 303 | //to create itself, create a main window, etc... 304 | //Hence, we wait for the hMutex to be released at the end of the InitInstance() function in the main process. 305 | //Only then we are seeking for the main window, at that point it's created for sure. 306 | if (hMutex = CreateMutexW(nullptr, TRUE, GetClassName()); GetLastError() == ERROR_ALREADY_EXISTS) { 307 | WaitForSingleObject(hMutex, 2000); //Wait maximum for two sec (more than enough). 308 | } 309 | 310 | if (const auto hWnd = FindWindowExW(nullptr, nullptr, GetClassName(), nullptr); hWnd != nullptr) { 311 | ShowWindow(hWnd, SW_SHOWNORMAL); 312 | SetForegroundWindow(hWnd); 313 | 314 | if (fHDROP) { 315 | const COPYDATASTRUCT cds { .dwData { 1 }, //Just a random ID. It's checked in the CMainFrame::OnCopyData. 316 | .cbData { cmdInfo.m_strFileName.GetLength() * 2 + sizeof(wchar_t) }, //Size with nullterminator. 317 | .lpData { reinterpret_cast(const_cast(cmdInfo.m_strFileName.GetString())) } }; 318 | SendMessageW(hWnd, WM_COPYDATA, 0, reinterpret_cast(&cds)); 319 | } 320 | 321 | return FALSE; 322 | } 323 | } 324 | 325 | //Adjusting current process privileges to SE_DEBUG_NAME level, 326 | //to be able to open Processes that's blocked otherwise. 327 | TOKEN_PRIVILEGES tkp { .PrivilegeCount { 1 } }; 328 | tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 329 | LookupPrivilegeValueW(nullptr, SE_DEBUG_NAME, &tkp.Privileges[0].Luid); 330 | HANDLE hToken { }; 331 | OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken); 332 | AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, nullptr, nullptr); 333 | CloseHandle(hToken); 334 | 335 | EnableTaskbarInteraction(FALSE); 336 | SetRegistryKey(ut::GetAppName().data()); 337 | InitTooltipManager(); 338 | 339 | CMFCToolTipInfo ttParams; 340 | ttParams.m_bVislManagerTheme = TRUE; 341 | theApp.GetTooltipManager()->SetTooltipParams(AFX_TOOLTIP_TYPE_ALL, RUNTIME_CLASS(CMFCToolTipCtrl), &ttParams); 342 | 343 | m_pDocManager = new CHexerDocMgr; 344 | const auto pDocTemplate = new CHexerMDTemplate(IDR_MAINFRAME, RUNTIME_CLASS(CHexerDoc), 345 | RUNTIME_CLASS(CChildFrame), RUNTIME_CLASS(CHexerView)); 346 | AddDocTemplate(pDocTemplate); 347 | 348 | //Main menu resource was redefined as IDR_HEXER_FRAME. 349 | //This stops MFC from setting two different app menus: 350 | //One when no child windows is opened, and one when any child window is opened. 351 | 352 | const auto pMainFrame = new CMainFrame; 353 | pMainFrame->LoadFrame(IDR_HEXER_FRAME); //IDR_HEXER_FRAME is also used in the CMainFrame::PreCreateWindow. 354 | m_pMainWnd = pMainFrame; 355 | ut::SetMainWnd(pMainFrame->m_hWnd); 356 | 357 | const auto hBMPFile = ut::GetHBITMAP(IDB_FILE); 358 | const auto hBMPDevice = ut::GetHBITMAP(IDB_DEVICE); 359 | const auto hBMPProcess = ut::GetHBITMAP(IDB_PROCESS); 360 | MENUITEMINFOW mii { .cbSize { sizeof(MENUITEMINFOW) }, .fMask { MIIM_BITMAP }, .hbmpItem { hBMPFile } }; 361 | const auto pFileMenu = pMainFrame->GetMenu()->GetSubMenu(0); //"File" sub-menu. 362 | pFileMenu->SetMenuItemInfoW(1, &mii, TRUE); //Icon for the "Open File..." menu. 363 | mii.hbmpItem = hBMPDevice; 364 | pFileMenu->SetMenuItemInfoW(2, &mii, TRUE); //Icon for the "Open Device..." menu. 365 | mii.hbmpItem = hBMPProcess; 366 | pFileMenu->SetMenuItemInfoW(3, &mii, TRUE); //Icon for the "Open Process..." menu. 367 | const auto pRFLSubMenu = pFileMenu->GetSubMenu(4); //"Recent Files List" sub-menu. 368 | GetAppSettings().RFLInitialize(pRFLSubMenu->m_hMenu, IDM_FILE_RFL00, hBMPFile, hBMPDevice, hBMPProcess); 369 | DrawMenuBar(pMainFrame->m_hWnd); 370 | 371 | //For Drag'n Drop to work, even in elevated mode. 372 | //helgeklein.com/blog/2010/03/how-to-enable-drag-and-drop-for-an-elevated-mfc-application-on-vistawindows-7/ 373 | ChangeWindowMessageFilter(WM_DROPFILES, MSGFLT_ADD); 374 | ChangeWindowMessageFilter(WM_COPYDATA, MSGFLT_ADD); 375 | ChangeWindowMessageFilter(0x0049, MSGFLT_ADD); 376 | DragAcceptFiles(m_pMainWnd->m_hWnd, TRUE); 377 | 378 | //First we process App's startup options, only then ProcessShellCommand. 379 | //So that if we restore Last Opened Files and at the same time it was a file drop 380 | //on a shortcut, the file dropped will de opened in the last tab. 381 | const auto& refGeneral = GetAppSettings().GetGeneralSettings(); 382 | switch (refGeneral.eOnStartup) { 383 | case CAppSettings::EOnStartup::DO_NOTHING: 384 | break; 385 | case CAppSettings::EOnStartup::SHOW_NEW_FILE: 386 | if (!fHDROP) { //Not showing dialog if it was a drop. 387 | OnFileNewFile(); 388 | } 389 | break; 390 | case CAppSettings::EOnStartup::SHOW_OPEN_FILE: 391 | if (!fHDROP) { //Not showing dialog if it was a drop. 392 | OnFileOpenFile(); 393 | } 394 | break; 395 | case CAppSettings::EOnStartup::SHOW_OPEN_DEVICE: 396 | if (!fHDROP) { 397 | OnFileOpenDevice(); 398 | } 399 | break; 400 | case CAppSettings::EOnStartup::SHOW_OPEN_PROC: 401 | if (!fHDROP) { 402 | OnFileOpenProcess(); 403 | } 404 | break; 405 | case CAppSettings::EOnStartup::RESTORE_LAST_OPENED: 406 | for (const auto& refData : GetAppSettings().GetLastOpenedList()) { 407 | OpenDocumentCustom(refData); 408 | } 409 | break; 410 | default: 411 | break; 412 | }; 413 | 414 | if (!ProcessShellCommand(cmdInfo)) { 415 | return FALSE; 416 | } 417 | 418 | if (hMutex) { 419 | ::ReleaseMutex(hMutex); 420 | } 421 | 422 | m_pMainWnd->ShowWindow(SW_SHOW); 423 | m_fMainAppInSingleAppMode = true; 424 | 425 | return TRUE; 426 | } 427 | 428 | int CHexerApp::ExitInstance() 429 | { 430 | if (m_fMainAppInSingleAppMode) { //To make sure it's the main app, when in the Single App mode. 431 | GetAppSettings().SaveSettings(); 432 | } 433 | 434 | return CWinAppEx::ExitInstance(); 435 | } 436 | 437 | void CHexerApp::OnAppAbout() 438 | { 439 | CDlgAbout aboutDlg; 440 | aboutDlg.DoModal(); 441 | } 442 | 443 | void CHexerApp::OnFileNewFile() 444 | { 445 | if (CDlgNewFile dlg; dlg.DoModal() == IDOK) { 446 | OpenDocumentCustom(dlg.GetOpenData()); 447 | } 448 | } 449 | 450 | void CHexerApp::OnFileOpenDevice() 451 | { 452 | if (CDlgOpenDevice dlg(AfxGetMainWnd()); dlg.DoModal() == IDOK) { 453 | for (const auto& refData : dlg.GetOpenData()) { 454 | OpenDocumentCustom(refData); 455 | } 456 | } 457 | } 458 | 459 | void CHexerApp::OnFileOpenProcess() 460 | { 461 | if (CDlgOpenProcess dlg(AfxGetMainWnd()); dlg.DoModal() == IDOK) { 462 | for (const auto& refData : dlg.GetOpenData()) { 463 | OpenDocumentCustom(refData); 464 | } 465 | } 466 | } 467 | 468 | void CHexerApp::OnToolsSettings() 469 | { 470 | CDlgSettings dlg; 471 | dlg.DoModal(m_stAppSettings); 472 | } 473 | 474 | void CHexerApp::OnFileRFL(UINT uID) 475 | { 476 | OpenDocumentCustom(GetAppSettings().RFLGetDataFromMenuID(uID)); 477 | } -------------------------------------------------------------------------------- /Hexer/CHexerView.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright © 2023-present Jovibor https://github.com/jovibor/ * 3 | * Hexer is a Hexadecimal Editor for Windows platform. * 4 | * Official git repository: https://github.com/jovibor/Hexer/ * 5 | * This software is available under "The Hexer License", see the LICENSE file. * 6 | *******************************************************************************/ 7 | #include "stdafx.h" 8 | #include "CHexerApp.h" 9 | #include "CMainFrame.h" 10 | #include "CChildFrame.h" 11 | #include "CHexerDoc.h" 12 | #include "CHexerView.h" 13 | #include "resource.h" 14 | 15 | import Utility; 16 | 17 | #ifdef _DEBUG 18 | #define new DEBUG_NEW 19 | #endif 20 | 21 | IMPLEMENT_DYNCREATE(CHexerView, CView) 22 | 23 | BEGIN_MESSAGE_MAP(CHexerView, CView) 24 | ON_COMMAND(IDM_FILE_SAVE, &CHexerView::OnFileSave) 25 | ON_COMMAND(IDM_FILE_PRINT, &CHexerView::OnFilePrint) 26 | ON_COMMAND(IDM_EDIT_UNDO, &CHexerView::OnEditUndo) 27 | ON_COMMAND(IDM_EDIT_REDO, &CHexerView::OnEditRedo) 28 | ON_COMMAND(IDM_EDIT_COPYHEX, &CHexerView::OnEditCopyHex) 29 | ON_COMMAND(IDM_EDIT_PASTEHEX, &CHexerView::OnEditPasteHex) 30 | ON_COMMAND(IDM_VIEW_PROCMEMORY, &CHexerView::OnViewProcMemory) 31 | ON_COMMAND(IDM_DA_RO, &CHexerView::OnDataAccessRO) 32 | ON_COMMAND(IDM_DA_RWSAFE, &CHexerView::OnDataAccessRWSAFE) 33 | ON_COMMAND(IDM_DA_RWINPLACE, &CHexerView::OnDataAccessRWINPLACE) 34 | ON_COMMAND(IDM_DA_DATAIO_MMAP, &CHexerView::OnDataIOMMAP) 35 | ON_COMMAND(IDM_DA_DATAIO_IOBUFF, &CHexerView::OnDataIOBuff) 36 | ON_COMMAND(IDM_DA_DATAIO_IOIMMEDIATE, &CHexerView::OnDataIOImmediate) 37 | ON_NOTIFY(HEXCTRL::HEXCTRL_MSG_DLGBKMMGR, IDC_HEXCTRL_MAIN, &CHexerView::OnHexCtrlDLG) 38 | ON_NOTIFY(HEXCTRL::HEXCTRL_MSG_DLGDATAINTERP, IDC_HEXCTRL_MAIN, &CHexerView::OnHexCtrlDLG) 39 | ON_NOTIFY(HEXCTRL::HEXCTRL_MSG_DLGTEMPLMGR, IDC_HEXCTRL_MAIN, &CHexerView::OnHexCtrlDLG) 40 | ON_NOTIFY(HEXCTRL::HEXCTRL_MSG_SETDATA, IDC_HEXCTRL_MAIN, &CHexerView::OnHexCtrlSetData) 41 | ON_NOTIFY(HEXCTRL::HEXCTRL_MSG_SETFONT, IDC_HEXCTRL_MAIN, &CHexerView::OnHexCtrlSetFont) 42 | ON_UPDATE_COMMAND_UI(IDM_FILE_SAVE, &CHexerView::OnUpdateFileSave) 43 | ON_UPDATE_COMMAND_UI(IDM_VIEW_PROCMEMORY, &CHexerView::OnUpdateProcMemory) 44 | ON_UPDATE_COMMAND_UI_RANGE(IDM_DA_RO, IDM_DA_RWINPLACE, &CHexerView::OnUpdateDataAccessMode) 45 | ON_UPDATE_COMMAND_UI_RANGE(IDM_DA_DATAIO_MMAP, IDM_DA_DATAIO_IOIMMEDIATE, &CHexerView::OnUpdateDataIOMode) 46 | ON_WM_SIZE() 47 | END_MESSAGE_MAP() 48 | 49 | auto CHexerView::GetDataInfo()const->ut::DATAINFO 50 | { 51 | const auto pDoc = GetDocument(); 52 | return { .wsvDataPath { pDoc->GetDataPath() }, .wsvFileName { pDoc->GetFileName() }, 53 | .wsvFriendlyName { pDoc->GetFriendlyName() }, .ullDataSize { pDoc->GetDataSize() }, 54 | .dwPageSize { GetHexCtrl()->GetPageSize() }, .eOpenMode { pDoc->GetOpenMode() }, 55 | .stDAC { pDoc->GetDataAccessMode() }, .eDataIOMode { pDoc->GetDataIOMode() } }; 56 | } 57 | 58 | auto CHexerView::GetDlgProcMemory()const->HWND 59 | { 60 | return m_dlgProcMem; 61 | } 62 | 63 | auto CHexerView::GetHexCtrl()const->HEXCTRL::IHexCtrl* 64 | { 65 | return &*m_pHexCtrl; 66 | } 67 | 68 | auto CHexerView::GetHWNDForPane(UINT uPaneID)->HWND 69 | { 70 | //If Pane with HexCtrl's dialog inside. 71 | if (const auto optDlg = ut::GetEHexWndFromPaneID(uPaneID); optDlg) { 72 | const auto hWnd = GetHexCtrl()->GetWndHandle(*optDlg); 73 | if (!IsPaneAlreadyLaunch(uPaneID)) { 74 | SetPaneAlreadyLaunch(uPaneID); 75 | UpdateHexCtrlDlgData(uPaneID); 76 | GetHexCtrl()->SetDlgProperties(*optDlg, HEXCTRL::HEXCTRL_FLAG_DLG_NOESC); 77 | } 78 | 79 | return hWnd; 80 | } 81 | 82 | return { }; 83 | } 84 | 85 | bool CHexerView::OnBeforeClose() 86 | { 87 | if (m_fIsHexCtrlDataModified) { 88 | const auto pDoc = GetDocument(); 89 | const auto wstr = std::format(L"\"{}\" is modified. Save changes?", pDoc->GetDataPath()); 90 | switch (MessageBoxW(wstr.data(), pDoc->GetFileName().data(), MB_YESNOCANCEL | MB_ICONQUESTION)) { 91 | case IDYES: 92 | SaveDataToDisk(); 93 | return true; 94 | case IDNO: 95 | return true; 96 | case IDCANCEL: 97 | return false; 98 | default: 99 | return true; 100 | } 101 | } 102 | 103 | return true; 104 | } 105 | 106 | 107 | //Private methods. 108 | 109 | auto CHexerView::GetMainFrame()const->CMainFrame* 110 | { 111 | return static_cast(AfxGetMainWnd()); 112 | } 113 | 114 | void CHexerView::HexCtrlSetData(bool fAdjust) 115 | { 116 | const auto pDoc = GetDocument(); 117 | const auto fMutable = pDoc->IsDataAccessRW(); 118 | GetHexCtrl()->SetData({ .spnData { pDoc->GetFileMMAPData(), pDoc->GetDataSize() }, 119 | .pHexVirtData { pDoc->GetIHexVirtData() }, .ullMaxVirtOffset { pDoc->GetMaxVirtOffset() }, 120 | .dwCacheSize { pDoc->GetCacheSize() }, .fMutable { fMutable } }, fAdjust); 121 | } 122 | 123 | void CHexerView::ChangeDataAccessMode(ut::DATAACCESS stDAC) 124 | { 125 | const auto pDoc = GetDocument(); 126 | if (pDoc->GetDataAccessMode() == stDAC) 127 | return; 128 | 129 | pDoc->ChangeDataAccessMode(stDAC); 130 | HexCtrlSetData(true); 131 | GetMainFrame()->UpdatePaneFileInfo(); 132 | const auto wstr = std::format(L"Data access changed: {} ({})", GetDocument()->GetFileName(), 133 | ut::GetWstrDATAACCESS(stDAC)); 134 | ut::Log::AddLogEntryInfo(wstr); 135 | } 136 | 137 | void CHexerView::ChangeDataIOMode(ut::EDataIOMode eDataIOMode) 138 | { 139 | const auto pDoc = GetDocument(); 140 | if (pDoc->GetDataIOMode() == eDataIOMode) 141 | return; 142 | 143 | pDoc->ChangeDataIOMode(eDataIOMode); 144 | HexCtrlSetData(true); 145 | GetMainFrame()->UpdatePaneFileInfo(); 146 | const auto wstr = std::format(L"Data IO mode changed: {} ({})", GetDocument()->GetFileName(), 147 | GetWstrEDataIOMode(pDoc->GetDataIOMode())); 148 | ut::Log::AddLogEntryInfo(wstr); 149 | } 150 | 151 | auto CHexerView::GetChildFrame()const->CChildFrame* 152 | { 153 | return static_cast(GetParentFrame()); 154 | } 155 | 156 | auto CHexerView::GetDocument()const->CHexerDoc* 157 | { 158 | return reinterpret_cast(m_pDocument); 159 | } 160 | 161 | bool CHexerView::IsPaneAlreadyLaunch(UINT uPaneID)const 162 | { 163 | switch (uPaneID) { 164 | case IDC_PANE_BKMMGR: 165 | return m_fIsAlreadyLaunchDlgBkmMgr; 166 | case IDC_PANE_DATAINTERP: 167 | return m_fIsAlreadyLaunchDlgDataInterp; 168 | case IDC_PANE_TEMPLMGR: 169 | return m_fIsAlreadyLaunchDlgTemplMgr; 170 | default: 171 | return { }; 172 | } 173 | } 174 | 175 | void CHexerView::OnActivateView(BOOL bActivate, CView* pActivateView, CView* pDeactiveView) 176 | { 177 | CView::OnActivateView(bActivate, pActivateView, pDeactiveView); 178 | } 179 | 180 | void CHexerView::OnDataAccessRO() 181 | { 182 | ChangeDataAccessMode({ 0 }); 183 | } 184 | 185 | void CHexerView::OnDataAccessRWSAFE() 186 | { 187 | ChangeDataAccessMode({ 1 }); 188 | } 189 | 190 | void CHexerView::OnDataAccessRWINPLACE() 191 | { 192 | ChangeDataAccessMode({ 2 }); 193 | } 194 | 195 | void CHexerView::OnDataIOMMAP() 196 | { 197 | ChangeDataIOMode(DATA_MMAP); 198 | } 199 | 200 | void CHexerView::OnDataIOBuff() 201 | { 202 | ChangeDataIOMode(DATA_IOBUFF); 203 | } 204 | 205 | void CHexerView::OnDataIOImmediate() 206 | { 207 | ChangeDataIOMode(DATA_IOIMMEDIATE); 208 | } 209 | 210 | void CHexerView::OnDraw(CDC* /*pDC*/) 211 | { 212 | } 213 | 214 | void CHexerView::OnEditCopyHex() 215 | { 216 | GetHexCtrl()->ExecuteCmd(HEXCTRL::EHexCmd::CMD_CLPBRD_COPY_HEX); 217 | } 218 | 219 | void CHexerView::OnEditPasteHex() 220 | { 221 | GetHexCtrl()->ExecuteCmd(HEXCTRL::EHexCmd::CMD_CLPBRD_PASTE_HEX); 222 | } 223 | 224 | void CHexerView::OnEditUndo() 225 | { 226 | GetHexCtrl()->ExecuteCmd(HEXCTRL::EHexCmd::CMD_MODIFY_UNDO); 227 | } 228 | 229 | void CHexerView::OnEditRedo() 230 | { 231 | GetHexCtrl()->ExecuteCmd(HEXCTRL::EHexCmd::CMD_MODIFY_REDO); 232 | } 233 | 234 | void CHexerView::OnFilePrint() 235 | { 236 | GetHexCtrl()->ExecuteCmd(HEXCTRL::EHexCmd::CMD_PRINT_DLG); 237 | } 238 | 239 | void CHexerView::OnFileSave() 240 | { 241 | SaveDataToDisk(); 242 | } 243 | 244 | void CHexerView::OnHexCtrlDLG(NMHDR* pNMHDR, LRESULT* /*pResult*/) 245 | { 246 | UINT uPaneID; 247 | switch (pNMHDR->code) { 248 | case HEXCTRL::HEXCTRL_MSG_DLGBKMMGR: 249 | uPaneID = IDC_PANE_BKMMGR; 250 | break; 251 | case HEXCTRL::HEXCTRL_MSG_DLGDATAINTERP: 252 | uPaneID = IDC_PANE_DATAINTERP; 253 | break; 254 | case HEXCTRL::HEXCTRL_MSG_DLGTEMPLMGR: 255 | uPaneID = IDC_PANE_TEMPLMGR; 256 | break; 257 | default: 258 | return; 259 | } 260 | 261 | GetMainFrame()->ShowPane(uPaneID, true, true); 262 | } 263 | 264 | void CHexerView::OnHexCtrlSetData(NMHDR* /*pNMHDR*/, LRESULT* /*pResult*/) 265 | { 266 | if (GetDocument()->IsDataAccessRWSAFE()) { 267 | m_fIsHexCtrlDataModified = true; 268 | } 269 | } 270 | 271 | void CHexerView::OnHexCtrlSetFont(NMHDR* /*pNMHDR*/, LRESULT* /*pResult*/) 272 | { 273 | theApp.GetAppSettings().GetHexCtrlSettings().stLogFont = GetHexCtrl()->GetFont(); 274 | theApp.GetAppSettings().GetHexCtrlSettings().stClrs = GetHexCtrl()->GetColors(); //Because font color could be changed. 275 | } 276 | 277 | void CHexerView::OnInitialUpdate() 278 | { 279 | CView::OnInitialUpdate(); 280 | 281 | GetChildFrame()->SetHexerView(this); 282 | const auto pDoc = GetDocument(); 283 | const auto pHex = GetHexCtrl(); 284 | const auto& refHexSet = theApp.GetAppSettings().GetHexCtrlSettings(); 285 | pHex->Create({ .hWndParent { m_hWnd }, .pColors { &refHexSet.stClrs }, .pLogFont { &refHexSet.stLogFont }, 286 | .uID { IDC_HEXCTRL_MAIN }, .dwStyle { WS_VISIBLE | WS_CHILD }, .dwCapacity { refHexSet.dwCapacity }, 287 | .dwGroupSize { refHexSet.dwGroupSize }, .flScrollRatio { refHexSet.flScrollRatio }, 288 | .fScrollLines { refHexSet.fScrollLines }, .fInfoBar { refHexSet.fInfoBar }, .fOffsetHex { refHexSet.fOffsetHex } }); 289 | pHex->SetCharsExtraSpace(refHexSet.dwCharsExtraSpace); 290 | pHex->SetDateInfo(refHexSet.dwDateFormat, refHexSet.wchDateSepar); 291 | pHex->SetPageSize(pDoc->IsProcess() ? pDoc->GetMemPageSize() : refHexSet.dwPageSize); 292 | pHex->SetUnprintableChar(refHexSet.wchUnprintable); 293 | pHex->SetHexCharsCase(refHexSet.fHexCharsCaseUpper); 294 | 295 | for (const auto& p : theApp.GetAppSettings().GetHexCtrlTemplates()) { 296 | pHex->GetTemplates()->AddTemplate(*p); 297 | } 298 | 299 | HexCtrlSetData(); 300 | } 301 | 302 | void CHexerView::OnSize(UINT nType, int cx, int cy) 303 | { 304 | CView::OnSize(nType, cx, cy); 305 | 306 | if (GetHexCtrl()->IsCreated()) { 307 | GetHexCtrl()->SetWindowPos(m_hWnd, 0, 0, cx, cy); 308 | } 309 | } 310 | 311 | void CHexerView::OnUpdate(CView* /*pSender*/, LPARAM lHint, CObject* /*pHint*/) 312 | { 313 | if (lHint == ut::WM_APP_SETTINGS_CHANGED) { 314 | const auto& refHexSet = theApp.GetAppSettings().GetHexCtrlSettings(); 315 | const auto pHex = GetHexCtrl(); 316 | pHex->SetRedraw(false); 317 | pHex->SetCapacity(refHexSet.dwCapacity); 318 | pHex->SetGroupSize(refHexSet.dwGroupSize); 319 | pHex->SetPageSize(refHexSet.dwPageSize); 320 | pHex->SetUnprintableChar(refHexSet.wchUnprintable); 321 | pHex->SetDateInfo(refHexSet.dwDateFormat, refHexSet.wchDateSepar); 322 | pHex->SetScrollRatio(refHexSet.flScrollRatio, refHexSet.fScrollLines); 323 | pHex->ShowInfoBar(refHexSet.fInfoBar); 324 | pHex->SetOffsetMode(refHexSet.fOffsetHex); 325 | pHex->SetHexCharsCase(refHexSet.fHexCharsCaseUpper); 326 | pHex->SetCharsExtraSpace(refHexSet.dwCharsExtraSpace); 327 | pHex->SetFont(refHexSet.stLogFont); 328 | pHex->SetColors(refHexSet.stClrs); 329 | pHex->SetRedraw(true); 330 | pHex->Redraw(); 331 | } 332 | } 333 | 334 | void CHexerView::OnUpdateDataAccessMode(CCmdUI* pCmdUI) 335 | { 336 | const auto pDoc = GetDocument(); 337 | const auto fRW = pDoc->IsDataWritable(); 338 | const auto stDAC = pDoc->GetDataAccessMode(); 339 | 340 | bool fEnable { false }; 341 | bool fCheck { false }; 342 | using enum ut::EDataAccessMode; 343 | switch (pCmdUI->m_nID) { 344 | case IDM_DA_RO: 345 | fEnable = true; 346 | fCheck = !stDAC.fMutable; 347 | break; 348 | case IDM_DA_RWSAFE: 349 | fEnable = pDoc->IsDataOKForDASAFE(); 350 | fCheck = stDAC.fMutable && stDAC.eDataAccessMode == ACCESS_SAFE; 351 | break; 352 | case IDM_DA_RWINPLACE: 353 | fEnable = fRW; 354 | fCheck = stDAC.fMutable && stDAC.eDataAccessMode == ACCESS_INPLACE; 355 | break; 356 | default: 357 | break; 358 | } 359 | 360 | pCmdUI->Enable(fEnable); 361 | pCmdUI->SetCheck(fCheck); 362 | } 363 | 364 | void CHexerView::OnUpdateDataIOMode(CCmdUI* pCmdUI) 365 | { 366 | const auto pDoc = GetDocument(); 367 | const auto fIsFile = pDoc->IsFile(); 368 | const auto fModeAllowed = pDoc->IsDataAccessRW() && !pDoc->IsDataAccessRWSAFE(); 369 | const auto eDataIOMode = pDoc->GetDataIOMode(); 370 | bool fEnable { false }; 371 | bool fCheck { false }; 372 | 373 | using enum ut::EDataIOMode; 374 | switch (pCmdUI->m_nID) { 375 | case IDM_DA_DATAIO_MMAP: 376 | fEnable = fModeAllowed && fIsFile; 377 | fCheck = fModeAllowed && eDataIOMode == DATA_MMAP; 378 | break; 379 | case IDM_DA_DATAIO_IOBUFF: 380 | fEnable = fModeAllowed && fIsFile; 381 | fCheck = fModeAllowed && eDataIOMode == DATA_IOBUFF; 382 | break; 383 | case IDM_DA_DATAIO_IOIMMEDIATE: 384 | fEnable = fModeAllowed; 385 | fCheck = fModeAllowed && eDataIOMode == DATA_IOIMMEDIATE; 386 | break; 387 | default: 388 | break; 389 | } 390 | 391 | pCmdUI->Enable(fEnable); 392 | pCmdUI->SetCheck(fCheck); 393 | } 394 | 395 | void CHexerView::OnUpdateFileSave(CCmdUI* pCmdUI) 396 | { 397 | pCmdUI->Enable(m_fIsHexCtrlDataModified); 398 | } 399 | 400 | void CHexerView::OnUpdateProcMemory(CCmdUI* pCmdUI) 401 | { 402 | pCmdUI->Enable(GetDocument()->IsProcess()); 403 | if (::IsWindow(m_dlgProcMem)) { 404 | pCmdUI->SetCheck(m_dlgProcMem.IsWindowVisible()); 405 | } 406 | } 407 | 408 | void CHexerView::OnViewProcMemory() 409 | { 410 | if (!::IsWindow(m_dlgProcMem)) { 411 | m_dlgProcMem.Init(GetHexCtrl(), GetDocument()->GetVecProcMemory()); 412 | m_dlgProcMem.Create(IDD_PROCMEMORY, AfxGetMainWnd()); 413 | } 414 | m_dlgProcMem.ShowWindow(m_dlgProcMem.IsWindowVisible() ? SW_HIDE : SW_SHOW); 415 | } 416 | 417 | void CHexerView::SetPaneAlreadyLaunch(UINT uPaneID) 418 | { 419 | switch (uPaneID) { 420 | case IDC_PANE_BKMMGR: 421 | m_fIsAlreadyLaunchDlgBkmMgr = true; 422 | break; 423 | case IDC_PANE_DATAINTERP: 424 | m_fIsAlreadyLaunchDlgDataInterp = true; 425 | break; 426 | case IDC_PANE_TEMPLMGR: 427 | m_fIsAlreadyLaunchDlgTemplMgr = true; 428 | break; 429 | default: 430 | break; 431 | } 432 | } 433 | 434 | void CHexerView::SaveDataToDisk() 435 | { 436 | if (!m_fIsHexCtrlDataModified) 437 | return; 438 | 439 | GetDocument()->SaveDataToDisk(); 440 | m_fIsHexCtrlDataModified = false; 441 | } 442 | 443 | void CHexerView::UpdateDlgBkmMgr()const 444 | { 445 | using enum HEXCTRL::EHexWnd; 446 | using enum HEXCTRL::EHexDlgItem; 447 | const auto pHex = GetHexCtrl(); 448 | const auto u64Data = theApp.GetAppSettings().GetPaneData(IDC_PANE_BKMMGR); 449 | 450 | const auto hWnd = pHex->GetDlgItemHandle(BKMMGR_CHK_HEX); 451 | const auto pBtn = static_cast(CWnd::FromHandle(hWnd)); 452 | if (pBtn->GetCheck() != (u64Data & ut::HEXCTRL_FLAG_BKMMGR_HEX) > 0) { 453 | pBtn->SendMessageW(BM_CLICK); 454 | } 455 | } 456 | 457 | void CHexerView::UpdateDlgDataInterp()const 458 | { 459 | using enum HEXCTRL::EHexWnd; 460 | using enum HEXCTRL::EHexDlgItem; 461 | const auto pHex = GetHexCtrl(); 462 | const auto u64Data = theApp.GetAppSettings().GetPaneData(IDC_PANE_DATAINTERP); 463 | 464 | const auto hWndHex = pHex->GetDlgItemHandle(DATAINTERP_CHK_HEX); 465 | const auto pBtnHex = static_cast(CWnd::FromHandle(hWndHex)); 466 | if (pBtnHex->GetCheck() != (u64Data & ut::HEXCTRL_FLAG_DATAINTERP_HEX) > 0) { 467 | pBtnHex->SendMessageW(BM_CLICK); 468 | } 469 | 470 | const auto hWndBE = pHex->GetDlgItemHandle(DATAINTERP_CHK_BE); 471 | const auto pBtnBE = static_cast(CWnd::FromHandle(hWndBE)); 472 | if (pBtnBE->GetCheck() != (u64Data & ut::HEXCTRL_FLAG_DATAINTERP_BE) > 0) { 473 | pBtnBE->SendMessageW(BM_CLICK); 474 | } 475 | } 476 | 477 | void CHexerView::UpdateDlgModify()const 478 | { 479 | } 480 | 481 | void CHexerView::UpdateDlgSearch()const 482 | { 483 | } 484 | 485 | void CHexerView::UpdateDlgTemplMgr()const 486 | { 487 | using enum HEXCTRL::EHexWnd; 488 | using enum HEXCTRL::EHexDlgItem; 489 | const auto pHex = GetHexCtrl(); 490 | const auto u64Data = theApp.GetAppSettings().GetPaneData(IDC_PANE_TEMPLMGR); 491 | 492 | const auto hWndMin = pHex->GetDlgItemHandle(TEMPLMGR_CHK_MIN); 493 | const auto pBtnMin = static_cast(CWnd::FromHandle(hWndMin)); 494 | if (pBtnMin->GetCheck() != (u64Data & ut::HEXCTRL_FLAG_TEMPLMGR_MIN) > 0) { 495 | pBtnMin->SendMessageW(BM_CLICK); 496 | } 497 | 498 | const auto hWndHex = pHex->GetDlgItemHandle(TEMPLMGR_CHK_HEX); 499 | const auto pBtnHex = static_cast(CWnd::FromHandle(hWndHex)); 500 | if (pBtnHex->GetCheck() != (u64Data & ut::HEXCTRL_FLAG_TEMPLMGR_HEX) > 0) { 501 | pBtnHex->SendMessageW(BM_CLICK); 502 | } 503 | 504 | const auto hWndTT = pHex->GetDlgItemHandle(TEMPLMGR_CHK_TT); 505 | const auto pBtnTT = static_cast(CWnd::FromHandle(hWndTT)); 506 | if (pBtnTT->GetCheck() != (u64Data & ut::HEXCTRL_FLAG_TEMPLMGR_TT) > 0) { 507 | pBtnTT->SendMessageW(BM_CLICK); 508 | } 509 | 510 | const auto hWndHgl = pHex->GetDlgItemHandle(TEMPLMGR_CHK_HGL); 511 | const auto pBtnHgl = static_cast(CWnd::FromHandle(hWndHgl)); 512 | if (pBtnHgl->GetCheck() != (u64Data & ut::HEXCTRL_FLAG_TEMPLMGR_HGL) > 0) { 513 | pBtnHgl->SendMessageW(BM_CLICK); 514 | } 515 | 516 | const auto hWndSwap = pHex->GetDlgItemHandle(TEMPLMGR_CHK_SWAP); 517 | const auto pBtnSwap = static_cast(CWnd::FromHandle(hWndSwap)); 518 | if (pBtnSwap->GetCheck() != (u64Data & ut::HEXCTRL_FLAG_TEMPLMGR_SWAP) > 0) { 519 | pBtnSwap->SendMessageW(BM_CLICK); 520 | } 521 | } 522 | 523 | void CHexerView::UpdateHexCtrlDlgData(UINT uPaneID)const 524 | { 525 | using enum HEXCTRL::EHexWnd; 526 | switch (*ut::GetEHexWndFromPaneID(uPaneID)) { 527 | case DLG_BKMMGR: 528 | UpdateDlgBkmMgr(); 529 | break; 530 | case DLG_DATAINTERP: 531 | UpdateDlgDataInterp(); 532 | break; 533 | case DLG_MODIFY: 534 | UpdateDlgModify(); 535 | break; 536 | case DLG_SEARCH: 537 | UpdateDlgSearch(); 538 | break; 539 | case DLG_TEMPLMGR: 540 | UpdateDlgTemplMgr(); 541 | break; 542 | default: 543 | break; 544 | } 545 | } -------------------------------------------------------------------------------- /Hexer/Dialogs/DlgOpenProcess.ixx: -------------------------------------------------------------------------------- 1 | module; 2 | /******************************************************************************* 3 | * Copyright © 2023-present Jovibor https://github.com/jovibor/ * 4 | * Hexer is a Hexadecimal Editor for Windows platform. * 5 | * Official git repository: https://github.com/jovibor/Hexer/ * 6 | * This software is available under "The Hexer License", see the LICENSE file. * 7 | *******************************************************************************/ 8 | #include 9 | #include "resource.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | export module DlgOpenProcess; 18 | 19 | #pragma comment(lib, "Wtsapi32.lib") 20 | import Utility; 21 | 22 | export class CDlgOpenProcess final : public CDialogEx { 23 | public: 24 | struct PROCDATA; 25 | struct MODULEDATA; 26 | CDlgOpenProcess(CWnd* pParent = nullptr) : CDialogEx(IDD_OPENPROCESS, pParent) { } 27 | [[nodiscard]] auto GetOpenData()const -> const std::vector&; 28 | private: 29 | void DoDataExchange(CDataExchange* pDX)override; 30 | void EnableDynamicLayoutHelper(bool fEnable); 31 | afx_msg void OnBnClickedRefresh(); 32 | afx_msg auto OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) -> HBRUSH; 33 | afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct); 34 | BOOL OnInitDialog()override; 35 | afx_msg void OnLButtonDown(UINT nFlags, CPoint point); 36 | afx_msg void OnLButtonUp(UINT nFlags, CPoint point); 37 | afx_msg void OnListModulesColumnClick(NMHDR* pNMHDR, LRESULT* pResult); 38 | afx_msg void OnListModulesGetDispInfo(NMHDR* pNMHDR, LRESULT* pResult); 39 | afx_msg void OnListModulesDblClick(NMHDR* pNMHDR, LRESULT* pResult); 40 | afx_msg void OnListProcsColumnClick(NMHDR* pNMHDR, LRESULT* pResult); 41 | afx_msg void OnListProcsItemChanged(NMHDR* pNMHDR, LRESULT* pResult); 42 | afx_msg void OnListProcsDblClick(NMHDR* pNMHDR, LRESULT* pResult); 43 | afx_msg void OnListProcsGetDispInfo(NMHDR* pNMHDR, LRESULT* pResult); 44 | afx_msg void OnListProcsGetTooltip(NMHDR* pNMHDR, LRESULT* pResult); 45 | afx_msg void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct); 46 | afx_msg void OnMouseMove(UINT nFlags, CPoint point); 47 | BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)override; 48 | void OnOK()override; 49 | void OnProcReady(bool fReady); 50 | void RefreshProcs(); 51 | DECLARE_MESSAGE_MAP(); 52 | private: 53 | lex::CListEx m_ListProcs; 54 | lex::CListEx m_ListModules; 55 | std::vector m_vecProcs; 56 | std::vector m_vecModules; 57 | std::vector m_vecOpenData; 58 | std::wstring m_wstrTTProcPath; //Tooltip for process image full path. 59 | std::locale m_locale; 60 | CButton m_btnOpen; 61 | CButton m_statInfo; 62 | bool m_fCurInSplitter { }; //Indicates that mouse cursor is in the splitter area. 63 | bool m_fLMDownResize { }; //Left mouse pressed in the splitter area to resize. 64 | bool m_fProcReady { false }; 65 | }; 66 | 67 | struct CDlgOpenProcess::PROCDATA { 68 | std::wstring wstrProcName; 69 | DWORD dwProcID { }; 70 | DWORD dwWorkingSet { }; 71 | }; 72 | 73 | struct CDlgOpenProcess::MODULEDATA { 74 | std::wstring wstrModName; 75 | DWORD dwWorkingSet { }; 76 | }; 77 | 78 | BEGIN_MESSAGE_MAP(CDlgOpenProcess, CDialogEx) 79 | ON_BN_CLICKED(IDC_OPENPROCESS_BTN_REFRESH, &CDlgOpenProcess::OnBnClickedRefresh) 80 | ON_NOTIFY(LVN_GETDISPINFOW, IDC_OPENPROCESS_LIST_MODULES, &CDlgOpenProcess::OnListModulesGetDispInfo) 81 | ON_NOTIFY(NM_DBLCLK, IDC_OPENPROCESS_LIST_MODULES, &CDlgOpenProcess::OnListModulesDblClick) 82 | ON_NOTIFY(LVN_GETDISPINFOW, IDC_OPENPROCESS_LIST_PROCS, &CDlgOpenProcess::OnListProcsGetDispInfo) 83 | ON_NOTIFY(lex::LISTEX_MSG_GETTOOLTIP, IDC_OPENPROCESS_LIST_PROCS, &CDlgOpenProcess::OnListProcsGetTooltip) 84 | ON_NOTIFY(NM_DBLCLK, IDC_OPENPROCESS_LIST_PROCS, &CDlgOpenProcess::OnListProcsDblClick) 85 | ON_NOTIFY(LVN_ITEMCHANGED, IDC_OPENPROCESS_LIST_PROCS, &CDlgOpenProcess::OnListProcsItemChanged) 86 | ON_WM_CTLCOLOR() 87 | ON_WM_DRAWITEM() 88 | ON_WM_LBUTTONDOWN() 89 | ON_WM_LBUTTONUP() 90 | ON_WM_MEASUREITEM() 91 | ON_WM_MOUSEMOVE() 92 | END_MESSAGE_MAP() 93 | 94 | auto CDlgOpenProcess::GetOpenData()const->const std::vector& 95 | { 96 | return m_vecOpenData; 97 | } 98 | 99 | void CDlgOpenProcess::DoDataExchange(CDataExchange* pDX) 100 | { 101 | CDialogEx::DoDataExchange(pDX); 102 | DDX_Control(pDX, IDOK, m_btnOpen); 103 | DDX_Control(pDX, IDC_OPENPROCESS_STAT_INFO, m_statInfo); 104 | } 105 | 106 | void CDlgOpenProcess::EnableDynamicLayoutHelper(bool fEnable) 107 | { 108 | if (fEnable && IsDynamicLayoutEnabled()) 109 | return; 110 | 111 | EnableDynamicLayout(fEnable ? TRUE : FALSE); 112 | 113 | if (fEnable) { 114 | const auto pLayout = GetDynamicLayout(); 115 | pLayout->Create(this); 116 | 117 | pLayout->AddItem(IDC_OPENPROCESS_LIST_PROCS, CMFCDynamicLayout::MoveNone(), 118 | CMFCDynamicLayout::SizeHorizontalAndVertical(50, 100)); 119 | pLayout->AddItem(IDC_OPENPROCESS_LIST_MODULES, CMFCDynamicLayout::MoveHorizontal(50), 120 | CMFCDynamicLayout::SizeHorizontalAndVertical(50, 100)); 121 | pLayout->AddItem(IDC_OPENPROCESS_BTN_REFRESH, CMFCDynamicLayout::MoveVertical(100), 122 | CMFCDynamicLayout::SizeNone()); 123 | pLayout->AddItem(IDC_OPENPROCESS_STAT_INFO, CMFCDynamicLayout::MoveVertical(100), 124 | CMFCDynamicLayout::SizeHorizontal(100)); 125 | pLayout->AddItem(IDOK, CMFCDynamicLayout::MoveHorizontalAndVertical(100, 100), 126 | CMFCDynamicLayout::SizeNone()); 127 | pLayout->AddItem(IDCANCEL, CMFCDynamicLayout::MoveHorizontalAndVertical(100, 100), 128 | CMFCDynamicLayout::SizeNone()); 129 | } 130 | } 131 | 132 | void CDlgOpenProcess::OnBnClickedRefresh() 133 | { 134 | RefreshProcs(); 135 | } 136 | 137 | auto CDlgOpenProcess::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)->HBRUSH 138 | { 139 | const auto hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor); 140 | 141 | if (pWnd == &m_statInfo) { 142 | if (m_fProcReady) { 143 | pDC->SetTextColor(RGB(0, 250, 0)); 144 | } 145 | else { 146 | pDC->SetTextColor(RGB(250, 0, 0)); 147 | } 148 | } 149 | 150 | return hbr; 151 | } 152 | 153 | void CDlgOpenProcess::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) 154 | { 155 | if (nIDCtl == IDC_OPENPROCESS_LIST_PROCS) { 156 | m_ListProcs.DrawItem(lpDrawItemStruct); 157 | return; 158 | } 159 | else if (nIDCtl == IDC_OPENPROCESS_LIST_MODULES) { 160 | m_ListModules.DrawItem(lpDrawItemStruct); 161 | return; 162 | } 163 | 164 | CDialogEx::OnDrawItem(nIDCtl, lpDrawItemStruct); 165 | } 166 | 167 | BOOL CDlgOpenProcess::OnInitDialog() 168 | { 169 | CDialogEx::OnInitDialog(); 170 | 171 | m_locale = std::locale("en_US.UTF-8"); 172 | const lex::LISTEXCREATE lcs { .hWndParent { m_hWnd }, .uID { IDC_OPENPROCESS_LIST_PROCS }, .dwTTStyleCell { TTS_NOANIMATE }, 173 | .dwTTDelayTime { 500 }, .dwTTShowTime { 3000 }, .ptTTOffset { 9, -20 }, .fDialogCtrl { true }, .fSortable { true } }; 174 | m_ListProcs.Create(lcs); 175 | m_ListProcs.SetExtendedStyle(LVS_EX_HEADERDRAGDROP | LVS_EX_FULLROWSELECT); 176 | m_ListProcs.InsertColumn(0, L"№", 0, 40); 177 | m_ListProcs.InsertColumn(1, L"Process Name", 0, 200); 178 | m_ListProcs.InsertColumn(2, L"Process ID", 0, 70); 179 | m_ListProcs.InsertColumn(3, L"Working Set", 0, 90); 180 | m_ListProcs.SetColumnSortMode(0, false); 181 | 182 | m_ListModules.CreateDialogCtrl(IDC_OPENPROCESS_LIST_MODULES, m_hWnd); 183 | m_ListModules.SetExtendedStyle(LVS_EX_HEADERDRAGDROP | LVS_EX_FULLROWSELECT); 184 | m_ListModules.SetSortable(true); 185 | m_ListModules.InsertColumn(0, L"Module Name", 0, 150); 186 | m_ListModules.InsertColumn(1, L"Working Set", 0, 90); 187 | 188 | const auto hIcon = AfxGetApp()->LoadIconW(IDR_HEXER_FRAME); 189 | SetIcon(hIcon, TRUE); 190 | SetIcon(hIcon, FALSE); 191 | m_btnOpen.EnableWindow(FALSE); 192 | RefreshProcs(); 193 | EnableDynamicLayoutHelper(true); 194 | 195 | return TRUE; 196 | } 197 | 198 | void CDlgOpenProcess::OnLButtonDown(UINT nFlags, CPoint point) 199 | { 200 | if (m_fCurInSplitter) { 201 | m_fLMDownResize = true; 202 | SetCapture(); 203 | EnableDynamicLayoutHelper(false); 204 | } 205 | 206 | CDialogEx::OnLButtonDown(nFlags, point); 207 | } 208 | 209 | void CDlgOpenProcess::OnLButtonUp(UINT nFlags, CPoint point) 210 | { 211 | m_fLMDownResize = false; 212 | ReleaseCapture(); 213 | EnableDynamicLayoutHelper(true); 214 | 215 | CDialogEx::OnLButtonUp(nFlags, point); 216 | } 217 | 218 | void CDlgOpenProcess::OnListModulesColumnClick(NMHDR* /*pNMHDR*/, LRESULT* /*pResult*/) 219 | { 220 | const auto iColumn = m_ListModules.GetSortColumn(); 221 | const auto fAscending = m_ListModules.GetSortAscending(); 222 | std::sort(m_vecModules.begin(), m_vecModules.end(), [iColumn, fAscending](const MODULEDATA& lhs, const MODULEDATA& rhs) { 223 | int iCompare { }; 224 | switch (iColumn) { 225 | case 0: //Module Name. 226 | iCompare = lhs.wstrModName.compare(rhs.wstrModName); 227 | break; 228 | case 1: //Working Set. 229 | iCompare = lhs.dwWorkingSet < rhs.dwWorkingSet ? -1 : (lhs.dwWorkingSet > rhs.dwWorkingSet ? 1 : 0); 230 | break; 231 | default: 232 | break; 233 | } 234 | 235 | return fAscending ? iCompare < 0 : iCompare > 0; 236 | }); 237 | m_ListModules.RedrawWindow(); 238 | } 239 | 240 | void CDlgOpenProcess::OnListModulesGetDispInfo(NMHDR* pNMHDR, LRESULT* /*pResult*/) 241 | { 242 | const auto pDI = reinterpret_cast(pNMHDR); 243 | const auto pItem = &pDI->item; 244 | if ((pItem->mask & LVIF_TEXT) == 0) 245 | return; 246 | 247 | const auto iItem = pItem->iItem; 248 | 249 | switch (pItem->iSubItem) { 250 | case 0: //Module Name. 251 | pItem->pszText = m_vecModules[iItem].wstrModName.data(); 252 | break; 253 | case 1: //Working Set. 254 | *std::format_to(pItem->pszText, m_locale, L"{:L}KB", m_vecModules[iItem].dwWorkingSet / 1024) = L'\0'; 255 | break; 256 | default: 257 | break; 258 | } 259 | } 260 | 261 | void CDlgOpenProcess::OnListModulesDblClick(NMHDR* /*pNMHDR*/, LRESULT* /*pResult*/) 262 | { 263 | } 264 | 265 | void CDlgOpenProcess::OnListProcsColumnClick(NMHDR* /*pNMHDR*/, LRESULT* /*pResult*/) 266 | { 267 | const auto iColumn = m_ListProcs.GetSortColumn(); 268 | const auto fAscending = m_ListProcs.GetSortAscending(); 269 | std::sort(m_vecProcs.begin(), m_vecProcs.end(), [iColumn, fAscending](const PROCDATA& lhs, const PROCDATA& rhs) { 270 | int iCompare { }; 271 | switch (iColumn) { 272 | case 0: 273 | break; 274 | case 1: //Process Name. 275 | iCompare = lhs.wstrProcName.compare(rhs.wstrProcName); 276 | break; 277 | case 2: //Process ID. 278 | iCompare = lhs.dwProcID < rhs.dwProcID ? -1 : (lhs.dwProcID > rhs.dwProcID ? 1 : 0); 279 | break; 280 | case 3: //Working Set. 281 | iCompare = lhs.dwWorkingSet < rhs.dwWorkingSet ? -1 : (lhs.dwWorkingSet > rhs.dwWorkingSet ? 1 : 0); 282 | break; 283 | default: 284 | break; 285 | } 286 | 287 | return fAscending ? iCompare < 0 : iCompare > 0; 288 | }); 289 | m_ListProcs.RedrawWindow(); 290 | } 291 | 292 | void CDlgOpenProcess::OnListProcsItemChanged(NMHDR* pNMHDR, LRESULT* /*pResult*/) 293 | { 294 | const auto* const pNMI = reinterpret_cast(pNMHDR); 295 | if (pNMI->iItem < 0 || pNMI->iSubItem < 0 || !(pNMI->uNewState & LVIS_SELECTED)) 296 | return; 297 | 298 | const auto iItemID = pNMI->iItem; 299 | const auto hProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_vecProcs[iItemID].dwProcID); 300 | if (hProc == nullptr) { 301 | OnProcReady(false); 302 | m_ListModules.SetItemCountEx(0); 303 | m_ListModules.RedrawWindow(); 304 | m_vecModules.clear(); 305 | return; 306 | } 307 | 308 | m_vecModules.clear(); 309 | HMODULE arrHModules[1024]; 310 | DWORD dwCbNeeded { }; 311 | if (::K32EnumProcessModules(hProc, arrHModules, sizeof(arrHModules), &dwCbNeeded)) { 312 | const DWORD dwModsCount = dwCbNeeded / sizeof(HMODULE); //How many modules the hProc has. 313 | for (auto i { 0UL }; i < dwModsCount; ++i) { 314 | if (wchar_t arrModName[MAX_PATH]; ::K32GetModuleFileNameExW(hProc, arrHModules[i], arrModName, MAX_PATH)) { 315 | MODULEINFO mi; 316 | ::K32GetModuleInformation(hProc, arrHModules[i], &mi, sizeof(MODULEINFO)); 317 | std::wstring_view wsvModPath { arrModName }; 318 | const auto wsvModName = wsvModPath.substr(wsvModPath.find_last_of(L'\\') + 1); 319 | m_vecModules.emplace_back(wsvModName.data(), mi.SizeOfImage); 320 | } 321 | } 322 | } 323 | 324 | ::CloseHandle(hProc); 325 | m_ListModules.SetItemCountEx(static_cast(m_vecModules.size())); 326 | m_ListModules.RedrawWindow(); 327 | OnProcReady(true); 328 | } 329 | 330 | void CDlgOpenProcess::OnListProcsDblClick(NMHDR* pNMHDR, LRESULT* /*pResult*/) 331 | { 332 | if (const auto* const pNMI = reinterpret_cast(pNMHDR); 333 | pNMI->iItem >= 0 && pNMI->iSubItem >= 0) { 334 | OnOK(); 335 | } 336 | } 337 | 338 | void CDlgOpenProcess::OnListProcsGetDispInfo(NMHDR* pNMHDR, LRESULT* /*pResult*/) 339 | { 340 | const auto pDI = reinterpret_cast(pNMHDR); 341 | const auto pItem = &pDI->item; 342 | if ((pItem->mask & LVIF_TEXT) == 0) 343 | return; 344 | 345 | const auto iItem = pItem->iItem; 346 | 347 | switch (pItem->iSubItem) { 348 | case 0: //№. 349 | *std::format_to(pItem->pszText, L"{}", iItem) = L'\0'; 350 | break; 351 | case 1: //Process Name. 352 | pItem->pszText = m_vecProcs[iItem].wstrProcName.data(); 353 | break; 354 | case 2: //Process ID. 355 | *std::format_to(pItem->pszText, L"{}", m_vecProcs[iItem].dwProcID) = L'\0'; 356 | break; 357 | case 3: //Working Set. 358 | *std::format_to(pItem->pszText, m_locale, L"{:L}KB", m_vecProcs[iItem].dwWorkingSet / 1024) = L'\0'; 359 | break; 360 | default: 361 | break; 362 | } 363 | } 364 | 365 | void CDlgOpenProcess::OnListProcsGetTooltip(NMHDR* pNMHDR, LRESULT* /*pResult*/) 366 | { 367 | const auto pTTI = reinterpret_cast(pNMHDR); 368 | const auto iItem = pTTI->iItem; 369 | const auto iSubItem = pTTI->iSubItem; 370 | if (iItem < 0 || iSubItem != 1) //First column. 371 | return; 372 | 373 | const auto hProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_vecProcs[iItem].dwProcID); 374 | if (hProc == nullptr) 375 | return; 376 | 377 | m_wstrTTProcPath.resize_and_overwrite(MAX_PATH, [hProc](wchar_t* pData, std::size_t sSize) { 378 | DWORD dwSize { static_cast(sSize) }; 379 | const auto ret = ::QueryFullProcessImageNameW(hProc, 0, pData, &dwSize); 380 | return ret ? dwSize : 0; }); 381 | ::CloseHandle(hProc); 382 | 383 | pTTI->stData.pwszText = m_wstrTTProcPath.data(); 384 | } 385 | 386 | void CDlgOpenProcess::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct) 387 | { 388 | if (nIDCtl == IDC_OPENPROCESS_LIST_PROCS) { 389 | m_ListProcs.MeasureItem(lpMeasureItemStruct); 390 | return; 391 | } 392 | else if (nIDCtl == IDC_OPENPROCESS_LIST_MODULES) { 393 | m_ListModules.MeasureItem(lpMeasureItemStruct); 394 | return; 395 | } 396 | 397 | CDialogEx::OnMeasureItem(nIDCtl, lpMeasureItemStruct); 398 | } 399 | 400 | void CDlgOpenProcess::OnMouseMove(UINT nFlags, CPoint point) 401 | { 402 | static constexpr auto iResAreaHalfWidth = 6; //Area where cursor turns into resizable (IDC_SIZEWE). 403 | static constexpr auto iWidthBetweenLists = 1; //Width between tree and list after resizing. 404 | static constexpr auto iMinLeftListWidth = 100; //Left list minimum allowed width. 405 | static const auto hCurResize = static_cast(LoadImageW(nullptr, IDC_SIZEWE, IMAGE_CURSOR, 0, 0, LR_SHARED)); 406 | static const auto hCurArrow = static_cast(LoadImageW(nullptr, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED)); 407 | 408 | CRect rcList; 409 | ::GetWindowRect(m_ListModules.GetHWND(), rcList); 410 | ScreenToClient(rcList); 411 | 412 | if (m_fLMDownResize) { 413 | CRect rcTree; 414 | ::GetWindowRect(m_ListProcs.GetHWND(), rcTree); 415 | ScreenToClient(rcTree); 416 | rcTree.right = point.x - iWidthBetweenLists; 417 | rcList.left = point.x; 418 | if (rcTree.Width() >= iMinLeftListWidth) { 419 | auto hdwp = BeginDeferWindowPos(2); //Simultaneously resizing lists. 420 | hdwp = DeferWindowPos(hdwp, m_ListProcs.GetHWND(), nullptr, rcTree.left, rcTree.top, 421 | rcTree.Width(), rcTree.Height(), SWP_NOACTIVATE | SWP_NOZORDER); 422 | hdwp = DeferWindowPos(hdwp, m_ListModules.GetHWND(), nullptr, rcList.left, rcList.top, 423 | rcList.Width(), rcList.Height(), SWP_NOACTIVATE | SWP_NOZORDER); 424 | EndDeferWindowPos(hdwp); 425 | } 426 | } 427 | else { 428 | if (const CRect rcSplitter(rcList.left - iResAreaHalfWidth, rcList.top, rcList.left + iResAreaHalfWidth, rcList.bottom); 429 | rcSplitter.PtInRect(point)) { 430 | m_fCurInSplitter = true; 431 | SetCursor(hCurResize); 432 | SetCapture(); 433 | } 434 | else { 435 | m_fCurInSplitter = false; 436 | SetCursor(hCurArrow); 437 | ReleaseCapture(); 438 | } 439 | } 440 | 441 | CDialogEx::OnMouseMove(nFlags, point); 442 | } 443 | 444 | BOOL CDlgOpenProcess::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) 445 | { 446 | const auto* const pNMI = reinterpret_cast(lParam); 447 | 448 | if (pNMI->hdr.idFrom == IDC_OPENPROCESS_LIST_PROCS) { 449 | if (pNMI->hdr.code == LVN_COLUMNCLICK) { 450 | OnListProcsColumnClick(reinterpret_cast(lParam), pResult); 451 | return TRUE; 452 | } 453 | } 454 | else if (pNMI->hdr.idFrom == IDC_OPENPROCESS_LIST_MODULES) { 455 | if (pNMI->hdr.code == LVN_COLUMNCLICK) { 456 | OnListModulesColumnClick(reinterpret_cast(lParam), pResult); 457 | return TRUE; 458 | } 459 | } 460 | 461 | 462 | return CDialogEx::OnNotify(wParam, lParam, pResult); 463 | } 464 | 465 | void CDlgOpenProcess::OnOK() 466 | { 467 | if (!m_fProcReady) 468 | return; 469 | 470 | m_vecOpenData.clear(); 471 | int nItem { -1 }; 472 | for (auto i { 0UL }; i < m_ListProcs.GetSelectedCount(); ++i) { 473 | nItem = m_ListProcs.GetNextItem(nItem, LVNI_SELECTED); 474 | auto& ref = m_vecProcs[nItem]; 475 | m_vecOpenData.emplace_back(ut::DATAOPEN { .wstrDataPath { std::move(ref.wstrProcName) }, 476 | .dwProcID { ref.dwProcID }, .eOpenMode { ut::EOpenMode::OPEN_PROC } }); 477 | } 478 | 479 | CDialogEx::OnOK(); 480 | } 481 | 482 | void CDlgOpenProcess::OnProcReady(bool fReady) 483 | { 484 | std::wstring wstr; 485 | if (fReady) { 486 | wstr = L"Process ready to be opened"; 487 | } 488 | else { 489 | wchar_t buffErr[MAX_PATH]; 490 | FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, GetLastError(), 491 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffErr, MAX_PATH, nullptr); 492 | (wstr += L"Process can't be opened: ") += buffErr; 493 | } 494 | 495 | m_fProcReady = fReady; 496 | m_btnOpen.EnableWindow(fReady); 497 | m_statInfo.SetWindowTextW(wstr.data()); 498 | } 499 | 500 | void CDlgOpenProcess::RefreshProcs() 501 | { 502 | m_vecProcs.clear(); 503 | DWORD dwLevel { 1 }; 504 | WTS_PROCESS_INFO_EXW* pWPI { }; 505 | DWORD dwCount { }; 506 | if (WTSEnumerateProcessesExW(WTS_CURRENT_SERVER_HANDLE, &dwLevel, WTS_ANY_SESSION, 507 | reinterpret_cast(&pWPI), &dwCount) == FALSE) { 508 | MessageBoxW(L"Process enumeration failed", L"Error", MB_ICONERROR); 509 | return; 510 | } 511 | 512 | m_vecProcs.reserve(dwCount); 513 | for (auto i { 0UL }; i < dwCount; ++i) { 514 | m_vecProcs.emplace_back(pWPI[i].pProcessName, pWPI[i].ProcessId, pWPI[i].WorkingSetSize); 515 | } 516 | 517 | WTSFreeMemoryExW(WTS_TYPE_CLASS::WTSTypeProcessInfoLevel1, pWPI, dwCount); 518 | 519 | m_ListProcs.SetItemCountEx(static_cast(m_vecProcs.size())); 520 | m_ListProcs.RedrawWindow(); 521 | } -------------------------------------------------------------------------------- /Hexer/Hexer.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include "resource.h" 4 | 5 | #define APSTUDIO_READONLY_SYMBOLS 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Generated from the TEXTINCLUDE 2 resource. 9 | // 10 | #ifndef APSTUDIO_INVOKED 11 | #endif 12 | #include "afxres.h" 13 | #include "verrsrc.h" 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | #undef APSTUDIO_READONLY_SYMBOLS 17 | 18 | ///////////////////////////////////////////////////////////////////////////// 19 | // English (United States) resources 20 | 21 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 22 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 23 | #pragma code_page(1252) 24 | 25 | #ifdef APSTUDIO_INVOKED 26 | ///////////////////////////////////////////////////////////////////////////// 27 | // 28 | // TEXTINCLUDE 29 | // 30 | 31 | 1 TEXTINCLUDE 32 | BEGIN 33 | "resource.h\0" 34 | END 35 | 36 | 2 TEXTINCLUDE 37 | BEGIN 38 | "#ifndef APSTUDIO_INVOKED\r\n" 39 | "#endif\r\n" 40 | "#include ""afxres.h""\r\n" 41 | "#include ""verrsrc.h""\r\n" 42 | "\0" 43 | END 44 | 45 | 3 TEXTINCLUDE 46 | BEGIN 47 | "#define _AFX_NO_OLE_RESOURCES\r\n" 48 | "#define _AFX_NO_TRACKER_RESOURCES\r\n" 49 | "#define _AFX_NO_PROPERTY_RESOURCES\r\n" 50 | "\r\n" 51 | "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" 52 | "LANGUAGE 9, 1\r\n" 53 | "#include ""res\\Hexer.rc2"" // non-Microsoft Visual C++ edited resources\r\n" 54 | "#include ""afxres.rc"" // Standard components\r\n" 55 | "#include ""afxprint.rc"" // printing/print preview resources\r\n" 56 | "#if !defined(_AFXDLL)\r\n" 57 | "#include ""afxribbon.rc"" // MFC ribbon and control bar resources\r\n" 58 | "#endif\r\n" 59 | "#endif\r\n" 60 | "\0" 61 | END 62 | 63 | #endif // APSTUDIO_INVOKED 64 | 65 | 66 | ///////////////////////////////////////////////////////////////////////////// 67 | // 68 | // Icon 69 | // 70 | 71 | // Icon with lowest ID value placed first to ensure application icon 72 | // remains consistent on all systems. 73 | IDR_HEXER_FRAME ICON "res\\IDR_HEXER_FRAME.ico" 74 | 75 | 76 | ///////////////////////////////////////////////////////////////////////////// 77 | // 78 | // Bitmap 79 | // 80 | 81 | IDR_TOOLBAR_MAIN BITMAP "res\\IDR_TOOLBAR_MAIN.bmp" 82 | 83 | IDB_DEVICE BITMAP "res\\IDB_DEVICE.bmp" 84 | 85 | IDB_PROCESS BITMAP "res\\IDB_PROCESS.bmp" 86 | 87 | IDB_FILE BITMAP "res\\IDB_FILE.bmp" 88 | 89 | 90 | ///////////////////////////////////////////////////////////////////////////// 91 | // 92 | // Toolbar 93 | // 94 | 95 | IDR_TOOLBAR_MAIN TOOLBAR 32, 34 96 | BEGIN 97 | BUTTON IDM_FILE_NEWFILE 98 | BUTTON IDM_FILE_OPENFILE 99 | BUTTON IDM_FILE_SAVE 100 | END 101 | 102 | 103 | ///////////////////////////////////////////////////////////////////////////// 104 | // 105 | // Menu 106 | // 107 | 108 | IDR_HEXER_FRAME MENU 109 | BEGIN 110 | POPUP "&File" 111 | BEGIN 112 | MENUITEM "&New File...\tCtrl+N", IDM_FILE_NEWFILE 113 | MENUITEM "&Open File...\tCtrl+O", IDM_FILE_OPENFILE 114 | MENUITEM "Open Device...\tCtrl+D", IDM_FILE_OPENDEVICE 115 | MENUITEM "Open Process...", IDM_FILE_OPENPROCESS 116 | POPUP "Recent Files List" 117 | BEGIN 118 | MENUITEM "", IDM_FILE_RFL00 119 | END 120 | MENUITEM SEPARATOR 121 | MENUITEM "&Save\tCtrl+S", IDM_FILE_SAVE 122 | MENUITEM SEPARATOR 123 | MENUITEM "&Close", ID_FILE_CLOSE 124 | MENUITEM SEPARATOR 125 | MENUITEM "&Print...\tCtrl+P", IDM_FILE_PRINT 126 | MENUITEM SEPARATOR 127 | MENUITEM "E&xit", ID_APP_EXIT 128 | END 129 | POPUP "&Edit" 130 | BEGIN 131 | MENUITEM "&Undo\tCtrl+Z", IDM_EDIT_UNDO 132 | MENUITEM "Redo", IDM_EDIT_REDO 133 | MENUITEM SEPARATOR 134 | MENUITEM "&Copy as Hex Bytes\tCtrl+C", IDM_EDIT_COPYHEX 135 | MENUITEM "&Paste as Hex Bytes\tCtrl+V", IDM_EDIT_PASTEHEX 136 | END 137 | POPUP "&View" 138 | BEGIN 139 | MENUITEM "Data Information...", IDM_VIEW_DATAINFO 140 | MENUITEM "Bookmark Manager...", IDM_VIEW_BKMMGR 141 | MENUITEM "Data Interpreter...", IDM_VIEW_DATAINTERP 142 | MENUITEM "Template Manager...", IDM_VIEW_TEMPLMGR 143 | MENUITEM "Log Information...", IDM_VIEW_LOGGER 144 | MENUITEM "Process Memory...", IDM_VIEW_PROCMEMORY 145 | MENUITEM SEPARATOR 146 | MENUITEM "Toolbar", ID_VIEW_TOOLBAR 147 | END 148 | POPUP "Tools" 149 | BEGIN 150 | POPUP "Data Access" 151 | BEGIN 152 | MENUITEM "Read Only", IDM_DA_RO 153 | MENUITEM "Read/Write Safe", IDM_DA_RWSAFE 154 | MENUITEM "Read/Write In-Place", IDM_DA_RWINPLACE 155 | MENUITEM SEPARATOR 156 | POPUP "Data IO Mode" 157 | BEGIN 158 | MENUITEM "Memory Mapped File", IDM_DA_DATAIO_MMAP 159 | MENUITEM "Data IO Buffered", IDM_DA_DATAIO_IOBUFF 160 | MENUITEM "Data IO Immediate", IDM_DA_DATAIO_IOIMMEDIATE 161 | END 162 | END 163 | MENUITEM SEPARATOR 164 | MENUITEM "Settings...", IDM_TOOLS_SETTINGS 165 | END 166 | POPUP "&Window" 167 | BEGIN 168 | MENUITEM "&New Window", ID_WINDOW_NEW 169 | END 170 | POPUP "&Help" 171 | BEGIN 172 | MENUITEM "&About...", ID_APP_ABOUT 173 | END 174 | END 175 | 176 | 177 | ///////////////////////////////////////////////////////////////////////////// 178 | // 179 | // Accelerator 180 | // 181 | 182 | IDR_HEXER_FRAME ACCELERATORS 183 | BEGIN 184 | "N", ID_FILE_NEW, VIRTKEY, CONTROL, NOINVERT 185 | "O", ID_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT 186 | "D", IDM_FILE_OPENDEVICE, VIRTKEY, CONTROL, NOINVERT 187 | "S", IDM_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT 188 | END 189 | 190 | 191 | ///////////////////////////////////////////////////////////////////////////// 192 | // 193 | // Dialog 194 | // 195 | 196 | IDD_ABOUTBOX DIALOGEX 0, 0, 205, 74 197 | STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU 198 | CAPTION "About Hexer" 199 | FONT 8, "MS Shell Dlg", 0, 0, 0x1 200 | BEGIN 201 | ICON IDR_HEXER_FRAME,IDC_STATIC,10,11,20,20 202 | DEFPUSHBUTTON "OK",IDOK,144,53,50,14,WS_GROUP 203 | CONTROL "https://github.com/jovibor/Hexer",IDC_LINK_HEXER, 204 | "MfcLink",WS_TABSTOP,37,26,109,11 205 | CONTROL "https://github.com/jovibor/HexCtrl",IDC_LINK_HEXCTRL, 206 | "MfcLink",WS_TABSTOP,37,36,111,11 207 | LTEXT "Static",IDC_STATIC_BUILDTIME,12,59,106,8,WS_DISABLED 208 | LTEXT "<--Version-->",IDC_ABOUT_STATIC_VERSION,38,9,162,17 209 | END 210 | 211 | IDD_OPENDEVICE_DRIVE DIALOGEX 0, 0, 380, 160 212 | STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CLIPCHILDREN | WS_SYSMENU 213 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 214 | BEGIN 215 | CONTROL "",IDC_OPENDRIVE_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,2,0,374,159 216 | END 217 | 218 | IDD_OPENDEVICE_VOLUME DIALOGEX 0, 0, 380, 160 219 | STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CLIPCHILDREN | WS_SYSMENU 220 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 221 | BEGIN 222 | CONTROL "",IDC_OPENVOLUME_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,2,0,374,159 223 | END 224 | 225 | IDD_OPENDEVICE_PATH DIALOGEX 0, 0, 383, 162 226 | STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CLIPCHILDREN | WS_SYSMENU 227 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 228 | BEGIN 229 | LTEXT "Path to open, e.g. \\\\.\\PhysicalDrive0",IDC_STATIC,39,46,127,8 230 | COMBOBOX IDC_OPENPATH_COMBO_PATH,39,59,305,29,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP 231 | END 232 | 233 | IDD_OPENDEVICE DIALOGEX 0, 0, 383, 173 234 | STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME 235 | CAPTION "Open Device" 236 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 237 | BEGIN 238 | CONTROL "",IDC_OPENDEVICE_TAB,"SysTabControl32",0x0,0,0,383,13 239 | DEFPUSHBUTTON "Open",IDOK,269,152,50,14 240 | PUSHBUTTON "Cancel",IDCANCEL,327,152,50,14 241 | LTEXT "Some entities may require elevation (as Admin) to open.",IDC_OPENDEVICE_STATIC_INFO,6,155,180,8 242 | END 243 | 244 | IDD_NEWFILE DIALOGEX 0, 0, 279, 90 245 | STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU 246 | CAPTION "New File" 247 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 248 | BEGIN 249 | DEFPUSHBUTTON "Create",IDOK,161,70,50,14,WS_DISABLED 250 | PUSHBUTTON "Cancel",IDCANCEL,219,70,50,14 251 | EDITTEXT IDC_NEWFILE_EDIT_SIZE,11,18,91,13,ES_AUTOHSCROLL 252 | COMBOBOX IDC_NEWFILE_COMBO_MEASURE,103,18,67,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP 253 | EDITTEXT IDC_NEWFILE_EDIT_PATH,11,45,240,13,ES_AUTOHSCROLL 254 | PUSHBUTTON "...",IDC_NEWFILE_BTN_BROWSE,251,44,19,14 255 | LTEXT "Size of the new file:",IDC_STATIC,11,7,76,8 256 | LTEXT "Name and path of the new file:",IDC_STATIC,11,34,107,8 257 | GROUPBOX "",IDC_STATIC,5,2,270,64,0,WS_EX_TRANSPARENT 258 | END 259 | 260 | IDD_SETTINGS DIALOGEX 0, 0, 305, 306 261 | STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME 262 | EXSTYLE WS_EX_TOOLWINDOW 263 | CAPTION "Settings" 264 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 265 | BEGIN 266 | DEFPUSHBUTTON "OK",IDOK,194,285,50,14 267 | PUSHBUTTON "Cancel",IDCANCEL,247,285,50,14 268 | CONTROL "",IDC_SETTINGS_TAB,"SysTabControl32",0x0,0,0,87,13 269 | PUSHBUTTON "Defaults",IDC_SETTINGS_DEFS,16,285,50,14 270 | PUSHBUTTON "Apply",IDC_SETTINGS_APPLY,140,285,50,14,WS_DISABLED 271 | END 272 | 273 | IDD_LOGGER DIALOGEX 0, 0, 309, 176 274 | STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CLIPCHILDREN 275 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 276 | BEGIN 277 | CONTROL "",IDC_LOGINFO_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_TABSTOP,0,0,309,175 278 | END 279 | 280 | IDD_DATAINFO DIALOGEX 0, 0, 195, 297 281 | STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CLIPCHILDREN 282 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 283 | BEGIN 284 | CONTROL "",IDC_FILEINFO_GRID,"MfcPropertyGrid",0x0,0,0,195,297 285 | END 286 | 287 | IDD_SETTINGSHEXCTRL DIALOGEX 0, 0, 210, 268 288 | STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU 289 | FONT 8, "MS Shell Dlg", 400, 0, 0x0 290 | BEGIN 291 | CONTROL "",IDC_SETTINGSHEXCTRL_GRID,"MfcPropertyGrid",0x100,0,0,209,268 292 | END 293 | 294 | IDD_SETTINGSGENERAL DIALOGEX 0, 0, 210, 268 295 | STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_CLIPCHILDREN | WS_SYSMENU 296 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 297 | BEGIN 298 | CONTROL "",IDC_SETTINGSGENERAL_GRID,"MfcPropertyGrid",0x100,0,0,209,268 299 | END 300 | 301 | IDD_OPENPROCESS DIALOGEX 0, 0, 587, 321 302 | STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME 303 | CAPTION "Open Process" 304 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 305 | BEGIN 306 | CONTROL "",IDC_OPENPROCESS_LIST_PROCS,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_TABSTOP,1,0,352,299 307 | CONTROL "",IDC_OPENPROCESS_LIST_MODULES,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_OWNERDRAWFIXED | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_TABSTOP,355,0,229,299 308 | PUSHBUTTON "Refresh",IDC_OPENPROCESS_BTN_REFRESH,12,303,50,14 309 | LTEXT "",IDC_OPENPROCESS_STAT_INFO,71,306,387,8 310 | DEFPUSHBUTTON "Open",IDOK,469,303,50,14 311 | PUSHBUTTON "Cancel",IDCANCEL,525,303,50,14 312 | END 313 | 314 | IDD_PROCMEMORY DIALOGEX 0, 0, 361, 323 315 | STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME 316 | CAPTION "Process Memory" 317 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 318 | BEGIN 319 | CONTROL "",IDC_PROCMEMORY_LIST,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | LVS_OWNERDATA | WS_TABSTOP,0,1,361,322 320 | END 321 | 322 | 323 | ///////////////////////////////////////////////////////////////////////////// 324 | // 325 | // DESIGNINFO 326 | // 327 | 328 | #ifdef APSTUDIO_INVOKED 329 | GUIDELINES DESIGNINFO 330 | BEGIN 331 | IDD_ABOUTBOX, DIALOG 332 | BEGIN 333 | END 334 | 335 | IDD_OPENDEVICE_DRIVE, DIALOG 336 | BEGIN 337 | END 338 | 339 | IDD_OPENDEVICE_VOLUME, DIALOG 340 | BEGIN 341 | END 342 | 343 | IDD_OPENDEVICE_PATH, DIALOG 344 | BEGIN 345 | END 346 | 347 | IDD_OPENDEVICE, DIALOG 348 | BEGIN 349 | END 350 | 351 | IDD_NEWFILE, DIALOG 352 | BEGIN 353 | END 354 | 355 | IDD_SETTINGS, DIALOG 356 | BEGIN 357 | END 358 | 359 | IDD_LOGGER, DIALOG 360 | BEGIN 361 | END 362 | 363 | IDD_DATAINFO, DIALOG 364 | BEGIN 365 | END 366 | 367 | IDD_SETTINGSHEXCTRL, DIALOG 368 | BEGIN 369 | END 370 | 371 | IDD_SETTINGSGENERAL, DIALOG 372 | BEGIN 373 | END 374 | 375 | IDD_OPENPROCESS, DIALOG 376 | BEGIN 377 | END 378 | 379 | IDD_PROCMEMORY, DIALOG 380 | BEGIN 381 | END 382 | END 383 | #endif // APSTUDIO_INVOKED 384 | 385 | 386 | ///////////////////////////////////////////////////////////////////////////// 387 | // 388 | // Dialog Info 389 | // 390 | 391 | IDD_ABOUTBOX DLGINIT 392 | BEGIN 393 | IDC_LINK_HEXER, 0x37c, 189, 0 394 | 0x4d3c, 0x4346, 0x694c, 0x6b6e, 0x555f, 0x6c72, 0x683e, 0x7474, 0x7370, 395 | 0x2f3a, 0x672f, 0x7469, 0x7568, 0x2e62, 0x6f63, 0x2f6d, 0x6f6a, 0x6976, 396 | 0x6f62, 0x2f72, 0x6548, 0x6578, 0x3c72, 0x4d2f, 0x4346, 0x694c, 0x6b6e, 397 | 0x555f, 0x6c72, 0x3c3e, 0x464d, 0x4c43, 0x6e69, 0x5f6b, 0x7255, 0x506c, 398 | 0x6572, 0x6966, 0x3e78, 0x2f3c, 0x464d, 0x4c43, 0x6e69, 0x5f6b, 0x7255, 399 | 0x506c, 0x6572, 0x6966, 0x3e78, 0x4d3c, 0x4346, 0x694c, 0x6b6e, 0x545f, 400 | 0x6f6f, 0x746c, 0x7069, 0x3c3e, 0x4d2f, 0x4346, 0x694c, 0x6b6e, 0x545f, 401 | 0x6f6f, 0x746c, 0x7069, 0x3c3e, 0x464d, 0x4c43, 0x6e69, 0x5f6b, 0x7546, 402 | 0x6c6c, 0x6554, 0x7478, 0x6f54, 0x6c6f, 0x6974, 0x3e70, 0x4146, 0x534c, 403 | 0x3c45, 0x4d2f, 0x4346, 0x694c, 0x6b6e, 0x465f, 0x6c75, 0x546c, 0x7865, 404 | 0x5474, 0x6f6f, 0x746c, 0x7069, "\076" 405 | IDC_LINK_HEXCTRL, 0x37c, 191, 0 406 | 0x4d3c, 0x4346, 0x694c, 0x6b6e, 0x555f, 0x6c72, 0x683e, 0x7474, 0x7370, 407 | 0x2f3a, 0x672f, 0x7469, 0x7568, 0x2e62, 0x6f63, 0x2f6d, 0x6f6a, 0x6976, 408 | 0x6f62, 0x2f72, 0x6548, 0x4378, 0x7274, 0x3c6c, 0x4d2f, 0x4346, 0x694c, 409 | 0x6b6e, 0x555f, 0x6c72, 0x3c3e, 0x464d, 0x4c43, 0x6e69, 0x5f6b, 0x7255, 410 | 0x506c, 0x6572, 0x6966, 0x3e78, 0x2f3c, 0x464d, 0x4c43, 0x6e69, 0x5f6b, 411 | 0x7255, 0x506c, 0x6572, 0x6966, 0x3e78, 0x4d3c, 0x4346, 0x694c, 0x6b6e, 412 | 0x545f, 0x6f6f, 0x746c, 0x7069, 0x3c3e, 0x4d2f, 0x4346, 0x694c, 0x6b6e, 413 | 0x545f, 0x6f6f, 0x746c, 0x7069, 0x3c3e, 0x464d, 0x4c43, 0x6e69, 0x5f6b, 414 | 0x7546, 0x6c6c, 0x6554, 0x7478, 0x6f54, 0x6c6f, 0x6974, 0x3e70, 0x4146, 415 | 0x534c, 0x3c45, 0x4d2f, 0x4346, 0x694c, 0x6b6e, 0x465f, 0x6c75, 0x546c, 416 | 0x7865, 0x5474, 0x6f6f, 0x746c, 0x7069, "\076" 417 | 0 418 | END 419 | 420 | IDD_DATAINFO DLGINIT 421 | BEGIN 422 | IDC_FILEINFO_GRID, 0x37c, 414, 0 423 | 0x4d3c, 0x4346, 0x7250, 0x706f, 0x7265, 0x7974, 0x7247, 0x6469, 0x485f, 424 | 0x6165, 0x6564, 0x4372, 0x7274, 0x3e6c, 0x5254, 0x4555, 0x2f3c, 0x464d, 425 | 0x5043, 0x6f72, 0x6570, 0x7472, 0x4779, 0x6972, 0x5f64, 0x6548, 0x6461, 426 | 0x7265, 0x7443, 0x6c72, 0x3c3e, 0x464d, 0x5043, 0x6f72, 0x6570, 0x7472, 427 | 0x4779, 0x6972, 0x5f64, 0x6544, 0x6373, 0x6972, 0x7470, 0x6f69, 0x416e, 428 | 0x6572, 0x3e61, 0x4146, 0x534c, 0x3c45, 0x4d2f, 0x4346, 0x7250, 0x706f, 429 | 0x7265, 0x7974, 0x7247, 0x6469, 0x445f, 0x7365, 0x7263, 0x7069, 0x6974, 430 | 0x6e6f, 0x7241, 0x6165, 0x3c3e, 0x464d, 0x5043, 0x6f72, 0x6570, 0x7472, 431 | 0x4779, 0x6972, 0x5f64, 0x6c41, 0x6870, 0x6261, 0x7465, 0x6369, 0x6f4d, 432 | 0x6564, 0x463e, 0x4c41, 0x4553, 0x2f3c, 0x464d, 0x5043, 0x6f72, 0x6570, 433 | 0x7472, 0x4779, 0x6972, 0x5f64, 0x6c41, 0x6870, 0x6261, 0x7465, 0x6369, 434 | 0x6f4d, 0x6564, 0x3c3e, 0x464d, 0x5043, 0x6f72, 0x6570, 0x7472, 0x4779, 435 | 0x6972, 0x5f64, 0x6f4d, 0x6964, 0x6966, 0x6465, 0x7250, 0x706f, 0x7265, 436 | 0x6974, 0x7365, 0x463e, 0x4c41, 0x4553, 0x2f3c, 0x464d, 0x5043, 0x6f72, 437 | 0x6570, 0x7472, 0x4779, 0x6972, 0x5f64, 0x6f4d, 0x6964, 0x6966, 0x6465, 438 | 0x7250, 0x706f, 0x7265, 0x6974, 0x7365, 0x3c3e, 0x464d, 0x5043, 0x6f72, 439 | 0x6570, 0x7472, 0x4779, 0x6972, 0x5f64, 0x5356, 0x6f44, 0x4e74, 0x7465, 440 | 0x6f4c, 0x6b6f, 0x543e, 0x5552, 0x3c45, 0x4d2f, 0x4346, 0x7250, 0x706f, 441 | 0x7265, 0x7974, 0x7247, 0x6469, 0x565f, 0x4453, 0x746f, 0x654e, 0x4c74, 442 | 0x6f6f, 0x3e6b, 0x4d3c, 0x4346, 0x7250, 0x706f, 0x7265, 0x7974, 0x7247, 443 | 0x6469, 0x445f, 0x7365, 0x7263, 0x7069, 0x6974, 0x6e6f, 0x6f52, 0x7377, 444 | 0x303e, 0x2f3c, 0x464d, 0x5043, 0x6f72, 0x6570, 0x7472, 0x4779, 0x6972, 445 | 0x5f64, 0x6544, 0x6373, 0x6972, 0x7470, 0x6f69, 0x526e, 0x776f, 0x3e73, 446 | 447 | 0 448 | END 449 | 450 | IDD_SETTINGSHEXCTRL DLGINIT 451 | BEGIN 452 | IDC_SETTINGSHEXCTRL_GRID, 0x37c, 414, 0 453 | 0x4d3c, 0x4346, 0x7250, 0x706f, 0x7265, 0x7974, 0x7247, 0x6469, 0x485f, 454 | 0x6165, 0x6564, 0x4372, 0x7274, 0x3e6c, 0x5254, 0x4555, 0x2f3c, 0x464d, 455 | 0x5043, 0x6f72, 0x6570, 0x7472, 0x4779, 0x6972, 0x5f64, 0x6548, 0x6461, 456 | 0x7265, 0x7443, 0x6c72, 0x3c3e, 0x464d, 0x5043, 0x6f72, 0x6570, 0x7472, 457 | 0x4779, 0x6972, 0x5f64, 0x6544, 0x6373, 0x6972, 0x7470, 0x6f69, 0x416e, 458 | 0x6572, 0x3e61, 0x4146, 0x534c, 0x3c45, 0x4d2f, 0x4346, 0x7250, 0x706f, 459 | 0x7265, 0x7974, 0x7247, 0x6469, 0x445f, 0x7365, 0x7263, 0x7069, 0x6974, 460 | 0x6e6f, 0x7241, 0x6165, 0x3c3e, 0x464d, 0x5043, 0x6f72, 0x6570, 0x7472, 461 | 0x4779, 0x6972, 0x5f64, 0x6c41, 0x6870, 0x6261, 0x7465, 0x6369, 0x6f4d, 462 | 0x6564, 0x463e, 0x4c41, 0x4553, 0x2f3c, 0x464d, 0x5043, 0x6f72, 0x6570, 463 | 0x7472, 0x4779, 0x6972, 0x5f64, 0x6c41, 0x6870, 0x6261, 0x7465, 0x6369, 464 | 0x6f4d, 0x6564, 0x3c3e, 0x464d, 0x5043, 0x6f72, 0x6570, 0x7472, 0x4779, 465 | 0x6972, 0x5f64, 0x6f4d, 0x6964, 0x6966, 0x6465, 0x7250, 0x706f, 0x7265, 466 | 0x6974, 0x7365, 0x463e, 0x4c41, 0x4553, 0x2f3c, 0x464d, 0x5043, 0x6f72, 467 | 0x6570, 0x7472, 0x4779, 0x6972, 0x5f64, 0x6f4d, 0x6964, 0x6966, 0x6465, 468 | 0x7250, 0x706f, 0x7265, 0x6974, 0x7365, 0x3c3e, 0x464d, 0x5043, 0x6f72, 469 | 0x6570, 0x7472, 0x4779, 0x6972, 0x5f64, 0x5356, 0x6f44, 0x4e74, 0x7465, 470 | 0x6f4c, 0x6b6f, 0x543e, 0x5552, 0x3c45, 0x4d2f, 0x4346, 0x7250, 0x706f, 471 | 0x7265, 0x7974, 0x7247, 0x6469, 0x565f, 0x4453, 0x746f, 0x654e, 0x4c74, 472 | 0x6f6f, 0x3e6b, 0x4d3c, 0x4346, 0x7250, 0x706f, 0x7265, 0x7974, 0x7247, 473 | 0x6469, 0x445f, 0x7365, 0x7263, 0x7069, 0x6974, 0x6e6f, 0x6f52, 0x7377, 474 | 0x303e, 0x2f3c, 0x464d, 0x5043, 0x6f72, 0x6570, 0x7472, 0x4779, 0x6972, 475 | 0x5f64, 0x6544, 0x6373, 0x6972, 0x7470, 0x6f69, 0x526e, 0x776f, 0x3e73, 476 | 477 | 0 478 | END 479 | 480 | IDD_SETTINGSGENERAL DLGINIT 481 | BEGIN 482 | IDC_SETTINGSGENERAL_GRID, 0x37c, 414, 0 483 | 0x4d3c, 0x4346, 0x7250, 0x706f, 0x7265, 0x7974, 0x7247, 0x6469, 0x485f, 484 | 0x6165, 0x6564, 0x4372, 0x7274, 0x3e6c, 0x5254, 0x4555, 0x2f3c, 0x464d, 485 | 0x5043, 0x6f72, 0x6570, 0x7472, 0x4779, 0x6972, 0x5f64, 0x6548, 0x6461, 486 | 0x7265, 0x7443, 0x6c72, 0x3c3e, 0x464d, 0x5043, 0x6f72, 0x6570, 0x7472, 487 | 0x4779, 0x6972, 0x5f64, 0x6544, 0x6373, 0x6972, 0x7470, 0x6f69, 0x416e, 488 | 0x6572, 0x3e61, 0x4146, 0x534c, 0x3c45, 0x4d2f, 0x4346, 0x7250, 0x706f, 489 | 0x7265, 0x7974, 0x7247, 0x6469, 0x445f, 0x7365, 0x7263, 0x7069, 0x6974, 490 | 0x6e6f, 0x7241, 0x6165, 0x3c3e, 0x464d, 0x5043, 0x6f72, 0x6570, 0x7472, 491 | 0x4779, 0x6972, 0x5f64, 0x6c41, 0x6870, 0x6261, 0x7465, 0x6369, 0x6f4d, 492 | 0x6564, 0x463e, 0x4c41, 0x4553, 0x2f3c, 0x464d, 0x5043, 0x6f72, 0x6570, 493 | 0x7472, 0x4779, 0x6972, 0x5f64, 0x6c41, 0x6870, 0x6261, 0x7465, 0x6369, 494 | 0x6f4d, 0x6564, 0x3c3e, 0x464d, 0x5043, 0x6f72, 0x6570, 0x7472, 0x4779, 495 | 0x6972, 0x5f64, 0x6f4d, 0x6964, 0x6966, 0x6465, 0x7250, 0x706f, 0x7265, 496 | 0x6974, 0x7365, 0x463e, 0x4c41, 0x4553, 0x2f3c, 0x464d, 0x5043, 0x6f72, 497 | 0x6570, 0x7472, 0x4779, 0x6972, 0x5f64, 0x6f4d, 0x6964, 0x6966, 0x6465, 498 | 0x7250, 0x706f, 0x7265, 0x6974, 0x7365, 0x3c3e, 0x464d, 0x5043, 0x6f72, 499 | 0x6570, 0x7472, 0x4779, 0x6972, 0x5f64, 0x5356, 0x6f44, 0x4e74, 0x7465, 500 | 0x6f4c, 0x6b6f, 0x543e, 0x5552, 0x3c45, 0x4d2f, 0x4346, 0x7250, 0x706f, 501 | 0x7265, 0x7974, 0x7247, 0x6469, 0x565f, 0x4453, 0x746f, 0x654e, 0x4c74, 502 | 0x6f6f, 0x3e6b, 0x4d3c, 0x4346, 0x7250, 0x706f, 0x7265, 0x7974, 0x7247, 503 | 0x6469, 0x445f, 0x7365, 0x7263, 0x7069, 0x6974, 0x6e6f, 0x6f52, 0x7377, 504 | 0x303e, 0x2f3c, 0x464d, 0x5043, 0x6f72, 0x6570, 0x7472, 0x4779, 0x6972, 505 | 0x5f64, 0x6544, 0x6373, 0x6972, 0x7470, 0x6f69, 0x526e, 0x776f, 0x3e73, 506 | 507 | 0 508 | END 509 | 510 | 511 | ///////////////////////////////////////////////////////////////////////////// 512 | // 513 | // AFX_DIALOG_LAYOUT 514 | // 515 | 516 | IDD_ABOUTBOX AFX_DIALOG_LAYOUT 517 | BEGIN 518 | 0 519 | END 520 | 521 | IDD_OPENDEVICE_DRIVE AFX_DIALOG_LAYOUT 522 | BEGIN 523 | 0 524 | END 525 | 526 | IDD_OPENDEVICE_VOLUME AFX_DIALOG_LAYOUT 527 | BEGIN 528 | 0 529 | END 530 | 531 | IDD_OPENDEVICE_PATH AFX_DIALOG_LAYOUT 532 | BEGIN 533 | 0, 534 | 50, 50, 0, 0, 535 | 50, 50, 0, 0 536 | END 537 | 538 | IDD_OPENDEVICE AFX_DIALOG_LAYOUT 539 | BEGIN 540 | 0 541 | END 542 | 543 | IDD_NEWFILE AFX_DIALOG_LAYOUT 544 | BEGIN 545 | 0 546 | END 547 | 548 | IDD_SETTINGS AFX_DIALOG_LAYOUT 549 | BEGIN 550 | 0 551 | END 552 | 553 | IDD_LOGGER AFX_DIALOG_LAYOUT 554 | BEGIN 555 | 0, 556 | 0, 0, 100, 100 557 | END 558 | 559 | IDD_DATAINFO AFX_DIALOG_LAYOUT 560 | BEGIN 561 | 0, 562 | 0, 0, 100, 100 563 | END 564 | 565 | IDD_SETTINGSHEXCTRL AFX_DIALOG_LAYOUT 566 | BEGIN 567 | 0, 568 | 0, 0, 100, 100 569 | END 570 | 571 | IDD_SETTINGSGENERAL AFX_DIALOG_LAYOUT 572 | BEGIN 573 | 0, 574 | 0, 0, 100, 100 575 | END 576 | 577 | IDD_OPENPROCESS AFX_DIALOG_LAYOUT 578 | BEGIN 579 | 0 580 | END 581 | 582 | IDD_PROCMEMORY AFX_DIALOG_LAYOUT 583 | BEGIN 584 | 0, 585 | 0, 0, 100, 100 586 | END 587 | 588 | 589 | ///////////////////////////////////////////////////////////////////////////// 590 | // 591 | // String Table 592 | // 593 | 594 | STRINGTABLE 595 | BEGIN 596 | IDM_FILE_NEWFILE "Create new file...\nNew File" 597 | IDM_FILE_OPENFILE "Open existing file...\nOpen File" 598 | IDM_FILE_SAVE "\nSave" 599 | END 600 | 601 | STRINGTABLE 602 | BEGIN 603 | IDR_HEXER_FRAME "Hexer" 604 | END 605 | 606 | STRINGTABLE 607 | BEGIN 608 | IDC_PANE_DATAINFO "Data Info" 609 | IDC_PANE_BKMMGR "Bookmark Manager" 610 | IDC_PANE_DATAINTERP "Data Interpreter" 611 | IDC_PANE_TEMPLMGR "Template Manager" 612 | IDC_PANE_LOGGER "Log Information" 613 | END 614 | 615 | STRINGTABLE 616 | BEGIN 617 | AFX_IDS_APP_TITLE "Hexer" 618 | END 619 | 620 | #endif // English (United States) resources 621 | ///////////////////////////////////////////////////////////////////////////// 622 | 623 | 624 | 625 | #ifndef APSTUDIO_INVOKED 626 | ///////////////////////////////////////////////////////////////////////////// 627 | // 628 | // Generated from the TEXTINCLUDE 3 resource. 629 | // 630 | #define _AFX_NO_OLE_RESOURCES 631 | #define _AFX_NO_TRACKER_RESOURCES 632 | #define _AFX_NO_PROPERTY_RESOURCES 633 | 634 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 635 | LANGUAGE 9, 1 636 | #include "res\Hexer.rc2" // non-Microsoft Visual C++ edited resources 637 | #include "afxres.rc" // Standard components 638 | #include "afxprint.rc" // printing/print preview resources 639 | #if !defined(_AFXDLL) 640 | #include "afxribbon.rc" // MFC ribbon and control bar resources 641 | #endif 642 | #endif 643 | 644 | ///////////////////////////////////////////////////////////////////////////// 645 | #endif // not APSTUDIO_INVOKED 646 | 647 | --------------------------------------------------------------------------------