├── .clangformat ├── .github ├── ISSUE_TEMPLATE │ └── bug_report.md ├── dependabot.yml ├── renovate.json └── workflows │ └── megalinter.yml ├── .gitignore ├── .mega-linter.yml ├── CMakeLists.txt ├── CWinMTRCommandLineParser.ixx ├── IWinMTROptionsProvider.ixx ├── LICENSE ├── README.md ├── WinMTR.ico ├── WinMTR.rc ├── WinMTR.sln ├── WinMTR.vcxproj ├── WinMTRConfig.h.in ├── WinMTRDialog-ClassDef.ixx ├── WinMTRDialog-StateMachine.cpp ├── WinMTRDialog-display.cpp ├── WinMTRDialog-exporter.cpp ├── WinMTRDialog-registry.cpp ├── WinMTRDialog-tracing.cpp ├── WinMTRDialog.ixx ├── WinMTRDnsUtil.ixx ├── WinMTRGlobal.cpp ├── WinMTRGlobal.h ├── WinMTRHelp.ixx ├── WinMTRICMPPIOdef.h ├── WinMTRICMPUtils.ixx ├── WinMTRIPUtils.ixx ├── WinMTRLicense.ixx ├── WinMTRMain.cpp ├── WinMTRMain.h ├── WinMTRNet-ClassDef.ixx ├── WinMTRNet-Getters.cpp ├── WinMTRNet-Tracing.cpp ├── WinMTRNet.ixx ├── WinMTROptions.ixx ├── WinMTRProperties.cpp ├── WinMTRProperties.h ├── WinMTRSNetHost.ixx ├── WinMTRStatusBar.ixx ├── WinMTRUtils.ixx ├── WinMTRVerUtil.ixx ├── WinMTRWSAhelper.ixx ├── app.manifest ├── resource.h ├── targetver.h ├── vcpkg-configuration.json └── vcpkg.json /.clangformat: -------------------------------------------------------------------------------- 1 | 2 | IndentWidth: 4 3 | TabWidth: 4 4 | UseTabStyle: ForContinuationAndIndentation 5 | AlignAfterOpenBracket: Align 6 | BracedInitializerIndentWidth: 4 7 | Standard: c++20 8 | SpacesInAngles: never -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: bug 6 | assignees: leeter 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. Windows 10] 28 | - Version [e.g. 2023H2] 29 | 30 | 31 | **Additional context** 32 | Add any other context about the problem here. 33 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "nuget" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | - package-ecosystem: "github-actions" 13 | directory: "/" 14 | schedule: 15 | interval: "weekly" 16 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ "config:best-practices" ] 4 | } 5 | -------------------------------------------------------------------------------- /.github/workflows/megalinter.yml: -------------------------------------------------------------------------------- 1 | # MegaLinter GitHub Action configuration file 2 | # More info at https://megalinter.io 3 | --- 4 | name: MegaLinter 5 | 6 | # Trigger mega-linter at every push. Action will also be visible from Pull 7 | # Requests to main 8 | on: 9 | # Comment this line to trigger action only on pull-requests 10 | # (not recommended if you don't pay for GH Actions) 11 | push: 12 | 13 | pull_request: 14 | branches: 15 | - main 16 | - master 17 | 18 | # Comment env block if you do not want to apply fixes 19 | env: 20 | # Apply linter fixes configuration 21 | # 22 | # When active, APPLY_FIXES must also be defined as environment variable 23 | # (in github/workflows/mega-linter.yml or other CI tool) 24 | APPLY_FIXES: all 25 | 26 | # Decide which event triggers application of fixes in a commit or a PR 27 | # (pull_request, push, all) 28 | APPLY_FIXES_EVENT: pull_request 29 | 30 | # If APPLY_FIXES is used, defines if the fixes are directly committed (commit) 31 | # or posted in a PR (pull_request) 32 | APPLY_FIXES_MODE: pull_request 33 | 34 | concurrency: 35 | group: ${{ github.ref }}-${{ github.workflow }} 36 | cancel-in-progress: true 37 | 38 | jobs: 39 | megalinter: 40 | name: MegaLinter 41 | runs-on: ubuntu-latest 42 | 43 | # Give the default GITHUB_TOKEN write permission to commit and push, comment 44 | # issues & post new PR; remove the ones you do not need 45 | permissions: 46 | contents: write 47 | issues: write 48 | pull-requests: write 49 | 50 | steps: 51 | 52 | # Git Checkout 53 | - name: Checkout Code 54 | uses: actions/checkout@85e6279cec87321a52edac9c87bce653a07cf6c2 # pin@v4 55 | with: 56 | token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} 57 | 58 | # If you use VALIDATE_ALL_CODEBASE = true, you can remove this line to 59 | # improve performance 60 | fetch-depth: 0 61 | 62 | # MegaLinter 63 | - name: MegaLinter 64 | 65 | # You can override MegaLinter flavor used to have faster performances 66 | # More info at https://megalinter.io/flavors/ 67 | uses: oxsecurity/megalinter/flavors/c_cpp@5a91fb06c83d0e69fbd23756d47438aa723b4a5a # pin@5a91fb06c83d0e69fbd23756d47438aa723b4a5a # v8.7.0 68 | 69 | id: ml 70 | 71 | # All available variables are described in documentation 72 | # https://megalinter.io/configuration/ 73 | env: 74 | 75 | # Validates all source when push on main, else just the git diff with 76 | # main. Override with true if you always want to lint all sources 77 | # 78 | # To validate the entire codebase, set to: 79 | # VALIDATE_ALL_CODEBASE: true 80 | # 81 | # To validate only diff with main, set to: 82 | # VALIDATE_ALL_CODEBASE: >- 83 | # ${{ 84 | # github.event_name == 'push' && 85 | # contains(fromJSON('["refs/heads/main", "refs/heads/master"]'), github.ref) 86 | # }} 87 | # VALIDATE_ALL_CODEBASE: >- 88 | # ${{ 89 | # github.event_name == 'push' && 90 | # contains(fromJSON('["refs/heads/main", "refs/heads/master"]'), github.ref) 91 | # }} 92 | VALIDATE_ALL_CODEBASE: false 93 | 94 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 95 | # ADD YOUR CUSTOM ENV VARIABLES HERE OR DEFINE THEM IN A FILE 96 | # .mega-linter.yml AT THE ROOT OF YOUR REPOSITORY 97 | 98 | # Uncomment to disable copy-paste and spell checks 99 | # DISABLE: COPYPASTE,SPELL 100 | 101 | # Upload MegaLinter artifacts 102 | - name: Archive production artifacts 103 | uses: actions/upload-artifact@6027e3dd177782cd8ab9af838c04fd81a07f1d47 # pin@v4 104 | 105 | if: success() || failure() 106 | with: 107 | name: MegaLinter reports 108 | path: | 109 | megalinter-reports 110 | mega-linter.log 111 | 112 | # Set APPLY_FIXES_IF var for use in future steps 113 | - name: Set APPLY_FIXES_IF var 114 | run: | 115 | printf 'APPLY_FIXES_IF=%s\n' "${{ 116 | steps.ml.outputs.has_updated_sources == 1 && 117 | ( 118 | env.APPLY_FIXES_EVENT == 'all' || 119 | env.APPLY_FIXES_EVENT == github.event_name 120 | ) && 121 | ( 122 | github.event_name == 'push' || 123 | github.event.pull_request.head.repo.full_name == github.repository 124 | ) 125 | }}" >> "${GITHUB_ENV}" 126 | 127 | # Set APPLY_FIXES_IF_* vars for use in future steps 128 | - name: Set APPLY_FIXES_IF_* vars 129 | run: | 130 | printf 'APPLY_FIXES_IF_PR=%s\n' "${{ 131 | env.APPLY_FIXES_IF == 'true' && 132 | env.APPLY_FIXES_MODE == 'pull_request' 133 | }}" >> "${GITHUB_ENV}" 134 | printf 'APPLY_FIXES_IF_COMMIT=%s\n' "${{ 135 | env.APPLY_FIXES_IF == 'true' && 136 | env.APPLY_FIXES_MODE == 'commit' && 137 | (!contains(fromJSON('["refs/heads/main", "refs/heads/master"]'), github.ref)) 138 | }}" >> "${GITHUB_ENV}" 139 | 140 | # Create pull request if applicable 141 | # (for now works only on PR from same repository, not from forks) 142 | - name: Create Pull Request with applied fixes 143 | uses: peter-evans/create-pull-request@0f2a09222f84e1d0d078fdec150cbe3ff4c5b799 # pin@v5 144 | id: cpr 145 | if: env.APPLY_FIXES_IF_PR == 'true' 146 | with: 147 | token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} 148 | commit-message: "[MegaLinter] Apply linters automatic fixes" 149 | title: "[MegaLinter] Apply linters automatic fixes" 150 | labels: bot 151 | 152 | - name: Create PR output 153 | if: env.APPLY_FIXES_IF_PR == 'true' 154 | run: | 155 | echo "PR Number - ${{ steps.cpr.outputs.pull-request-number }}" 156 | echo "PR URL - ${{ steps.cpr.outputs.pull-request-url }}" 157 | 158 | # Push new commit if applicable 159 | # (for now works only on PR from same repository, not from forks) 160 | - name: Prepare commit 161 | if: env.APPLY_FIXES_IF_COMMIT == 'true' 162 | run: sudo chown -Rc $UID .git/ 163 | 164 | - name: Commit and push applied linter fixes 165 | uses: stefanzweifel/git-auto-commit-action@ddb7ae415961225797e0234a7018a30ba1e66bb3 # pin@v5 166 | if: env.APPLY_FIXES_IF_COMMIT == 'true' 167 | with: 168 | branch: >- 169 | ${{ 170 | github.event.pull_request.head.ref || 171 | github.head_ref || 172 | github.ref 173 | }} 174 | commit_message: "[MegaLinter] Apply linters fixes" 175 | commit_user_name: megalinter-bot 176 | commit_user_email: nicolas.vuillamy@ox.security 177 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # This .gitignore file was automatically created by Microsoft(R) Visual Studio. 3 | ################################################################################ 4 | 5 | /.vs 6 | /Release 7 | /Release_x64 8 | /WinMTR.suo 9 | /Debug 10 | /Debug_x64 11 | *.user 12 | *.aps 13 | /CMakeFiles 14 | /out/build 15 | /WinMTR.dir/Debug 16 | /x64/Debug/ZERO_CHECK 17 | *.filters 18 | /WinMTRConfig.h 19 | /CMakeCache.txt 20 | /Debug_x64_san 21 | /packages/* 22 | /ARM64/Release 23 | /Release_ARM64 24 | /Release_x32 25 | /Release Installer_x64 26 | /megalinter-reports/ 27 | /vcpkg_installed/x64-windows 28 | /vcpkg_installed/ARM64-windows-static 29 | -------------------------------------------------------------------------------- /.mega-linter.yml: -------------------------------------------------------------------------------- 1 | # Configuration file for MegaLinter 2 | # See all available variables at https://megalinter.io/configuration/ and in linters documentation 3 | 4 | APPLY_FIXES: all 5 | 6 | DISABLE: 7 | - SPELL 8 | 9 | DISABLE_LINTERS: 10 | - REPOSITORY_CHECKOV 11 | - REPOSITORY_KICS 12 | - REPOSITORY_DEVSKIM 13 | 14 | PRINT_ALL_FILES: false 15 | FILTER_REGEX_EXCLUDE: '(\.automation/test|\.automation/generated|\.venv|\.github/workflows|docs/javascripts|docs/overrides|docs/json-schemas|flavors|clj-kondo|TEMPLATES)' 16 | JSON_JSONLINT_FILTER_REGEX_EXCLUDE: '(\.vscode/)' 17 | YAML_YAMLLINT_FILTER_REGEX_EXCLUDE: '(templates/\.mega-linter\.yml)' 18 | YAML_PRETTIER_FILTER_REGEX_EXCLUDE: '(templates/\.mega-linter\.yml|mkdocs\.yml)' 19 | YAML_V8R_FILTER_REGEX_EXCLUDE: '(descriptors|templates/\.mega-linter\.yml|\.codecov\.yml)' 20 | CPP_CPPLINT_FILE_EXTENSIONS: [".cpp", ".h", ".cc", ".hpp", ".cxx", ".cu", ".hxx", ".c++", ".hh", ".h++", ".cuh", ".ixx"] 21 | BASH_FILTER_REGEX_EXCLUDE: "(lib)" 22 | MARKDOWN_FILTER_REGEX_EXCLUDE: '(license\.md|docs/licenses)' 23 | MARKDOWN_MARKDOWN_LINK_CHECK_DISABLE_ERRORS: true 24 | SPELL_VALE_FILE_EXTENSIONS: 25 | - .md 26 | SPELL_FILTER_REGEX_EXCLUDE: (\.mega-linter\.yml|valestyles|\.github|docs/licenses) -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | # specify the C++ standard 4 | set(CMAKE_CXX_STANDARD 20) 5 | set(CMAKE_CXX_STANDARD_REQUIRED True) 6 | set(CMAKE_CXX_EXTENSIONS OFF) 7 | # set the project name 8 | project(WinMTR VERSION 0.10.0.1) 9 | 10 | #if (MSVC_VERSION GREATER_EQUAL "1900") 11 | # include(CheckCXXCompilerFlag) 12 | # CHECK_CXX_COMPILER_FLAG("/std:c++latest" _cpp_latest_flag_supported) 13 | # if (_cpp_latest_flag_supported) 14 | # add_compile_options("/std:c++latest") 15 | # endif() 16 | #endif() 17 | 18 | add_definitions(-D_AFXDLL -DUNICODE -D_UNICODE) 19 | set(CMAKE_MFC_FLAG 1) 20 | file(GLOB WinMTR_HEADERS *.h) 21 | file(GLOB WinMTR_SOURCE *.cpp) 22 | file(GLOB WinMTR_RESOURCE *.rc) 23 | 24 | 25 | 26 | # add the executable 27 | add_executable(WinMTR WIN32 ${WinMTR_HEADERS} ${WinMTR_SOURCE} ${WinMTR_RESOURCE}) 28 | 29 | 30 | configure_file(WinMTRConfig.h.in WinMTRConfig.h) 31 | 32 | #target_include_directories(WinMTR PUBLIC 33 | # "${PROJECT_BINARY_DIR}" 34 | # "${CMAKE_CURRENT_SOURCE_DIR}" 35 | # ) 36 | target_link_libraries(WinMTR onecore.lib) 37 | 38 | 39 | -------------------------------------------------------------------------------- /CWinMTRCommandLineParser.ixx: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2022 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | module; 22 | #pragma warning (disable : 4005) 23 | #include "targetver.h" 24 | #define WIN32_LEAN_AND_MEAN 25 | #define VC_EXTRALEAN 26 | 27 | #include 28 | #include 29 | 30 | export module WinMTR.CommandLineParser; 31 | 32 | import WinMTR.Dialog; 33 | 34 | export namespace utils { 35 | 36 | class CWinMTRCommandLineParser final : 37 | public CCommandLineInfo 38 | { 39 | public: 40 | CWinMTRCommandLineParser(WinMTRDialog& dlg) noexcept 41 | :dlg(dlg) {} 42 | private: 43 | 44 | void ParseParam(const WCHAR* pszParam, BOOL bFlag, [[maybe_unused]] BOOL bLast) noexcept override final; 45 | #ifdef _UNICODE 46 | void ParseParam([[maybe_unused]] const char* pszParam, [[maybe_unused]] BOOL bFlag, [[maybe_unused]] BOOL bLast) noexcept override final 47 | { 48 | } 49 | #endif 50 | private: 51 | 52 | WinMTRDialog& dlg; 53 | 54 | enum class expect_next { 55 | none, 56 | interval, 57 | ping_size, 58 | lru 59 | }; 60 | expect_next next = expect_next::none; 61 | bool m_help = false; 62 | 63 | public: 64 | bool isAskingForHelp() const noexcept { 65 | return m_help; 66 | } 67 | 68 | }; 69 | } 70 | 71 | 72 | module : private; 73 | 74 | import ; 75 | import WinMTRUtils; 76 | 77 | 78 | void utils::CWinMTRCommandLineParser::ParseParam(const WCHAR* pszParam, BOOL bFlag, [[maybe_unused]] BOOL bLast) noexcept 79 | { 80 | using namespace std::literals; 81 | if (bFlag) { 82 | if (L"h"sv == pszParam || L"-help"sv == pszParam) { 83 | this->m_help = true; 84 | } 85 | else if (L"n"sv == pszParam || L"-numeric"sv == pszParam) { 86 | this->dlg.SetUseDNS(false, WinMTRDialog::options_source::cmd_line); 87 | } 88 | else if (L"i"sv == pszParam || L"-interval"sv == pszParam) { 89 | this->next = expect_next::interval; 90 | } 91 | else if (L"m"sv == pszParam || L"-maxLRU"sv == pszParam) { 92 | this->next = expect_next::lru; 93 | } 94 | else if (L"s"sv == pszParam || L"-size"sv == pszParam) { 95 | this->next = expect_next::ping_size; 96 | } 97 | return; 98 | } 99 | wchar_t* end = nullptr; 100 | switch (this->next) { 101 | case expect_next::lru: 102 | { 103 | auto parsed = std::wcstol(pszParam, &end, 10); 104 | if (parsed < WinMTRUtils::MIN_MAX_LRU || parsed > WinMTRUtils::MAX_MAX_LRU) { 105 | parsed = WinMTRUtils::DEFAULT_MAX_LRU; 106 | } 107 | this->dlg.SetMaxLRU(parsed, WinMTRDialog::options_source::cmd_line); 108 | } 109 | break; 110 | case expect_next::interval: 111 | { 112 | auto parsed = std::wcstof(pszParam, &end); 113 | if (parsed > WinMTRUtils::MAX_INTERVAL || parsed < WinMTRUtils::MIN_INTERVAL) { 114 | parsed = WinMTRUtils::DEFAULT_INTERVAL; 115 | } 116 | this->dlg.SetInterval(parsed, WinMTRDialog::options_source::cmd_line); 117 | } 118 | break; 119 | case expect_next::ping_size: 120 | { 121 | auto parsed = std::wcstol(pszParam, &end, 10); 122 | if (parsed > WinMTRUtils::MAX_PING_SIZE || parsed < WinMTRUtils::MIN_PING_SIZE) { 123 | parsed = WinMTRUtils::DEFAULT_PING_SIZE; 124 | } 125 | this->dlg.SetPingSize(parsed, WinMTRDialog::options_source::cmd_line); 126 | } 127 | break; 128 | default: 129 | break; 130 | } 131 | this->next = expect_next::none; 132 | } -------------------------------------------------------------------------------- /IWinMTROptionsProvider.ixx: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2021 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | export module WinMTROptionsProvider; 22 | /*** 23 | * Note: Implementers must ensure that calling any of the methods is thread safe 24 | */ 25 | export struct __declspec(novtable) IWinMTROptionsProvider { 26 | virtual unsigned getPingSize() const noexcept = 0; 27 | virtual double getInterval() const noexcept = 0; 28 | virtual bool getUseDNS() const noexcept = 0; 29 | }; 30 | 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | WinMTR – Appnor's Free Network Diagnostic Tool 2 | 3 | Thank you for downloading WinMTR v0.93! 4 | 5 | # About 6 | 7 | WinMTR is a free MS Windows visual application that combines the functionality of the traceroute and ping in a single network diagnostic tool. WinMTR is Open Source Software, maintained by Appnor MSP, a fully managed hosting & cloud provider. 8 | 9 | It was started in 2000 by Vasile Laurentiu Stanimir as a clone for the popular Matt’s Traceroute (hence MTR) Linux/UNIX utility. 10 | 11 | # License & Redistribution 12 | 13 | WinMTR is offered as Open Source Software under GPL v2. 14 | Read more about the licensing conditions: http://www.gnu.org/licenses/gpl-2.0.html 15 | Download the code from: https://github.com/leeter/WinMTR-refresh 16 | 17 | # Installation 18 | 19 | You will get a .zip archive containing two folders WinMTR-32 and WinMTR-64. 20 | Both contain two files: WinMTR.exe and README.TXT. 21 | Just extract the WinMTR.exe for your platform (32 or 64 bit) and click to run it. 22 | If you don’t know what version you need, just click on both files and see which one works ;-) 23 | As you can see, WinMTR requires no other installation effort. 24 | 25 | Trick: You can copy the WinMTR.exe file in Windows/System32 so it’s accessible via the command line – cmd! 26 | 27 | ## Supported platforms: 28 | * Windows 11 latest release 29 | * Windows 10x64 (until MS support drop) 30 | 31 | ## Best effort platforms (the maintainer doesn't have hardware, and the compiler doesn't always cooperate) 32 | * Windows 11 on ARM 33 | 34 | # Usage 35 | 36 | Visual: 37 | 38 | * Start WinMTR. 39 | * Write the name or IP ofthe host (e.g. google.com) 40 | * Press the Options buttonto configure ping size,maximum hops and pinginterval (the defaults areOK). 41 | * Push the Start buttonand wait. 42 | * Copy or export theresults in text or HTMLformat. Useful if you wantto document or file acomplaint with your ISP. 43 | * Click on Clear History to remove the hosts you have previously traced. 44 | 45 | Command line: 46 | 47 | * Run winmtr.exe --help to see what are the options 48 | * Run winmtr hostname (e.g. winmtr www.yahoo.com) 49 | 50 | # Troubleshooting 51 | 52 | a) I type in the address and nothing happens. 53 | 54 | Usually this has to do with lame anti-virus or firewall applications. Stop all that when doing debugging or when using WinMTR. Or, configure them properly. 55 | 56 | b) I get an error saying the program cannot be executed. 57 | 58 | You are running the 64 bit version on a 32 bit platform. Try the WinMTR.exe stored in the WinMTR_x32 folder. 59 | 60 | c) I get an error unspecified here. 61 | 62 | Please report it to us to make sure it’s not a bug in the application. 63 | 64 | 65 | # Old Changelog 66 | * 31.01.2011 - Version v0.92 is out, fixing reporting errors for very slow connections. 67 | * 11.01.2011 - Version v0.91 is out under GPL v2, by popular request. 68 | * 24.12.2010 - New version! for 32 and 64 bit Operating Systems. Now works on Windows 7 as a regular user. Various bug fixes. License changed from GPL to commercial, but not for long ;-) (v0.9) 69 | * 20.01.2002 - Last entered hosts an options are now hold in registry. Home page and development moved to Sourceforge. 70 | * 05.09.2001 - Replace edit box with combo box which hold last entered host names. Fixed a memory leak which caused program to crash after a long time running. (v0.7) 71 | * 11.27.2000 - Added resizing support and flat buttons. (v0.6) 72 | 11.26.2000 - Added copy data to clipboard and possibility to save data to file as text or HTML.(v0.5) 73 | * 08.03.2000 - Added double-click on host name in list for detailed information. (v0.4) 74 | * 08.02.2000 - Fixed ICMP error codes handling. Print an error message corresponding to ICP_HOST_UNREACHABLE error code instead of a empty line. (v0.3) 75 | * 08.01.2000 - Support for full command-line operations. (v0.2) 76 | * 07.28.2000 - First release. (v0.1) 77 | 78 | # Bug Reports 79 | 80 | Let us know if you identify bugs. Make sure you mention the WinMTR version. Also, we need as much info as possible about your Operating System and current setup. 81 | Before submitting a bug make sure it is not something related to your own specific configurations (e.g. anti-viruses, firewalls). 82 | 83 | # Feature requests 84 | 85 | If you need some functionality from which others can also benefit, please let us know. We will try to integrate your request on our future releases. 86 | Specific features can be implemented on request under a commercial support agreement. Costs depend on complexity and timing. Contact us for a custom quotation. 87 | If you are a developer planning to extend the current open source code, please let us know, so we can integrate it in the official tree 88 | 89 | 90 | # Contact 91 | 92 | © GPL v2 - 2010-2010 Appnor MSP S.A. - http://www.appnor.com 93 | 94 | © GPL v2 - 2020-2023 Leetsoftwerx 95 | -------------------------------------------------------------------------------- /WinMTR.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leeter/WinMTR-refresh/8f4ad8851773d65062fabeb372f4b731361c13e6/WinMTR.ico -------------------------------------------------------------------------------- /WinMTR.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 | #include "afxres.h" 11 | 12 | ///////////////////////////////////////////////////////////////////////////// 13 | #undef APSTUDIO_READONLY_SYMBOLS 14 | 15 | ///////////////////////////////////////////////////////////////////////////// 16 | // English (United States) resources 17 | 18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 19 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 20 | #pragma code_page(1252) 21 | 22 | #ifdef APSTUDIO_INVOKED 23 | ///////////////////////////////////////////////////////////////////////////// 24 | // 25 | // TEXTINCLUDE 26 | // 27 | 28 | 1 TEXTINCLUDE 29 | BEGIN 30 | "resource.h\0" 31 | END 32 | 33 | 2 TEXTINCLUDE 34 | BEGIN 35 | "#include ""afxres.h""\r\n" 36 | "\0" 37 | END 38 | 39 | 3 TEXTINCLUDE 40 | BEGIN 41 | "#define _AFX_NO_SPLITTER_RESOURCES\r\n" 42 | "#define _AFX_NO_OLE_RESOURCES\r\n" 43 | "#define _AFX_NO_TRACKER_RESOURCES\r\n" 44 | "#define _AFX_NO_PROPERTY_RESOURCES\r\n" 45 | "\r\n" 46 | "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" 47 | "#ifdef _WIN32\r\n" 48 | "LANGUAGE 9, 1\r\n" 49 | "#pragma code_page(1252)\r\n" 50 | "#endif //_WIN32\r\n" 51 | "#include ""afxres.rc"" // Standard components\r\n" 52 | "#endif\r\n" 53 | "\0" 54 | END 55 | 56 | #endif // APSTUDIO_INVOKED 57 | 58 | 59 | ///////////////////////////////////////////////////////////////////////////// 60 | // 61 | // Icon 62 | // 63 | 64 | // Icon with lowest ID value placed first to ensure application icon 65 | // remains consistent on all systems. 66 | IDR_MAINFRAME ICON "WinMTR.ico" 67 | 68 | 69 | ///////////////////////////////////////////////////////////////////////////// 70 | // 71 | // Dialog 72 | // 73 | 74 | IDD_WINMTR_DIALOG DIALOGEX 0, 0, 390, 193 75 | STYLE DS_SETFONT | DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME 76 | EXSTYLE WS_EX_APPWINDOW 77 | FONT 8, "MS Sans Serif", 0, 0, 0x1 78 | BEGIN 79 | DEFPUSHBUTTON "&Start",ID_RESTART,203,12,50,14,BS_FLAT 80 | PUSHBUTTON "&Options",ID_OPTIONS,270,12,51,14,BS_FLAT 81 | PUSHBUTTON "E&xit",IDCANCEL,328,12,49,14,BS_FLAT 82 | PUSHBUTTON "&Copy Text to clipboard",ID_CTTC,14,39,89,14,BS_FLAT 83 | PUSHBUTTON "Co&py HTML to clipboard",ID_CHTC,113,39,89,14,BS_FLAT 84 | PUSHBUTTON "Export &TEXT",ID_EXPT,270,39,51,14,BS_FLAT 85 | PUSHBUTTON "Export &HTML",ID_EXPH,328,39,49,14,BS_FLAT 86 | CONTROL "List1",IDC_LIST_MTR,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,7,60,376,126 87 | LTEXT "Host:",IDC_STATIC,13,12,20,13,SS_CENTERIMAGE 88 | GROUPBOX "",IDC_STATIC,7,3,251,29,BS_FLAT 89 | GROUPBOX "",IDC_STATICS,263,3,120,29,BS_FLAT 90 | GROUPBOX "",IDC_STATICJ,7,31,376,26,BS_FLAT 91 | COMBOBOX IDC_COMBO_HOST,35,12,164,73,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP 92 | END 93 | 94 | IDD_DIALOG_OPTIONS DIALOGEX 0, 0, 251, 188 95 | STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 96 | CAPTION "Options" 97 | FONT 8, "MS Sans Serif", 0, 0, 0x0 98 | BEGIN 99 | DEFPUSHBUTTON "&OK",IDOK,53,167,50,14,BS_FLAT 100 | PUSHBUTTON "&Cancel",IDCANCEL,141,167,50,14,BS_FLAT 101 | GROUPBOX "",IDC_STATIC,7,91,237,67,BS_FLAT 102 | ICON IDR_MAINFRAME,IDC_STATIC,15,12,20,20 103 | LTEXT "Interval (sec):",IDC_STATIC,15,102,45,10,NOT WS_GROUP 104 | EDITTEXT IDC_EDIT_INTERVAL,71,99,34,13,ES_AUTOHSCROLL 105 | LTEXT "Ping size (bytes):",IDC_STATIC,139,102,53,10,NOT WS_GROUP 106 | EDITTEXT IDC_EDIT_SIZE,196,99,34,13,ES_AUTOHSCROLL | ES_NUMBER 107 | CONTROL "Resolve names",IDC_CHECK_DNS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,167,119,63,8 108 | GROUPBOX "",IDC_STATIC,7,7,237,82,BS_FLAT 109 | CTEXT "WinMTR-Refresh v0.98 is offered under GPL V2",IDC_STATIC,42,14,194,17 110 | PUSHBUTTON "&License and Credits",ID_LICENSE,81,67,94,14,BS_FLAT 111 | LTEXT "Max. hosts in LRU list:",IDC_STATIC,15,119,74,10,NOT WS_GROUP 112 | EDITTEXT IDC_EDIT_MAX_LRU,90,116,34,13,ES_AUTOHSCROLL | ES_NUMBER 113 | CONTROL "Use IPv4",IDC_IPV4_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,31,141,43,10 114 | CONTROL "Use IPv6",IDC_USEIPV6_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,159,139,43,10 115 | END 116 | 117 | IDD_DIALOG_LICENSE DIALOGEX 0, 0, 175, 70 118 | STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 119 | CAPTION "License & Credits" 120 | FONT 8, "MS Sans Serif", 0, 0, 0x0 121 | BEGIN 122 | DEFPUSHBUTTON "OK",IDOK,59,43,50,14 123 | LTEXT "Read more on",IDC_STATIC,36,27,46,8 124 | CONTROL "Github",IDC_MFCLINK1,"MfcLink",WS_TABSTOP,83,26,60,14 125 | LTEXT "WinMTR-Refresh is licensed under GPL V2.",IDC_STATIC,33,14,113,8 126 | END 127 | 128 | IDD_DIALOG_PROPERTIES DIALOG 0, 0, 201, 159 129 | STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 130 | CAPTION "Host properties" 131 | FONT 8, "MS Sans Serif" 132 | BEGIN 133 | DEFPUSHBUTTON "OK",IDOK,71,138,50,14,BS_FLAT 134 | LTEXT "Name:",IDC_STATIC,15,18,24,8 135 | EDITTEXT IDC_EDIT_PHOST,48,16,136,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY 136 | LTEXT "IP Address:",IDC_STATIC,14,32,40,9 137 | EDITTEXT IDC_EDIT_PIP,58,31,126,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY 138 | GROUPBOX "Packets",IDC_STATIC,7,74,89,60,BS_FLAT 139 | GROUPBOX "Ping time",IDC_STATIC,108,74,86,60,BS_FLAT 140 | GROUPBOX "Host",IDC_STATIC,7,7,187,62,BS_FLAT 141 | LTEXT "Loss (%):",IDC_STATIC,13,117,31,9 142 | LTEXT "Received:",IDC_STATIC,13,101,36,9 143 | LTEXT "Sent:",IDC_STATIC,13,85,21,9 144 | LTEXT "Last:",IDC_STATIC,114,84,18,9 145 | LTEXT "Best:",IDC_STATIC,114,96,20,8 146 | LTEXT "Average:",IDC_STATIC,114,107,32,8 147 | LTEXT "Worst:",IDC_STATIC,114,118,23,8 148 | EDITTEXT IDC_EDIT_PSENT,53,82,35,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER 149 | EDITTEXT IDC_EDIT_PRECV,53,99,35,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER 150 | EDITTEXT IDC_EDIT_PLOSS,53,116,35,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER 151 | EDITTEXT IDC_EDIT_PLAST,150,81,34,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY 152 | EDITTEXT IDC_EDIT_PBEST,150,94,34,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY 153 | EDITTEXT IDC_EDIT_PAVRG,150,106,34,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY 154 | EDITTEXT IDC_EDIT_PWORST,150,118,34,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY 155 | EDITTEXT IDC_EDIT_PCOMMENT,14,50,170,12,ES_AUTOHSCROLL | ES_READONLY 156 | END 157 | 158 | IDD_DIALOG_HELP DIALOGEX 0, 0, 256, 122 159 | STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU 160 | CAPTION "WinMTR-Refresh" 161 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 162 | BEGIN 163 | DEFPUSHBUTTON "OK",IDOK,144,101,50,14 164 | LTEXT "WinMTR-Refresh v0.98 is offered under GPL V2",IDC_STATIC,7,9,176,10 165 | LTEXT "Usage: WinMTR [options] target_host_name",IDC_STATIC,7,29,144,8 166 | LTEXT "Options:",IDC_STATIC,7,39,28,8 167 | LTEXT " --interval, -i VALUE. Set ping interval.",IDC_STATIC,26,47,131,8 168 | LTEXT " --size, -s VALUE. Set ping size.",IDC_STATIC,26,57,109,8 169 | LTEXT " --maxLRU, -m VALUE. Set max hosts in LRU list.",IDC_STATIC,26,67,163,8 170 | LTEXT " --help, -h. Print this help.",IDC_STATIC,26,89,92,8 171 | LTEXT " --numeric, -n. Do not resolve names.",IDC_STATIC,26,78,129,8 172 | END 173 | 174 | 175 | ///////////////////////////////////////////////////////////////////////////// 176 | // 177 | // Version 178 | // 179 | 180 | VS_VERSION_INFO VERSIONINFO 181 | FILEVERSION 0,9,8,0 182 | PRODUCTVERSION 0,9,8,0 183 | FILEFLAGSMASK 0x3fL 184 | #ifdef _DEBUG 185 | FILEFLAGS 0x1L 186 | #else 187 | FILEFLAGS 0x0L 188 | #endif 189 | FILEOS 0x4L 190 | FILETYPE 0x1L 191 | FILESUBTYPE 0x0L 192 | BEGIN 193 | BLOCK "StringFileInfo" 194 | BEGIN 195 | BLOCK "040904b0" 196 | BEGIN 197 | VALUE "FileDescription", "WinMTR-Refresh" 198 | VALUE "FileVersion", "0.9.8.0" 199 | VALUE "InternalName", "WinMTR" 200 | VALUE "LegalCopyright", "WinMTR 0.9.8.0 (c) 2010-2011 Appnor MSP, 2020-2024 Leetsoftwerx." 201 | VALUE "OriginalFilename", "WinMTR.EXE" 202 | VALUE "ProductName", "WinMTR Application" 203 | VALUE "ProductVersion", "0.9.8.0" 204 | END 205 | END 206 | BLOCK "VarFileInfo" 207 | BEGIN 208 | VALUE "Translation", 0x409, 1200 209 | END 210 | END 211 | 212 | 213 | ///////////////////////////////////////////////////////////////////////////// 214 | // 215 | // DESIGNINFO 216 | // 217 | 218 | #ifdef APSTUDIO_INVOKED 219 | GUIDELINES DESIGNINFO 220 | BEGIN 221 | IDD_WINMTR_DIALOG, DIALOG 222 | BEGIN 223 | LEFTMARGIN, 7 224 | RIGHTMARGIN, 383 225 | VERTGUIDE, 270 226 | VERTGUIDE, 321 227 | VERTGUIDE, 328 228 | VERTGUIDE, 377 229 | TOPMARGIN, 7 230 | BOTTOMMARGIN, 186 231 | HORZGUIDE, 12 232 | HORZGUIDE, 39 233 | END 234 | 235 | IDD_DIALOG_OPTIONS, DIALOG 236 | BEGIN 237 | LEFTMARGIN, 7 238 | RIGHTMARGIN, 244 239 | TOPMARGIN, 7 240 | BOTTOMMARGIN, 181 241 | END 242 | 243 | IDD_DIALOG_LICENSE, DIALOG 244 | BEGIN 245 | LEFTMARGIN, 7 246 | RIGHTMARGIN, 168 247 | TOPMARGIN, 7 248 | BOTTOMMARGIN, 63 249 | END 250 | 251 | IDD_DIALOG_PROPERTIES, DIALOG 252 | BEGIN 253 | LEFTMARGIN, 7 254 | RIGHTMARGIN, 194 255 | TOPMARGIN, 7 256 | BOTTOMMARGIN, 152 257 | END 258 | 259 | IDD_DIALOG_HELP, DIALOG 260 | BEGIN 261 | LEFTMARGIN, 7 262 | RIGHTMARGIN, 249 263 | VERTGUIDE, 26 264 | TOPMARGIN, 7 265 | BOTTOMMARGIN, 115 266 | END 267 | END 268 | #endif // APSTUDIO_INVOKED 269 | 270 | 271 | ///////////////////////////////////////////////////////////////////////////// 272 | // 273 | // Dialog Info 274 | // 275 | 276 | IDD_DIALOG_LICENSE DLGINIT 277 | BEGIN 278 | IDC_MFCLINK1, 0x37c, 197, 0 279 | 0x4d3c, 0x4346, 0x694c, 0x6b6e, 0x555f, 0x6c72, 0x683e, 0x7474, 0x7370, 280 | 0x2f3a, 0x672f, 0x7469, 0x7568, 0x2e62, 0x6f63, 0x2f6d, 0x656c, 0x7465, 281 | 0x7265, 0x572f, 0x6e69, 0x544d, 0x2d52, 0x6572, 0x7266, 0x7365, 0x3c68, 282 | 0x4d2f, 0x4346, 0x694c, 0x6b6e, 0x555f, 0x6c72, 0x3c3e, 0x464d, 0x4c43, 283 | 0x6e69, 0x5f6b, 0x7255, 0x506c, 0x6572, 0x6966, 0x3e78, 0x2f3c, 0x464d, 284 | 0x4c43, 0x6e69, 0x5f6b, 0x7255, 0x506c, 0x6572, 0x6966, 0x3e78, 0x4d3c, 285 | 0x4346, 0x694c, 0x6b6e, 0x545f, 0x6f6f, 0x746c, 0x7069, 0x3c3e, 0x4d2f, 286 | 0x4346, 0x694c, 0x6b6e, 0x545f, 0x6f6f, 0x746c, 0x7069, 0x3c3e, 0x464d, 287 | 0x4c43, 0x6e69, 0x5f6b, 0x7546, 0x6c6c, 0x6554, 0x7478, 0x6f54, 0x6c6f, 288 | 0x6974, 0x3e70, 0x4146, 0x534c, 0x3c45, 0x4d2f, 0x4346, 0x694c, 0x6b6e, 289 | 0x465f, 0x6c75, 0x546c, 0x7865, 0x5474, 0x6f6f, 0x746c, 0x7069, "\076" 290 | 0 291 | END 292 | 293 | 294 | ///////////////////////////////////////////////////////////////////////////// 295 | // 296 | // AFX_DIALOG_LAYOUT 297 | // 298 | 299 | IDD_DIALOG_OPTIONS AFX_DIALOG_LAYOUT 300 | BEGIN 301 | 0 302 | END 303 | 304 | IDD_DIALOG_HELP AFX_DIALOG_LAYOUT 305 | BEGIN 306 | 0 307 | END 308 | 309 | IDD_DIALOG_LICENSE AFX_DIALOG_LAYOUT 310 | BEGIN 311 | 0 312 | END 313 | 314 | 315 | ///////////////////////////////////////////////////////////////////////////// 316 | // 317 | // String Table 318 | // 319 | 320 | STRINGTABLE 321 | BEGIN 322 | IDP_SOCKETS_INIT_FAILED "Windows sockets initialization failed." 323 | IDS_STRING_SB_NAME "WinMTR-Refresh v0.98 GPL V2" 324 | IDS_STRING_SB_PING "0000000" 325 | IDS_STRING_CLEAR_HISTORY "Clear History" 326 | IDS_STRING_UNABLE_TO_RESOLVE_HOSTNAME "Unable to resolve hostname." 327 | IDS_STRING_STOP "Stop" 328 | IDS_STRING_START "Start" 329 | IDS_STRING_WAITING_STOP_TRACE 330 | "Waiting for last packets in order to stop trace ..." 331 | IDS_STRING_DBL_CLICK_MORE_INFO 332 | "Double click on host name for more information." 333 | END 334 | 335 | STRINGTABLE 336 | BEGIN 337 | IDS_STRING_NO_RESPONSE_FROM_HOST "No response from host" 338 | END 339 | 340 | #endif // English (United States) resources 341 | ///////////////////////////////////////////////////////////////////////////// 342 | 343 | 344 | 345 | #ifndef APSTUDIO_INVOKED 346 | ///////////////////////////////////////////////////////////////////////////// 347 | // 348 | // Generated from the TEXTINCLUDE 3 resource. 349 | // 350 | #define _AFX_NO_SPLITTER_RESOURCES 351 | #define _AFX_NO_OLE_RESOURCES 352 | #define _AFX_NO_TRACKER_RESOURCES 353 | #define _AFX_NO_PROPERTY_RESOURCES 354 | 355 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 356 | #ifdef _WIN32 357 | LANGUAGE 9, 1 358 | #pragma code_page(1252) 359 | #endif //_WIN32 360 | #include "afxres.rc" // Standard components 361 | #endif 362 | 363 | ///////////////////////////////////////////////////////////////////////////// 364 | #endif // not APSTUDIO_INVOKED 365 | 366 | -------------------------------------------------------------------------------- /WinMTR.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32819.101 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinMTR", "WinMTR.vcxproj", "{EE7B51B5-96FC-BED3-F2A6-0713CECBB579}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug - Sanitizers|ARM64 = Debug - Sanitizers|ARM64 11 | Debug - Sanitizers|Win32 = Debug - Sanitizers|Win32 12 | Debug - Sanitizers|x64 = Debug - Sanitizers|x64 13 | Debug|ARM64 = Debug|ARM64 14 | Debug|Win32 = Debug|Win32 15 | Debug|x64 = Debug|x64 16 | Release Installer|ARM64 = Release Installer|ARM64 17 | Release Installer|Win32 = Release Installer|Win32 18 | Release Installer|x64 = Release Installer|x64 19 | Release|ARM64 = Release|ARM64 20 | Release|Win32 = Release|Win32 21 | Release|x64 = Release|x64 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug - Sanitizers|ARM64.ActiveCfg = Debug - Sanitizers|ARM64 25 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug - Sanitizers|ARM64.Build.0 = Debug - Sanitizers|ARM64 26 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug - Sanitizers|Win32.ActiveCfg = Debug - Sanitizers|Win32 27 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug - Sanitizers|Win32.Build.0 = Debug - Sanitizers|Win32 28 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug - Sanitizers|x64.ActiveCfg = Debug - Sanitizers|x64 29 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug - Sanitizers|x64.Build.0 = Debug - Sanitizers|x64 30 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug|ARM64.ActiveCfg = Debug|ARM64 31 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug|ARM64.Build.0 = Debug|ARM64 32 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug|Win32.ActiveCfg = Debug|Win32 33 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug|Win32.Build.0 = Debug|Win32 34 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug|x64.ActiveCfg = Debug|x64 35 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug|x64.Build.0 = Debug|x64 36 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release Installer|ARM64.ActiveCfg = Release Installer|ARM64 37 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release Installer|ARM64.Build.0 = Release Installer|ARM64 38 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release Installer|Win32.ActiveCfg = Release Installer|Win32 39 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release Installer|Win32.Build.0 = Release Installer|Win32 40 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release Installer|x64.ActiveCfg = Release Installer|x64 41 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release Installer|x64.Build.0 = Release Installer|x64 42 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release|ARM64.ActiveCfg = Release|ARM64 43 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release|ARM64.Build.0 = Release|ARM64 44 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release|Win32.ActiveCfg = Release|Win32 45 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release|Win32.Build.0 = Release|Win32 46 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release|x64.ActiveCfg = Release|x64 47 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release|x64.Build.0 = Release|x64 48 | EndGlobalSection 49 | GlobalSection(SolutionProperties) = preSolution 50 | HideSolutionNode = FALSE 51 | EndGlobalSection 52 | GlobalSection(ExtensibilityGlobals) = postSolution 53 | SolutionGuid = {6D570BE2-1BB5-4050-9652-5F72B80AF2A2} 54 | EndGlobalSection 55 | EndGlobal 56 | -------------------------------------------------------------------------------- /WinMTRConfig.h.in: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // the configured options and settings for Tutorial 3 | #define WinMTR_VERSION_MAJOR @WinMTR_VERSION_MAJOR@ 4 | #define WinMTR_VERSION_MINOR @WinMTR_VERSION_MINOR@ -------------------------------------------------------------------------------- /WinMTRDialog-ClassDef.ixx: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2023 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | module; 21 | #include "targetver.h" 22 | #define WIN32_LEAN_AND_MEAN 23 | #define VC_EXTRALEAN 24 | #include 25 | #include 26 | #include 27 | //#include 28 | 29 | #ifndef _AFX_NO_AFXCMN_SUPPORT 30 | #include 31 | #endif 32 | #pragma warning (disable : 4005) 33 | #include "resource.h" 34 | 35 | export module WinMTR.Dialog:ClassDef; 36 | 37 | import ; 38 | import ; 39 | import ; 40 | import ; 41 | import ; 42 | import ; 43 | import ; 44 | import WinMTROptionsProvider; 45 | import WinMTRStatusBar; 46 | import WinMTR.Net; 47 | 48 | //***************************************************************************** 49 | // CLASS: WinMTRDialog 50 | // 51 | // 52 | //***************************************************************************** 53 | 54 | export class WinMTRDialog final : public CDialog, public IWinMTROptionsProvider 55 | { 56 | public: 57 | WinMTRDialog(CWnd* pParent = nullptr) noexcept; 58 | 59 | enum { IDD = IDD_WINMTR_DIALOG }; 60 | enum class options_source : bool { 61 | none, 62 | cmd_line 63 | }; 64 | 65 | afx_msg BOOL InitRegistry() noexcept; 66 | 67 | WinMTRStatusBar statusBar; 68 | 69 | enum class STATES { 70 | IDLE = 0, 71 | TRACING, 72 | STOPPING, 73 | EXIT 74 | }; 75 | 76 | enum class STATE_TRANSITIONS { 77 | IDLE_TO_IDLE = 0, 78 | IDLE_TO_TRACING, 79 | IDLE_TO_EXIT, 80 | TRACING_TO_TRACING, 81 | TRACING_TO_STOPPING, 82 | TRACING_TO_EXIT, 83 | STOPPING_TO_IDLE, 84 | STOPPING_TO_STOPPING, 85 | STOPPING_TO_EXIT 86 | }; 87 | 88 | 89 | 90 | bool InitMTRNet() noexcept; 91 | 92 | int DisplayRedraw(); 93 | void Transit(STATES new_state); 94 | 95 | private: 96 | CButton m_buttonOptions; 97 | CButton m_buttonExit; 98 | CButton m_buttonStart; 99 | CComboBox m_comboHost; 100 | CListCtrl m_listMTR; 101 | 102 | CStatic m_staticS; 103 | CStatic m_staticJ; 104 | 105 | CButton m_buttonExpT; 106 | CButton m_buttonExpH; 107 | std::wstring msz_defaulthostname; 108 | std::shared_ptr wmtrnet; 109 | std::mutex tracer_mutex; 110 | std::optional trace_lacky; 111 | HICON m_hIcon; 112 | std::atomic interval; 113 | STATES state; 114 | STATE_TRANSITIONS transition; 115 | std::atomic_uint pingsize; 116 | int maxLRU; 117 | int nrLRU = 0; 118 | bool m_autostart = false; 119 | bool hasPingsizeFromCmdLine = false; 120 | bool hasMaxLRUFromCmdLine = false; 121 | bool hasIntervalFromCmdLine = false; 122 | std::atomic_bool useDNS; 123 | bool hasUseDNSFromCmdLine = false; 124 | bool useIPv4 = true; 125 | bool useIPv6 = true; 126 | std::atomic_bool tracing; 127 | 128 | void ClearHistory(); 129 | winrt::Windows::Foundation::IAsyncAction pingThread(std::stop_token token, std::wstring shost); 130 | winrt::fire_and_forget stopTrace(); 131 | public: 132 | 133 | void SetHostName(std::wstring host); 134 | void SetInterval(float i, options_source fromCmdLine = options_source::none) noexcept; 135 | void SetPingSize(unsigned ps, options_source fromCmdLine = options_source::none) noexcept; 136 | void SetMaxLRU(int mlru, options_source fromCmdLine = options_source::none) noexcept; 137 | void SetUseDNS(bool udns, options_source fromCmdLine = options_source::none) noexcept; 138 | 139 | inline double getInterval() const noexcept { return interval; } 140 | inline unsigned getPingSize() const noexcept { return pingsize; } 141 | inline bool getUseDNS() const noexcept { return useDNS; } 142 | 143 | protected: 144 | void DoDataExchange(CDataExchange* pDX) override; 145 | 146 | BOOL OnInitDialog() override; 147 | afx_msg void OnPaint(); 148 | afx_msg void OnSize(UINT, int, int); 149 | afx_msg void OnSizing(UINT, LPRECT); 150 | afx_msg HCURSOR OnQueryDragIcon(); 151 | afx_msg void OnRestart() noexcept; 152 | afx_msg void OnOptions(); 153 | void OnCancel() override; 154 | 155 | afx_msg void OnCTTC() noexcept; 156 | afx_msg void OnCHTC() noexcept; 157 | afx_msg void OnEXPT() noexcept; 158 | afx_msg void OnEXPH() noexcept; 159 | 160 | afx_msg void OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult); 161 | 162 | DECLARE_MESSAGE_MAP() 163 | public: 164 | afx_msg void OnCbnSelchangeComboHost(); 165 | afx_msg void OnCbnSelendokComboHost(); 166 | afx_msg void OnCbnCloseupComboHost(); 167 | afx_msg void OnTimer(UINT_PTR nIDEvent) noexcept; 168 | afx_msg void OnClose(); 169 | afx_msg void OnBnClickedCancel(); 170 | }; -------------------------------------------------------------------------------- /WinMTRDialog-StateMachine.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2023 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | module; 22 | 23 | #pragma warning (disable : 4005) 24 | #include "targetver.h" 25 | #define WIN32_LEAN_AND_MEAN 26 | #include 27 | #include 28 | #include 29 | 30 | #include "resource.h" 31 | 32 | module WinMTR.Dialog:StateMachine; 33 | 34 | import :ClassDef; 35 | import ; 36 | import ; 37 | import ; 38 | 39 | #ifdef _DEBUG 40 | #define new DEBUG_NEW 41 | #undef THIS_FILE 42 | static char THIS_FILE[] = __FILE__; 43 | #endif 44 | 45 | #ifdef DEBUG 46 | #define TRACE_MSG(msg) \ 47 | { \ 48 | std::wostringstream dbg_msg(std::wostringstream::out); \ 49 | dbg_msg << msg << std::endl; \ 50 | OutputDebugStringW(dbg_msg.str().c_str()); \ 51 | } 52 | #else 53 | #define TRACE_MSG(msg) 54 | #endif 55 | 56 | 57 | 58 | void WinMTRDialog::Transit(STATES new_state) 59 | { 60 | switch (new_state) { 61 | case STATES::IDLE: 62 | switch (state) { 63 | case STATES::STOPPING: 64 | transition = STATE_TRANSITIONS::STOPPING_TO_IDLE; 65 | break; 66 | case STATES::IDLE: 67 | transition = STATE_TRANSITIONS::IDLE_TO_IDLE; 68 | break; 69 | default: 70 | TRACE_MSG(L"Received state IDLE after " << static_cast(state)); 71 | return; 72 | } 73 | state = STATES::IDLE; 74 | break; 75 | case STATES::TRACING: 76 | switch (state) { 77 | case STATES::IDLE: 78 | transition = STATE_TRANSITIONS::IDLE_TO_TRACING; 79 | break; 80 | case STATES::TRACING: 81 | transition = STATE_TRANSITIONS::TRACING_TO_TRACING; 82 | break; 83 | default: 84 | TRACE_MSG(L"Received state TRACING after " << static_cast(state)); 85 | return; 86 | } 87 | state = STATES::TRACING; 88 | break; 89 | case STATES::STOPPING: 90 | switch (state) { 91 | case STATES::STOPPING: 92 | transition = STATE_TRANSITIONS::STOPPING_TO_STOPPING; 93 | break; 94 | case STATES::TRACING: 95 | transition = STATE_TRANSITIONS::TRACING_TO_STOPPING; 96 | break; 97 | default: 98 | TRACE_MSG(L"Received state STOPPING after " << static_cast(state)); 99 | return; 100 | } 101 | state = STATES::STOPPING; 102 | break; 103 | case STATES::EXIT: 104 | switch (state) { 105 | case STATES::IDLE: 106 | transition = STATE_TRANSITIONS::IDLE_TO_EXIT; 107 | break; 108 | case STATES::STOPPING: 109 | transition = STATE_TRANSITIONS::STOPPING_TO_EXIT; 110 | break; 111 | case STATES::TRACING: 112 | transition = STATE_TRANSITIONS::TRACING_TO_EXIT; 113 | break; 114 | case STATES::EXIT: 115 | break; 116 | default: 117 | TRACE_MSG(L"Received state EXIT after " << static_cast(state)); 118 | return; 119 | } 120 | state = STATES::EXIT; 121 | break; 122 | default: 123 | TRACE_MSG(L"Received state " << static_cast>(state)); 124 | } 125 | 126 | // modify controls according to new state 127 | switch (transition) { 128 | case STATE_TRANSITIONS::IDLE_TO_TRACING: 129 | { 130 | m_buttonStart.EnableWindow(FALSE); 131 | CString newText; 132 | newText.LoadStringW(IDS_STRING_STOP); 133 | m_buttonStart.SetWindowText(newText); 134 | m_comboHost.EnableWindow(FALSE); 135 | m_buttonOptions.EnableWindow(FALSE); 136 | newText.LoadStringW(IDS_STRING_DBL_CLICK_MORE_INFO); 137 | statusBar.SetPaneText(0, newText); 138 | // using a different thread to create an MTA so we don't have explosion issues with the 139 | // thread pool 140 | CString sHost; 141 | this->m_comboHost.GetWindowTextW(sHost); 142 | 143 | if (sHost.IsEmpty()) [[unlikely]] { // Technically never because this is caught in the calling function 144 | sHost = L"localhost"; 145 | } 146 | std::unique_lock trace_lock{ tracer_mutex }; 147 | // create the jthread and stop token all in one go 148 | trace_lacky.emplace([this](std::stop_token stop_token, auto sHost) noexcept { 149 | winrt::init_apartment(winrt::apartment_type::multi_threaded); 150 | try { 151 | auto tracer_local = this->pingThread(stop_token, sHost); 152 | { 153 | std::unique_lock lock(this->tracer_mutex); 154 | } 155 | // keep the thread alive 156 | tracer_local.get(); 157 | } 158 | catch (winrt::hresult_canceled const&) { 159 | // don't care this happens 160 | } 161 | catch (winrt::hresult_illegal_method_call const&) { 162 | // don't care this happens 163 | } 164 | }, std::wstring(sHost)); 165 | } 166 | m_buttonStart.EnableWindow(TRUE); 167 | break; 168 | case STATE_TRANSITIONS::IDLE_TO_IDLE: 169 | // nothing to be done 170 | break; 171 | case STATE_TRANSITIONS::STOPPING_TO_IDLE: 172 | { 173 | CString newText; 174 | newText.LoadStringW(IDS_STRING_START); 175 | m_buttonStart.EnableWindow(TRUE); 176 | statusBar.SetPaneText(0, CString((LPCSTR)IDS_STRING_SB_NAME)); 177 | m_buttonStart.SetWindowText(newText); 178 | m_comboHost.EnableWindow(TRUE); 179 | m_buttonOptions.EnableWindow(TRUE); 180 | m_comboHost.SetFocus(); 181 | } 182 | 183 | break; 184 | case STATE_TRANSITIONS::STOPPING_TO_STOPPING: 185 | DisplayRedraw(); 186 | break; 187 | case STATE_TRANSITIONS::TRACING_TO_TRACING: 188 | DisplayRedraw(); 189 | break; 190 | case STATE_TRANSITIONS::TRACING_TO_STOPPING: 191 | { 192 | m_buttonStart.EnableWindow(FALSE); 193 | m_comboHost.EnableWindow(FALSE); 194 | m_buttonOptions.EnableWindow(FALSE); 195 | this->stopTrace(); 196 | CString newText; 197 | newText.LoadStringW(IDS_STRING_WAITING_STOP_TRACE); 198 | statusBar.SetPaneText(0, newText); 199 | DisplayRedraw(); 200 | } 201 | break; 202 | case STATE_TRANSITIONS::IDLE_TO_EXIT: 203 | m_buttonStart.EnableWindow(FALSE); 204 | m_comboHost.EnableWindow(FALSE); 205 | m_buttonOptions.EnableWindow(FALSE); 206 | break; 207 | case STATE_TRANSITIONS::TRACING_TO_EXIT: 208 | { 209 | m_buttonStart.EnableWindow(FALSE); 210 | m_comboHost.EnableWindow(FALSE); 211 | m_buttonOptions.EnableWindow(FALSE); 212 | this->stopTrace(); 213 | CString newText; 214 | newText.LoadStringW(IDS_STRING_WAITING_STOP_TRACE); 215 | statusBar.SetPaneText(0, newText); 216 | } 217 | break; 218 | case STATE_TRANSITIONS::STOPPING_TO_EXIT: 219 | m_buttonStart.EnableWindow(FALSE); 220 | m_comboHost.EnableWindow(FALSE); 221 | m_buttonOptions.EnableWindow(FALSE); 222 | break; 223 | default: 224 | TRACE_MSG("Unknown transition " << static_cast>(transition)); 225 | break; 226 | } 227 | } 228 | 229 | 230 | void WinMTRDialog::OnTimer(UINT_PTR nIDEvent) noexcept 231 | { 232 | static unsigned int call_count = 0; 233 | call_count += 1; 234 | //std::unique_lock lock(traceThreadMutex, std::try_to_lock); 235 | const bool is_tracing = tracing.load(std::memory_order_acquire); 236 | if (state == STATES::EXIT && !is_tracing) { 237 | OnOK(); 238 | } 239 | 240 | if (!is_tracing) { 241 | Transit(STATES::IDLE); 242 | } 243 | else if ((call_count % 10 == 0)) { 244 | if (state == STATES::TRACING) Transit(STATES::TRACING); 245 | else if (state == STATES::STOPPING) Transit(STATES::STOPPING); 246 | } 247 | 248 | CDialog::OnTimer(nIDEvent); 249 | } 250 | 251 | 252 | void WinMTRDialog::OnClose() 253 | { 254 | Transit(STATES::EXIT); 255 | } 256 | 257 | 258 | void WinMTRDialog::OnBnClickedCancel() 259 | { 260 | Transit(STATES::EXIT); 261 | } 262 | -------------------------------------------------------------------------------- /WinMTRDialog-display.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2023 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | module; 22 | 23 | #pragma warning (disable : 4005) 24 | #include "targetver.h" 25 | #define WIN32_LEAN_AND_MEAN 26 | #include 27 | #include 28 | #include 29 | #ifndef _AFX_NO_AFXCMN_SUPPORT 30 | #include 31 | #endif 32 | #include "resource.h" 33 | #include "WinMTRProperties.h" 34 | module WinMTR.Dialog:display; 35 | import :ClassDef; 36 | import ; 37 | import ; 38 | import ; 39 | 40 | import WinMTRVerUtil; 41 | import WinMTRIPUtils; 42 | import WinMTRUtils; 43 | 44 | using namespace std::literals; 45 | 46 | namespace { 47 | constexpr auto DEFAULT_PING_SIZE = 64; 48 | constexpr auto DEFAULT_INTERVAL = 1.0; 49 | constexpr auto DEFAULT_MAX_LRU = 128; 50 | constexpr auto DEFAULT_DNS = true; 51 | 52 | #define MTR_NR_COLS 9 53 | constexpr wchar_t MTR_COLS[MTR_NR_COLS][10] = { 54 | L"Hostname", 55 | L"Nr", 56 | L"Loss %", 57 | L"Sent", 58 | L"Recv", 59 | L"Best", 60 | L"Avrg", 61 | L"Worst", 62 | L"Last" 63 | }; 64 | 65 | constexpr int MTR_COL_LENGTH[MTR_NR_COLS] = { 66 | 190, 30, 50, 40, 40, 50, 50, 50, 50 67 | }; 68 | constexpr auto WINMTR_DIALOG_TIMER = 100; 69 | 70 | } 71 | 72 | //***************************************************************************** 73 | // BEGIN_MESSAGE_MAP 74 | // 75 | // 76 | //***************************************************************************** 77 | BEGIN_MESSAGE_MAP(WinMTRDialog, CDialog) 78 | ON_WM_PAINT() 79 | ON_WM_SIZE() 80 | ON_WM_SIZING() 81 | ON_WM_QUERYDRAGICON() 82 | ON_BN_CLICKED(ID_RESTART, OnRestart) 83 | ON_BN_CLICKED(ID_OPTIONS, OnOptions) 84 | ON_BN_CLICKED(ID_CTTC, OnCTTC) 85 | ON_BN_CLICKED(ID_CHTC, OnCHTC) 86 | ON_BN_CLICKED(ID_EXPT, OnEXPT) 87 | ON_BN_CLICKED(ID_EXPH, OnEXPH) 88 | ON_NOTIFY(NM_DBLCLK, IDC_LIST_MTR, OnDblclkList) 89 | ON_CBN_SELCHANGE(IDC_COMBO_HOST, &WinMTRDialog::OnCbnSelchangeComboHost) 90 | ON_CBN_SELENDOK(IDC_COMBO_HOST, &WinMTRDialog::OnCbnSelendokComboHost) 91 | ON_CBN_CLOSEUP(IDC_COMBO_HOST, &WinMTRDialog::OnCbnCloseupComboHost) 92 | ON_WM_TIMER() 93 | ON_WM_CLOSE() 94 | ON_BN_CLICKED(IDCANCEL, &WinMTRDialog::OnBnClickedCancel) 95 | END_MESSAGE_MAP() 96 | 97 | 98 | //***************************************************************************** 99 | // WinMTRDialog::WinMTRDialog 100 | // 101 | // 102 | //***************************************************************************** 103 | WinMTRDialog::WinMTRDialog(CWnd* pParent) noexcept 104 | : CDialog(WinMTRDialog::IDD, pParent), 105 | interval(DEFAULT_INTERVAL), 106 | state(STATES::IDLE), 107 | transition(STATE_TRANSITIONS::IDLE_TO_IDLE), 108 | pingsize(DEFAULT_PING_SIZE), 109 | maxLRU(DEFAULT_MAX_LRU), 110 | useDNS(DEFAULT_DNS) 111 | 112 | { 113 | m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 114 | 115 | wmtrnet = std::make_shared(this); 116 | } 117 | 118 | //***************************************************************************** 119 | // WinMTRDialog::DoDataExchange 120 | // 121 | // 122 | //***************************************************************************** 123 | void WinMTRDialog::DoDataExchange(CDataExchange* pDX) 124 | { 125 | CDialog::DoDataExchange(pDX); 126 | DDX_Control(pDX, ID_OPTIONS, m_buttonOptions); 127 | DDX_Control(pDX, IDCANCEL, m_buttonExit); 128 | DDX_Control(pDX, ID_RESTART, m_buttonStart); 129 | DDX_Control(pDX, IDC_COMBO_HOST, m_comboHost); 130 | DDX_Control(pDX, IDC_LIST_MTR, m_listMTR); 131 | DDX_Control(pDX, IDC_STATICS, m_staticS); 132 | DDX_Control(pDX, IDC_STATICJ, m_staticJ); 133 | DDX_Control(pDX, ID_EXPH, m_buttonExpH); 134 | DDX_Control(pDX, ID_EXPT, m_buttonExpT); 135 | } 136 | 137 | 138 | //***************************************************************************** 139 | // WinMTRDialog::OnInitDialog 140 | // 141 | // 142 | //***************************************************************************** 143 | BOOL WinMTRDialog::OnInitDialog() 144 | { 145 | CDialog::OnInitDialog(); 146 | const auto verNumber = WinMTRVerUtil::getExeVersion(); 147 | #ifndef _WIN64 148 | constexpr auto bitness = 32; 149 | #else 150 | constexpr auto bitness = 64; 151 | #endif 152 | const auto caption = std::format(L"WinMTR-Refresh v{} {} bit"sv, verNumber, bitness); 153 | SetTimer(1, WINMTR_DIALOG_TIMER, nullptr); 154 | SetWindowTextW(caption.c_str()); 155 | 156 | SetIcon(m_hIcon, TRUE); 157 | SetIcon(m_hIcon, FALSE); 158 | 159 | if (!statusBar.Create(this)) 160 | AfxMessageBox(L"Error creating status bar"); 161 | statusBar.GetStatusBarCtrl().SetMinHeight(23); 162 | 163 | UINT sbi[1] = { IDS_STRING_SB_NAME }; 164 | statusBar.SetIndicators(sbi); 165 | statusBar.SetPaneInfo(0, statusBar.GetItemID(0), SBPS_STRETCH, 0); 166 | // removing for now but leaving commenteded this goes to a domain buying site, so either they lost the domain or are 167 | // out of business. I'll fix this when that changes. 168 | //{ // Add appnor URL 169 | // //std::unique_ptr m_pWndButton = std::make_unique(); 170 | // if (!m_pWndButton.Create(_T("www.appnor.com"), WS_CHILD|WS_VISIBLE|WS_TABSTOP, CRect(0,0,0,0), &statusBar, 1234)) { 171 | // TRACE(_T("Failed to create button control.\n")); 172 | // return FALSE; 173 | // } 174 | 175 | // m_pWndButton.SetURL(L"http://www.appnor.com/?utm_source=winmtr&utm_medium=desktop&utm_campaign=software"); 176 | // 177 | // if(!statusBar.AddPane(1234,1)) { 178 | // AfxMessageBox(_T("Pane index out of range\nor pane with same ID already exists in the status bar"), MB_ICONERROR); 179 | // return FALSE; 180 | // } 181 | // 182 | // statusBar.SetPaneWidth(statusBar.CommandToIndex(1234), 100); 183 | // statusBar.AddPaneControl(&m_pWndButton, 1234, true); 184 | //} 185 | 186 | for (int i = 0; i < MTR_NR_COLS; i++) { 187 | m_listMTR.InsertColumn(i, MTR_COLS[i], LVCFMT_LEFT, MTR_COL_LENGTH[i], -1); 188 | } 189 | 190 | m_comboHost.SetFocus(); 191 | 192 | // We need to resize the dialog to make room for control bars. 193 | // First, figure out how big the control bars are. 194 | CRect rcClientStart; 195 | CRect rcClientNow; 196 | GetClientRect(rcClientStart); 197 | RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 198 | 0, reposQuery, rcClientNow); 199 | 200 | // Now move all the controls so they are in the same relative 201 | // position within the remaining client area as they would be 202 | // with no control bars. 203 | //CPoint ptOffset(rcClientNow.left - rcClientStart.left, 204 | //rcClientNow.top - rcClientStart.top); 205 | const auto ptOffset = rcClientNow.TopLeft() - rcClientStart.TopLeft(); 206 | 207 | CRect rcChild; 208 | CWnd* pwndChild = GetWindow(GW_CHILD); 209 | while (pwndChild) 210 | { 211 | pwndChild->GetWindowRect(rcChild); 212 | ScreenToClient(rcChild); 213 | rcChild.OffsetRect(ptOffset); 214 | pwndChild->MoveWindow(rcChild, FALSE); 215 | pwndChild = pwndChild->GetNextWindow(); 216 | } 217 | 218 | // Adjust the dialog window dimensions 219 | CRect rcWindow; 220 | GetWindowRect(rcWindow); 221 | rcWindow.right += rcClientStart.Width() - rcClientNow.Width(); 222 | rcWindow.bottom += rcClientStart.Height() - rcClientNow.Height(); 223 | MoveWindow(rcWindow, FALSE); 224 | 225 | // And position the control bars 226 | RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0); 227 | 228 | InitRegistry(); 229 | 230 | if (m_autostart) { 231 | m_comboHost.SetWindowText(msz_defaulthostname.c_str()); 232 | OnRestart(); 233 | } 234 | 235 | return FALSE; 236 | } 237 | 238 | //***************************************************************************** 239 | // WinMTRDialog::OnSizing 240 | // 241 | // 242 | //***************************************************************************** 243 | void WinMTRDialog::OnSizing(UINT fwSide, LPRECT pRect) 244 | { 245 | CDialog::OnSizing(fwSide, pRect); 246 | 247 | int iWidth = (pRect->right) - (pRect->left); 248 | int iHeight = (pRect->bottom) - (pRect->top); 249 | 250 | if (iWidth < 600) 251 | pRect->right = pRect->left + 600; 252 | if (iHeight < 250) 253 | pRect->bottom = pRect->top + 250; 254 | } 255 | 256 | 257 | //***************************************************************************** 258 | // WinMTRDialog::OnSize 259 | // 260 | // 261 | //***************************************************************************** 262 | void WinMTRDialog::OnSize(UINT nType, int cx, int cy) 263 | { 264 | CDialog::OnSize(nType, cx, cy); 265 | CRect r; 266 | GetClientRect(&r); 267 | CRect lb; 268 | if (::IsWindow(m_staticS.m_hWnd)) { 269 | const auto dpi = GetDpiForWindow(m_staticS.m_hWnd); 270 | m_staticS.GetWindowRect(&lb); 271 | ScreenToClient(&lb); 272 | const auto scaledXOffset = MulDiv(10, dpi, 96); 273 | m_staticS.SetWindowPos(nullptr, lb.TopLeft().x, lb.TopLeft().y, r.Width() - lb.TopLeft().x - scaledXOffset, lb.Height(), SWP_NOMOVE | SWP_NOZORDER); 274 | } 275 | 276 | if (::IsWindow(m_staticJ.m_hWnd)) { 277 | const auto dpi = GetDpiForWindow(m_staticJ.m_hWnd); 278 | m_staticJ.GetWindowRect(&lb); 279 | ScreenToClient(&lb); 280 | const auto scaledXOffset = MulDiv(21, dpi, 96); 281 | m_staticJ.SetWindowPos(nullptr, lb.TopLeft().x, lb.TopLeft().y, r.Width() - scaledXOffset, lb.Height(), SWP_NOMOVE | SWP_NOZORDER); 282 | } 283 | 284 | if (::IsWindow(m_buttonExit.m_hWnd)) { 285 | const auto dpi = GetDpiForWindow(m_buttonExit.m_hWnd); 286 | m_buttonExit.GetWindowRect(&lb); 287 | ScreenToClient(&lb); 288 | const auto scaledXOffset = MulDiv(21, dpi, 96); 289 | m_buttonExit.SetWindowPos(nullptr, r.Width() - lb.Width() - scaledXOffset, lb.TopLeft().y, lb.Width(), lb.Height(), SWP_NOSIZE | SWP_NOZORDER); 290 | } 291 | 292 | if (::IsWindow(m_buttonExpH.m_hWnd)) { 293 | const auto dpi = GetDpiForWindow(m_buttonExpH.m_hWnd); 294 | m_buttonExpH.GetWindowRect(&lb); 295 | ScreenToClient(&lb); 296 | const auto scaledXOffset = MulDiv(21, dpi, 96); 297 | m_buttonExpH.SetWindowPos(nullptr, r.Width() - lb.Width() - scaledXOffset, lb.TopLeft().y, lb.Width(), lb.Height(), SWP_NOSIZE | SWP_NOZORDER); 298 | } 299 | if (::IsWindow(m_buttonExpT.m_hWnd)) { 300 | const auto dpi = GetDpiForWindow(m_buttonExpT.m_hWnd); 301 | m_buttonExpT.GetWindowRect(&lb); 302 | ScreenToClient(&lb); 303 | const auto scaledXOffset = MulDiv(103, dpi, 96); 304 | m_buttonExpT.SetWindowPos(nullptr, r.Width() - lb.Width() - scaledXOffset, lb.TopLeft().y, lb.Width(), lb.Height(), SWP_NOSIZE | SWP_NOZORDER); 305 | } 306 | 307 | if (::IsWindow(m_listMTR.m_hWnd)) { 308 | const auto dpi = GetDpiForWindow(m_listMTR.m_hWnd); 309 | m_listMTR.GetWindowRect(&lb); 310 | ScreenToClient(&lb); 311 | const auto scaledX = MulDiv(21, dpi, 96); 312 | const auto scaledY = MulDiv(25, dpi, 96); 313 | m_listMTR.SetWindowPos(nullptr, lb.TopLeft().x, lb.TopLeft().y, r.Width() - scaledX, r.Height() - lb.top - scaledY, SWP_NOMOVE | SWP_NOZORDER); 314 | } 315 | 316 | RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 317 | 0, reposQuery, r); 318 | 319 | RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0); 320 | 321 | } 322 | 323 | 324 | //***************************************************************************** 325 | // WinMTRDialog::OnPaint 326 | // 327 | // 328 | //***************************************************************************** 329 | void WinMTRDialog::OnPaint() 330 | { 331 | if (IsIconic()) 332 | { 333 | CPaintDC dc(this); 334 | 335 | SendMessage(WM_ICONERASEBKGND, (WPARAM)dc.GetSafeHdc(), 0); 336 | const auto dpi = GetDpiForWindow(*this); 337 | const int cxIcon = GetSystemMetricsForDpi(SM_CXICON, dpi); 338 | const int cyIcon = GetSystemMetricsForDpi(SM_CYICON, dpi); 339 | CRect rect; 340 | GetClientRect(&rect); 341 | const int x = (rect.Width() - cxIcon + 1) / 2; 342 | const int y = (rect.Height() - cyIcon + 1) / 2; 343 | 344 | dc.DrawIcon(x, y, m_hIcon); 345 | } 346 | else 347 | { 348 | CDialog::OnPaint(); 349 | } 350 | } 351 | 352 | 353 | //***************************************************************************** 354 | // WinMTRDialog::OnQueryDragIcon 355 | // 356 | // 357 | //***************************************************************************** 358 | HCURSOR WinMTRDialog::OnQueryDragIcon() 359 | { 360 | return (HCURSOR)m_hIcon; 361 | } 362 | 363 | 364 | //***************************************************************************** 365 | // WinMTRDialog::OnDblclkList 366 | // 367 | //***************************************************************************** 368 | void WinMTRDialog::OnDblclkList([[maybe_unused]] NMHDR* pNMHDR, LRESULT* pResult) 369 | { 370 | using namespace std::string_view_literals; 371 | *pResult = 0; 372 | 373 | if (state == STATES::TRACING) { 374 | 375 | POSITION pos = m_listMTR.GetFirstSelectedItemPosition(); 376 | if (pos != nullptr) { 377 | int nItem = m_listMTR.GetNextSelectedItem(pos); 378 | WinMTRProperties wmtrprop; 379 | 380 | if (const auto lstate = wmtrnet->getStateAt(nItem); !isValidAddress(lstate.addr)) { 381 | wmtrprop.host.clear(); 382 | wmtrprop.ip.clear(); 383 | wmtrprop.comment = lstate.getName(); 384 | 385 | wmtrprop.pck_loss = wmtrprop.pck_sent = wmtrprop.pck_recv = 0; 386 | 387 | wmtrprop.ping_avrg = wmtrprop.ping_last = 0.0; 388 | wmtrprop.ping_best = wmtrprop.ping_worst = 0.0; 389 | } 390 | else { 391 | wmtrprop.host = lstate.getName(); 392 | wmtrprop.ip = addr_to_string(lstate.addr); 393 | 394 | wmtrprop.comment = L"Host alive."sv; 395 | 396 | wmtrprop.ping_avrg = static_cast(lstate.getAvg()); 397 | wmtrprop.ping_last = static_cast(lstate.last); 398 | wmtrprop.ping_best = static_cast(lstate.best); 399 | wmtrprop.ping_worst = static_cast(lstate.worst); 400 | 401 | wmtrprop.pck_loss = lstate.getPercent(); 402 | wmtrprop.pck_recv = lstate.returned; 403 | wmtrprop.pck_sent = lstate.xmit; 404 | } 405 | 406 | wmtrprop.DoModal(); 407 | } 408 | } 409 | } 410 | 411 | 412 | //***************************************************************************** 413 | // WinMTRDialog::SetHostName 414 | // 415 | //***************************************************************************** 416 | void WinMTRDialog::SetHostName(std::wstring host) 417 | { 418 | m_autostart = true; 419 | msz_defaulthostname = std::move(host); 420 | } 421 | 422 | 423 | //***************************************************************************** 424 | // WinMTRDialog::SetPingSize 425 | // 426 | //***************************************************************************** 427 | void WinMTRDialog::SetPingSize(unsigned ps, options_source fromCmdLine) noexcept 428 | { 429 | pingsize = ps; 430 | hasPingsizeFromCmdLine = static_cast(fromCmdLine); 431 | } 432 | 433 | //***************************************************************************** 434 | // WinMTRDialog::SetMaxLRU 435 | // 436 | //***************************************************************************** 437 | void WinMTRDialog::SetMaxLRU(int mlru, options_source fromCmdLine) noexcept 438 | { 439 | maxLRU = mlru; 440 | hasMaxLRUFromCmdLine = static_cast(fromCmdLine); 441 | } 442 | 443 | 444 | //***************************************************************************** 445 | // WinMTRDialog::SetInterval 446 | // 447 | //***************************************************************************** 448 | void WinMTRDialog::SetInterval(float i, options_source fromCmdLine) noexcept 449 | { 450 | interval = i; 451 | hasMaxLRUFromCmdLine = static_cast(fromCmdLine); 452 | } 453 | 454 | //***************************************************************************** 455 | // WinMTRDialog::SetUseDNS 456 | // 457 | //***************************************************************************** 458 | void WinMTRDialog::SetUseDNS(bool udns, options_source fromCmdLine) noexcept 459 | { 460 | useDNS = udns; 461 | hasUseDNSFromCmdLine = static_cast(fromCmdLine); 462 | } 463 | 464 | 465 | //***************************************************************************** 466 | // WinMTRDialog::WinMTRDialog 467 | // 468 | // 469 | //***************************************************************************** 470 | void WinMTRDialog::OnCancel() 471 | { 472 | } 473 | 474 | 475 | //***************************************************************************** 476 | // WinMTRDialog::DisplayRedraw 477 | // 478 | // 479 | //***************************************************************************** 480 | int WinMTRDialog::DisplayRedraw() 481 | { 482 | wchar_t buf[255] = {}, nr_crt[255] = {}; 483 | const auto netstate = wmtrnet->getCurrentState(); 484 | const auto nh = netstate.size(); 485 | while (m_listMTR.GetItemCount() > nh) { 486 | m_listMTR.DeleteItem(m_listMTR.GetItemCount() - 1); 487 | } 488 | 489 | static CString noResponse((LPCWSTR)IDS_STRING_NO_RESPONSE_FROM_HOST); 490 | 491 | for (int i = 0; const auto & host : netstate) { 492 | 493 | auto name = host.getName(); 494 | if (name.empty()) { 495 | name = noResponse; 496 | } 497 | 498 | auto result = std::format_to_n(nr_crt, std::size(nr_crt) - 1, WinMTRUtils::int_number_format, i + 1); 499 | *result.out = '\0'; 500 | if (m_listMTR.GetItemCount() <= i) 501 | m_listMTR.InsertItem(i, name.c_str()); 502 | else 503 | m_listMTR.SetItem(i, 0, LVIF_TEXT, name.c_str(), 0, 0, 0, 0); 504 | 505 | m_listMTR.SetItem(i, 1, LVIF_TEXT, nr_crt, 0, 0, 0, 0); 506 | constexpr auto writable_size = std::size(buf) - 1; 507 | result = std::format_to_n(buf, writable_size, WinMTRUtils::int_number_format, host.getPercent()); 508 | *result.out = '\0'; 509 | m_listMTR.SetItem(i, 2, LVIF_TEXT, buf, 0, 0, 0, 0); 510 | 511 | result = std::format_to_n(buf, writable_size, WinMTRUtils::int_number_format, host.xmit); 512 | *result.out = '\0'; 513 | m_listMTR.SetItem(i, 3, LVIF_TEXT, buf, 0, 0, 0, 0); 514 | 515 | result = std::format_to_n(buf, writable_size, WinMTRUtils::int_number_format, host.returned); 516 | *result.out = '\0'; 517 | m_listMTR.SetItem(i, 4, LVIF_TEXT, buf, 0, 0, 0, 0); 518 | 519 | result = std::format_to_n(buf, writable_size, WinMTRUtils::int_number_format, host.best); 520 | *result.out = '\0'; 521 | m_listMTR.SetItem(i, 5, LVIF_TEXT, buf, 0, 0, 0, 0); 522 | 523 | result = std::format_to_n(buf, writable_size, WinMTRUtils::int_number_format, host.getAvg()); 524 | *result.out = '\0'; 525 | m_listMTR.SetItem(i, 6, LVIF_TEXT, buf, 0, 0, 0, 0); 526 | 527 | result = std::format_to_n(buf, writable_size, WinMTRUtils::int_number_format, host.worst); 528 | *result.out = '\0'; 529 | m_listMTR.SetItem(i, 7, LVIF_TEXT, buf, 0, 0, 0, 0); 530 | 531 | result = std::format_to_n(buf, writable_size, WinMTRUtils::int_number_format, host.last); 532 | *result.out = '\0'; 533 | m_listMTR.SetItem(i, 8, LVIF_TEXT, buf, 0, 0, 0, 0); 534 | 535 | i++; 536 | } 537 | 538 | return 0; 539 | } 540 | 541 | void WinMTRDialog::OnCbnSelchangeComboHost() 542 | { 543 | } 544 | 545 | void WinMTRDialog::OnCbnSelendokComboHost() 546 | { 547 | } 548 | 549 | 550 | void WinMTRDialog::OnCbnCloseupComboHost() 551 | { 552 | if (m_comboHost.GetCurSel() == m_comboHost.GetCount() - 1) { 553 | ClearHistory(); 554 | } 555 | } -------------------------------------------------------------------------------- /WinMTRDialog-exporter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2023 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | module; 22 | 23 | #pragma warning (disable : 4005) 24 | #include "targetver.h" 25 | #define WIN32_LEAN_AND_MEAN 26 | #include 27 | #include 28 | #include 29 | #ifndef _AFX_NO_AFXCMN_SUPPORT 30 | #include 31 | #endif 32 | #include "resource.h" 33 | #include 34 | #include 35 | module WinMTR.Dialog:exporter; 36 | 37 | import :ClassDef; 38 | import ; 39 | import ; 40 | import ; 41 | import ; 42 | import ; 43 | import ; 44 | 45 | import WinMTR.Net; 46 | import WinMTRSNetHost; 47 | using namespace std::literals; 48 | namespace { 49 | [[nodiscard]] 50 | std::wstring makeTextOutput(const WinMTRNet& wmtrnet) { 51 | std::wostringstream out_buf; 52 | out_buf << L"|-------------------------------------------------------------------------------------------|\r\n" \ 53 | L"| WinMTR statistics |\r\n" \ 54 | L"| Host - %% | Sent | Recv | Best | Avrg | Wrst | Last |\r\n" \ 55 | L"|-------------------------------------------------|------|------|------|------|------|------|\r\n"sv; 56 | std::ostream_iterator out(out_buf); 57 | CString noResponse; 58 | noResponse.LoadStringW(IDS_STRING_NO_RESPONSE_FROM_HOST); 59 | 60 | for (const auto curr_state = wmtrnet.getCurrentState(); const auto & hop : curr_state) { 61 | auto name = hop.getName(); 62 | if (name.empty()) { 63 | name = noResponse; 64 | } 65 | std::format_to(out, L"| {:40} - {:4} | {:4} | {:4} | {:4} | {:4} | {:4} | {:4} |\r\n"sv, 66 | name, hop.getPercent(), 67 | hop.xmit, hop.returned, hop.best, 68 | hop.getAvg(), hop.worst, hop.last); 69 | } 70 | 71 | out_buf << L"|_________________________________________________|______|______|______|______|______|______|\r\n"sv; 72 | 73 | CString cs_tmp; 74 | (void)cs_tmp.LoadStringW(IDS_STRING_SB_NAME); 75 | out_buf << L" "sv << cs_tmp.GetString(); 76 | return out_buf.str(); 77 | } 78 | // jscpd:ignore-start 79 | std::wostream& makeHTMLOutput(WinMTRNet& wmtrnet, std::wostream& out) { 80 | out << L"" \ 81 | L""sv; 82 | std::ostream_iterator outitr(out); 83 | 84 | CString noResponse; 85 | noResponse.LoadStringW(IDS_STRING_NO_RESPONSE_FROM_HOST); 86 | 87 | for (const auto curr_state = wmtrnet.getCurrentState(); const auto & hop : curr_state) { 88 | auto name = hop.getName(); 89 | if (name.empty()) { 90 | name = noResponse; 91 | } 92 | std::format_to(outitr 93 | , L""sv 94 | , name 95 | , hop.getPercent() 96 | , hop.xmit 97 | , hop.returned 98 | , hop.best 99 | , hop.getAvg() 100 | , hop.worst 101 | , hop.last 102 | ); 103 | } 104 | 105 | out << L"
Host%%SentRecvBestAvrgWrstLast
{}{}{}{}{}{}{}{}
"sv; 106 | return out; 107 | } 108 | // jscpd:ignore-end 109 | } 110 | 111 | //***************************************************************************** 112 | // WinMTRDialog::OnCTTC 113 | // 114 | // 115 | //***************************************************************************** 116 | void WinMTRDialog::OnCTTC() noexcept 117 | { 118 | using namespace winrt::Windows::ApplicationModel::DataTransfer; 119 | const auto f_buf = makeTextOutput(*wmtrnet); 120 | auto dataPackage = DataPackage(); 121 | dataPackage.SetText(f_buf); 122 | 123 | Clipboard::SetContentWithOptions(dataPackage, nullptr); 124 | } 125 | 126 | 127 | //***************************************************************************** 128 | // WinMTRDialog::OnCHTC 129 | // 130 | // 131 | //***************************************************************************** 132 | void WinMTRDialog::OnCHTC() noexcept 133 | { 134 | using namespace winrt::Windows::ApplicationModel::DataTransfer; 135 | std::wostringstream out; 136 | makeHTMLOutput(*wmtrnet, out); 137 | const auto f_buf = out.str(); 138 | const auto htmlFormat = HtmlFormatHelper::CreateHtmlFormat(f_buf); 139 | auto dataPackage = DataPackage(); 140 | dataPackage.SetHtmlFormat(htmlFormat); 141 | Clipboard::SetContentWithOptions(dataPackage, nullptr); 142 | } 143 | 144 | 145 | //***************************************************************************** 146 | // WinMTRDialog::OnEXPT 147 | // 148 | // 149 | //***************************************************************************** 150 | void WinMTRDialog::OnEXPT() noexcept 151 | { 152 | const TCHAR BASED_CODE szFilter[] = _T("Text Files (*.txt)|*.txt|All Files (*.*)|*.*||"); 153 | 154 | CFileDialog dlg(FALSE, 155 | _T("TXT"), 156 | nullptr, 157 | OFN_HIDEREADONLY, 158 | szFilter, 159 | this); 160 | if (dlg.DoModal() == IDOK) { 161 | const auto f_buf = makeTextOutput(*wmtrnet); 162 | 163 | if (std::wfstream fp(dlg.GetPathName(), std::ios::binary | std::ios::out | std::ios::trunc); fp) { 164 | fp << f_buf << std::endl; 165 | } 166 | } 167 | } 168 | 169 | 170 | //***************************************************************************** 171 | // WinMTRDialog::OnEXPH 172 | // 173 | // 174 | //***************************************************************************** 175 | void WinMTRDialog::OnEXPH() noexcept 176 | { 177 | const TCHAR szFilter[] = _T("HTML Files (*.htm, *.html)|*.htm;*.html|All Files (*.*)|*.*||"); 178 | 179 | CFileDialog dlg(FALSE, 180 | _T("HTML"), 181 | nullptr, 182 | OFN_HIDEREADONLY, 183 | szFilter, 184 | this); 185 | 186 | if (dlg.DoModal() == IDOK) { 187 | if (std::wfstream fp(dlg.GetPathName(), std::ios::binary | std::ios::out | std::ios::trunc); fp) { 188 | fp << L"WinMTR Statistics" \ 192 | L"

WinMTR statistics

"sv; 193 | makeHTMLOutput(*wmtrnet, fp) << L""sv << std::endl; 194 | } 195 | } 196 | } 197 | 198 | -------------------------------------------------------------------------------- /WinMTRDialog-registry.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2023 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | module; 22 | 23 | #pragma warning (disable : 4005) 24 | #include "targetver.h" 25 | #define WIN32_LEAN_AND_MEAN 26 | #include 27 | #include 28 | #include 29 | #ifndef _AFX_NO_AFXCMN_SUPPORT 30 | #include 31 | #endif 32 | #include "resource.h" 33 | 34 | module WinMTR.Dialog:registry; 35 | import :ClassDef; 36 | 37 | import ; 38 | import ; 39 | import WinMTRVerUtil; 40 | import WinMTR.Options; 41 | 42 | using namespace std::literals; 43 | namespace { 44 | static constexpr auto reg_host_fmt = L"Host{:d}"sv; 45 | const auto NrLRU_REG_KEY = L"NrLRU"; 46 | const auto config_key_name = LR"(Software\WinMTR\Config)"; 47 | const auto lru_key_name = LR"(Software\WinMTR\LRU)"; 48 | } 49 | //***************************************************************************** 50 | // WinMTRDialog::InitRegistry 51 | // 52 | // 53 | //***************************************************************************** 54 | BOOL WinMTRDialog::InitRegistry() noexcept 55 | { 56 | CRegKey versionKey; 57 | if (versionKey.Create(HKEY_CURRENT_USER, 58 | LR"(Software\WinMTR)", 59 | nullptr, 60 | REG_OPTION_NON_VOLATILE, 61 | KEY_ALL_ACCESS) != ERROR_SUCCESS) { 62 | return FALSE; 63 | 64 | } 65 | static const auto WINMTR_VERSION = L"0.96"; 66 | static const auto WINMTR_LICENSE = L"GPL - GNU Public License"; 67 | static const auto WINMTR_HOMEPAGE = L"https://github.com/leeter/WinMTR-refresh"; 68 | versionKey.SetStringValue(L"Version", WinMTRVerUtil::getExeVersion().c_str()); 69 | versionKey.SetStringValue(L"License", WINMTR_LICENSE); 70 | versionKey.SetStringValue(L"HomePage", WINMTR_HOMEPAGE); 71 | CRegKey config_key; 72 | if (config_key.Create(versionKey, 73 | L"Config", 74 | nullptr, 75 | REG_OPTION_NON_VOLATILE, 76 | KEY_ALL_ACCESS) != ERROR_SUCCESS) { 77 | return FALSE; 78 | } 79 | DWORD tmp_dword; 80 | if (config_key.QueryDWORDValue(L"PingSize", tmp_dword) != ERROR_SUCCESS) { 81 | tmp_dword = pingsize; 82 | config_key.SetDWORDValue(L"PingSize", tmp_dword); 83 | } 84 | else { 85 | if (!hasPingsizeFromCmdLine) pingsize = tmp_dword; 86 | } 87 | 88 | if (config_key.QueryDWORDValue(L"MaxLRU", tmp_dword) != ERROR_SUCCESS) { 89 | tmp_dword = maxLRU; 90 | config_key.SetDWORDValue(L"MaxLRU", tmp_dword); 91 | } 92 | else { 93 | if (!hasMaxLRUFromCmdLine) maxLRU = tmp_dword; 94 | } 95 | 96 | if (config_key.QueryDWORDValue(L"UseDNS", tmp_dword) != ERROR_SUCCESS) { 97 | tmp_dword = useDNS ? 1 : 0; 98 | config_key.SetDWORDValue(L"UseDNS", tmp_dword); 99 | } 100 | else { 101 | if (!hasUseDNSFromCmdLine) useDNS = (BOOL)tmp_dword; 102 | } 103 | 104 | if (config_key.QueryDWORDValue(L"Interval", tmp_dword) != ERROR_SUCCESS) { 105 | tmp_dword = static_cast(interval * 1000); 106 | config_key.SetDWORDValue(L"Interval", tmp_dword); 107 | } 108 | else { 109 | if (!hasIntervalFromCmdLine) interval = (float)tmp_dword / 1000.0; 110 | } 111 | CRegKey lru_key; 112 | if (lru_key.Create(versionKey, 113 | L"LRU", 114 | nullptr, 115 | REG_OPTION_NON_VOLATILE, 116 | KEY_ALL_ACCESS) != ERROR_SUCCESS) 117 | return FALSE; 118 | if (lru_key.QueryDWORDValue(NrLRU_REG_KEY, tmp_dword) != ERROR_SUCCESS) { 119 | tmp_dword = nrLRU; 120 | lru_key.SetDWORDValue(NrLRU_REG_KEY, tmp_dword); 121 | } 122 | else { 123 | wchar_t key_name[20]; 124 | wchar_t str_host[NI_MAXHOST]; 125 | nrLRU = tmp_dword; 126 | constexpr auto key_name_size = std::size(key_name) - 1; 127 | for (int i = 0; i < maxLRU; i++) { 128 | auto result = std::format_to_n(key_name, key_name_size, reg_host_fmt, i + 1); 129 | *result.out = '\0'; 130 | auto value_size = static_cast(std::size(str_host)); 131 | if (lru_key.QueryStringValue(key_name, str_host, &value_size) == ERROR_SUCCESS) { 132 | str_host[value_size] = L'\0'; 133 | m_comboHost.AddString((CString)str_host); 134 | } 135 | } 136 | } 137 | m_comboHost.AddString(CString((LPCTSTR)IDS_STRING_CLEAR_HISTORY)); 138 | return TRUE; 139 | } 140 | 141 | void WinMTRDialog::ClearHistory() 142 | { 143 | DWORD tmp_dword; 144 | wchar_t key_name[20] = {}; 145 | CRegKey lru_key; 146 | lru_key.Open(HKEY_CURRENT_USER, LR"(Software\WinMTR\LRU)", KEY_ALL_ACCESS); 147 | constexpr auto key_name_size = std::size(key_name) - 1; 148 | for (int i = 0; i <= nrLRU; i++) { 149 | auto result = std::format_to_n(key_name, key_name_size, reg_host_fmt, i); 150 | *result.out = '\0'; 151 | lru_key.DeleteValue(key_name); 152 | } 153 | nrLRU = 0; 154 | tmp_dword = nrLRU; 155 | lru_key.SetDWORDValue(NrLRU_REG_KEY, tmp_dword); 156 | 157 | m_comboHost.Clear(); 158 | m_comboHost.ResetContent(); 159 | m_comboHost.AddString(CString((LPCSTR)IDS_STRING_CLEAR_HISTORY)); 160 | } 161 | 162 | 163 | //***************************************************************************** 164 | // WinMTRDialog::OnRestart 165 | // 166 | // 167 | //***************************************************************************** 168 | void WinMTRDialog::OnRestart() noexcept 169 | { 170 | // If clear history is selected, just clear the registry and listbox and return 171 | if (m_comboHost.GetCurSel() == m_comboHost.GetCount() - 1) { 172 | ClearHistory(); 173 | return; 174 | } 175 | 176 | CString sHost; 177 | if (state == STATES::IDLE) { 178 | m_comboHost.GetWindowTextW(sHost); 179 | sHost.TrimLeft(); 180 | sHost.TrimLeft(); 181 | 182 | if (sHost.IsEmpty()) { 183 | AfxMessageBox(L"No host specified!"); 184 | m_comboHost.SetFocus(); 185 | return; 186 | } 187 | m_listMTR.DeleteAllItems(); 188 | } 189 | 190 | if (state == STATES::IDLE) { 191 | 192 | if (InitMTRNet()) { 193 | if (m_comboHost.FindString(-1, sHost) == CB_ERR) { 194 | m_comboHost.InsertString(m_comboHost.GetCount() - 1, sHost); 195 | 196 | wchar_t key_name[20]; 197 | CRegKey lru_key; 198 | lru_key.Open(HKEY_CURRENT_USER, lru_key_name, KEY_ALL_ACCESS); 199 | 200 | if (nrLRU >= maxLRU) 201 | nrLRU = 0; 202 | 203 | nrLRU++; 204 | auto result = std::format_to_n(key_name, std::size(key_name) - 1, reg_host_fmt, nrLRU); 205 | *result.out = '\0'; 206 | lru_key.SetStringValue(key_name, static_cast(sHost)); 207 | auto tmp_dword = static_cast(nrLRU); 208 | lru_key.SetDWORDValue(NrLRU_REG_KEY, tmp_dword); 209 | } 210 | Transit(STATES::TRACING); 211 | } 212 | } 213 | else { 214 | Transit(STATES::STOPPING); 215 | } 216 | } 217 | 218 | //***************************************************************************** 219 | // WinMTRDialog::OnOptions 220 | // 221 | // 222 | //***************************************************************************** 223 | void WinMTRDialog::OnOptions() 224 | { 225 | WinMTROptions optDlg; 226 | 227 | optDlg.SetPingSize(pingsize); 228 | optDlg.SetInterval(interval); 229 | optDlg.SetMaxLRU(maxLRU); 230 | optDlg.SetUseDNS(useDNS); 231 | optDlg.SetUseIPv4(useIPv4); 232 | optDlg.SetUseIPv6(useIPv6); 233 | 234 | if (IDOK == optDlg.DoModal()) { 235 | 236 | pingsize = optDlg.GetPingSize(); 237 | interval = optDlg.GetInterval(); 238 | maxLRU = optDlg.GetMaxLRU(); 239 | useDNS = optDlg.GetUseDNS(); 240 | useIPv4 = optDlg.GetUseIPv4(); 241 | useIPv6 = optDlg.GetUseIPv6(); 242 | 243 | /*HKEY hKey;*/ 244 | DWORD tmp_dword; 245 | wchar_t key_name[20]; 246 | { 247 | CRegKey config_key; 248 | config_key.Open(HKEY_CURRENT_USER, config_key_name, KEY_ALL_ACCESS); 249 | tmp_dword = pingsize; 250 | config_key.SetDWORDValue(L"PingSize", tmp_dword); 251 | tmp_dword = maxLRU; 252 | config_key.SetDWORDValue(L"MaxLRU", tmp_dword); 253 | tmp_dword = useDNS ? 1 : 0; 254 | config_key.SetDWORDValue(L"UseDNS", tmp_dword); 255 | tmp_dword = static_cast(interval * 1000); 256 | config_key.SetDWORDValue(L"Interval", tmp_dword); 257 | } 258 | if (maxLRU < nrLRU) { 259 | CRegKey lru_key; 260 | lru_key.Open(HKEY_CURRENT_USER, lru_key_name, KEY_ALL_ACCESS); 261 | constexpr auto key_name_size = std::size(key_name) - 1; 262 | for (int i = maxLRU; i <= nrLRU; i++) { 263 | auto result = std::format_to_n(key_name, key_name_size, reg_host_fmt, i); 264 | *result.out = '\0'; 265 | lru_key.DeleteValue(key_name); 266 | } 267 | nrLRU = maxLRU; 268 | tmp_dword = nrLRU; 269 | lru_key.SetDWORDValue(NrLRU_REG_KEY, tmp_dword); 270 | } 271 | } 272 | } 273 | -------------------------------------------------------------------------------- /WinMTRDialog-tracing.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2023 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | module; 22 | #pragma warning (disable : 4005) 23 | #include "targetver.h" 24 | #define WIN32_LEAN_AND_MEAN 25 | #define NOMINMAX 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "resource.h" 32 | 33 | module WinMTR.Dialog:tracing; 34 | 35 | import :ClassDef; 36 | import WinMTRSNetHost; 37 | import WinMTRDnsUtil; 38 | import ; 39 | import ; 40 | import ; 41 | import ; 42 | import ; 43 | import ; 44 | 45 | using namespace std::literals; 46 | 47 | //***************************************************************************** 48 | // WinMTRDialog::InitMTRNet 49 | // 50 | // 51 | //***************************************************************************** 52 | bool WinMTRDialog::InitMTRNet() noexcept 53 | { 54 | CString sHost; 55 | m_comboHost.GetWindowTextW(sHost); 56 | 57 | if (sHost.IsEmpty()) [[unlikely]] { // Technically never because this is caught in the calling function 58 | sHost = L"localhost"; 59 | } 60 | 61 | SOCKADDR_INET addrstore{}; 62 | for (auto af : { AF_INET, AF_INET6 }) { 63 | INT addrSize = sizeof(addrstore); 64 | if (auto res = WSAStringToAddressW( 65 | sHost.GetBuffer() 66 | , af 67 | , nullptr 68 | , reinterpret_cast(&addrstore) 69 | , &addrSize); 70 | !res) { 71 | return true; 72 | } 73 | } 74 | 75 | const auto buf = std::format(L"Resolving host {}..."sv, sHost.GetString()); 76 | statusBar.SetPaneText(0, buf.c_str()); 77 | std::unique_ptr holder; 78 | ADDRINFOEXW hint = { .ai_family = AF_UNSPEC }; 79 | if (const auto result = GetAddrInfoExW( 80 | sHost 81 | , nullptr 82 | , NS_ALL 83 | , nullptr 84 | , &hint 85 | , std::out_ptr(holder) 86 | , nullptr 87 | , nullptr 88 | , nullptr 89 | , nullptr); result != ERROR_SUCCESS) { 90 | statusBar.SetPaneText(0, CString((LPCTSTR)IDS_STRING_SB_NAME)); 91 | AfxMessageBox(IDS_STRING_UNABLE_TO_RESOLVE_HOSTNAME); 92 | return false; 93 | } 94 | 95 | return true; 96 | } 97 | 98 | winrt::Windows::Foundation::IAsyncAction WinMTRDialog::pingThread(std::stop_token stop_token, std::wstring sHost) 99 | { 100 | if (tracing.exchange(true)) { 101 | throw new std::runtime_error("Tracing started twice!"); 102 | } 103 | struct tracexit { 104 | WinMTRDialog* dialog; 105 | ~tracexit() noexcept { 106 | dialog->tracing.store(false, std::memory_order_release); 107 | } 108 | }tracexit{ this }; 109 | 110 | SOCKADDR_INET addrstore = {}; 111 | 112 | for (auto af : { AF_INET, AF_INET6 }) { 113 | INT addrSize = sizeof(addrstore); 114 | if (auto res = WSAStringToAddressW( 115 | sHost.data() 116 | , af 117 | , nullptr 118 | , reinterpret_cast(&addrstore) 119 | , &addrSize); 120 | !res) { 121 | co_await this->wmtrnet->DoTrace(stop_token, std::move(addrstore)); 122 | co_return; 123 | } 124 | } 125 | 126 | int hintFamily = AF_UNSPEC; //both 127 | if (!this->useIPv4) { 128 | hintFamily = AF_INET6; 129 | } 130 | else if (!this->useIPv6) { 131 | hintFamily = AF_INET; 132 | } 133 | timeval timeout{ .tv_sec = 30 }; 134 | auto result = co_await GetAddrInfoAsync(sHost, &timeout, hintFamily); 135 | if (!result || result->empty()) { 136 | AfxMessageBox(IDS_STRING_UNABLE_TO_RESOLVE_HOSTNAME); 137 | co_return; 138 | } 139 | addrstore = result->front(); 140 | co_await this->wmtrnet->DoTrace(stop_token, std::move(addrstore)); 141 | } 142 | 143 | winrt::fire_and_forget WinMTRDialog::stopTrace() 144 | { 145 | // grab the thread under a mutex so we don't mess this up and cause a data race 146 | decltype(trace_lacky) temp; 147 | { 148 | std::unique_lock trace_lock{ tracer_mutex }; 149 | std::swap(temp, trace_lacky); 150 | } 151 | // don't bother trying call something not there 152 | if (!temp) { 153 | co_return; 154 | } 155 | co_await winrt::resume_background(); 156 | temp.reset(); //trigger the stop token 157 | co_return; 158 | } -------------------------------------------------------------------------------- /WinMTRDialog.ixx: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2023 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | //***************************************************************************** 22 | // FILE: WinMTRDialog.cpp 23 | // 24 | // 25 | //***************************************************************************** 26 | module; 27 | #include "targetver.h" 28 | #define WIN32_LEAN_AND_MEAN 29 | #define VC_EXTRALEAN 30 | #include 31 | #include 32 | #include 33 | 34 | #pragma warning (disable : 4005) 35 | 36 | export module WinMTR.Dialog; 37 | 38 | export import :ClassDef; 39 | 40 | module : private; 41 | 42 | import :tracing; 43 | import :exporter; 44 | import :registry; 45 | import :StateMachine; 46 | import :display; 47 | -------------------------------------------------------------------------------- /WinMTRDnsUtil.ixx: -------------------------------------------------------------------------------- 1 | module; 2 | #pragma warning (disable : 4005) 3 | #include "targetver.h" 4 | #define WIN32_LEAN_AND_MEAN 5 | #define VC_EXTRALEAN 6 | #define NOMCX 7 | #define NOIME 8 | #define NOGDI 9 | #define NONLS 10 | #define NOAPISET 11 | #define NOSERVICE 12 | #define NOMINMAX 13 | #include 14 | #include 15 | #include 16 | export module WinMTRDnsUtil; 17 | 18 | import ; 19 | import ; 20 | import ; 21 | import ; 22 | import ; 23 | import ; 24 | import ; 25 | import ; 26 | import ; 27 | import ; 28 | 29 | 30 | export template 31 | concept layout_compatible = std::is_layout_compatible_v; 32 | 33 | export template A> 34 | std::optional get_sockaddr_from_addrinfo(const A* info) { 35 | if (info->ai_addr == nullptr) { 36 | return std::nullopt; 37 | } 38 | SOCKADDR_INET addrstore = {}; 39 | 40 | std::memcpy(&addrstore, info->ai_addr, info->ai_addrlen); 41 | return addrstore; 42 | } 43 | 44 | //export template A> 45 | //std::optional get_name_from_addrinfo(const ADDRINFOEXW* info) { 46 | // if (info->ai_canonname == nullptr) { 47 | // return std::nullopt; 48 | // } 49 | // 50 | // return std::wstring(info->ai_canonname); 51 | //} 52 | 53 | export struct addrinfo_deleter final { 54 | void operator()(PADDRINFOEXW adder_info) const noexcept { 55 | FreeAddrInfoExW(adder_info); 56 | } 57 | }; 58 | 59 | class name_lookup_async final { 60 | using coro_handle = std::coroutine_handle<>; 61 | 62 | struct overlappedLacky final : public WSAOVERLAPPED { 63 | name_lookup_async* parent; 64 | }; 65 | overlappedLacky lacky{ .parent{this} }; 66 | concurrency::task_continuation_context m_context = concurrency::task_continuation_context::get_current_winrt_context(); 67 | coro_handle m_resume{ nullptr }; 68 | const std::wstring_view m_Name; 69 | timeval* m_timeout; 70 | PADDRINFOEXW m_results{ nullptr }; 71 | DWORD m_dwError = ERROR_SUCCESS; 72 | int m_family; 73 | int m_flags; 74 | name_lookup_async(const name_lookup_async&) = delete; 75 | public: 76 | name_lookup_async(const std::wstring_view pName, timeval* timeout, int family = AF_UNSPEC, int flags = 0) noexcept 77 | :m_Name(pName) 78 | , m_timeout(timeout) 79 | , m_family(family) 80 | , m_flags(flags) 81 | { 82 | } 83 | 84 | ~name_lookup_async() noexcept 85 | { 86 | if (m_results) { 87 | FreeAddrInfoExW(m_results); 88 | } 89 | 90 | } 91 | 92 | bool await_ready() const noexcept 93 | { 94 | return false; 95 | } 96 | 97 | void await_suspend(coro_handle resume_handle) 98 | { 99 | m_resume = resume_handle; 100 | // AF_UNSPEC counts as AF_INET | AF_INET6 101 | ADDRINFOEXW hint = { .ai_flags = m_flags, .ai_family = m_family }; 102 | const auto result = GetAddrInfoExW( 103 | m_Name.data() 104 | , nullptr ///PCWSTR pServiceName, 105 | , NS_DNS 106 | , nullptr //LPGUID lpNspId, 107 | , &hint 108 | , &m_results // PADDRINFOEXW * ppResult, 109 | , m_timeout 110 | , &lacky 111 | , name_lookup_async::lookup_callback 112 | , nullptr //LPHANDLE lpHandle 113 | ); 114 | 115 | if (result != WSA_IO_PENDING) { 116 | winrt::throw_hresult(HRESULT_FROM_WIN32(result)); 117 | } 118 | } 119 | 120 | std::expected, winrt::hresult> await_resume() const noexcept 121 | { 122 | if (m_dwError != ERROR_SUCCESS) { 123 | return std::unexpected{ winrt::hresult{HRESULT_FROM_WIN32(m_dwError) } }; 124 | } 125 | 126 | std::vector addresses; 127 | for (auto result = m_results; result; result = result->ai_next) { 128 | if (const auto addr = get_sockaddr_from_addrinfo(result); addr) { 129 | addresses.push_back(*addr); 130 | } 131 | } 132 | 133 | return addresses; 134 | } 135 | 136 | private: 137 | static void 138 | CALLBACK lookup_callback( 139 | __in DWORD dwError, 140 | __in [[maybe_unused]] DWORD dwBytes, 141 | __in LPWSAOVERLAPPED lpOverlapped 142 | ) noexcept; 143 | }; 144 | 145 | export auto GetAddrInfoAsync(const std::wstring_view pName, timeval* timeout, int family = AF_UNSPEC, int flags = 0) noexcept { 146 | 147 | return name_lookup_async{ pName, timeout, family, flags }; 148 | } 149 | module: private; 150 | 151 | void 152 | CALLBACK name_lookup_async::lookup_callback( 153 | __in DWORD dwError, 154 | __in [[maybe_unused]] DWORD dwBytes, 155 | __in LPWSAOVERLAPPED lpOverlapped 156 | ) noexcept { 157 | auto context = static_cast(lpOverlapped)->parent; 158 | context->m_dwError = dwError; 159 | concurrency::create_task([=] { 160 | context->m_resume(); 161 | }, context->m_context); 162 | } -------------------------------------------------------------------------------- /WinMTRGlobal.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2021 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | 22 | #include "WinMTRGlobal.h" -------------------------------------------------------------------------------- /WinMTRGlobal.h: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2021 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | //***************************************************************************** 22 | // FILE: WinMTRGlobal.h 23 | // 24 | // 25 | // DESCRIPTION: 26 | // 27 | // 28 | // NOTES: 29 | // 30 | // 31 | //***************************************************************************** 32 | #pragma once 33 | #ifndef WINMTR_GLOBAL_H_ 34 | #define WINMTR_GLOBAL_H_ 35 | #pragma warning (disable : 4005) 36 | #include "targetver.h" 37 | #define WIN32_LEAN_AND_MEAN 38 | #define VC_EXTRALEAN 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | #ifndef _AFX_NO_AFXCMN_SUPPORT 45 | #include 46 | #endif 47 | 48 | 49 | 50 | 51 | 52 | #define SAVED_PINGS 100 53 | constexpr auto MaxHost = 256; 54 | //#define MaxSequence 65536 55 | #define MaxSequence 32767 56 | //#define MaxSequence 5 57 | 58 | //#define MAXPACKET 4096 59 | //#define MINPACKET 64 60 | 61 | //#define MaxTransit 4 62 | 63 | 64 | //#define ICMP_ECHO 8 65 | //#define ICMP_ECHOREPLY 0 66 | // 67 | //#define ICMP_TSTAMP 13 68 | //#define ICMP_TSTAMPREPLY 14 69 | // 70 | //#define ICMP_TIME_EXCEEDED 11 71 | // 72 | //#define ICMP_HOST_UNREACHABLE 3 73 | // 74 | //#define MAX_UNKNOWN_HOSTS 10 75 | 76 | //#define IP_HEADER_LENGTH 20 77 | 78 | #ifdef DEBUG 79 | #include 80 | #define TRACE_MSG(msg) \ 81 | { \ 82 | std::wostringstream dbg_msg(std::wostringstream::out); \ 83 | dbg_msg << msg << std::endl; \ 84 | OutputDebugStringW(dbg_msg.str().c_str()); \ 85 | } 86 | #else 87 | #define TRACE_MSG(msg) 88 | #endif 89 | 90 | #endif // ifndef WINMTR_GLOBAL_H_ 91 | -------------------------------------------------------------------------------- /WinMTRHelp.ixx: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2022 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | // WinMTRHelp.cpp : implementation file 22 | // 23 | module; 24 | #pragma warning (disable : 4005) 25 | #include "targetver.h" 26 | #define WIN32_LEAN_AND_MEAN 27 | #define VC_EXTRALEAN 28 | #include 29 | #include 30 | #include "resource.h" 31 | export module WinMTR.Help; 32 | 33 | 34 | // WinMTRHelp dialog 35 | 36 | export class WinMTRHelp final : public CDialog 37 | { 38 | DECLARE_DYNAMIC(WinMTRHelp) 39 | 40 | public: 41 | WinMTRHelp(CWnd* pParent = nullptr) // standard constructor 42 | : CDialog(WinMTRHelp::IDD, pParent) 43 | {} 44 | ~WinMTRHelp() override = default; 45 | 46 | // Dialog Data 47 | enum { IDD = IDD_DIALOG_HELP }; 48 | 49 | protected: 50 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 51 | 52 | DECLARE_MESSAGE_MAP() 53 | public: 54 | afx_msg void OnBnClickedOk(); 55 | }; 56 | 57 | module : private; 58 | 59 | // WinMTRHelp dialog 60 | 61 | IMPLEMENT_DYNAMIC(WinMTRHelp, CDialog) 62 | 63 | 64 | void WinMTRHelp::DoDataExchange(CDataExchange* pDX) 65 | { 66 | CDialog::DoDataExchange(pDX); 67 | } 68 | 69 | 70 | BEGIN_MESSAGE_MAP(WinMTRHelp, CDialog) 71 | ON_BN_CLICKED(IDOK, &WinMTRHelp::OnBnClickedOk) 72 | END_MESSAGE_MAP() 73 | 74 | 75 | // WinMTRHelp message handlers 76 | 77 | 78 | void WinMTRHelp::OnBnClickedOk() 79 | { 80 | // TODO: Add your control notification handler code here 81 | CDialog::OnOK(); 82 | } 83 | -------------------------------------------------------------------------------- /WinMTRICMPPIOdef.h: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2021 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | #pragma once 21 | #pragma warning (disable : 4005) 22 | #include "targetver.h" 23 | #define WIN32_LEAN_AND_MEAN 24 | #define NOMINMAX 25 | #define NOMCX 26 | #define NOIME 27 | #define NOGDI 28 | #define NONLS 29 | #define NOAPISET 30 | #define NOSERVICE 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | 37 | //typedef struct _IO_STATUS_BLOCK { 38 | // union { 39 | // NTSTATUS Status; 40 | // PVOID Pointer; 41 | // } DUMMYUNIONNAME; 42 | // ULONG_PTR Information; 43 | //} IO_STATUS_BLOCK, * PIO_STATUS_BLOCK; 44 | // 45 | //typedef 46 | //VOID 47 | //(NTAPI* PIO_APC_ROUTINE) ( 48 | // IN PVOID ApcContext, 49 | // IN PIO_STATUS_BLOCK IoStatusBlock, 50 | // IN ULONG Reserved 51 | // ); 52 | #define PIO_APC_ROUTINE_DEFINED 53 | 54 | #include 55 | #include 56 | #include 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /WinMTRICMPUtils.ixx: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2021 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | module; 22 | #pragma warning (disable : 4005) 23 | #include 24 | #ifdef _RESUMABLE_ENABLE_LEGACY_AWAIT_ADAPTERS 25 | #error "don't compile with /await" 26 | #endif 27 | export module WinMTRICMPUtils; 28 | 29 | import ; 30 | import ; 31 | import ; 32 | import ; 33 | import ; 34 | import ; 35 | import ; 36 | import ; 37 | import ; 38 | import "WinMTRICMPPIOdef.h"; 39 | 40 | constexpr auto ECHO_REPLY_TIMEOUT = 5000; 41 | 42 | export 43 | template 44 | struct ping_reply { 45 | using type = void; 46 | }; 47 | 48 | export 49 | template<> 50 | struct ping_reply { 51 | using type = ICMP_ECHO_REPLY; 52 | }; 53 | 54 | export 55 | template<> 56 | struct ping_reply { 57 | using type = ICMPV6_ECHO_REPLY; 58 | }; 59 | 60 | export 61 | template 62 | using ping_reply_t = ping_reply::type; 63 | 64 | export 65 | template 66 | struct any_address { 67 | static constexpr void value() noexcept {}; 68 | }; 69 | 70 | export 71 | template<> 72 | struct any_address { 73 | static constexpr auto value() noexcept { 74 | return ADDR_ANY; 75 | } 76 | }; 77 | 78 | export 79 | template<> 80 | struct any_address { 81 | static SOCKADDR_IN6* value() noexcept { 82 | static sockaddr_in6 anyaddr = { .sin6_family = AF_INET6, .sin6_addr = in6addr_any }; 83 | return &anyaddr; 84 | } 85 | }; 86 | 87 | export 88 | template 89 | concept icmp_type = requires { 90 | typename T::reply_type; 91 | typename T::reply_type_ptr; 92 | typename T::addrtype; 93 | typename T::storagetype; 94 | }; 95 | 96 | export 97 | template 98 | concept supports_ICMP_ping = icmp_type && requires( 99 | _In_ HANDLE IcmpHandle, 100 | _In_opt_ HANDLE Event, 101 | #ifdef PIO_APC_ROUTINE_DEFINED 102 | _In_opt_ PIO_APC_ROUTINE ApcRoutine, 103 | #else 104 | _In_opt_ FARPROC ApcRoutine, 105 | #endif 106 | _In_opt_ PVOID ApcContext, 107 | _In_ typename T::addrtype SourceAddress, 108 | _In_ typename T::addrtype DestinationAddress, 109 | _In_reads_bytes_(RequestSize) LPVOID RequestData, 110 | _In_ WORD RequestSize, 111 | _In_opt_ PIP_OPTION_INFORMATION RequestOptions, 112 | _Out_writes_bytes_(ReplySize) LPVOID ReplyBuffer, 113 | _In_range_(>= , sizeof(ICMP_ECHO_REPLY) + RequestSize + 8) 114 | DWORD ReplySize, 115 | _In_ DWORD Timeout) { 116 | { T::pingmethod(IcmpHandle, 117 | Event, 118 | ApcRoutine, 119 | ApcContext, 120 | SourceAddress, 121 | DestinationAddress, 122 | RequestData, 123 | RequestSize, 124 | RequestOptions, 125 | ReplyBuffer, 126 | ReplySize, 127 | Timeout) } noexcept -> std::convertible_to; 128 | }; 129 | 130 | export 131 | template 132 | concept supports_ICMP_ping_parse = icmp_type && requires( 133 | _Out_writes_bytes_(ReplySize) LPVOID ReplyBuffer, 134 | _In_range_(> , sizeof(T::reply_type) + 8) 135 | DWORD ReplySize) { 136 | { 137 | T::parsemethod( 138 | ReplyBuffer, 139 | ReplySize) } noexcept -> std::convertible_to; 140 | }; 141 | 142 | export 143 | template 144 | concept icmp_pingable = icmp_type && supports_ICMP_ping && supports_ICMP_ping_parse && requires( 145 | std::add_const_t rtp 146 | , std::add_pointer_t storage) { 147 | { T::get_anyaddr() } noexcept -> std::convertible_to; 148 | { T::to_addr_from_ping(rtp) } noexcept -> std::convertible_to; 149 | { T::to_addr_from_storage(storage) } noexcept -> std::convertible_to; 150 | }; 151 | 152 | export 153 | template 154 | struct icmp_ping_traits { 155 | using reply_type = ping_reply_t; 156 | using reply_type_ptr = std::add_pointer_t; 157 | using addrtype = void; 158 | using storagetype = void; 159 | static constexpr auto pingmethod = 0; 160 | static constexpr auto parsemethod = 0; 161 | static auto get_anyaddr() noexcept -> addrtype { 162 | return; 163 | } 164 | static storagetype to_addr_from_ping(const reply_type_ptr reply) noexcept { 165 | return {}; 166 | } 167 | }; 168 | 169 | export 170 | template<> 171 | struct icmp_ping_traits { 172 | using reply_type = ping_reply_t; 173 | using reply_type_ptr = std::add_pointer_t; 174 | using addrtype = IPAddr; 175 | using storagetype = sockaddr_in; 176 | static inline DWORD 177 | WINAPI 178 | pingmethod( 179 | _In_ HANDLE IcmpHandle, 180 | _In_opt_ HANDLE Event, 181 | #ifdef PIO_APC_ROUTINE_DEFINED 182 | _In_opt_ PIO_APC_ROUTINE ApcRoutine, 183 | #else 184 | _In_opt_ FARPROC ApcRoutine, 185 | #endif 186 | _In_opt_ PVOID ApcContext, 187 | _In_ addrtype SourceAddress, 188 | _In_ addrtype DestinationAddress, 189 | _In_reads_bytes_(RequestSize) LPVOID RequestData, 190 | _In_ WORD RequestSize, 191 | _In_opt_ PIP_OPTION_INFORMATION RequestOptions, 192 | _Out_writes_bytes_(ReplySize) LPVOID ReplyBuffer, 193 | _In_range_(>= , sizeof(ICMP_ECHO_REPLY) + RequestSize + 8) 194 | DWORD ReplySize, 195 | _In_ DWORD Timeout 196 | ) noexcept { 197 | return IcmpSendEcho2Ex(IcmpHandle, Event, ApcRoutine, ApcContext, SourceAddress, DestinationAddress, RequestData, RequestSize, RequestOptions, ReplyBuffer, ReplySize, Timeout); 198 | } 199 | static inline DWORD 200 | WINAPI 201 | parsemethod( 202 | _Out_writes_bytes_(ReplySize) LPVOID ReplyBuffer, 203 | _In_range_(> , sizeof(reply_type) + 8) 204 | DWORD ReplySize 205 | ) noexcept { 206 | return IcmpParseReplies(ReplyBuffer, ReplySize); 207 | } 208 | static auto get_anyaddr() noexcept -> addrtype { 209 | return any_address::value(); 210 | } 211 | 212 | static addrtype to_addr_from_storage(storagetype* storage) noexcept { 213 | return storage->sin_addr.S_un.S_addr; 214 | } 215 | 216 | static storagetype to_addr_from_ping(const reply_type_ptr reply) noexcept { 217 | sockaddr_in naddr = { .sin_family = AF_INET }; 218 | naddr.sin_addr.S_un.S_addr = reply->Address; 219 | return naddr; 220 | } 221 | }; 222 | 223 | export 224 | template<> 225 | struct icmp_ping_traits { 226 | using reply_type = ping_reply_t; 227 | using reply_type_ptr = std::add_pointer_t; 228 | using addrtype = sockaddr_in6*; 229 | using storagetype = std::remove_pointer_t; 230 | static inline DWORD 231 | WINAPI 232 | pingmethod( 233 | _In_ HANDLE IcmpHandle, 234 | _In_opt_ HANDLE Event, 235 | #ifdef PIO_APC_ROUTINE_DEFINED 236 | _In_opt_ PIO_APC_ROUTINE ApcRoutine, 237 | #else 238 | _In_opt_ FARPROC ApcRoutine, 239 | #endif 240 | _In_opt_ PVOID ApcContext, 241 | _In_ addrtype SourceAddress, 242 | _In_ addrtype DestinationAddress, 243 | _In_reads_bytes_(RequestSize) LPVOID RequestData, 244 | _In_ WORD RequestSize, 245 | _In_opt_ PIP_OPTION_INFORMATION RequestOptions, 246 | _Out_writes_bytes_(ReplySize) LPVOID ReplyBuffer, 247 | _In_range_(>= , sizeof(ICMP_ECHO_REPLY) + RequestSize + 8) 248 | DWORD ReplySize, 249 | _In_ DWORD Timeout 250 | ) noexcept { 251 | return Icmp6SendEcho2(IcmpHandle, Event, ApcRoutine, ApcContext, SourceAddress, DestinationAddress, RequestData, RequestSize, RequestOptions, ReplyBuffer, ReplySize, Timeout); 252 | } 253 | static inline DWORD 254 | WINAPI 255 | parsemethod( 256 | _Out_writes_bytes_(ReplySize) LPVOID ReplyBuffer, 257 | _In_range_(> , sizeof(reply_type) + 8) 258 | DWORD ReplySize 259 | ) noexcept { 260 | return Icmp6ParseReplies(ReplyBuffer, ReplySize); 261 | } 262 | static auto get_anyaddr() noexcept -> addrtype { 263 | return any_address::value(); 264 | } 265 | 266 | static constexpr addrtype to_addr_from_storage(storagetype* storage) noexcept { 267 | return storage; 268 | } 269 | static storagetype to_addr_from_ping(const reply_type_ptr reply) noexcept { 270 | sockaddr_in6 naddr = { .sin6_family = AF_INET6 }; 271 | std::ranges::copy(reply->Address.sin6_addr, naddr.sin6_addr.u.Word); 272 | return naddr; 273 | } 274 | }; 275 | 276 | export 277 | template 278 | struct icmp_ping final { 279 | struct wait_traits 280 | { 281 | using type = PTP_WAIT; 282 | 283 | static void close(type value) noexcept 284 | { 285 | CloseThreadpoolWait(value); 286 | } 287 | 288 | static constexpr type invalid() noexcept 289 | { 290 | return nullptr; 291 | } 292 | }; 293 | using coro_handle = std::coroutine_handle<>; 294 | icmp_ping(HANDLE icmpHandle, HANDLE waitevent, traits::addrtype addr, UCHAR ttl, std::span requestData, std::span replyData) noexcept 295 | :m_reqData(requestData) 296 | , m_replyData(replyData) 297 | , m_waitHandle(waitevent) 298 | , m_handle(icmpHandle) 299 | , m_addr(addr) 300 | , m_ttl(ttl) 301 | { 302 | 303 | } 304 | 305 | void await_suspend(coro_handle resume_handle) 306 | { 307 | m_resume = resume_handle; 308 | IP_OPTION_INFORMATION stIPInfo = { 309 | .Ttl = m_ttl, 310 | .Flags = IP_FLAG_DF 311 | }; 312 | auto local = traits::get_anyaddr(); 313 | 314 | const auto io_res = traits::pingmethod( 315 | m_handle 316 | , m_waitHandle 317 | , nullptr 318 | , this 319 | , local 320 | , m_addr 321 | , m_reqData.data() 322 | , static_cast(m_reqData.size()) 323 | , &stIPInfo 324 | , m_replyData.data() 325 | , static_cast(m_replyData.size()) 326 | , ECHO_REPLY_TIMEOUT); 327 | 328 | if (io_res != ERROR_SUCCESS) [[unlikely]] { 329 | winrt::throw_hresult(HRESULT_FROM_WIN32(io_res)); 330 | } 331 | if (const auto err = GetLastError(); err != ERROR_IO_PENDING) [[unlikely]] { 332 | winrt::throw_last_error(); 333 | } 334 | 335 | 336 | // 337 | // Set the timer to fire in 5 seconds. 338 | // 339 | ULARGE_INTEGER ulDueTime{ 340 | .QuadPart = static_cast(-(5ll * 10ll * 1000ll * 1000ll)) 341 | }; 342 | FILETIME FileDueTime{ 343 | .dwLowDateTime = ulDueTime.LowPart, 344 | .dwHighDateTime = ulDueTime.HighPart 345 | }; 346 | m_tpwait.attach(CreateThreadpoolWait(&WaitCallback, this, nullptr)); 347 | if (!m_tpwait) [[unlikely]] { 348 | winrt::throw_last_error(); 349 | } 350 | 351 | SetThreadpoolWait(m_tpwait.get(), m_waitHandle, &FileDueTime); 352 | 353 | } 354 | 355 | auto await_resume() const noexcept 356 | { 357 | return traits::parsemethod(m_replyData.data(), static_cast(m_replyData.size())); 358 | } 359 | 360 | bool await_ready() const noexcept 361 | { 362 | return false; 363 | } 364 | private: 365 | static void CALLBACK WaitCallback( 366 | PTP_CALLBACK_INSTANCE Instance, 367 | PVOID Context, 368 | PTP_WAIT Wait, 369 | TP_WAIT_RESULT WaitResult 370 | ) noexcept { 371 | auto context = static_cast*>(Context); 372 | concurrency::create_task([context]() noexcept { 373 | context->m_resume(); 374 | }, context->m_context); 375 | } 376 | 377 | concurrency::task_continuation_context m_context = concurrency::task_continuation_context::get_current_winrt_context(); 378 | coro_handle m_resume{ nullptr }; 379 | std::span m_reqData; 380 | std::span m_replyData; 381 | winrt::handle_type m_tpwait; 382 | HANDLE m_waitHandle; 383 | HANDLE m_handle; 384 | traits::addrtype m_addr; 385 | DWORD m_replysize = 0; 386 | UCHAR m_ttl; 387 | }; 388 | 389 | 390 | export 391 | template>, class traits = icmp_ping_traits> 392 | inline auto IcmpSendEchoAsync(HANDLE icmpHandle, HANDLE waitevent, T addr, UCHAR ttl, std::span requestData, std::span replyData) noexcept { 393 | return icmp_ping{icmpHandle, waitevent, traits::to_addr_from_storage(addr), ttl, requestData, replyData}; 394 | } 395 | 396 | export 397 | template 398 | [[nodiscard]] 399 | constexpr auto reply_reply_buffer_size(unsigned requestSize) noexcept { 400 | return sizeof(ping_reply_t) + 8 + sizeof(IO_STATUS_BLOCK) + requestSize; 401 | } 402 | -------------------------------------------------------------------------------- /WinMTRIPUtils.ixx: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2022 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | module; 22 | #pragma warning (disable : 4005) 23 | #include "targetver.h" 24 | #define WIN32_LEAN_AND_MEAN 25 | #define VC_EXTRALEAN 26 | #define NOMCX 27 | #define NOIME 28 | #define NOGDI 29 | #define NONLS 30 | #define NOAPISET 31 | #define NOSERVICE 32 | #define NOMINMAX 33 | #include 34 | #include 35 | export module WinMTRIPUtils; 36 | 37 | import ; 38 | import ; 39 | import ; 40 | 41 | export template 42 | concept socket_type = requires(T a) { 43 | a.sa_family; 44 | requires std::convertible_to; 45 | }; 46 | 47 | template 48 | requires socket_type || std::convertible_to || std::convertible_to 49 | inline constexpr auto getAddressFamily(const T & addr) noexcept { 50 | using cvref_t = std::remove_cvref_t; 51 | if constexpr (socket_type) { 52 | return addr.sa_family; 53 | } 54 | else if constexpr (std::is_same_v) { 55 | return addr.si_family; 56 | } 57 | else if (std::is_same_v) { 58 | return addr.ss_family; 59 | } 60 | } 61 | 62 | export template 63 | inline constexpr size_t getAddressSize(const T& addr) noexcept { 64 | return getAddressFamily(addr) == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6); 65 | } 66 | 67 | export template 68 | concept socket_addr_type = socket_type || std::convertible_to || std::convertible_to; 69 | 70 | export template 71 | inline constexpr bool isValidAddress(const T& addr) noexcept { 72 | const ADDRESS_FAMILY family = getAddressFamily(addr); 73 | 74 | return (family == AF_INET || family == AF_INET6); 75 | } 76 | 77 | export template 78 | [[nodiscard]] 79 | auto addr_to_string(const T & addr) noexcept -> std::wstring { 80 | if (!isValidAddress(addr)) { 81 | return {}; 82 | } 83 | // remove const at cost of a copy 84 | std::remove_cv_t laddr = addr; 85 | std::wstring out; 86 | out.resize(40); // max IPv6 Address length + 1 for terminator 87 | const auto addrlen = getAddressSize(addr); 88 | // mutated by WSAAddressToStringW 89 | DWORD addrstrsize = static_cast(out.size()); 90 | if (const auto result = WSAAddressToStringW(reinterpret_cast(&laddr), static_cast(addrlen), nullptr, out.data(), &addrstrsize); !result && addrstrsize > 1) { 91 | out.resize(addrstrsize - 1); 92 | } 93 | return out; 94 | } 95 | -------------------------------------------------------------------------------- /WinMTRMain.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2021 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | 22 | //***************************************************************************** 23 | // FILE: WinMTRMain.cpp 24 | // 25 | // 26 | // HISTORY: 27 | // 28 | // 29 | // -- versions 0.8 30 | // 31 | // - 01.18.2002 - Store LRU hosts in registry (v0.8) 32 | // - 05.08.2001 - Replace edit box with combo box which hold last entered hostnames. 33 | // Fixed a memory leak which caused program to crash after a long 34 | // time running. (v0.7) 35 | // - 11.27.2000 - Added resizing support and flat buttons. (v0.6) 36 | // - 11.26.2000 - Added copy data to clipboard and posibility to save data to file as text or HTML.(v0.5) 37 | // - 08.03.2000 - added double-click on hostname for detailed information (v0.4) 38 | // - 08.02.2000 - fix icmp error codes handling. (v0.3) 39 | // - 08.01.2000 - support for full command-line parameter specification (v0.2) 40 | // - 07.30.2000 - support for command-line host specification 41 | // by Silviu Simen (ssimen@ubisoft.ro) (v0.1b) 42 | // - 07.28.2000 - first release (v0.1) 43 | //***************************************************************************** 44 | 45 | #include "WinMTRGlobal.h" 46 | #include 47 | #include "WinMTRMain.h" 48 | import WinMTR.Help; 49 | import ; 50 | import WinMTR.CommandLineParser; 51 | import WinMTR.Dialog; 52 | 53 | 54 | #ifdef _DEBUG 55 | #define new DEBUG_NEW 56 | #undef THIS_FILE 57 | static char THIS_FILE[] = __FILE__; 58 | #endif 59 | 60 | #pragma comment(linker,"\"/manifestdependency:type='win32' \ 61 | name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \ 62 | processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 63 | 64 | WinMTRMain WinMTRinst; 65 | 66 | //***************************************************************************** 67 | // BEGIN_MESSAGE_MAP 68 | // 69 | // 70 | //***************************************************************************** 71 | BEGIN_MESSAGE_MAP(WinMTRMain, CWinApp) 72 | ON_COMMAND(ID_HELP, CWinApp::OnHelp) 73 | END_MESSAGE_MAP() 74 | 75 | //***************************************************************************** 76 | // WinMTRMain::WinMTRMain 77 | // 78 | // 79 | //***************************************************************************** 80 | WinMTRMain::WinMTRMain() 81 | { 82 | 83 | } 84 | 85 | //***************************************************************************** 86 | // WinMTRMain::InitInstance 87 | // 88 | // 89 | //***************************************************************************** 90 | BOOL WinMTRMain::InitInstance() 91 | { 92 | std::locale::global(std::locale(".UTF8")); 93 | struct rt_apartment { 94 | rt_apartment() { 95 | winrt::init_apartment(winrt::apartment_type::single_threaded); 96 | } 97 | ~rt_apartment() noexcept { 98 | winrt::uninit_apartment(); 99 | } 100 | }apartment; 101 | 102 | /*if (!AfxSocketInit()) 103 | { 104 | AfxMessageBox(IDP_SOCKETS_INIT_FAILED); 105 | return FALSE; 106 | }*/ 107 | 108 | AfxEnableControlContainer(); 109 | 110 | #ifdef _AFXDLL 111 | Enable3dControls(); // Call this when using MFC in a shared DLL 112 | #endif 113 | 114 | WinMTRDialog mtrDialog; 115 | utils::CWinMTRCommandLineParser cmd_info(mtrDialog); 116 | ParseCommandLine(cmd_info); 117 | if (cmd_info.isAskingForHelp()) { 118 | WinMTRHelp mtrHelp; 119 | m_pMainWnd = &mtrHelp; 120 | mtrHelp.DoModal(); 121 | return FALSE; 122 | } 123 | 124 | m_pMainWnd = &mtrDialog; 125 | 126 | [[maybe_unused]] 127 | auto nResponse = mtrDialog.DoModal(); 128 | 129 | 130 | return FALSE; 131 | } 132 | 133 | -------------------------------------------------------------------------------- /WinMTRMain.h: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2021 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | //***************************************************************************** 22 | // FILE: WinMTRMain.h 23 | // 24 | // 25 | // DESCRIPTION: 26 | // 27 | // 28 | // NOTES: 29 | // 30 | // 31 | //***************************************************************************** 32 | 33 | #ifndef WINMTRMAIN_H_ 34 | #define WINMTRMAIN_H_ 35 | 36 | #include 37 | 38 | //***************************************************************************** 39 | // CLASS: WinMTRMain 40 | // 41 | // 42 | //***************************************************************************** 43 | 44 | class WinMTRMain final : public CWinApp 45 | { 46 | public: 47 | WinMTRMain(); 48 | 49 | virtual BOOL InitInstance() override final; 50 | 51 | DECLARE_MESSAGE_MAP() 52 | 53 | private: 54 | 55 | }; 56 | 57 | #endif // ifndef WINMTRMAIN_H_ 58 | 59 | -------------------------------------------------------------------------------- /WinMTRNet-ClassDef.ixx: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2023 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | module; 21 | #pragma warning (disable : 4005) 22 | #include "targetver.h" 23 | #define WIN32_LEAN_AND_MEAN 24 | #define VC_EXTRALEAN 25 | #define NOMCX 26 | #define NOIME 27 | #define NOGDI 28 | #define NONLS 29 | #define NOAPISET 30 | #define NOSERVICE 31 | #define NOMINMAX 32 | #include 33 | #include 34 | export module WinMTR.Net:ClassDef; 35 | 36 | import ; 37 | import ; 38 | import ; 39 | import ; 40 | import ; 41 | import ; 42 | import ; 43 | import ; 44 | import WinMTRSNetHost; 45 | import WinMTROptionsProvider; 46 | import winmtr.helper; 47 | 48 | struct trace_thread; 49 | 50 | //***************************************************************************** 51 | // CLASS: WinMTRNet 52 | // 53 | // 54 | //***************************************************************************** 55 | export class WinMTRNet final : public std::enable_shared_from_this { 56 | WinMTRNet(const WinMTRNet&) = delete; 57 | WinMTRNet& operator=(const WinMTRNet&) = delete; 58 | public: 59 | 60 | WinMTRNet(const IWinMTROptionsProvider* wp) 61 | :host(), 62 | last_remote_addr(), 63 | options(wp), 64 | wsaHelper(MAKEWORD(2, 2)), 65 | tracing() { 66 | 67 | if (!wsaHelper) [[unlikely]] { 68 | //AfxMessageBox(IDP_SOCKETS_INIT_FAILED); 69 | return; 70 | } 71 | } 72 | ~WinMTRNet() noexcept = default; 73 | 74 | 75 | [[nodiscard("The task should be awaited")]] 76 | winrt::Windows::Foundation::IAsyncAction DoTrace(std::stop_token stop_token, SOCKADDR_INET address); 77 | 78 | void ResetHops() noexcept 79 | { 80 | for (auto& h : this->host) { 81 | h = s_nethost(); 82 | } 83 | } 84 | [[nodiscard]] 85 | int GetMax() const; 86 | 87 | [[nodiscard]] 88 | std::vector getCurrentState() const; 89 | s_nethost getStateAt(int at) const 90 | { 91 | std::unique_lock lock(ghMutex); 92 | return host[at]; 93 | } 94 | 95 | static constexpr auto MAX_HOPS = 30; 96 | private: 97 | std::array host; 98 | SOCKADDR_INET last_remote_addr; 99 | mutable std::recursive_mutex ghMutex; 100 | std::optional tracer; 101 | std::optional context; 102 | const IWinMTROptionsProvider* options; 103 | winmtr::helper::WSAHelper wsaHelper; 104 | std::atomic_bool tracing; 105 | 106 | [[nodiscard]] 107 | SOCKADDR_INET GetAddr(int at) const 108 | { 109 | std::unique_lock lock(ghMutex); 110 | return host[at].addr; 111 | } 112 | winrt::fire_and_forget SetAddr(int at, SOCKADDR_INET addr); 113 | void SetName(int at, std::wstring n) 114 | { 115 | std::unique_lock lock(ghMutex); 116 | host[at].name = std::move(n); 117 | } 118 | 119 | void addNewReturn(int at, int last) 120 | { 121 | std::unique_lock lock(ghMutex); 122 | host[at].last = last; 123 | host[at].total += last; 124 | if (host[at].best > last || host[at].xmit == 1) { 125 | host[at].best = last; 126 | }; 127 | if (host[at].worst < last) { 128 | host[at].worst = last; 129 | } 130 | host[at].returned++; 131 | } 132 | void AddXmit(int at) 133 | { 134 | std::unique_lock lock(ghMutex); 135 | host[at].xmit++; 136 | } 137 | 138 | template 139 | [[nodiscard("The task should be awaited")]] 140 | winrt::Windows::Foundation::IAsyncAction handleICMP(T remote_addr, std::stop_token stop_token, trace_thread& current); 141 | }; -------------------------------------------------------------------------------- /WinMTRNet-Getters.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2023 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | module; 21 | #pragma warning (disable : 4005) 22 | #include "targetver.h" 23 | #define WIN32_LEAN_AND_MEAN 24 | #define VC_EXTRALEAN 25 | #define NOMCX 26 | #define NOIME 27 | #define NOGDI 28 | #define NONLS 29 | #define NOAPISET 30 | #define NOSERVICE 31 | #define NOMINMAX 32 | #include 33 | module WinMTR.Net:Getters; 34 | 35 | import ; 36 | import ; 37 | import ; 38 | import ; 39 | import WinMTRSNetHost; 40 | import WinMTRIPUtils; 41 | import :ClassDef; 42 | 43 | [[nodiscard]] 44 | inline bool operator==(const SOCKADDR_INET& lhs, const SOCKADDR_INET& rhs) noexcept { 45 | return std::memcmp(&lhs, &rhs, sizeof(SOCKADDR_INET)) == 0; 46 | } 47 | 48 | 49 | [[nodiscard]] 50 | std::vector WinMTRNet::getCurrentState() const 51 | { 52 | std::unique_lock lock(ghMutex); 53 | auto max = GetMax(); 54 | auto end = std::cbegin(host); 55 | std::advance(end, max); 56 | return std::vector(std::cbegin(host), end); 57 | } 58 | 59 | [[nodiscard]] 60 | int WinMTRNet::GetMax() const 61 | { 62 | std::unique_lock lock(ghMutex); 63 | int max = MAX_HOPS; 64 | 65 | // first match: traced address responds on ping requests, and the address is in the hosts list 66 | for (int i = 1; const auto & h : host) { 67 | if (h.addr == last_remote_addr) { 68 | max = i; 69 | break; 70 | } 71 | ++i; 72 | } 73 | 74 | // second match: traced address doesn't responds on ping requests 75 | if (max == MAX_HOPS) { 76 | while ((max > 1) && (host[max - 1].addr == host[max - 2].addr && isValidAddress(host[max - 1].addr))) max--; 77 | } 78 | return max; 79 | } -------------------------------------------------------------------------------- /WinMTRNet-Tracing.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2023 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | module; 21 | #pragma warning (disable : 4005) 22 | #include "targetver.h" 23 | #define WIN32_LEAN_AND_MEAN 24 | #define VC_EXTRALEAN 25 | #define NOMCX 26 | #define NOIME 27 | #define NOGDI 28 | #define NONLS 29 | #define NOAPISET 30 | #define NOSERVICE 31 | #define NOMINMAX 32 | #include 33 | #include 34 | #include 35 | module WinMTR.Net:Tracing; 36 | 37 | 38 | #ifdef DEBUG 39 | import ; 40 | #define TRACE_MSG(msg) \ 41 | { \ 42 | std::wostringstream dbg_msg(std::wostringstream::out); \ 43 | dbg_msg << msg << std::endl; \ 44 | OutputDebugStringW(dbg_msg.str().c_str()); \ 45 | } 46 | #else 47 | #define TRACE_MSG(msg) 48 | #endif 49 | 50 | import ; 51 | import ; 52 | import ; 53 | import ; 54 | import "WinMTRICMPPIOdef.h"; 55 | import WinMTRIPUtils; 56 | import WinMTRICMPUtils; 57 | import :ClassDef; 58 | 59 | struct ICMPHandleTraits 60 | { 61 | using type = HANDLE; 62 | 63 | static void close(type value) noexcept 64 | { 65 | WINRT_VERIFY_(TRUE, ::IcmpCloseHandle(value)); 66 | } 67 | 68 | [[nodiscard]] 69 | static type invalid() noexcept 70 | { 71 | return INVALID_HANDLE_VALUE; 72 | } 73 | }; 74 | 75 | using IcmpHandle = winrt::handle_type; 76 | 77 | struct trace_thread final { 78 | trace_thread(const trace_thread&) = delete; 79 | trace_thread& operator=(const trace_thread&) = delete; 80 | trace_thread(trace_thread&&) = default; 81 | trace_thread& operator=(trace_thread&&) = default; 82 | 83 | trace_thread(ADDRESS_FAMILY af, UCHAR ttl) noexcept 84 | :ttl(ttl) 85 | { 86 | if (af == AF_INET) { 87 | icmpHandle.attach(IcmpCreateFile()); 88 | } 89 | else if (af == AF_INET6) { 90 | icmpHandle.attach(Icmp6CreateFile()); 91 | } 92 | } 93 | IcmpHandle icmpHandle; 94 | UCHAR ttl; 95 | }; 96 | 97 | [[nodiscard("The task should be awaited")]] 98 | winrt::Windows::Foundation::IAsyncAction WinMTRNet::DoTrace(std::stop_token stop_token, SOCKADDR_INET address) 99 | { 100 | tracing = true; 101 | ResetHops(); 102 | last_remote_addr = address; 103 | 104 | auto threadMaker = [&address, this, stop_token](UCHAR i) { 105 | trace_thread current{ address.si_family, static_cast(i + 1) }; 106 | using namespace std::string_view_literals; 107 | TRACE_MSG(L"Thread with TTL="sv << current.ttl << L" started."sv); 108 | if (address.si_family == AF_INET) { 109 | return this->handleICMP(address.Ipv4, stop_token, current); 110 | } 111 | else if (address.si_family == AF_INET6) { 112 | return this->handleICMP(address.Ipv6, stop_token, current); 113 | } 114 | winrt::throw_hresult(HRESULT_FROM_WIN32(WSAEOPNOTSUPP)); 115 | }; 116 | 117 | std::stop_callback callback{ stop_token, [this]() noexcept { 118 | this->tracing = false; 119 | TRACE_MSG(L"Cancellation"); 120 | } }; 121 | //// one thread per TTL value 122 | co_await std::invoke([](std::integer_sequence, auto threadMaker) { 123 | return winrt::when_all(std::invoke(threadMaker, threads)...); 124 | }, std::make_integer_sequence{}, threadMaker); 125 | TRACE_MSG(L"Tracing Ended"); 126 | } 127 | 128 | template 129 | requires std::is_same_v || std::is_same_v 130 | constexpr SOCKADDR_INET to_sockaddr_inet(T addr) noexcept { 131 | if constexpr (std::is_same_v) { 132 | return { .Ipv4 = addr }; 133 | } 134 | else { 135 | return { .Ipv6 = addr }; 136 | } 137 | } 138 | 139 | template 140 | [[nodiscard("The task should be awaited")]] 141 | winrt::Windows::Foundation::IAsyncAction WinMTRNet::handleICMP(T remote_addr, std::stop_token stop_token, trace_thread& current) { 142 | using namespace std::literals; 143 | using traits = icmp_ping_traits; 144 | trace_thread mine = std::move(current); 145 | T local_addr = remote_addr; 146 | co_await winrt::resume_background(); 147 | using namespace std::string_view_literals; 148 | const auto nDataLen = this->options->getPingSize(); 149 | std::vector achReqData{ nDataLen, static_cast(32) }; //whitespaces 150 | std::vector achRepData{ reply_reply_buffer_size(nDataLen) }; 151 | winrt::handle wait_handle{ CreateEventW(nullptr, FALSE, FALSE, nullptr) }; 152 | 153 | T* addr = reinterpret_cast(&local_addr); 154 | while (this->tracing) { 155 | 156 | // this is a backup for if the atomic above doesn't work 157 | if (stop_token.stop_requested()) [[unlikely]] 158 | { 159 | this->tracing = false; 160 | co_return; 161 | } 162 | // For some strange reason, ICMP API is not filling the TTL for icmp echo reply 163 | // Check if the current thread should be closed 164 | if (mine.ttl > this->GetMax()) break; 165 | 166 | // NOTE: some servers does not respond back everytime, if TTL expires in transit; e.g. : 167 | // ping -n 20 -w 5000 -l 64 -i 7 www.chinapost.com.tw -> less that half of the replies are coming back from 219.80.240.93 168 | // but if we are pinging ping -n 20 -w 5000 -l 64 219.80.240.93 we have 0% loss 169 | // A resolution would be: 170 | // - as soon as we get a hop, we start pinging directly that hop, with a greater TTL 171 | // - a drawback would be that, some servers are configured to reply for TTL transit expire, but not to ping requests, so, 172 | // for these servers we'll have 100% loss 173 | const auto dwReplyCount = co_await IcmpSendEchoAsync(mine.icmpHandle.get(), wait_handle.get(), addr, mine.ttl, achReqData, achRepData); 174 | this->AddXmit(mine.ttl - 1); 175 | if (dwReplyCount) { 176 | auto icmp_echo_reply = reinterpret_cast(achRepData.data()); 177 | TRACE_MSG(L"TTL "sv << mine.ttl << L" Status "sv << icmp_echo_reply->Status << L" Reply count "sv << dwReplyCount); 178 | 179 | switch (icmp_echo_reply->Status) { 180 | case IP_SUCCESS: 181 | [[likely]] case IP_TTL_EXPIRED_TRANSIT: 182 | this->addNewReturn(mine.ttl - 1, icmp_echo_reply->RoundTripTime); 183 | { 184 | auto naddr = traits::to_addr_from_ping(icmp_echo_reply); 185 | this->SetAddr(mine.ttl - 1, to_sockaddr_inet(naddr)); 186 | } 187 | break; 188 | case IP_BUF_TOO_SMALL: 189 | this->SetName(current.ttl - 1, L"Reply buffer too small."s); 190 | break; 191 | case IP_DEST_NET_UNREACHABLE: 192 | this->SetName(current.ttl - 1, L"Destination network unreachable."s); 193 | break; 194 | case IP_DEST_HOST_UNREACHABLE: 195 | this->SetName(current.ttl - 1, L"Destination host unreachable."s); 196 | break; 197 | case IP_DEST_PROT_UNREACHABLE: 198 | this->SetName(current.ttl - 1, L"Destination protocol unreachable."s); 199 | break; 200 | case IP_DEST_PORT_UNREACHABLE: 201 | this->SetName(current.ttl - 1, L"Destination port unreachable."s); 202 | break; 203 | case IP_NO_RESOURCES: 204 | this->SetName(current.ttl - 1, L"Insufficient IP resources were available."s); 205 | break; 206 | case IP_BAD_OPTION: 207 | this->SetName(current.ttl - 1, L"Bad IP option was specified."s); 208 | break; 209 | case IP_HW_ERROR: 210 | this->SetName(current.ttl - 1, L"Hardware error occurred."s); 211 | break; 212 | case IP_PACKET_TOO_BIG: 213 | this->SetName(current.ttl - 1, L"Packet was too big."s); 214 | break; 215 | case IP_REQ_TIMED_OUT: 216 | this->SetName(current.ttl - 1, L"Request timed out."s); 217 | break; 218 | case IP_BAD_REQ: 219 | this->SetName(current.ttl - 1, L"Bad request."s); 220 | break; 221 | case IP_BAD_ROUTE: 222 | this->SetName(current.ttl - 1, L"Bad route."s); 223 | break; 224 | case IP_TTL_EXPIRED_REASSEM: 225 | this->SetName(current.ttl - 1, L"The time to live expired during fragment reassembly."s); 226 | break; 227 | case IP_PARAM_PROBLEM: 228 | this->SetName(current.ttl - 1, L"Parameter problem."s); 229 | break; 230 | case IP_SOURCE_QUENCH: 231 | this->SetName(current.ttl - 1, L"Datagrams are arriving too fast to be processed and datagrams may have been discarded."s); 232 | break; 233 | case IP_OPTION_TOO_BIG: 234 | this->SetName(current.ttl - 1, L"An IP option was too big."s); 235 | break; 236 | case IP_BAD_DESTINATION: 237 | this->SetName(current.ttl - 1, L"Bad destination."s); 238 | break; 239 | case IP_GENERAL_FAILURE: 240 | default: 241 | this->SetName(current.ttl - 1, L"General failure."s); 242 | break; 243 | } 244 | const auto intervalInSec = this->options->getInterval() * 1s; 245 | const auto roundTripDuration = std::chrono::milliseconds(icmp_echo_reply->RoundTripTime); 246 | if (intervalInSec > roundTripDuration) { 247 | using namespace winrt; 248 | const auto sleepTime = intervalInSec - roundTripDuration; 249 | co_await std::chrono::duration_cast(sleepTime); 250 | } 251 | } 252 | 253 | } /* end ping loop */ 254 | co_return; 255 | } 256 | 257 | winrt::fire_and_forget WinMTRNet::SetAddr(int at, SOCKADDR_INET addr) 258 | { 259 | { 260 | std::unique_lock lock(ghMutex); 261 | if (isValidAddress(host[at].addr) || !isValidAddress(addr)) { 262 | co_return; 263 | } 264 | host[at].addr = addr; 265 | //TRACE_MSG(L"Start DnsResolverThread for new address " << addr << L". Old addr value was " << host[at].addr); 266 | } 267 | if (!options->getUseDNS()) { 268 | co_return; 269 | } 270 | auto local_at = at; 271 | // this could happen after a cleanup is called, so keep this alive until the coroutine returns 272 | auto sharedThis = shared_from_this(); 273 | co_await winrt::resume_background(); 274 | wchar_t buf[NI_MAXHOST] = {}; 275 | auto tempaddr = sharedThis->GetAddr(local_at); 276 | 277 | if (const auto nresult = GetNameInfoW( 278 | reinterpret_cast(&tempaddr) 279 | , static_cast(getAddressSize(tempaddr)) 280 | , buf 281 | , static_cast(std::size(buf)) 282 | , nullptr 283 | , 0 284 | , 0); 285 | // zero on success 286 | !nresult) { 287 | sharedThis->SetName(local_at, buf); 288 | } 289 | else { 290 | sharedThis->SetName(local_at, addr_to_string(tempaddr)); 291 | } 292 | 293 | TRACE_MSG(L"DNS resolver thread stopped."); 294 | } 295 | -------------------------------------------------------------------------------- /WinMTRNet.ixx: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2021 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | 22 | //***************************************************************************** 23 | // FILE: WinMTRNet.cpp 24 | // 25 | //***************************************************************************** 26 | export module WinMTR.Net; 27 | 28 | export import :ClassDef; 29 | 30 | module : private; 31 | 32 | import :Getters; 33 | import :Tracing; 34 | -------------------------------------------------------------------------------- /WinMTROptions.ixx: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2021 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | //***************************************************************************** 22 | // FILE: WinMTROptions.cpp 23 | // 24 | // 25 | //***************************************************************************** 26 | 27 | module; 28 | #pragma warning (disable : 4005) 29 | #include "targetver.h" 30 | #define WIN32_LEAN_AND_MEAN 31 | #define VC_EXTRALEAN 32 | #define NOMINMAX 33 | #include 34 | #include "resource.h" 35 | export module WinMTR.Options; 36 | 37 | //***************************************************************************** 38 | // CLASS: WinMTROptions 39 | // 40 | // 41 | //***************************************************************************** 42 | export class WinMTROptions final : public CDialog 43 | { 44 | public: 45 | WinMTROptions(CWnd* pParent = nullptr); 46 | 47 | inline void SetUseDNS(bool udns) noexcept { useDNS = udns; }; 48 | inline void SetInterval(double i) noexcept { interval = i; }; 49 | inline void SetPingSize(int ps) noexcept { pingsize = ps; }; 50 | inline void SetMaxLRU(int mlru) noexcept { maxLRU = mlru; }; 51 | inline void SetUseIPv4(bool uip4) noexcept { useIPv4 = uip4; } 52 | inline void SetUseIPv6(bool uip6) noexcept { useIPv6 = uip6; } 53 | 54 | inline auto GetInterval() const noexcept { return interval; }; 55 | inline auto GetPingSize() const noexcept { return pingsize; }; 56 | inline auto GetMaxLRU() const noexcept { return maxLRU; }; 57 | inline auto GetUseDNS() const noexcept { return useDNS; } 58 | inline auto GetUseIPv4() const noexcept { return useIPv4; } 59 | inline auto GetUseIPv6() const noexcept { return useIPv6; } 60 | 61 | enum { IDD = IDD_DIALOG_OPTIONS }; 62 | CEdit m_editSize; 63 | CEdit m_editInterval; 64 | CEdit m_editMaxLRU; 65 | CButton m_checkDNS; 66 | CButton m_useIPv4; 67 | CButton m_useIPv6; 68 | 69 | protected: 70 | void DoDataExchange(CDataExchange* pDX) override; 71 | 72 | BOOL OnInitDialog() override; 73 | void OnOK() override; 74 | 75 | afx_msg void OnLicense(); 76 | DECLARE_MESSAGE_MAP() 77 | 78 | private: 79 | double interval = 0.0; 80 | unsigned pingsize = 0; 81 | unsigned maxLRU = 0; 82 | bool useDNS = false; 83 | bool useIPv4 = true; 84 | bool useIPv6 = true; 85 | 86 | public: 87 | afx_msg void OnBnClickedIpv4Check(); 88 | afx_msg void OnBnClickedUseipv6Check(); 89 | }; 90 | 91 | module : private; 92 | 93 | #ifdef _DEBUG 94 | #define new DEBUG_NEW 95 | #undef THIS_FILE 96 | static char THIS_FILE[] = __FILE__; 97 | #endif 98 | 99 | import ; 100 | import ; 101 | import WinMTRUtils; 102 | 103 | import WinMTR.License; 104 | 105 | //***************************************************************************** 106 | // BEGIN_MESSAGE_MAP 107 | // 108 | // 109 | //***************************************************************************** 110 | BEGIN_MESSAGE_MAP(WinMTROptions, CDialog) 111 | ON_BN_CLICKED(ID_LICENSE, OnLicense) 112 | ON_BN_CLICKED(IDC_IPV4_CHECK, &WinMTROptions::OnBnClickedIpv4Check) 113 | ON_BN_CLICKED(IDC_USEIPV6_CHECK, &WinMTROptions::OnBnClickedUseipv6Check) 114 | END_MESSAGE_MAP() 115 | 116 | 117 | //***************************************************************************** 118 | // WinMTROptions::WinMTROptions 119 | // 120 | // 121 | //***************************************************************************** 122 | WinMTROptions::WinMTROptions(CWnd* pParent) : CDialog(WinMTROptions::IDD, pParent) 123 | { 124 | } 125 | 126 | 127 | //***************************************************************************** 128 | // WinMTROptions::DoDataExchange 129 | // 130 | // 131 | //***************************************************************************** 132 | void WinMTROptions::DoDataExchange(CDataExchange* pDX) 133 | { 134 | CDialog::DoDataExchange(pDX); 135 | DDX_Control(pDX, IDC_EDIT_SIZE, m_editSize); 136 | DDV_MinMaxUInt(pDX, pingsize, WinMTRUtils::MIN_PING_SIZE, WinMTRUtils::MAX_PING_SIZE); 137 | DDX_Control(pDX, IDC_EDIT_INTERVAL, m_editInterval); 138 | DDV_MinMaxDouble(pDX, interval, WinMTRUtils::MIN_INTERVAL, WinMTRUtils::MAX_INTERVAL); 139 | DDX_Control(pDX, IDC_EDIT_MAX_LRU, m_editMaxLRU); 140 | DDV_MinMaxUInt(pDX, maxLRU, WinMTRUtils::MIN_MAX_LRU, WinMTRUtils::MAX_MAX_LRU); 141 | DDX_Control(pDX, IDC_CHECK_DNS, m_checkDNS); 142 | DDX_Control(pDX, IDC_USEIPV6_CHECK, m_useIPv6); 143 | DDX_Control(pDX, IDC_IPV4_CHECK, m_useIPv4); 144 | } 145 | 146 | 147 | //***************************************************************************** 148 | // WinMTROptions::OnInitDialog 149 | // 150 | // 151 | //***************************************************************************** 152 | BOOL WinMTROptions::OnInitDialog() 153 | { 154 | CDialog::OnInitDialog(); 155 | 156 | wchar_t strtmp[20] = {}; 157 | constexpr auto writable_size = std::size(strtmp) - 1; 158 | 159 | auto result = std::format_to_n(std::begin(strtmp), writable_size, WinMTRUtils::float_number_format, interval); 160 | *result.out = '\0'; 161 | m_editInterval.SetWindowText(strtmp); 162 | 163 | result = std::format_to_n(std::begin(strtmp), writable_size, WinMTRUtils::int_number_format, pingsize); 164 | *result.out = '\0'; 165 | m_editSize.SetWindowText(strtmp); 166 | 167 | result = std::format_to_n(std::begin(strtmp), writable_size, WinMTRUtils::int_number_format, maxLRU); 168 | *result.out = '\0'; 169 | m_editMaxLRU.SetWindowText(strtmp); 170 | 171 | m_checkDNS.SetCheck(useDNS); 172 | m_useIPv4.SetCheck(useIPv4); 173 | m_useIPv6.SetCheck(useIPv6); 174 | 175 | m_editInterval.SetFocus(); 176 | return FALSE; 177 | } 178 | 179 | 180 | //***************************************************************************** 181 | // WinMTROptions::OnOK 182 | // 183 | // 184 | //***************************************************************************** 185 | void WinMTROptions::OnOK() 186 | { 187 | wchar_t tmpstr[20]; 188 | 189 | useDNS = m_checkDNS.GetCheck(); 190 | 191 | m_editInterval.GetWindowText(tmpstr, 20); 192 | wchar_t* end = nullptr; 193 | interval = wcstod(tmpstr, &end); 194 | 195 | m_editSize.GetWindowText(tmpstr, 20); 196 | end = nullptr; 197 | pingsize = wcstoul(tmpstr, &end, 10); 198 | 199 | m_editMaxLRU.GetWindowText(tmpstr, 20); 200 | end = nullptr; 201 | maxLRU = wcstoul(tmpstr, &end, 10); 202 | 203 | useIPv4 = m_useIPv4.GetCheck(); 204 | useIPv6 = m_useIPv6.GetCheck(); 205 | 206 | CDialog::OnOK(); 207 | } 208 | 209 | //***************************************************************************** 210 | // WinMTROptions::OnLicense 211 | // 212 | // 213 | //***************************************************************************** 214 | void WinMTROptions::OnLicense() 215 | { 216 | WinMTRLicense mtrlicense; 217 | mtrlicense.DoModal(); 218 | } 219 | 220 | 221 | 222 | void WinMTROptions::OnBnClickedIpv4Check() 223 | { 224 | 225 | if (!m_useIPv4.GetCheck()) { 226 | m_useIPv6.SetCheck(true); 227 | } 228 | } 229 | 230 | 231 | void WinMTROptions::OnBnClickedUseipv6Check() 232 | { 233 | 234 | if (!m_useIPv6.GetCheck()) { 235 | m_useIPv4.SetCheck(true); 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /WinMTRProperties.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2021 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | 22 | //***************************************************************************** 23 | // FILE: WinMTRProperties.cpp 24 | // 25 | // 26 | //***************************************************************************** 27 | 28 | #include "WinMTRGlobal.h" 29 | #include "WinMTRProperties.h" 30 | import ; 31 | import WinMTRUtils; 32 | 33 | #include "resource.h" 34 | 35 | #ifdef _DEBUG 36 | #define new DEBUG_NEW 37 | #undef THIS_FILE 38 | static char THIS_FILE[] = __FILE__; 39 | #endif 40 | 41 | 42 | //***************************************************************************** 43 | // BEGIN_MESSAGE_MAP 44 | // 45 | // 46 | //***************************************************************************** 47 | BEGIN_MESSAGE_MAP(WinMTRProperties, CDialog) 48 | END_MESSAGE_MAP() 49 | 50 | 51 | //***************************************************************************** 52 | // WinMTRProperties::WinMTRProperties 53 | // 54 | // 55 | //***************************************************************************** 56 | WinMTRProperties::WinMTRProperties(CWnd* pParent) noexcept : CDialog(WinMTRProperties::IDD, pParent) 57 | ,ping_last() 58 | ,ping_best() 59 | ,ping_avrg() 60 | ,ping_worst() 61 | ,pck_sent() 62 | ,pck_recv() 63 | ,pck_loss() 64 | { 65 | } 66 | 67 | 68 | //***************************************************************************** 69 | // WinMTRroperties::DoDataExchange 70 | // 71 | // 72 | //***************************************************************************** 73 | void WinMTRProperties::DoDataExchange(CDataExchange* pDX) 74 | { 75 | CDialog::DoDataExchange(pDX); 76 | DDX_Control(pDX, IDC_EDIT_PHOST, m_editHost); 77 | DDX_Control(pDX, IDC_EDIT_PIP, m_editIP); 78 | DDX_Control(pDX, IDC_EDIT_PCOMMENT, m_editComment); 79 | 80 | DDX_Control(pDX, IDC_EDIT_PLOSS, m_editLoss); 81 | DDX_Control(pDX, IDC_EDIT_PSENT, m_editSent); 82 | DDX_Control(pDX, IDC_EDIT_PRECV, m_editRecv); 83 | 84 | DDX_Control(pDX, IDC_EDIT_PLAST, m_editLast); 85 | DDX_Control(pDX, IDC_EDIT_PBEST, m_editBest); 86 | DDX_Control(pDX, IDC_EDIT_PWORST, m_editWorst); 87 | DDX_Control(pDX, IDC_EDIT_PAVRG, m_editAvrg); 88 | } 89 | 90 | 91 | //***************************************************************************** 92 | // WinMTRProperties::OnInitDialog 93 | // 94 | // 95 | //***************************************************************************** 96 | BOOL WinMTRProperties::OnInitDialog() 97 | { 98 | CDialog::OnInitDialog(); 99 | wchar_t buf[255] = {}; 100 | 101 | m_editIP.SetWindowText(ip.c_str()); 102 | m_editHost.SetWindowText(host.c_str()); 103 | m_editComment.SetWindowText(comment.c_str()); 104 | constexpr auto writable_size = std::size(buf) - 1; 105 | auto result = std::format_to_n(buf, writable_size, WinMTRUtils::int_number_format, pck_loss); 106 | *result.out = '\0'; 107 | m_editLoss.SetWindowText(buf); 108 | result = std::format_to_n(buf, writable_size, WinMTRUtils::int_number_format, pck_sent); 109 | *result.out = '\0'; 110 | m_editSent.SetWindowText(buf); 111 | result = std::format_to_n(buf, writable_size, WinMTRUtils::int_number_format, pck_recv); 112 | *result.out = '\0'; 113 | m_editRecv.SetWindowText(buf); 114 | 115 | result = std::format_to_n(buf, writable_size, WinMTRUtils::float_number_format, ping_last); 116 | *result.out = '\0'; 117 | m_editLast.SetWindowText(buf); 118 | result = std::format_to_n(buf, writable_size, WinMTRUtils::float_number_format, ping_best); 119 | *result.out = '\0'; 120 | m_editBest.SetWindowText(buf); 121 | result = std::format_to_n(buf, writable_size, WinMTRUtils::float_number_format, ping_worst); 122 | *result.out = '\0'; 123 | m_editWorst.SetWindowText(buf); 124 | result = std::format_to_n(buf, writable_size, WinMTRUtils::float_number_format, ping_avrg); 125 | *result.out = '\0'; 126 | m_editAvrg.SetWindowText(buf); 127 | 128 | return FALSE; 129 | } 130 | 131 | -------------------------------------------------------------------------------- /WinMTRProperties.h: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2021 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | 22 | //***************************************************************************** 23 | // FILE: WinMTRProperties.h 24 | // 25 | // 26 | // DESCRIPTION: 27 | // 28 | // 29 | // NOTES: 30 | // 31 | // 32 | //***************************************************************************** 33 | 34 | #ifndef WINMTRPROPERTIES_H_ 35 | #define WINMTRPROPERTIES_H_ 36 | #pragma warning (disable : 4005) 37 | import ; 38 | 39 | #include "resource.h" 40 | 41 | //***************************************************************************** 42 | // CLASS: WinMTRLicense 43 | // 44 | // 45 | //***************************************************************************** 46 | 47 | class WinMTRProperties : public CDialog 48 | { 49 | public: 50 | WinMTRProperties(CWnd* pParent = NULL) noexcept; 51 | 52 | 53 | enum { IDD = IDD_DIALOG_PROPERTIES }; 54 | 55 | std::wstring host; 56 | std::wstring ip; 57 | std::wstring comment; 58 | 59 | float ping_last; 60 | float ping_best; 61 | float ping_avrg; 62 | float ping_worst; 63 | 64 | int pck_sent; 65 | int pck_recv; 66 | int pck_loss; 67 | 68 | CEdit m_editHost, 69 | m_editIP, 70 | m_editComment, 71 | m_editSent, 72 | m_editRecv, 73 | m_editLoss, 74 | m_editLast, 75 | m_editBest, 76 | m_editWorst, 77 | m_editAvrg; 78 | 79 | protected: 80 | virtual void DoDataExchange(CDataExchange* pDX); 81 | 82 | virtual BOOL OnInitDialog(); 83 | 84 | DECLARE_MESSAGE_MAP() 85 | }; 86 | 87 | #endif // ifndef WINMTRLICENSE_H_ 88 | -------------------------------------------------------------------------------- /WinMTRSNetHost.ixx: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2022 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | module; 22 | #pragma warning (disable : 4005) 23 | #include "targetver.h" 24 | #define WIN32_LEAN_AND_MEAN 25 | #define VC_EXTRALEAN 26 | #define NOMCX 27 | #define NOIME 28 | #define NOGDI 29 | #define NONLS 30 | #define NOAPISET 31 | #define NOSERVICE 32 | #define NOMINMAX 33 | #include 34 | #include 35 | export module WinMTRSNetHost; 36 | 37 | import WinMTRIPUtils; 38 | import ; 39 | 40 | 41 | export struct s_nethost final { 42 | SOCKADDR_INET addr = {}; 43 | std::wstring name; 44 | int xmit = 0; // number of PING packets sent 45 | int returned = 0; // number of ICMP echo replies received 46 | unsigned long total = 0; // total time 47 | int last = 0; // last time 48 | int best = 0; // best time 49 | int worst = 0; // worst time 50 | [[nodiscard]] 51 | inline auto getPercent() const noexcept { 52 | return (xmit == 0) ? 0 : (100 - (100 * returned / xmit)); 53 | } 54 | [[nodiscard]] 55 | inline int getAvg() const noexcept { 56 | return returned == 0 ? 0 : total / returned; 57 | } 58 | [[nodiscard]] 59 | auto getName() const -> std::wstring { 60 | if (name.empty()) { 61 | return addr_to_string(addr); 62 | } 63 | return name; 64 | } 65 | }; 66 | -------------------------------------------------------------------------------- /WinMTRStatusBar.ixx: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2021 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | //#ifndef WINMTRSTATUSBAR_H_ 22 | //#define WINMTRSTATUSBAR_H_ 23 | module; 24 | #pragma warning (disable : 4005) 25 | #include "targetver.h" 26 | #include 27 | export module WinMTRStatusBar; 28 | import ; 29 | import ; 30 | 31 | export class WinMTRStatusBar final : public CStatusBar 32 | { 33 | // Construction 34 | public: 35 | 36 | // Attributes 37 | public: 38 | 39 | // Operations 40 | public: 41 | 42 | int GetPanesCount() const noexcept{ 43 | return m_nCount; 44 | } 45 | 46 | void SetPaneWidth(int nIndex, int nWidth) 47 | { 48 | _STATUSBAR_PANE_ pane; 49 | PaneInfoGet(nIndex, &pane); 50 | pane.cxText = nWidth; 51 | PaneInfoSet(nIndex, pane); 52 | } 53 | 54 | BOOL AddPane( 55 | UINT nID, // ID of the pane 56 | int nIndex // index of the pane 57 | ); 58 | 59 | BOOL RemovePane( 60 | UINT nID // ID of the pane 61 | ); 62 | 63 | BOOL AddPaneControl(CWnd* pWnd, UINT nID, BOOL bAutoDestroy) 64 | { 65 | return AddPaneControl( pWnd->GetSafeHwnd(), nID, bAutoDestroy); 66 | } 67 | 68 | BOOL AddPaneControl(HWND hWnd, UINT nID, BOOL bAutoDestroy); 69 | 70 | void DisableControl( int nIndex, BOOL bDisable=TRUE) noexcept 71 | { 72 | const UINT uItemID = GetItemID(nIndex); 73 | for (const auto & cntl : m_arrPaneControls){ 74 | if( uItemID == cntl.nID ){ 75 | if(cntl.hWnd && ::IsWindow(cntl.hWnd) ) { 76 | ::EnableWindow(cntl.hWnd, bDisable); 77 | } 78 | } 79 | } 80 | } 81 | 82 | void SetPaneInfo(int nIndex, UINT nID, UINT nStyle, int cxWidth) noexcept 83 | { 84 | CStatusBar::SetPaneInfo(nIndex, nID, nStyle, cxWidth); 85 | BOOL bDisabled = ((nStyle&SBPS_DISABLED) == 0); 86 | DisableControl(nIndex, bDisabled); 87 | } 88 | 89 | void SetPaneStyle(int nIndex, UINT nStyle) noexcept 90 | { 91 | CStatusBar::SetPaneStyle(nIndex, nStyle); 92 | BOOL bDisabled = ((nStyle&SBPS_DISABLED) == 0); 93 | DisableControl(nIndex, bDisabled); 94 | } 95 | 96 | BOOL SetIndicators(std::span indicators) noexcept { 97 | return CStatusBar::SetIndicators(indicators.data(), static_cast(indicators.size())); 98 | } 99 | // Overrides 100 | // ClassWizard generated virtual function overrides 101 | //{{AFX_VIRTUAL(WinMTRStatusBar) 102 | //}}AFX_VIRTUAL 103 | 104 | // Implementation 105 | public: 106 | virtual ~WinMTRStatusBar() = default; 107 | 108 | protected: 109 | 110 | struct _STATUSBAR_PANE_ 111 | { 112 | _STATUSBAR_PANE_() noexcept{ 113 | nID = cxText = nStyle = nFlags = 0; 114 | } 115 | 116 | UINT nID; // IDC of indicator: 0 => normal text area 117 | int cxText; // width of string area in pixels 118 | // on both sides there is a 3 pixel gap and 119 | // a one pixel border, making a pane 6 pixels wider 120 | UINT nStyle; // style flags (SBPS_*) 121 | UINT nFlags; // state flags (SBPF_*) 122 | CString strText; // text in the pane 123 | }; 124 | 125 | struct _STATUSBAR_PANE_CTRL_ 126 | { 127 | HWND hWnd; 128 | UINT nID; 129 | bool bAutoDestroy; 130 | _STATUSBAR_PANE_CTRL_(HWND hWnd, UINT nID, bool bAutoDestroy) noexcept 131 | :hWnd(hWnd),nID(nID),bAutoDestroy(bAutoDestroy){} 132 | _STATUSBAR_PANE_CTRL_() noexcept 133 | :_STATUSBAR_PANE_CTRL_(nullptr, 0, false){} 134 | _STATUSBAR_PANE_CTRL_(const _STATUSBAR_PANE_CTRL_&) = delete; 135 | ~_STATUSBAR_PANE_CTRL_() noexcept; 136 | _STATUSBAR_PANE_CTRL_(_STATUSBAR_PANE_CTRL_&&) noexcept = default; 137 | _STATUSBAR_PANE_CTRL_& operator=(_STATUSBAR_PANE_CTRL_&&) noexcept = default; 138 | }; 139 | 140 | std::vector<_STATUSBAR_PANE_CTRL_> m_arrPaneControls; 141 | 142 | _STATUSBAR_PANE_* GetPanePtr(int nIndex) const noexcept 143 | { 144 | ASSERT((nIndex >= 0 && nIndex < m_nCount) || m_nCount == 0); 145 | return static_cast<_STATUSBAR_PANE_*>(m_pData) + nIndex; 146 | } 147 | 148 | bool PaneInfoGet(int nIndex, _STATUSBAR_PANE_* pPane) const noexcept; 149 | bool PaneInfoSet(int nIndex, const _STATUSBAR_PANE_& pPane) noexcept; 150 | 151 | void RepositionControls() noexcept; 152 | 153 | // Generated message map functions 154 | protected: 155 | //{{AFX_MSG(WinMTRStatusBar) 156 | afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct) noexcept; 157 | //}}AFX_MSG 158 | DECLARE_MESSAGE_MAP() 159 | LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam) noexcept final override; 160 | }; 161 | 162 | module : private; 163 | 164 | #ifdef _DEBUG 165 | #define new DEBUG_NEW 166 | #undef THIS_FILE 167 | static char THIS_FILE[] = __FILE__; 168 | #endif 169 | 170 | 171 | namespace { 172 | class deferWindowPos { 173 | HDWP m_hdwp; 174 | public: 175 | deferWindowPos(int nNumWindows) noexcept 176 | :m_hdwp(::BeginDeferWindowPos(nNumWindows)) { 177 | } 178 | 179 | ~deferWindowPos() noexcept 180 | { 181 | if (*this) { 182 | VERIFY(EndDeferWindowPos(m_hdwp)); 183 | } 184 | } 185 | 186 | /// 187 | /// Indicates if we can defer windows or not, if any of the methods returned nullptr 188 | /// then the operation should be aborted and no further methods called. 189 | /// 190 | explicit operator bool() const noexcept { 191 | return m_hdwp != nullptr; 192 | } 193 | 194 | void defer(_In_ HWND hWnd, 195 | _In_opt_ HWND hWndInsertAfter, 196 | _In_ int x, 197 | _In_ int y, 198 | _In_ int cx, 199 | _In_ int cy, 200 | _In_ UINT uFlags) noexcept { 201 | if (*this) { 202 | m_hdwp = DeferWindowPos(m_hdwp, hWnd, hWndInsertAfter, x, y, cx, cy, uFlags); 203 | } 204 | } 205 | }; 206 | } 207 | 208 | 209 | BEGIN_MESSAGE_MAP(WinMTRStatusBar, CStatusBar) 210 | //{{AFX_MSG_MAP(WinMTRStatusBar) 211 | ON_WM_CREATE() 212 | //}}AFX_MSG_MAP 213 | END_MESSAGE_MAP() 214 | 215 | 216 | ///////////////////////////////////////////////////////////////////////////// 217 | // WinMTRStatusBar message handlers 218 | ////////////////////////////////////////////////////////////////////////// 219 | 220 | int WinMTRStatusBar::OnCreate(LPCREATESTRUCT lpCreateStruct) noexcept 221 | { 222 | if (CStatusBar::OnCreate(lpCreateStruct) == -1) 223 | return -1; 224 | 225 | return 0; 226 | } 227 | 228 | ////////////////////////////////////////////////////////////////////////// 229 | 230 | LRESULT WinMTRStatusBar::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) noexcept 231 | { 232 | LRESULT lResult = CStatusBar::WindowProc(message, wParam, lParam); 233 | if (message == WM_SIZE) { 234 | RepositionControls(); 235 | } 236 | return lResult; 237 | } 238 | 239 | ////////////////////////////////////////////////////////////////////////// 240 | 241 | void WinMTRStatusBar::RepositionControls() noexcept 242 | { 243 | deferWindowPos dwp(static_cast(m_arrPaneControls.size())); 244 | 245 | CRect rcClient; 246 | GetClientRect(&rcClient); 247 | for (const auto& cntl : m_arrPaneControls) 248 | { 249 | int iIndex = CommandToIndex(cntl.nID); 250 | HWND hWnd = cntl.hWnd; 251 | const auto dpi = GetDpiForWindow(hWnd); 252 | CRect rcPane; 253 | GetItemRect(iIndex, &rcPane); 254 | 255 | // CStatusBar::GetItemRect() sometimes returns invalid size 256 | // of the last pane - we will re-compute it 257 | int cx = ::GetSystemMetricsForDpi(SM_CXEDGE, dpi); 258 | DWORD dwPaneStyle = GetPaneStyle(iIndex); 259 | if (iIndex == (m_nCount - 1)) 260 | { 261 | if ((dwPaneStyle & SBPS_STRETCH) == 0) 262 | { 263 | UINT nID, nStyle; 264 | int cxWidth; 265 | GetPaneInfo(iIndex, nID, nStyle, cxWidth); 266 | rcPane.right = rcPane.left + cxWidth + cx * 3; 267 | } // if( (dwPaneStyle & SBPS_STRETCH ) == 0 ) 268 | else 269 | { 270 | CRect rcClient; 271 | GetClientRect(&rcClient); 272 | rcPane.right = rcClient.right; 273 | if ((GetStyle() & SBARS_SIZEGRIP) == SBARS_SIZEGRIP) 274 | { 275 | int cxSmIcon = ::GetSystemMetricsForDpi(SM_CXSMICON, dpi); 276 | rcPane.right -= cxSmIcon + cx; 277 | } // if( (GetStyle() & SBARS_SIZEGRIP) == SBARS_SIZEGRIP ) 278 | } // else from if( (dwPaneStyle & SBPS_STRETCH ) == 0 ) 279 | } // if( iIndex == (m_nCount-1) ) 280 | 281 | if ((GetPaneStyle(iIndex) & SBPS_NOBORDERS) == 0) { 282 | rcPane.DeflateRect(cx, cx); 283 | } 284 | else { 285 | rcPane.DeflateRect(cx, 1, cx, 1); 286 | } 287 | 288 | if (hWnd && ::IsWindow(hWnd)) { 289 | dwp.defer( 290 | hWnd, 291 | nullptr, 292 | rcPane.left, 293 | rcPane.top, 294 | rcPane.Width(), 295 | rcPane.Height(), 296 | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_SHOWWINDOW 297 | ); 298 | 299 | ::RedrawWindow( 300 | hWnd, 301 | nullptr, 302 | nullptr, 303 | RDW_INVALIDATE | RDW_UPDATENOW 304 | | RDW_ERASE | RDW_ERASENOW 305 | ); 306 | 307 | } // if (hWnd && ::IsWindow(hWnd)){ 308 | } 309 | }; 310 | 311 | ////////////////////////////////////////////////////////////////////////// 312 | 313 | BOOL WinMTRStatusBar::AddPane( 314 | UINT nID, // ID of the pane 315 | int nIndex // index of the pane 316 | ) 317 | { 318 | if (nIndex < 0 || nIndex > m_nCount) { 319 | ASSERT(FALSE); 320 | return FALSE; 321 | } 322 | 323 | if (CommandToIndex(nID) != -1) { 324 | ASSERT(FALSE); 325 | return FALSE; 326 | } 327 | 328 | std::vector<_STATUSBAR_PANE_> arrPanesTmp; 329 | arrPanesTmp.reserve(static_cast(m_nCount) + 1); 330 | for (int iIndex = 0; iIndex < m_nCount + 1; iIndex++) 331 | { 332 | _STATUSBAR_PANE_ pNewPane; 333 | 334 | if (iIndex == nIndex) { 335 | pNewPane.nID = nID; 336 | pNewPane.nStyle = SBPS_NORMAL; 337 | } 338 | else { 339 | int idx = iIndex; 340 | if (iIndex > nIndex) idx--; 341 | 342 | _STATUSBAR_PANE_* pOldPane = GetPanePtr(idx); 343 | pNewPane = *pOldPane; 344 | } 345 | arrPanesTmp.emplace_back(std::move(pNewPane)); 346 | } 347 | 348 | std::vector IDArray; 349 | IDArray.reserve(arrPanesTmp.size()); 350 | for (const auto& pane : arrPanesTmp) { 351 | IDArray.emplace_back(pane.nID); 352 | } 353 | 354 | // set the indicators 355 | SetIndicators(IDArray); 356 | for (int iIndex = 0; const auto & pane : arrPanesTmp) { 357 | if (iIndex != nIndex) { 358 | PaneInfoSet(iIndex, pane); 359 | } 360 | 361 | ++iIndex; 362 | } 363 | 364 | 365 | RepositionControls(); 366 | 367 | return TRUE; 368 | } 369 | 370 | ////////////////////////////////////////////////////////////////////////// 371 | 372 | BOOL WinMTRStatusBar::RemovePane( 373 | UINT nID // ID of the pane 374 | ) 375 | { 376 | if (CommandToIndex(nID) == -1 || m_nCount == 1) { 377 | ASSERT(FALSE); 378 | return FALSE; 379 | } 380 | 381 | std::vector<_STATUSBAR_PANE_> arrPanesTmp; 382 | arrPanesTmp.reserve(m_nCount); 383 | for (int nIndex = 0; nIndex < m_nCount; nIndex++) 384 | { 385 | _STATUSBAR_PANE_* pOldPane = GetPanePtr(nIndex); 386 | 387 | if (pOldPane->nID == nID) 388 | continue; 389 | 390 | _STATUSBAR_PANE_ pNewPane = *pOldPane; 391 | arrPanesTmp.emplace_back(std::move(pNewPane)); 392 | } 393 | std::vector IDArray; 394 | IDArray.reserve(arrPanesTmp.size()); 395 | for (const auto& pane : arrPanesTmp) { 396 | IDArray.emplace_back(pane.nID); 397 | } 398 | 399 | // set the indicators 400 | SetIndicators(IDArray); 401 | // free memory 402 | 403 | for (int nIndex = 0; const auto & pane : arrPanesTmp) { 404 | this->PaneInfoSet(nIndex, pane); 405 | ++nIndex; 406 | } 407 | m_arrPaneControls.erase(std::remove_if(m_arrPaneControls.begin(), m_arrPaneControls.end(), [nID](const auto& cntl) { 408 | return cntl.nID == nID; 409 | }), 410 | m_arrPaneControls.end()); 411 | 412 | RepositionControls(); 413 | 414 | return TRUE; 415 | } 416 | 417 | ////////////////////////////////////////////////////////////////////////// 418 | 419 | BOOL WinMTRStatusBar::AddPaneControl(HWND hWnd, UINT nID, BOOL bAutoDestroy) 420 | { 421 | if (CommandToIndex(nID) == -1) { 422 | return FALSE; 423 | } 424 | 425 | m_arrPaneControls.emplace_back(hWnd, nID, bAutoDestroy); 426 | 427 | RepositionControls(); 428 | return TRUE; 429 | } 430 | 431 | ////////////////////////////////////////////////////////////////////////// 432 | 433 | bool WinMTRStatusBar::PaneInfoGet(int nIndex, _STATUSBAR_PANE_* pPane) const noexcept 434 | { 435 | if (nIndex < m_nCount && nIndex >= 0) 436 | { 437 | GetPaneInfo(nIndex, pPane->nID, pPane->nStyle, pPane->cxText); 438 | CString strPaneText; 439 | GetPaneText(nIndex, strPaneText); 440 | // not actually UB since strText is a CString 441 | // TODO: need to figure out why the cast 442 | pPane->strText = LPCTSTR(strPaneText); 443 | return true; 444 | } 445 | return true; 446 | } 447 | 448 | ////////////////////////////////////////////////////////////////////////// 449 | 450 | bool WinMTRStatusBar::PaneInfoSet(int nIndex, const _STATUSBAR_PANE_& pPane) noexcept 451 | { 452 | if (nIndex < m_nCount && nIndex >= 0) { 453 | SetPaneInfo(nIndex, pPane.nID, pPane.nStyle, pPane.cxText); 454 | SetPaneText(nIndex, static_cast(pPane.strText)); 455 | return true; 456 | } 457 | return false; 458 | } 459 | 460 | 461 | 462 | WinMTRStatusBar::_STATUSBAR_PANE_CTRL_::~_STATUSBAR_PANE_CTRL_() noexcept 463 | { 464 | if (this->hWnd && ::IsWindow(this->hWnd)) { 465 | ::ShowWindow(this->hWnd, SW_HIDE); 466 | if (this->bAutoDestroy) { 467 | ::DestroyWindow(this->hWnd); 468 | } 469 | } 470 | } 471 | //#endif // WINMTRSTATUSBAR_H_ 472 | -------------------------------------------------------------------------------- /WinMTRUtils.ixx: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2022 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | export module WinMTRUtils; 22 | import ; 23 | using namespace std::literals; 24 | export namespace WinMTRUtils { 25 | export constexpr auto int_number_format = L"{:Ld}"sv; 26 | export constexpr auto float_number_format = L"{:.1Lf}"sv; 27 | export constexpr auto DEFAULT_PING_SIZE = 64u; 28 | export constexpr auto MAX_PING_SIZE = 1u << 15u; 29 | export constexpr auto MIN_PING_SIZE = DEFAULT_PING_SIZE; 30 | export constexpr auto DEFAULT_INTERVAL = 1.0; 31 | export constexpr auto MIN_INTERVAL = DEFAULT_INTERVAL; 32 | export constexpr auto MAX_INTERVAL = 120.0; 33 | export constexpr auto DEFAULT_MAX_LRU = 128u; 34 | export constexpr auto MIN_MAX_LRU = 1u; 35 | export constexpr auto MAX_MAX_LRU = 1024u; 36 | } -------------------------------------------------------------------------------- /WinMTRVerUtil.ixx: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2023 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | module; 21 | #pragma warning (disable : 4005) 22 | #include "targetver.h" 23 | #define NOMINMAX 24 | #define WIN32_LEAN_AND_MEAN 25 | #include 26 | 27 | export module WinMTRVerUtil; 28 | 29 | import ; 30 | 31 | export namespace WinMTRVerUtil { 32 | const std::wstring& getExeVersion(); 33 | } 34 | 35 | module : private; 36 | 37 | import ; 38 | import ; 39 | import ; 40 | 41 | using namespace std::literals; 42 | 43 | namespace { 44 | struct verInfo { 45 | std::wstring versionStr; 46 | verInfo() { 47 | WCHAR modulepath[MAX_PATH + 1]{}; 48 | if (!GetModuleFileNameW(nullptr, modulepath, std::size(modulepath))) { 49 | return; 50 | } 51 | DWORD legacy; 52 | DWORD versize; 53 | if (versize = GetFileVersionInfoSizeExW(FILE_VER_GET_LOCALISED, modulepath, &legacy); versize == 0) { 54 | return; 55 | } 56 | 57 | std::vector buffer(static_cast(versize)); 58 | 59 | if (!GetFileVersionInfoExW(FILE_VER_GET_LOCALISED, modulepath, 0, versize, buffer.data())) [[unlikely]] { 60 | return; 61 | } 62 | LPVOID subblock = nullptr; 63 | UINT len = 0; 64 | if (!VerQueryValueW(buffer.data(), L"\\", &subblock, &len)) [[unlikely]] { 65 | return; 66 | } 67 | 68 | if (!len) [[unlikely]] { 69 | return; 70 | } 71 | 72 | const VS_FIXEDFILEINFO* verInfo = reinterpret_cast(subblock); 73 | if (verInfo->dwSignature != 0xfeef04bd) 74 | { 75 | return; 76 | } 77 | const int major = HIWORD(verInfo->dwProductVersionMS); 78 | const int minor = LOWORD(verInfo->dwProductVersionMS); 79 | const int revision = HIWORD(verInfo->dwProductVersionLS); 80 | // not currently in use, maybe in the future 81 | //const int build = LOWORD(verInfo->dwProductVersionLS); 82 | 83 | versionStr = std::format(L"{}.{}{}"sv, major, minor, revision); 84 | } 85 | }; 86 | } 87 | 88 | const std::wstring& WinMTRVerUtil::getExeVersion() { 89 | // YAY magic statics making this thread safe! 90 | static verInfo info; 91 | return info.versionStr; 92 | } -------------------------------------------------------------------------------- /WinMTRWSAhelper.ixx: -------------------------------------------------------------------------------- 1 | /* 2 | WinMTR 3 | Copyright (C) 2010-2019 Appnor MSP S.A. - http://www.appnor.com 4 | Copyright (C) 2019-2021 Leetsoftwerx 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; version 2 9 | of the License. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | module; 22 | #include "targetver.h" 23 | #define VC_EXTRALEAN 24 | #define WIN32_LEAN_AND_MEAN 25 | #define NOSERVICE 26 | #define NOUSER 27 | #define NOGDI 28 | #define NOKERNEL 29 | #define NOUSER 30 | #define NONLS 31 | #include 32 | 33 | export module winmtr.helper; 34 | 35 | export namespace winmtr::helper { 36 | class WSAHelper { 37 | bool valid; 38 | public: 39 | WSAHelper(WORD version) noexcept 40 | :valid(false){ 41 | WSAData data = {}; 42 | valid = !WSAStartup(version, &data); 43 | } 44 | 45 | ~WSAHelper() noexcept { 46 | if (valid) { 47 | WSACleanup(); 48 | } 49 | } 50 | 51 | explicit operator bool() const noexcept{ 52 | return valid; 53 | } 54 | }; 55 | } 56 | -------------------------------------------------------------------------------- /app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | UTF-8 21 | true 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by WinMTR.rc 4 | // 5 | #define IDD_WINMTR_DIALOG 102 6 | #define IDP_SOCKETS_INIT_FAILED 103 7 | #define IDS_STRING_SB_NAME 104 8 | #define IDS_STRING_SB_PING 105 9 | #define IDS_STRING_CLEAR_HISTORY 106 10 | #define IDS_STRING_UNABLE_TO_RESOLVE_HOSTNAME 107 11 | #define IDS_STRING_STOP 108 12 | #define IDS_STRING_START 109 13 | #define IDS_STRING_WAITING_STOP_TRACE 110 14 | #define IDS_STRING_DBL_CLICK_MORE_INFO 111 15 | #define IDS_STRING_NO_RESPONSE_FROM_HOST 112 16 | #define IDR_MAINFRAME 128 17 | #define IDD_DIALOG_OPTIONS 129 18 | #define IDD_DIALOG_LICENSE 130 19 | #define IDD_DIALOG_PROPERTIES 131 20 | #define IDD_DIALOG_HELP 132 21 | #define IDC_EDIT_HOST 1000 22 | #define IDC_LIST_MTR 1001 23 | #define ID_RESTART 1002 24 | #define ID_OPTIONS 1003 25 | #define IDC_EDIT_INTERVAL 1004 26 | #define ID_CTTC 1004 27 | #define IDC_EDIT_SIZE 1005 28 | #define ID_CHTC 1005 29 | #define IDC_CHECK_DNS 1006 30 | #define ID_EXPT 1006 31 | #define ID_EXPH 1007 32 | #define ID_LICENSE 1008 33 | #define IDC_EDIT_LICENSE 1011 34 | #define IDC_EDIT_PHOST 1012 35 | #define IDC_EDIT_PIP 1013 36 | #define IDC_EDIT_PSENT 1014 37 | #define IDC_EDIT_PRECV 1015 38 | #define IDC_EDIT_PLOSS 1016 39 | #define IDC_EDIT_PLAST 1017 40 | #define IDC_EDIT_PBEST 1018 41 | #define IDC_EDIT_PAVRG 1019 42 | #define IDC_EDIT_PWORST 1020 43 | #define IDC_EDIT_PCOMMENT 1021 44 | #define IDC_STATICS 1022 45 | #define IDC_STATICJ 1023 46 | #define IDC_COMBO_HOST 1024 47 | #define IDC_EDIT_MAX_LRU 1025 48 | #define IDC_MFCLINK1 1026 49 | #define IDC_IPV4_CHECK 1027 50 | #define IDC_USEIPV6_CHECK 1028 51 | 52 | // Next default values for new objects 53 | // 54 | #ifdef APSTUDIO_INVOKED 55 | #ifndef APSTUDIO_READONLY_SYMBOLS 56 | #define _APS_NEXT_RESOURCE_VALUE 138 57 | #define _APS_NEXT_COMMAND_VALUE 32771 58 | #define _APS_NEXT_CONTROL_VALUE 1029 59 | #define _APS_NEXT_SYMED_VALUE 101 60 | #endif 61 | #endif 62 | -------------------------------------------------------------------------------- /targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /vcpkg-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "default-registry": { 3 | "kind": "git", 4 | "baseline": "7adc2e4d49e8d0efc07a369079faa6bc3dbb90f3", 5 | "repository": "https://github.com/microsoft/vcpkg" 6 | }, 7 | "registries": [ 8 | { 9 | "kind": "artifact", 10 | "location": "https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip", 11 | "name": "microsoft" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /vcpkg.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": [ 3 | "cppwinrt" 4 | ] 5 | } 6 | --------------------------------------------------------------------------------