├── .github └── workflows │ └── msbuild.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── WinMTR.sln ├── src-cmd ├── WinMTRCmd.cpp ├── WinMTRCmd.h ├── WinMTRCmd.vcxproj ├── WinMTRGlobal.h ├── WinMTRNet.cpp ├── WinMTRNet.h ├── WinMTRParams.cpp └── WinMTRParams.h └── src ├── README.MD ├── WinMTR.ico ├── WinMTR.rc ├── WinMTR.vcxproj ├── WinMTRDialog.cpp ├── WinMTRDialog.h ├── WinMTRGlobal.h ├── WinMTRHelp.cpp ├── WinMTRHelp.h ├── WinMTRMain.cpp ├── WinMTRMain.h ├── WinMTRNet.cpp ├── WinMTRNet.h ├── WinMTROptions.cpp ├── WinMTROptions.h ├── WinMTRProperties.cpp ├── WinMTRProperties.h ├── WinMTRStatusBar.cpp ├── WinMTRStatusBar.h └── resource.h /.github/workflows/msbuild.yml: -------------------------------------------------------------------------------- 1 | name: MSBuild 2 | 3 | on: [push] 4 | 5 | env: 6 | # Path to the solution file relative to the root of the project. 7 | SOLUTION_FILE_PATH: ./ 8 | 9 | # Configuration type to build. 10 | # You can convert this to a build matrix if you need coverage of multiple configuration types. 11 | # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix 12 | BUILD_CONFIGURATION: Release 13 | 14 | jobs: 15 | build: 16 | runs-on: windows-latest 17 | 18 | steps: 19 | - uses: actions/checkout@v2 20 | 21 | - name: Add MSBuild to PATH 22 | uses: microsoft/setup-msbuild@v1.0.2 23 | 24 | - name: Restore NuGet packages 25 | working-directory: ${{env.GITHUB_WORKSPACE}} 26 | run: nuget restore ${{env.SOLUTION_FILE_PATH}} 27 | 28 | - name: Build 29 | working-directory: ${{env.GITHUB_WORKSPACE}} 30 | # Add additional options to the MSBuild command line here (like platform or verbosity level). 31 | # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference 32 | run: msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}} 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | .idea 6 | .vs 7 | src/bin 8 | src/obj 9 | src-cmd/bin 10 | src-cmd/obj 11 | *.user 12 | *.suo 13 | *.aps 14 | *.tmp 15 | # Compiled Dynamic libraries 16 | *.so 17 | *.dylib 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | 24 | .github -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | CHANGELOG 2 | ======== 3 | **Release 1.1 - 26.09.2021** 4 | - `[x]` * Changed unsecure functions 5 | - `[x]` * Beautify interface 6 | - `[x]` * Redesigned reports 7 | 8 | **Release 1.02 - 21.09.2021** 9 | - `[x]` * new icon 10 | - `[x]` + Connected with WinMTR Commandline Project 11 | - `[x]` * Beautify code 12 | 13 | **Release 1.01 - 18.09.2021** 14 | - `[x]` - removed extra screens 15 | - `[x]` + added ARM versions 16 | - `[x]` ! Code improvements 17 | 18 | **Release 1.00 - 13.01.2014** 19 | - `[x]` - removed Windows 2000 support 20 | - `[x]` + added IPv6 support 21 | - `[x]` + clickable entries when stopped... *(why the heck wasn't it possible before?)* 22 | - `[x]` * added start delay of about 30ms for each hop *(870ms before the 30th hop gets queried) 23 | this should improve performance and reduces network load*
24 | - `[x]` ! fixed trace list freeze *(list didn't update while tracing, happens when tracing just one hop)* 25 | - `[x]` * theme support *(more fancy look :P)* 26 | - ~~`[ ]` + remembers window size~~ 27 | - `[x]` ! CTRL+A works for host input 28 | - `[ ]` + host history: pressing del key or right mouse will remove selected entry 29 | - `[ ]` * new icon 30 | 31 | **Release 0.92 - 31.01.2011** 32 | - `[x]` fixing reporting errors for very slow connections. 33 | 34 | **Release 0.91 - 11.01.2011** 35 | - `[x]` * Version is out under GPL v2, by popular request. 36 | 37 | **Release 0.9 - 24.12.2010** 38 | - `[x]` ! New version! for 32 and 64-bit Operating Systems. 39 | - `[x]` ! Now works on Windows 7 as a regular user. 40 | - `[x]` * Various bug fixes. 41 | - `[x]` * License changed from GPL to commercial, but not for long :wink: 42 | 43 | **Release 0.8 - 20.01.2002** 44 | - `[x]` * Last entered hosts an options are now hold in registry. Home page and development moved to Sourceforge. 45 | 46 | **Release 0.7 - 09.05.2001** 47 | - `[x]` * 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. 48 | 49 | **Release 0.6 - 27.11.2000** 50 | - `[x]` + Added resizing support and flat buttons. 51 | 52 | **Release 0.5 - 26.11.2000** 53 | - `[x]` + Added copy data to clipboard and possibility to save data to file as text or HTML. 54 | 55 | **Release 0.4 - 03.08.2000** 56 | - `[x]` + Added double-click on host name in list for detailed information. 57 | 58 | **Release 0.3 - 02.08.2000** 59 | - `[x]` ! Fixed ICMP error codes handling. Print an error message corresponding to ICP_HOST_UNREACHABLE error code instead of a empty line. 60 | 61 | **Release 0.2 - 01.08.2000** 62 | - `[x]` + Support for full command-line operations. 63 | 64 | **Release 0.1 - 28.07.2000** 65 | - `[x]` + First release. -------------------------------------------------------------------------------- /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 | {description} 294 | Copyright (C) {year} {fullname} 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 | {signature of Ty Coon}, 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 Live 2 | ============== 3 | **WinMTR Live** in an extended fork of [Appnor's WinMTR](http://winmtr.net/) ([SourceForge](http://sourceforge.net/projects/winmtr/))
4 | with IPv6 support and other different enhancements and bug fixes 5 | 6 | Origin Author: [René Schümann](https://github.com/White-Tiger) ([GitHub](https://github.com/White-Tiger/WinMTR)) 7 | 8 | **WinMTRCmd** combines traceroute and ping functionality in a single network diagnostic tool. It is a command-line application based on WinMTR, which in turn is based on the original MTR. 9 | 10 | Origin Author: [Martin Riess](mailto:volrathmr+winmtrcmd@gmail.com) ([SourceForge](http://sourceforge.net/p/winmtrcmd)) 11 | 12 | ### Download (binaries) 13 | * [**view all available**](https://github.com/aunited/WinMTR/releases) 14 | 15 | ### Requirements 16 | * Windows XP+ 17 | * Microsoft Visual C++ 2015-2022 Redistributable 18 | 19 | 20 | -------------------------------------------------------------------------------- /WinMTR.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.0.31612.314 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinMTR", "src\WinMTR.vcxproj", "{EE7B51B5-96FC-BED3-F2A6-0713CECBB579}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinMTRCmd", "src-cmd\WinMTRCmd.vcxproj", "{340746A1-78CE-F631-EFC6-5B7A479108B6}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|ARM = Debug|ARM 13 | Debug|ARM64 = Debug|ARM64 14 | Debug|Win32 = Debug|Win32 15 | Debug|x64 = Debug|x64 16 | Release|ARM = Release|ARM 17 | Release|ARM64 = Release|ARM64 18 | Release|Win32 = Release|Win32 19 | Release|x64 = Release|x64 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug|ARM.ActiveCfg = Debug|ARM 23 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug|ARM.Build.0 = Debug|ARM 24 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug|ARM64.ActiveCfg = Debug|ARM64 25 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug|ARM64.Build.0 = Debug|ARM64 26 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug|Win32.ActiveCfg = Debug|Win32 27 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug|Win32.Build.0 = Debug|Win32 28 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug|x64.ActiveCfg = Debug|x64 29 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Debug|x64.Build.0 = Debug|x64 30 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release|ARM.ActiveCfg = Release|ARM 31 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release|ARM.Build.0 = Release|ARM 32 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release|ARM64.ActiveCfg = Release|ARM64 33 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release|ARM64.Build.0 = Release|ARM64 34 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release|Win32.ActiveCfg = Release|Win32 35 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release|Win32.Build.0 = Release|Win32 36 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release|x64.ActiveCfg = Release|x64 37 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579}.Release|x64.Build.0 = Release|x64 38 | {340746A1-78CE-F631-EFC6-5B7A479108B6}.Debug|ARM.ActiveCfg = Debug|ARM 39 | {340746A1-78CE-F631-EFC6-5B7A479108B6}.Debug|ARM.Build.0 = Debug|ARM 40 | {340746A1-78CE-F631-EFC6-5B7A479108B6}.Debug|ARM64.ActiveCfg = Debug|ARM64 41 | {340746A1-78CE-F631-EFC6-5B7A479108B6}.Debug|ARM64.Build.0 = Debug|ARM64 42 | {340746A1-78CE-F631-EFC6-5B7A479108B6}.Debug|Win32.ActiveCfg = Debug|Win32 43 | {340746A1-78CE-F631-EFC6-5B7A479108B6}.Debug|Win32.Build.0 = Debug|Win32 44 | {340746A1-78CE-F631-EFC6-5B7A479108B6}.Debug|x64.ActiveCfg = Debug|x64 45 | {340746A1-78CE-F631-EFC6-5B7A479108B6}.Debug|x64.Build.0 = Debug|x64 46 | {340746A1-78CE-F631-EFC6-5B7A479108B6}.Release|ARM.ActiveCfg = Release|ARM 47 | {340746A1-78CE-F631-EFC6-5B7A479108B6}.Release|ARM.Build.0 = Release|ARM 48 | {340746A1-78CE-F631-EFC6-5B7A479108B6}.Release|ARM64.ActiveCfg = Release|ARM64 49 | {340746A1-78CE-F631-EFC6-5B7A479108B6}.Release|ARM64.Build.0 = Release|ARM64 50 | {340746A1-78CE-F631-EFC6-5B7A479108B6}.Release|Win32.ActiveCfg = Release|Win32 51 | {340746A1-78CE-F631-EFC6-5B7A479108B6}.Release|Win32.Build.0 = Release|Win32 52 | {340746A1-78CE-F631-EFC6-5B7A479108B6}.Release|x64.ActiveCfg = Release|x64 53 | {340746A1-78CE-F631-EFC6-5B7A479108B6}.Release|x64.Build.0 = Release|x64 54 | EndGlobalSection 55 | GlobalSection(SolutionProperties) = preSolution 56 | HideSolutionNode = FALSE 57 | EndGlobalSection 58 | GlobalSection(ExtensibilityGlobals) = postSolution 59 | SolutionGuid = {23DA2F70-6CD6-4986-B806-42DC68726DED} 60 | EndGlobalSection 61 | EndGlobal 62 | -------------------------------------------------------------------------------- /src-cmd/WinMTRCmd.cpp: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRCmd.cpp 3 | // 4 | // 5 | //***************************************************************************** 6 | 7 | #include "WinMTRCmd.h" 8 | #include "WinMTRGlobal.h" 9 | #include "WinMTRNet.h" 10 | #include "WinMTRParams.h" 11 | 12 | //***************************************************************************** 13 | // _tmain 14 | // 15 | // 16 | //***************************************************************************** 17 | int _tmain(int, _TCHAR** argv) 18 | { 19 | WinMTRCmd cmd(argv[0]); 20 | cmd.Run(); 21 | return 0; 22 | } 23 | 24 | //***************************************************************************** 25 | // WinMTRCmd::WinMTRCmd 26 | // 27 | // 28 | //***************************************************************************** 29 | WinMTRCmd::WinMTRCmd(_TCHAR *name) 30 | : programName(name) 31 | { 32 | for (int i = 0; i < 256; i++) 33 | indexMapping[i] = -1; 34 | for (int i = 0; dataFields[i].key != 0; i++) 35 | indexMapping[dataFields[i].key] = i; 36 | } 37 | 38 | //***************************************************************************** 39 | // WinMTRCmd::ParseCommandLineParams 40 | // 41 | // 42 | //***************************************************************************** 43 | void ExitThread(void *p) 44 | { 45 | char c; 46 | do { 47 | c = _getch(); 48 | } while(c != 'x' && c != 'X'); 49 | 50 | exit(0); 51 | } 52 | 53 | void WinMTRCmd::Run() 54 | { 55 | WinMTRParams params; 56 | LPTSTR cmdLine = GetCommandLineParams(); 57 | WinMTRNet* net; 58 | int addr; 59 | FILE *file; 60 | 61 | // initialize default parameters 62 | params.SetHostName(""); 63 | params.SetReport(DEFAULT_REPORT); 64 | params.SetWide(DEFAULT_WIDE); 65 | params.SetUseDNS(DEFAULT_DNS); 66 | params.SetCycles(DEFAULT_CYCLES); 67 | params.SetInterval(DEFAULT_INTERVAL); 68 | params.SetPingSize(DEFAULT_PING_SIZE); 69 | params.SetTimeout(DEFAULT_TIMEOUT); 70 | params.SetFields(DEFAULT_FIELDS); 71 | 72 | // parse and validate command-line params 73 | if (!ParseCommandLineParams(cmdLine, ¶ms)) return; 74 | if (!ValidateParams(¶ms)) return; 75 | 76 | net = new WinMTRNet(¶ms); 77 | 78 | // resolve the hostname 79 | addr = GetAddr(params.hostname); 80 | if (addr == INADDR_NONE) 81 | { 82 | delete net; 83 | fprintf(stderr, "error: could not resolve hostname\n"); 84 | return; 85 | } 86 | 87 | // get the name of the local host for later use 88 | gethostname(localHostname, 256); 89 | 90 | if (params.report) { 91 | // perform the trace sync 92 | net->DoTrace(addr, false); 93 | 94 | // print the trace report 95 | if (params.reportToFile) 96 | { 97 | file = fopen(params.filename, "w"); 98 | if (file == NULL) { 99 | fprintf(stderr, "error: could not redirect report to '%s': %s\n", 100 | params.filename, strerror(errno)); 101 | PrintReport(stdout, net, UnsafeGet, params.fields, params.wide); 102 | } else { 103 | PrintReport(file, net, UnsafeGet, params.fields, params.wide); 104 | fclose(file); 105 | } 106 | } 107 | else 108 | PrintReport(stdout, net, UnsafeGet, params.fields, params.wide); 109 | } else { 110 | // start the thread listening for the exit command 111 | _beginthread(ExitThread, 0, 0); 112 | 113 | // perform the trace async 114 | net->DoTrace(addr, true); 115 | 116 | // update the display in a loop while tracing 117 | while(net->IsTracing()) { 118 | Sleep((int)(params.interval * 1000)); 119 | CLS(); 120 | printf("(X) Exit\n"); 121 | PrintReport(stdout, net, SafeGet, params.fields, params.wide); 122 | } 123 | } 124 | 125 | delete net; 126 | } 127 | 128 | //***************************************************************************** 129 | // WinMTRCmd::ParseCommandLineParams 130 | // 131 | // 132 | //***************************************************************************** 133 | bool WinMTRCmd::ParseCommandLineParams(LPTSTR cmd, WinMTRParams *wmtrparams) 134 | { 135 | char value[128]; 136 | std::string host_name = ""; 137 | 138 | if(GetParamValue(cmd, "version",'v', value, true)) { 139 | printf("WinMTRCmd %s - %s\n" 140 | "based on %s\n" 141 | "and %s\n" 142 | "%s\n", WINMTRCMD_VERSION, WINMTRCMD_HOMEPAGE, MTR_VERSION_STR, 143 | WINMTR_VERSION_STR, WINMTRCMD_LICENSE); 144 | return false; 145 | } 146 | 147 | if(GetParamValue(cmd, "help",'h', value, true)) { 148 | printf("usage: %s [--help|-h] [--help-format|-p] [--version|-v]\n" 149 | "\t\t [--report|-r] [--wide|-w] [--numeric|-n]\n" 150 | "\t\t [--cycles=COUNT|-c=COUNT] [--interval=SECONDS|-i=SECONDS]\n" 151 | "\t\t [--size=BYTES|-s=BYTES] [--timeout=SECONDS|-t=SECONDS]\n" 152 | "\t\t [--file=PATH|-f=PATH] [--order=FIELDS ORDER|-o=FIELDS ORDER]\n" 153 | "\t\t HOSTNAME\n", programName); 154 | return false; 155 | } 156 | 157 | if(GetParamValue(cmd, "help-format",'p', value, true)) { 158 | printf("order format usage: [key+], for example '%s'\n" 159 | "\tkey: field description\n", DEFAULT_FIELDS); 160 | for (int i = 0; dataFields[i].key != 0; ++i) { 161 | printf("\t%s\n", dataFields[i].descr); 162 | } 163 | return false; 164 | } 165 | 166 | if (GetParamValue(cmd, "report", 'r', value, true)) { 167 | wmtrparams->SetReport(true); 168 | } 169 | if(GetParamValue(cmd, "wide",'w', value, true)) { 170 | wmtrparams->SetWide(true); 171 | } 172 | if(GetParamValue(cmd, "numeric",'n', value, true)) { 173 | wmtrparams->SetUseDNS(false); 174 | } 175 | if(GetParamValue(cmd, "cycles",'c', value, false)) { 176 | wmtrparams->SetCycles(atoi(value)); 177 | } 178 | if(GetParamValue(cmd, "interval",'i', value, false)) { 179 | wmtrparams->SetInterval((float)atof(value)); 180 | } 181 | if(GetParamValue(cmd, "size",'s', value, false)) { 182 | wmtrparams->SetPingSize(atoi(value)); 183 | } 184 | if(GetParamValue(cmd, "timeout",'t', value, false)) { 185 | wmtrparams->SetTimeout((float)atof(value)); 186 | } 187 | if(GetParamValue(cmd, "file",'f', value, false)) { 188 | wmtrparams->SetFilename(value); 189 | } 190 | if(GetParamValue(cmd, "order",'o', value, false)) { 191 | wmtrparams->SetFields(value); 192 | } 193 | if(GetHostNameParamValue(cmd, host_name)) { 194 | wmtrparams->SetHostName(host_name.c_str()); 195 | } 196 | return true; 197 | } 198 | 199 | //***************************************************************************** 200 | // WinMTRCmd::ValidateParams 201 | // 202 | // 203 | //***************************************************************************** 204 | bool WinMTRCmd::ValidateParams(WinMTRParams *wmtrparams) 205 | { 206 | if (strlen(wmtrparams->hostname) == 0) { 207 | printf("error: no hostname specified\n"); 208 | return false; 209 | } 210 | 211 | if (wmtrparams->pingsize < MINPACKET || wmtrparams->pingsize > MAXPACKET) { 212 | printf("error: size has to be in the range [%d, %d]\n", MINPACKET, MAXPACKET); 213 | return false; 214 | } 215 | 216 | return true; 217 | } 218 | 219 | //***************************************************************************** 220 | // WinMTRCmd::GetCommandLineParams 221 | // 222 | // 223 | //***************************************************************************** 224 | LPTSTR WinMTRCmd::GetCommandLineParams() 225 | { 226 | LPTSTR cmdLine = GetCommandLine(); 227 | LPTSTR offset; 228 | 229 | if (*cmdLine == 0) { 230 | return cmdLine; 231 | } 232 | if (*cmdLine == '"') { 233 | offset = strchr(cmdLine + 1, '"') + 1; 234 | } else { 235 | offset = strchr(cmdLine, ' '); 236 | if (!offset) { 237 | offset = cmdLine + strlen(cmdLine); 238 | } 239 | } 240 | while (*offset == ' ') 241 | ++offset; 242 | if (*offset) { 243 | strcpy(cmdLineParams, offset); 244 | strcat(cmdLineParams, " "); 245 | } else { 246 | *cmdLineParams = ' '; 247 | *(cmdLineParams + 1) = 0; 248 | } 249 | return cmdLineParams; 250 | } 251 | 252 | //***************************************************************************** 253 | // WinMTRCmd::GetParamValue 254 | // 255 | // 256 | //***************************************************************************** 257 | bool WinMTRCmd::GetParamValue(LPTSTR cmd, char * param, char sparam, char *value, bool flag) 258 | { 259 | char *p; 260 | 261 | char p_long[128]; 262 | char p_short[128]; 263 | bool inString = false; 264 | 265 | sprintf(p_long,"--%s ", param); 266 | sprintf(p_short,"-%c ", sparam); 267 | 268 | if( (p=strstr(cmd, p_long)) ) ; 269 | else 270 | p=strstr(cmd, p_short); 271 | 272 | if(p == NULL) 273 | return false; 274 | 275 | if(flag) 276 | return true; 277 | 278 | while(*p && *p!=' ') 279 | p++; 280 | while(*p==' ') p++; 281 | 282 | int i = 0; 283 | while(*p && (*p!=' ' || inString)) 284 | { 285 | if (*p == '"') 286 | { 287 | if (inString) break; 288 | else inString = true; 289 | } else 290 | value[i++] = *p; 291 | 292 | p++; 293 | } 294 | value[i]='\0'; 295 | 296 | return true; 297 | } 298 | 299 | //***************************************************************************** 300 | // WinMTRCmd::GetHostNameParamValue 301 | // 302 | // 303 | //***************************************************************************** 304 | bool WinMTRCmd::GetHostNameParamValue(LPTSTR cmd, std::string& host_name) 305 | { 306 | int size = strlen(cmd); 307 | std::string name = ""; 308 | 309 | while(cmd[--size] == ' '); 310 | size++; 311 | 312 | while(size-- && cmd[size] != ' ' && (cmd[size] != '-' || cmd[size - 1] != ' ')) { 313 | name = cmd[size ] + name; 314 | } 315 | 316 | if(size == -1) { 317 | if(name.length() == 0) { 318 | return false; 319 | } else { 320 | host_name = name; 321 | return true; 322 | } 323 | } 324 | if(cmd[size] == '-' && cmd[size - 1] == ' ') { 325 | // no target specified 326 | return false; 327 | } 328 | 329 | while(cmd[--size] == ' '); 330 | size++; 331 | 332 | std::string possible_argument = ""; 333 | 334 | while(size-- && cmd[size] != ' ') { 335 | possible_argument = cmd[size] + possible_argument; 336 | } 337 | 338 | if(possible_argument.length() && (possible_argument[0] != '-' || possible_argument == "-n" 339 | || possible_argument == "-w" || possible_argument == "-r" || possible_argument == "--numeric" 340 | || possible_argument == "--wide" || possible_argument == "--report")) { 341 | host_name = name; 342 | return true; 343 | } 344 | 345 | return false; 346 | } 347 | 348 | //***************************************************************************** 349 | // WinMTRCmd::PrintReport 350 | // 351 | // 352 | //***************************************************************************** 353 | 354 | void WinMTRCmd::PrintReport(FILE* file, WinMTRNet* net, int getType, 355 | const char* fields, bool reportwide) 356 | { 357 | int max; 358 | char name[81]; 359 | char buf[1024]; 360 | char fmt[16]; 361 | int len = 0, len_hosts = 33; 362 | VoidGetMethod voidNetGet; 363 | 364 | max = net->GetMax(); 365 | 366 | if (reportwide) { 367 | // get the longest hostname 368 | len_hosts = strlen(localHostname); 369 | for (int at = 0; at < max; at++) { 370 | int nlen; 371 | net->GetName(at, name); 372 | if ((nlen = strlen(name))) 373 | if (len_hosts < nlen) 374 | len_hosts = nlen; 375 | } 376 | } 377 | 378 | _snprintf(fmt, sizeof(fmt), "HOST: %%-%ds", len_hosts + 2); 379 | _snprintf(buf, sizeof(buf), fmt, localHostname); 380 | len = reportwide ? strlen(buf) : len_hosts; 381 | for (int i = 0; fields[i] != 0; i++) { 382 | int j = indexMapping[fields[i]]; 383 | if (j < 0) continue; 384 | 385 | _snprintf(fmt, sizeof(fmt), "%%%ds", dataFields[j].length); 386 | _snprintf(buf + len, sizeof(buf) - len, fmt, dataFields[j].title); 387 | len += dataFields[j].length; 388 | } 389 | fprintf(file, "%s\n", buf); 390 | 391 | for (int at = 0; at < max; at++) { 392 | net->GetName(at, name); 393 | 394 | _snprintf(fmt, sizeof(fmt), " %%2d.|-- %%-%ds", len_hosts); 395 | _snprintf(buf, sizeof(buf), fmt, at + 1, name); 396 | len = reportwide ? strlen(buf) : len_hosts; 397 | for (int i = 0; i < fields[i] != 0; i++) { 398 | int j = indexMapping[fields[i]]; 399 | if (j < 0) continue; 400 | 401 | voidNetGet = dataFields[j].get[getType]; 402 | if (voidNetGet != NULL) 403 | { 404 | if (dataFields[j].floatReturn) 405 | _snprintf(buf + len, sizeof(buf) - len, dataFields[j].format, 406 | (net->*((FloatGetMethod)voidNetGet))(at)); 407 | else 408 | _snprintf(buf + len, sizeof(buf) - len, dataFields[j].format, 409 | (net->*((IntGetMethod)voidNetGet))(at)); 410 | } 411 | else 412 | _snprintf(buf + len, sizeof(buf) - len, dataFields[j].format); 413 | len += dataFields[j].length; 414 | } 415 | fprintf(file, "%s\n", buf); 416 | } 417 | } 418 | 419 | //***************************************************************************** 420 | // WinMTRCmd::GetAddr 421 | // 422 | // 423 | //***************************************************************************** 424 | int WinMTRCmd::GetAddr(char* s) 425 | { 426 | struct hostent *host; 427 | 428 | int isIP=1; 429 | char *t = s; 430 | while(*t) { 431 | if(!isdigit(*t) && *t!='.') { 432 | isIP=0; 433 | break; 434 | } 435 | t++; 436 | } 437 | 438 | if(!isIP) { 439 | host = gethostbyname(s); 440 | if (host) 441 | return *(int *)host->h_addr; 442 | else 443 | return INADDR_NONE; 444 | } else 445 | return inet_addr(s); 446 | } 447 | 448 | //***************************************************************************** 449 | // WinMTRCmd::dataFields 450 | // 451 | // 452 | //***************************************************************************** 453 | #define NETM(a) (VoidGetMethod)&WinMTRNet::a 454 | 455 | WinMTRCmd::fields WinMTRCmd::dataFields[] = { 456 | // key, Remark, Header, Format, Width, Float Return, Getter 457 | {' ', ": Space between fields", " ", " ", 1, false, NULL, NULL }, 458 | {'L', "L: Loss Ratio", "Loss%", " %5.1f%%", 7, true, 459 | NETM(GetPercent), NETM(GetPercentUnsafe) }, 460 | {'D', "D: Dropped Packets", "Drop", " %4d", 5, false, 461 | NETM(GetDropped), NETM(GetDroppedUnsafe) }, 462 | {'R', "R: Received Packets", "Rcv", " %4d", 5, false, 463 | NETM(GetReturned), NETM(GetReturnedUnsafe) }, 464 | {'S', "S: Sent Packets", "Snt", " %4d", 5, false, 465 | NETM(GetXmit), NETM(GetXmitUnsafe) }, 466 | {'N', "N: Newest RTT(ms)", "Last", " %4d", 5, false, 467 | NETM(GetLast), NETM(GetLastUnsafe) }, 468 | {'B', "B: Min/Best RTT(ms)", "Best", " %4d", 5, false, 469 | NETM(GetBest), NETM(GetBestUnsafe) }, 470 | {'A', "A: Average RTT(ms)", "Avg", " %6.1f", 7, true, 471 | NETM(GetAvg), NETM(GetAvgUnsafe) }, 472 | {'W', "W: Max/Worst RTT(ms)", "Wrst", " %4d", 5, false, 473 | NETM(GetWorst), NETM(GetWorstUnsafe) }, 474 | {'V', "V: Standard Deviation", "StDev", " %6.1f", 7, true, 475 | NETM(GetStDev), NETM(GetStDevUnsafe) }, 476 | {'G', "G: Geometric Mean", "Gmean", " %6.1f", 7, true, 477 | NETM(GetGMean), NETM(GetGMeanUnsafe) }, 478 | {'J', "J: Current Jitter", "Jttr", " %4d", 5, false, 479 | NETM(GetJitter), NETM(GetJitterUnsafe) }, 480 | {'M', "M: Jitter Mean/Avg.", "Javg", " %6.1f", 7, true, 481 | NETM(GetJAvg), NETM(GetJAvgUnsafe) }, 482 | {'X', "X: Worst Jitter", "Jmax", " %4d", 5, false, 483 | NETM(GetJWorst), NETM(GetJWorstUnsafe) }, 484 | {'I', "I: Interarrival Jitter", "Jint", " %4d", 5, false, 485 | NETM(GetJInta), NETM(GetJIntaUnsafe) }, 486 | {'\0', NULL, NULL, NULL, 0, false, NULL, NULL} 487 | }; 488 | -------------------------------------------------------------------------------- /src-cmd/WinMTRCmd.h: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRCmd.h 3 | // 4 | // 5 | // DESCRIPTION: The entry class for WinMTRCmd, fetches program parameters, 6 | // utilizes WinMTRNet to perform the mtr service and prints 7 | // reports. 8 | // 9 | // 10 | // NOTES: This class is based on WinMTRDialog and WinMTRMain from WinMTR-v092. 11 | // The report print code has been directly taken from mtr-0.84 and 12 | // adapted to C++ and the WinMTRNet class. 13 | // 14 | // 15 | //***************************************************************************** 16 | 17 | #ifndef WINMTRCMD_H_ 18 | #define WINMTRCMD_H_ 19 | 20 | #include "WinMTRGlobal.h" 21 | #include "WinMTRNet.h" 22 | #include "WinMTRParams.h" 23 | 24 | //***************************************************************************** 25 | // CLASS: WinMTRCmd 26 | // 27 | // 28 | //***************************************************************************** 29 | 30 | class WinMTRCmd { 31 | 32 | public: 33 | WinMTRCmd(_TCHAR *name); 34 | 35 | void Run(); 36 | 37 | private: 38 | typedef void* (WinMTRNet::*VoidGetMethod)(int at); 39 | typedef int (WinMTRNet::*IntGetMethod)(int at); 40 | typedef float (WinMTRNet::*FloatGetMethod)(int at); 41 | 42 | static const int SafeGet = 0; 43 | static const int UnsafeGet = 1; 44 | 45 | static struct fields { 46 | unsigned char key; 47 | char *descr; 48 | char *title; 49 | char *format; 50 | int length; 51 | bool floatReturn; 52 | VoidGetMethod get[2]; 53 | }; 54 | 55 | bool ParseCommandLineParams(LPTSTR cmd, WinMTRParams *wmtrparams); 56 | bool ValidateParams(WinMTRParams *wmtrdlg); 57 | LPTSTR GetCommandLineParams(); 58 | bool GetParamValue(LPTSTR cmd, char * param, char sparam, char *value, bool flag); 59 | bool GetHostNameParamValue(LPTSTR cmd, std::string& value); 60 | 61 | void PrintReport(FILE* file, WinMTRNet* net, int getType, 62 | const char* fields, bool reportWide); 63 | int GetAddr(char* s); 64 | 65 | private: 66 | _TCHAR *programName; 67 | _TCHAR localHostname[256]; 68 | _TCHAR cmdLineParams[256]; 69 | 70 | static fields dataFields[]; 71 | int indexMapping[256]; 72 | }; 73 | 74 | #endif // ifndef WINMTRCMD_H_ -------------------------------------------------------------------------------- /src-cmd/WinMTRCmd.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | ARM 7 | 8 | 9 | Debug 10 | ARM64 11 | 12 | 13 | Debug 14 | Win32 15 | 16 | 17 | Debug 18 | x64 19 | 20 | 21 | Release 22 | ARM 23 | 24 | 25 | Release 26 | ARM64 27 | 28 | 29 | Release 30 | Win32 31 | 32 | 33 | Release 34 | x64 35 | 36 | 37 | 38 | 39 | 40 | WinMTRCmd 41 | {340746A1-78CE-F631-EFC6-5B7A479108B6} 42 | 10.0 43 | 44 | 45 | 46 | Application 47 | false 48 | MultiByte 49 | v143 50 | 51 | 52 | Application 53 | false 54 | MultiByte 55 | v143 56 | 57 | 58 | Application 59 | false 60 | MultiByte 61 | v143 62 | 63 | 64 | Application 65 | false 66 | MultiByte 67 | v143 68 | 69 | 70 | Application 71 | false 72 | MultiByte 73 | v142 74 | 75 | 76 | Application 77 | false 78 | MultiByte 79 | v142 80 | 81 | 82 | Application 83 | false 84 | MultiByte 85 | v142 86 | 87 | 88 | Application 89 | false 90 | MultiByte 91 | v143 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | .\bin\Release_x32\ 131 | .\obj\Release_x32\ 132 | false 133 | 134 | 135 | false 136 | .\bin\Release_ARM\ 137 | .\obj\Release_ARM\ 138 | 139 | 140 | false 141 | .\bin\Release_ARM64\ 142 | .\bin\Release_ARM64\ 143 | 144 | 145 | .\bin\Release_x64\ 146 | .\obj\Release_x64\ 147 | false 148 | 149 | 150 | .\bin\Debug_x32\ 151 | .\obj\Debug_x32\ 152 | true 153 | 154 | 155 | true 156 | .\bin\Debug_ARM\ 157 | .\obj\Debug_ARM\ 158 | 159 | 160 | true 161 | 162 | 163 | .\bin\Debug_x64\ 164 | .\obj\Debug_x64\ 165 | true 166 | 167 | 168 | 169 | MultiThreaded 170 | OnlyExplicitInline 171 | true 172 | 173 | 174 | MaxSpeed 175 | true 176 | Level3 177 | WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 178 | .\obj\Release_x32\ 179 | .\obj\Release_x32\WinMTRCmd.pch 180 | .\obj\Release_x32\ 181 | .\obj\Release_x32\ 182 | 183 | 184 | 185 | true 186 | NDEBUG;%(PreprocessorDefinitions) 187 | .\obj\Release_x32\WinMTRCmd.tlb 188 | true 189 | Win32 190 | 191 | 192 | 0x0409 193 | NDEBUG;%(PreprocessorDefinitions) 194 | 195 | 196 | true 197 | .\obj\Release_x32\WinMTRCmd.bsc 198 | 199 | 200 | true 201 | Console 202 | .\bin\Release_x32\mtr.exe 203 | odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 204 | AsInvoker 205 | false 206 | true 207 | 208 | 209 | 210 | 211 | MultiThreaded 212 | OnlyExplicitInline 213 | true 214 | 215 | 216 | MaxSpeed 217 | true 218 | Level3 219 | WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 220 | .\obj\Release_ARM\ 221 | .\obj\Release_ARM\WinMTRCmd.pch 222 | .\obj\Release_ARM\ 223 | .\obj\Release_ARM\ 224 | 225 | 226 | 227 | 228 | true 229 | NDEBUG;%(PreprocessorDefinitions) 230 | .\obj\Release_ARM\WinMTRCmd.tlb 231 | true 232 | 233 | 234 | 0x0409 235 | NDEBUG;%(PreprocessorDefinitions) 236 | 237 | 238 | true 239 | .\obj\Release_ARM\WinMTRCmd.bsc 240 | 241 | 242 | true 243 | Console 244 | .\bin\Release_ARM\mtr.exe 245 | odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 246 | AsInvoker 247 | false 248 | true 249 | 250 | 251 | 252 | 253 | MultiThreaded 254 | OnlyExplicitInline 255 | true 256 | 257 | 258 | MaxSpeed 259 | true 260 | Level3 261 | WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 262 | .\obj\Release_ARM64\ 263 | .\obj\Release_ARM64\WinMTRCmd.pch 264 | .\obj\Release_ARM64\ 265 | .\obj\Release_ARM64\ 266 | 267 | 268 | 269 | 270 | true 271 | NDEBUG;%(PreprocessorDefinitions) 272 | .\obj\Release_ARM64\WinMTRCmd.tlb 273 | true 274 | 275 | 276 | 0x0409 277 | NDEBUG;%(PreprocessorDefinitions) 278 | 279 | 280 | true 281 | .\obj\Release_ARM64\WinMTRCmd.bsc 282 | 283 | 284 | true 285 | Console 286 | .\bin\Release_ARM64\mtr.exe 287 | odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 288 | AsInvoker 289 | false 290 | true 291 | 292 | 293 | 294 | 295 | MultiThreaded 296 | OnlyExplicitInline 297 | true 298 | true 299 | MaxSpeed 300 | true 301 | Level3 302 | WIN32;_WIN64;_AMD64;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 303 | .\obj\Release_x64\ 304 | .\obj\Release_x64\WinMTRCmd.pch 305 | .\obj\Release_x64\ 306 | .\obj\Release_x64\ 307 | Default 308 | stdc11 309 | 310 | 311 | true 312 | NDEBUG;%(PreprocessorDefinitions) 313 | .\obj\Release_x64\WinMTRCmd.tlb 314 | true 315 | 316 | 317 | 0x0409 318 | NDEBUG;%(PreprocessorDefinitions) 319 | 320 | 321 | true 322 | .\obj\Release_x64\WinMTRCmd.bsc 323 | 324 | 325 | true 326 | Console 327 | .\bin\Release_x64\mtr.exe 328 | odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 329 | AsInvoker 330 | false 331 | true 332 | 333 | 334 | 335 | 336 | MultiThreadedDebug 337 | Default 338 | 339 | 340 | Disabled 341 | true 342 | Level3 343 | 344 | 345 | EditAndContinue 346 | WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 347 | .\bin\Debug_x32\ 348 | .\bin\Debug_x32\WinMTRCmd.pch 349 | .\obj\Debug_x32\ 350 | .\obj\Debug_x32\ 351 | EnableFastChecks 352 | 353 | 354 | true 355 | _DEBUG;%(PreprocessorDefinitions) 356 | .\obj\Debug_x32\WinMTRCmd.tlb 357 | true 358 | Win32 359 | 360 | 361 | 0x0409 362 | _DEBUG;%(PreprocessorDefinitions) 363 | 364 | 365 | true 366 | .\Debug_x32\WinMTRCmd.bsc 367 | 368 | 369 | true 370 | true 371 | Console 372 | .\bin\Debug_x32\mtr.exe 373 | odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 374 | AsInvoker 375 | false 376 | true 377 | 378 | 379 | 380 | 381 | MultiThreadedDebug 382 | Default 383 | 384 | 385 | Disabled 386 | true 387 | Level3 388 | 389 | 390 | EditAndContinue 391 | WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 392 | .\bin\Debug_ARM\ 393 | .\bin\Debug_ARM\WinMTRCmd.pch 394 | .\obj\Debug_ARM\ 395 | .\obj\Debug_ARM\ 396 | EnableFastChecks 397 | 398 | 399 | true 400 | _DEBUG;%(PreprocessorDefinitions) 401 | .\obj\Debug_ARM\WinMTRCmd.tlb 402 | true 403 | 404 | 405 | 0x0409 406 | _DEBUG;%(PreprocessorDefinitions) 407 | 408 | 409 | true 410 | .\Debug_ARM\WinMTRCmd.bsc 411 | 412 | 413 | true 414 | true 415 | Console 416 | .\bin\Debug_ARM\mtr.exe 417 | odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 418 | AsInvoker 419 | false 420 | true 421 | 422 | 423 | 424 | 425 | MultiThreadedDebug 426 | Default 427 | 428 | 429 | Disabled 430 | true 431 | Level3 432 | 433 | 434 | EditAndContinue 435 | WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 436 | .\bin\Debug_ARM64\ 437 | .\bin\Debug_ARM64\WinMTRCmd.pch 438 | .\obj\Debug_ARM64\ 439 | .\obj\Debug_ARM64\ 440 | EnableFastChecks 441 | 442 | 443 | true 444 | _DEBUG;%(PreprocessorDefinitions) 445 | .\obj\Debug_ARM64\WinMTRCmd.tlb 446 | true 447 | 448 | 449 | 0x0409 450 | _DEBUG;%(PreprocessorDefinitions) 451 | 452 | 453 | true 454 | .\Debug_ARM64\WinMTRCmd.bsc 455 | 456 | 457 | true 458 | true 459 | Console 460 | .\bin\Debug_ARM64\mtr.exe 461 | odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 462 | AsInvoker 463 | false 464 | true 465 | 466 | 467 | 468 | 469 | MultiThreadedDebug 470 | Default 471 | false 472 | Disabled 473 | true 474 | Level3 475 | ProgramDatabase 476 | WIN32;_WIN64;_AMD64;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 477 | .\obj\Debug_x64\ 478 | .\obj\Debug_x64\WinMTRCmd.pch 479 | .\obj\Debug_x64\ 480 | .\obj\Debug_x64\ 481 | EnableFastChecks 482 | 483 | 484 | true 485 | _DEBUG;%(PreprocessorDefinitions) 486 | .\obj\Debug_x64\WinMTRCmd.tlb 487 | true 488 | 489 | 490 | 0x0409 491 | _DEBUG;%(PreprocessorDefinitions) 492 | 493 | 494 | true 495 | .\obj\Debug_x64\WinMTRCmd.bsc 496 | 497 | 498 | true 499 | true 500 | Console 501 | .\bin\Debug_x64\mtr.exe 502 | odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 503 | AsInvoker 504 | false 505 | true 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | -------------------------------------------------------------------------------- /src-cmd/WinMTRGlobal.h: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRGlobal.h 3 | // 4 | // 5 | // DESCRIPTION: Contains global definitions for the WinMTRCmd application. 6 | // 7 | // 8 | // NOTES: Based on WinMTRGlobal.h from WinMTR-v092. 9 | // 10 | // 11 | //***************************************************************************** 12 | 13 | #ifndef GLOBAL_H_ 14 | #define GLOBAL_H_ 15 | 16 | #ifndef _WIN64 17 | #define _USE_32BIT_TIME_T 18 | #endif 19 | 20 | #define VC_EXTRALEAN 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #pragma comment(lib, "Ws2_32.lib") 40 | 41 | #define WINMTR_VERSION_STR "WinMTR 0.9 (c) 2010-2011 Appnor MSP - http://WinMTR.sourceforge.net" 42 | #define MTR_VERSION_STR "mtr 0.84 - http://www.bitwizard.nl/mtr/" 43 | 44 | #define WINMTRCMD_VERSION "0.1" 45 | #define WINMTRCMD_HOMEPAGE "http://WinMTRCmd.sourceforge.net" 46 | #define WINMTRCMD_LICENSE "GPL - GNU Public License" 47 | 48 | #define DEFAULT_REPORT FALSE 49 | #define DEFAULT_WIDE FALSE 50 | #define DEFAULT_DNS TRUE 51 | #define DEFAULT_CYCLES 10 52 | #define DEFAULT_INTERVAL 1.0 53 | #define DEFAULT_PING_SIZE 64 54 | #define DEFAULT_TIMEOUT 5.0 55 | #define DEFAULT_FIELDS "LS NABWV" 56 | 57 | #define MAX_HOPS 40 58 | 59 | #define MAXPACKET 4096 60 | #define MINPACKET 64 61 | 62 | #define CLS() system("cls") 63 | 64 | #endif // ifndef GLOBAL_H_ 65 | -------------------------------------------------------------------------------- /src-cmd/WinMTRNet.cpp: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRNet.cpp 3 | // 4 | //***************************************************************************** 5 | #include "WinMTRGlobal.h" 6 | #include "WinMTRNet.h" 7 | #include "WinMTRParams.h" 8 | #include 9 | 10 | #define TRACE_MSG(msg) \ 11 | { \ 12 | std::ostringstream dbg_msg(std::ostringstream::out); \ 13 | dbg_msg << msg << std::endl; \ 14 | OutputDebugString(dbg_msg.str().c_str()); \ 15 | } 16 | 17 | #define IPFLAG_DONT_FRAGMENT 0x02 18 | 19 | struct trace_thread { 20 | int address; 21 | WinMTRNet *winmtr; 22 | int ttl; 23 | }; 24 | 25 | struct dns_resolver_thread { 26 | int index; 27 | WinMTRNet *winmtr; 28 | }; 29 | 30 | void FinishThread(void *p); 31 | void TraceThread(void *p); 32 | void DnsResolverThread(void *p); 33 | 34 | WinMTRNet::WinMTRNet(WinMTRParams *p) { 35 | 36 | ghMutex = CreateMutex(NULL, FALSE, NULL); 37 | tracing = false; 38 | initialized = false; 39 | wmtrparams = p; 40 | WSADATA wsaData; 41 | 42 | if( WSAStartup(MAKEWORD(2, 2), &wsaData) ) { 43 | fprintf(stderr, "error: failed initializing windows sockets library\n"); 44 | return; 45 | } 46 | 47 | hICMP_DLL = LoadLibrary(_T("ICMP.DLL")); 48 | if (hICMP_DLL == 0) { 49 | fprintf(stderr, "error: unable to locate ICMP.DLL\n"); 50 | return; 51 | } 52 | 53 | /* 54 | * Get pointers to ICMP.DLL functions 55 | */ 56 | lpfnIcmpCreateFile = (LPFNICMPCREATEFILE)GetProcAddress(hICMP_DLL,"IcmpCreateFile"); 57 | lpfnIcmpCloseHandle = (LPFNICMPCLOSEHANDLE)GetProcAddress(hICMP_DLL,"IcmpCloseHandle"); 58 | lpfnIcmpSendEcho = (LPFNICMPSENDECHO)GetProcAddress(hICMP_DLL,"IcmpSendEcho"); 59 | if ((!lpfnIcmpCreateFile) || (!lpfnIcmpCloseHandle) || (!lpfnIcmpSendEcho)) { 60 | fprintf(stderr, "error: wrong ICMP.DLL system library\n"); 61 | return; 62 | } 63 | 64 | /* 65 | * IcmpCreateFile() - Open the ping service 66 | */ 67 | hICMP = (HANDLE) lpfnIcmpCreateFile(); 68 | if (hICMP == INVALID_HANDLE_VALUE) { 69 | fprintf(stderr, "error: could not create ICMP file handle\n"); 70 | return; 71 | } 72 | 73 | ResetHops(); 74 | 75 | initialized = true; 76 | return; 77 | } 78 | 79 | WinMTRNet::~WinMTRNet() 80 | { 81 | if(initialized) { 82 | /* 83 | * IcmpCloseHandle - Close the ICMP handle 84 | */ 85 | lpfnIcmpCloseHandle(hICMP); 86 | 87 | // Shut down... 88 | FreeLibrary(hICMP_DLL); 89 | 90 | WSACleanup(); 91 | 92 | CloseHandle(ghMutex); 93 | } 94 | } 95 | 96 | void WinMTRNet::ResetHops() 97 | { 98 | memset(host, 0, MAX_HOPS * sizeof(s_nethost)); 99 | } 100 | 101 | void WinMTRNet::DoTrace(int address, bool async) 102 | { 103 | tracing = true; 104 | 105 | ResetHops(); 106 | 107 | last_remote_addr = address; 108 | 109 | // one thread per TTL value 110 | for(int i = 0; i < MAX_HOPS; i++) { 111 | trace_thread *current = new trace_thread; 112 | current->address = address; 113 | current->winmtr = this; 114 | current->ttl = i + 1; 115 | hThreads[i] = (HANDLE)_beginthread(TraceThread, 0 , current); 116 | } 117 | 118 | if (async) 119 | _beginthread(FinishThread, 0 , this); 120 | else 121 | FinishThread(this); 122 | } 123 | 124 | void WinMTRNet::StopTrace() 125 | { 126 | tracing = false; 127 | } 128 | 129 | bool WinMTRNet::IsTracing() 130 | { 131 | return tracing; 132 | } 133 | 134 | void FinishThread(void *p) 135 | { 136 | WinMTRNet *wmtrnet = (WinMTRNet*)p; 137 | 138 | WaitForMultipleObjects(MAX_HOPS, wmtrnet->hThreads, TRUE, INFINITE); 139 | 140 | wmtrnet->tracing = false; 141 | } 142 | 143 | void TraceThread(void *p) 144 | { 145 | trace_thread* current = (trace_thread*)p; 146 | WinMTRNet *wmtrnet = current->winmtr; 147 | TRACE_MSG("Thread with TTL=" << current->ttl << " started."); 148 | 149 | s_nethost *nethost; 150 | IPINFO stIPInfo, *lpstIPInfo; 151 | DWORD dwReplyCount; 152 | int rtt; 153 | char achReqData[8192]; 154 | int nDataLen = wmtrnet->wmtrparams->pingsize; 155 | char achRepData[sizeof(ICMPECHO) + 8192]; 156 | int cycle = 0; 157 | float oldavg, oldjavg; 158 | 159 | nethost = &wmtrnet->host[current->ttl - 1]; 160 | 161 | /* 162 | * Init IPInfo structure 163 | */ 164 | lpstIPInfo = &stIPInfo; 165 | stIPInfo.Ttl = current->ttl; 166 | stIPInfo.Tos = 0; 167 | stIPInfo.Flags = IPFLAG_DONT_FRAGMENT; 168 | stIPInfo.OptionsSize = 0; 169 | stIPInfo.OptionsData = NULL; 170 | 171 | for (int i=0; itracing && cycle++ < wmtrnet->wmtrparams->cycles) { 174 | 175 | // For some strange reason, ICMP API is not filling the TTL for icmp echo reply 176 | // Check if the current thread should be closed 177 | if( current->ttl > wmtrnet->GetMax() ) break; 178 | 179 | // NOTE: some servers does not respond back everytime, if TTL expires in transit; e.g. : 180 | // 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 181 | // but if we are pinging ping -n 20 -w 5000 -l 64 219.80.240.93 we have 0% loss 182 | // A resolution would be: 183 | // - as soon as we get a hop, we start pinging directly that hop, with a greater TTL 184 | // - a drawback would be that, some servers are configured to reply for TTL transit expire, but not to ping requests, so, 185 | // for these servers we'll have 100% loss 186 | dwReplyCount = wmtrnet->lpfnIcmpSendEcho(wmtrnet->hICMP, current->address, achReqData, nDataLen, lpstIPInfo, achRepData, sizeof(achRepData), 187 | (int)(wmtrnet->wmtrparams->timeout * 1000)); 188 | 189 | PICMPECHO icmp_echo_reply = (PICMPECHO)achRepData; 190 | rtt = icmp_echo_reply->RoundTripTime; 191 | 192 | nethost->xmit++; 193 | if (dwReplyCount != 0) { 194 | TRACE_MSG("TTL " << current->ttl << " reply TTL " << icmp_echo_reply->Options.Ttl << " Status " << icmp_echo_reply->Status << " Reply count " << dwReplyCount); 195 | 196 | WaitForSingleObject(wmtrnet->ghMutex, INFINITE); 197 | switch(icmp_echo_reply->Status) { 198 | case IP_SUCCESS: 199 | case IP_TTL_EXPIRED_TRANSIT: 200 | 201 | // the following code is taken directly from the mtr-0.84 net implementation 202 | 203 | nethost->jitter = rtt - nethost->last; 204 | if (nethost->jitter < 0) nethost->jitter = -nethost->jitter; 205 | nethost->last = rtt; 206 | 207 | if (nethost->returned < 1) 208 | { 209 | nethost->best = nethost->worst = rtt; 210 | nethost->gmean = rtt; 211 | nethost->avg = 0; 212 | nethost->var = 0; 213 | nethost->jitter = nethost->jworst = nethost->jinta = 0; 214 | } 215 | 216 | if (rtt < nethost->best ) nethost->best = rtt; 217 | if (rtt > nethost->worst) nethost->worst = rtt; 218 | 219 | if (nethost->jitter > nethost->jworst) 220 | nethost->jworst = nethost->jitter; 221 | 222 | nethost->returned++; 223 | 224 | oldavg = nethost->avg; 225 | nethost->avg += (float)(rtt - oldavg) / nethost->returned; 226 | nethost->var += (rtt - oldavg) * (rtt - nethost->avg); 227 | 228 | oldjavg = nethost->javg; 229 | nethost->javg += (nethost->jitter - oldjavg) / nethost->returned; 230 | 231 | nethost->jinta += nethost->jitter - ((nethost->jinta + 8) >> 4); 232 | 233 | if (nethost->returned > 1) 234 | nethost->gmean = pow((float) nethost->gmean, (nethost->returned - 1.0f) / nethost->returned) 235 | * pow((float) rtt, 1.0f / nethost->returned); 236 | else 237 | nethost->gmean = rtt; 238 | 239 | wmtrnet->SetAddr(current->ttl - 1, icmp_echo_reply->Address); 240 | break; 241 | case IP_BUF_TOO_SMALL: 242 | wmtrnet->SetName(current->ttl - 1, "Reply buffer too small."); 243 | break; 244 | case IP_DEST_NET_UNREACHABLE: 245 | wmtrnet->SetName(current->ttl - 1, "Destination network unreachable."); 246 | break; 247 | case IP_DEST_HOST_UNREACHABLE: 248 | wmtrnet->SetName(current->ttl - 1, "Destination host unreachable."); 249 | break; 250 | case IP_DEST_PROT_UNREACHABLE: 251 | wmtrnet->SetName(current->ttl - 1, "Destination protocol unreachable."); 252 | break; 253 | case IP_DEST_PORT_UNREACHABLE: 254 | wmtrnet->SetName(current->ttl - 1, "Destination port unreachable."); 255 | break; 256 | case IP_NO_RESOURCES: 257 | wmtrnet->SetName(current->ttl - 1, "Insufficient IP resources were available."); 258 | break; 259 | case IP_BAD_OPTION: 260 | wmtrnet->SetName(current->ttl - 1, "Bad IP option was specified."); 261 | break; 262 | case IP_HW_ERROR: 263 | wmtrnet->SetName(current->ttl - 1, "Hardware error occurred."); 264 | break; 265 | case IP_PACKET_TOO_BIG: 266 | wmtrnet->SetName(current->ttl - 1, "Packet was too big."); 267 | break; 268 | case IP_REQ_TIMED_OUT: 269 | wmtrnet->SetName(current->ttl - 1, "Request timed out."); 270 | break; 271 | case IP_BAD_REQ: 272 | wmtrnet->SetName(current->ttl - 1, "Bad request."); 273 | break; 274 | case IP_BAD_ROUTE: 275 | wmtrnet->SetName(current->ttl - 1, "Bad route."); 276 | break; 277 | case IP_TTL_EXPIRED_REASSEM: 278 | wmtrnet->SetName(current->ttl - 1, "The time to live expired during fragment reassembly."); 279 | break; 280 | case IP_PARAM_PROBLEM: 281 | wmtrnet->SetName(current->ttl - 1, "Parameter problem."); 282 | break; 283 | case IP_SOURCE_QUENCH: 284 | wmtrnet->SetName(current->ttl - 1, "Datagrams are arriving too fast to be processed and datagrams may have been discarded."); 285 | break; 286 | case IP_OPTION_TOO_BIG: 287 | wmtrnet->SetName(current->ttl - 1, "An IP option was too big."); 288 | break; 289 | case IP_BAD_DESTINATION: 290 | wmtrnet->SetName(current->ttl - 1, "Bad destination."); 291 | break; 292 | case IP_GENERAL_FAILURE: 293 | wmtrnet->SetName(current->ttl - 1, "General failure."); 294 | break; 295 | default: 296 | wmtrnet->SetName(current->ttl - 1, "General failure."); 297 | } 298 | ReleaseMutex(wmtrnet->ghMutex); 299 | 300 | if(wmtrnet->wmtrparams->interval * 1000 > icmp_echo_reply->RoundTripTime) 301 | Sleep(wmtrnet->wmtrparams->interval * 1000 - icmp_echo_reply->RoundTripTime); 302 | } 303 | 304 | } /* end ping loop */ 305 | 306 | TRACE_MSG("Thread with TTL=" << current->ttl << " stopped."); 307 | 308 | delete p; 309 | _endthread(); 310 | } 311 | 312 | int WinMTRNet::GetAddr(int at) 313 | { 314 | WaitForSingleObject(ghMutex, INFINITE); 315 | int addr = ntohl(host[at].addr); 316 | ReleaseMutex(ghMutex); 317 | return addr; 318 | } 319 | 320 | int WinMTRNet::GetName(int at, char *n) 321 | { 322 | WaitForSingleObject(ghMutex, INFINITE); 323 | GetNameUnsafe(at, n); 324 | ReleaseMutex(ghMutex); 325 | return 0; 326 | } 327 | 328 | int WinMTRNet::GetBest(int at) 329 | { 330 | WaitForSingleObject(ghMutex, INFINITE); 331 | int ret = host[at].best; 332 | ReleaseMutex(ghMutex); 333 | return ret; 334 | } 335 | 336 | int WinMTRNet::GetWorst(int at) 337 | { 338 | WaitForSingleObject(ghMutex, INFINITE); 339 | int ret = host[at].worst; 340 | ReleaseMutex(ghMutex); 341 | return ret; 342 | } 343 | 344 | float WinMTRNet::GetAvg(int at) 345 | { 346 | WaitForSingleObject(ghMutex, INFINITE); 347 | float ret = host[at].avg; 348 | ReleaseMutex(ghMutex); 349 | return ret; 350 | } 351 | 352 | float WinMTRNet::GetPercent(int at) 353 | { 354 | WaitForSingleObject(ghMutex, INFINITE); 355 | float ret = (host[at].xmit == 0) ? 0 : (100.0f - (100.0f * host[at].returned / host[at].xmit)); 356 | ReleaseMutex(ghMutex); 357 | return ret; 358 | } 359 | 360 | int WinMTRNet::GetLast(int at) 361 | { 362 | WaitForSingleObject(ghMutex, INFINITE); 363 | int ret = host[at].last; 364 | ReleaseMutex(ghMutex); 365 | return ret; 366 | } 367 | 368 | int WinMTRNet::GetReturned(int at) 369 | { 370 | WaitForSingleObject(ghMutex, INFINITE); 371 | int ret = host[at].returned; 372 | ReleaseMutex(ghMutex); 373 | return ret; 374 | } 375 | 376 | int WinMTRNet::GetXmit(int at) 377 | { 378 | WaitForSingleObject(ghMutex, INFINITE); 379 | int ret = host[at].xmit; 380 | ReleaseMutex(ghMutex); 381 | return ret; 382 | } 383 | 384 | int WinMTRNet::GetDropped(int at) 385 | { 386 | WaitForSingleObject(ghMutex, INFINITE); 387 | int ret = host[at].xmit - host[at].returned; 388 | ReleaseMutex(ghMutex); 389 | return ret; 390 | } 391 | 392 | float WinMTRNet::GetStDev(int at) 393 | { 394 | WaitForSingleObject(ghMutex, INFINITE); 395 | float ret = GetStDevUnsafe(at); 396 | ReleaseMutex(ghMutex); 397 | return ret; 398 | } 399 | 400 | float WinMTRNet::GetGMean(int at) 401 | { 402 | WaitForSingleObject(ghMutex, INFINITE); 403 | float ret = host[at].gmean; 404 | ReleaseMutex(ghMutex); 405 | return ret; 406 | } 407 | 408 | int WinMTRNet::GetJitter(int at) 409 | { 410 | WaitForSingleObject(ghMutex, INFINITE); 411 | int ret = host[at].jitter; 412 | ReleaseMutex(ghMutex); 413 | return ret; 414 | } 415 | 416 | float WinMTRNet::GetJAvg(int at) 417 | { 418 | WaitForSingleObject(ghMutex, INFINITE); 419 | float ret = host[at].javg; 420 | ReleaseMutex(ghMutex); 421 | return ret; 422 | } 423 | 424 | int WinMTRNet::GetJWorst(int at) 425 | { 426 | WaitForSingleObject(ghMutex, INFINITE); 427 | int ret = host[at].jworst; 428 | ReleaseMutex(ghMutex); 429 | return ret; 430 | } 431 | 432 | int WinMTRNet::GetJInta(int at) 433 | { 434 | WaitForSingleObject(ghMutex, INFINITE); 435 | int ret = host[at].jinta; 436 | ReleaseMutex(ghMutex); 437 | return ret; 438 | } 439 | 440 | int WinMTRNet::GetMax() 441 | { 442 | WaitForSingleObject(ghMutex, INFINITE); 443 | int ret = GetMaxUnsafe(); 444 | ReleaseMutex(ghMutex); 445 | return ret; 446 | } 447 | 448 | int WinMTRNet::GetAddrUnsafe(int at) 449 | { 450 | return ntohl(host[at].addr); 451 | } 452 | 453 | int WinMTRNet::GetNameUnsafe(int at, char *n) 454 | { 455 | if(!strcmp(host[at].name, "")) { 456 | int addr = GetAddr(at); 457 | sprintf (n, "%d.%d.%d.%d", 458 | (addr >> 24) & 0xff, 459 | (addr >> 16) & 0xff, 460 | (addr >> 8) & 0xff, 461 | addr & 0xff 462 | ); 463 | if(addr==0) 464 | strcpy(n,"???"); 465 | } else { 466 | strcpy(n, host[at].name); 467 | } 468 | return 0; 469 | } 470 | 471 | int WinMTRNet::GetBestUnsafe(int at) 472 | { 473 | return host[at].best; 474 | } 475 | 476 | int WinMTRNet::GetWorstUnsafe(int at) 477 | { 478 | return host[at].worst; 479 | } 480 | 481 | float WinMTRNet::GetAvgUnsafe(int at) 482 | { 483 | return host[at].avg; 484 | } 485 | 486 | float WinMTRNet::GetPercentUnsafe(int at) 487 | { 488 | return (host[at].xmit == 0) ? 0.0f : 489 | (100.0f - (100.0f * host[at].returned / host[at].xmit)); 490 | } 491 | 492 | int WinMTRNet::GetLastUnsafe(int at) 493 | { 494 | return host[at].last; 495 | } 496 | 497 | int WinMTRNet::GetReturnedUnsafe(int at) 498 | { 499 | return host[at].returned; 500 | } 501 | 502 | int WinMTRNet::GetXmitUnsafe(int at) 503 | { 504 | return host[at].xmit; 505 | } 506 | 507 | int WinMTRNet::GetDroppedUnsafe(int at) 508 | { 509 | return host[at].xmit - host[at].returned; 510 | } 511 | 512 | float WinMTRNet::GetStDevUnsafe(int at) 513 | { 514 | if (host[at].returned > 1) { 515 | return sqrt(host[at].var / (host[at].returned - 1.0f)); 516 | } else 517 | return 0; 518 | } 519 | 520 | float WinMTRNet::GetGMeanUnsafe(int at) 521 | { 522 | return host[at].gmean; 523 | } 524 | 525 | int WinMTRNet::GetJitterUnsafe(int at) 526 | { 527 | return host[at].jitter; 528 | } 529 | 530 | float WinMTRNet::GetJAvgUnsafe(int at) 531 | { 532 | return host[at].javg; 533 | } 534 | 535 | int WinMTRNet::GetJWorstUnsafe(int at) 536 | { 537 | return host[at].jworst; 538 | } 539 | 540 | int WinMTRNet::GetJIntaUnsafe(int at) 541 | { 542 | return host[at].jinta; 543 | } 544 | 545 | int WinMTRNet::GetMaxUnsafe() 546 | { 547 | int max = MAX_HOPS; 548 | 549 | // first match: traced address responds on ping requests, and the address is in the hosts list 550 | for(int i = 0; i < MAX_HOPS; i++) { 551 | if(host[i].addr == last_remote_addr) { 552 | max = i + 1; 553 | break; 554 | } 555 | } 556 | 557 | // second match: traced address doesn't responds on ping requests 558 | if(max == MAX_HOPS) { 559 | while((max > 1) && (host[max - 1].addr == host[max - 2].addr) && (host[max - 1].addr != 0) ) max--; 560 | } 561 | 562 | return max; 563 | } 564 | 565 | void WinMTRNet::SetAddr(int at, __int32 addr) 566 | { 567 | if(host[at].addr == 0 && addr != 0) { 568 | TRACE_MSG("Start DnsResolverThread for new address " << addr << ". Old addr value was " << host[at].addr); 569 | host[at].addr = addr; 570 | if(wmtrparams->useDNS) 571 | { 572 | dns_resolver_thread *dnt = new dns_resolver_thread; 573 | dnt->index = at; 574 | dnt->winmtr = this; 575 | _beginthread(DnsResolverThread, 0, dnt); 576 | } 577 | } 578 | } 579 | 580 | void WinMTRNet::SetName(int at, char *n) 581 | { 582 | strcpy(host[at].name, n); 583 | } 584 | 585 | void DnsResolverThread(void *p) 586 | { 587 | TRACE_MSG("DNS resolver thread started."); 588 | dns_resolver_thread *dnt = (dns_resolver_thread*)p; 589 | WinMTRNet* wn = dnt->winmtr; 590 | 591 | struct hostent *phent ; 592 | 593 | char buf[100]; 594 | int addr = wn->GetAddr(dnt->index); 595 | sprintf (buf, "%d.%d.%d.%d", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); 596 | 597 | int haddr = htonl(addr); 598 | phent = gethostbyaddr( (const char*)&haddr, sizeof(int), AF_INET); 599 | 600 | WaitForSingleObject(wn->ghMutex, INFINITE); 601 | if(phent) { 602 | wn->SetName(dnt->index, phent->h_name); 603 | } else { 604 | wn->SetName(dnt->index, buf); 605 | } 606 | ReleaseMutex(wn->ghMutex); 607 | 608 | delete p; 609 | TRACE_MSG("DNS resolver thread stopped."); 610 | _endthread(); 611 | } 612 | -------------------------------------------------------------------------------- /src-cmd/WinMTRNet.h: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRNet.h 3 | // 4 | // 5 | // DESCRIPTION: The WinMTRNet class implements the core ping and traceroute 6 | // functionality. 7 | // 8 | // 9 | // NOTES: This class is heavily based on the WinMTRNet class from WinMTR-v092. 10 | // Additional code from mtr-0.84 has been merged into this to provide 11 | // a broader spectrum of statistics. 12 | // 13 | // 14 | //***************************************************************************** 15 | 16 | #ifndef WINMTRNET_H_ 17 | #define WINMTRNET_H_ 18 | 19 | 20 | class WinMTRParams; 21 | 22 | typedef ip_option_information IPINFO, *PIPINFO, FAR *LPIPINFO; 23 | 24 | #ifdef _WIN64 25 | typedef icmp_echo_reply32 ICMPECHO, *PICMPECHO, FAR *LPICMPECHO; 26 | #else 27 | typedef icmp_echo_reply ICMPECHO, *PICMPECHO, FAR *LPICMPECHO; 28 | #endif 29 | 30 | struct s_nethost { 31 | __int32 addr; // IP as a decimal, big endian 32 | int xmit; // number of PING packets sent 33 | int returned; // number of ICMP echo replies received 34 | int last; // last time 35 | int best; // best time 36 | int worst; // worst time 37 | float avg; // average 38 | float var; // variance 39 | float gmean; // geometric mean 40 | int jitter; // current jitter, defined as t1-t0 41 | float javg; // avg jitter 42 | int jworst; // max jitter 43 | int jinta; // estimated variance,? rfc1889's "Interarrival Jitter" 44 | char name[255]; 45 | }; 46 | 47 | //***************************************************************************** 48 | // CLASS: WinMTRNet 49 | // 50 | // 51 | //***************************************************************************** 52 | 53 | class WinMTRNet { 54 | typedef HANDLE (WINAPI *LPFNICMPCREATEFILE)(VOID); 55 | typedef BOOL (WINAPI *LPFNICMPCLOSEHANDLE)(HANDLE); 56 | typedef DWORD (WINAPI *LPFNICMPSENDECHO)(HANDLE, u_long, LPVOID, WORD, LPVOID, LPVOID, DWORD, DWORD); 57 | 58 | friend void FinishThread(void *p); 59 | friend void TraceThread(void *p); 60 | friend void DnsResolverThread(void *p); 61 | 62 | public: 63 | 64 | WinMTRNet(WinMTRParams *p); 65 | ~WinMTRNet(); 66 | void DoTrace(int address, bool async); 67 | void ResetHops(); 68 | void StopTrace(); 69 | bool IsTracing(); 70 | 71 | int GetAddr(int at); 72 | int GetName(int at, char *n); 73 | int GetBest(int at); 74 | int GetWorst(int at); 75 | float GetAvg(int at); 76 | float GetPercent(int at); 77 | int GetLast(int at); 78 | int GetReturned(int at); 79 | int GetXmit(int at); 80 | int GetDropped(int at); 81 | float GetStDev(int at); 82 | float GetGMean(int at); 83 | int GetJitter(int at); 84 | float GetJAvg(int at); 85 | int GetJWorst(int at); 86 | int GetJInta(int at); 87 | int GetMax(); 88 | 89 | // these getter versions are not thread safe, but significantly faster 90 | int GetAddrUnsafe(int at); 91 | int GetNameUnsafe(int at, char *n); 92 | int GetBestUnsafe(int at); 93 | int GetWorstUnsafe(int at); 94 | float GetAvgUnsafe(int at); 95 | float GetPercentUnsafe(int at); 96 | int GetLastUnsafe(int at); 97 | int GetReturnedUnsafe(int at); 98 | int GetXmitUnsafe(int at); 99 | int GetDroppedUnsafe(int at); 100 | float GetStDevUnsafe(int at); 101 | float GetGMeanUnsafe(int at); 102 | int GetJitterUnsafe(int at); 103 | float GetJAvgUnsafe(int at); 104 | int GetJWorstUnsafe(int at); 105 | int GetJIntaUnsafe(int at); 106 | int GetMaxUnsafe(); 107 | 108 | private: 109 | void SetAddr(int at, __int32 addr); 110 | void SetName(int at, char *n); 111 | 112 | private: 113 | HANDLE hThreads[MAX_HOPS]; 114 | 115 | WinMTRParams *wmtrparams; 116 | __int32 last_remote_addr; 117 | bool tracing; 118 | bool initialized; 119 | HANDLE hICMP; 120 | LPFNICMPCREATEFILE lpfnIcmpCreateFile; 121 | LPFNICMPCLOSEHANDLE lpfnIcmpCloseHandle; 122 | LPFNICMPSENDECHO lpfnIcmpSendEcho; 123 | 124 | HINSTANCE hICMP_DLL; 125 | 126 | struct s_nethost host[MAX_HOPS]; 127 | HANDLE ghMutex; 128 | }; 129 | 130 | #endif // ifndef WINMTRNET_H_ 131 | -------------------------------------------------------------------------------- /src-cmd/WinMTRParams.cpp: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRParams.cpp 3 | // 4 | // 5 | //***************************************************************************** 6 | 7 | #include "WinMTRParams.h" 8 | 9 | //***************************************************************************** 10 | // WinMTRParams::WinMTRParams 11 | // 12 | //***************************************************************************** 13 | 14 | WinMTRParams::WinMTRParams() 15 | : reportToFile(FALSE) 16 | { 17 | } 18 | 19 | //***************************************************************************** 20 | // WinMTRParams::SetHostName 21 | // 22 | //***************************************************************************** 23 | void WinMTRParams::SetHostName(const char *host) 24 | { 25 | _snprintf(hostname, SIZE_HOSTNAME, "%s", host); 26 | } 27 | 28 | //***************************************************************************** 29 | // WinMTRParams::SetCycles 30 | // 31 | //***************************************************************************** 32 | void WinMTRParams::SetCycles(int c) 33 | { 34 | cycles = c; 35 | } 36 | 37 | //***************************************************************************** 38 | // WinMTRParams::SetInterval 39 | // 40 | //***************************************************************************** 41 | void WinMTRParams::SetInterval(float i) 42 | { 43 | interval = i; 44 | } 45 | 46 | //***************************************************************************** 47 | // WinMTRParams::SetPingSize 48 | // 49 | //***************************************************************************** 50 | void WinMTRParams::SetPingSize(int ps) 51 | { 52 | pingsize = ps; 53 | } 54 | 55 | //***************************************************************************** 56 | // WinMTRParams::SetTimeout 57 | // 58 | //***************************************************************************** 59 | void WinMTRParams::SetTimeout(float t) 60 | { 61 | timeout = t; 62 | } 63 | 64 | //***************************************************************************** 65 | // WinMTRParams::SetReport 66 | // 67 | //***************************************************************************** 68 | void WinMTRParams::SetReport(bool b) 69 | { 70 | report = b; 71 | } 72 | 73 | //***************************************************************************** 74 | // WinMTRParams::SetUseDNS 75 | // 76 | //***************************************************************************** 77 | void WinMTRParams::SetUseDNS(bool udns) 78 | { 79 | useDNS = udns; 80 | } 81 | 82 | //***************************************************************************** 83 | // WinMTRParams::SetWide 84 | // 85 | //***************************************************************************** 86 | void WinMTRParams::SetWide(bool w) 87 | { 88 | wide = w; 89 | } 90 | 91 | //***************************************************************************** 92 | // WinMTRParams::SetFormat 93 | // 94 | //***************************************************************************** 95 | void WinMTRParams::SetFields(const char* f) 96 | { 97 | _snprintf(fields, SIZE_FIELDS, "%s", f); 98 | } 99 | 100 | //***************************************************************************** 101 | // WinMTRParams::SetFilename 102 | // 103 | //***************************************************************************** 104 | void WinMTRParams::SetFilename(const char *f) 105 | { 106 | reportToFile = TRUE; 107 | _snprintf(filename, SIZE_FILENAME, "%s", f); 108 | } 109 | -------------------------------------------------------------------------------- /src-cmd/WinMTRParams.h: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRParams.h 3 | // 4 | // 5 | // DESCRIPTION: The WinMTRParams class collects the parameters for running 6 | // an instance of WinMTRNet. 7 | // 8 | // 9 | // NOTES: 10 | // 11 | // 12 | //***************************************************************************** 13 | 14 | #ifndef WINMTROPTIONS_H_ 15 | #define WINMTROPTIONS_H_ 16 | 17 | #include "WinMTRGlobal.h" 18 | 19 | //***************************************************************************** 20 | // CLASS: WinMTRParams 21 | // 22 | // 23 | //***************************************************************************** 24 | 25 | #define SIZE_HOSTNAME 1024 26 | #define SIZE_FIELDS 64 27 | #define SIZE_FILENAME 1024 28 | 29 | class WinMTRParams { 30 | 31 | public: 32 | 33 | char hostname[SIZE_HOSTNAME]; 34 | int cycles; 35 | float interval; 36 | int pingsize; 37 | float timeout; 38 | bool report; 39 | bool useDNS; 40 | bool wide; 41 | char fields[SIZE_FIELDS]; 42 | bool reportToFile; 43 | char filename[SIZE_FILENAME]; 44 | 45 | WinMTRParams(); 46 | 47 | void SetHostName(const char *host); 48 | void SetCycles(int c); 49 | void SetInterval(float i); 50 | void SetPingSize(int ps); 51 | void SetTimeout(float t); 52 | void SetReport(bool b); 53 | void SetUseDNS(bool udns); 54 | void SetWide(bool w); 55 | void SetFields(const char *f); 56 | void SetFilename(const char *f); 57 | }; 58 | 59 | #endif // ifndef WINMTRPARAMS_H_ -------------------------------------------------------------------------------- /src/README.MD: -------------------------------------------------------------------------------- 1 | WinMTR - GUI MTR implementation for Windows 2 | ============= 3 | Thank you for downloading WinMTR v1.1! 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 | Read more about WinMTR’s history: http://winmtr.net/history/ 11 | 12 | ## License & Redistribution 13 | 14 | WinMTR is offered as Open Source Software under GPL v2. 15 | Read more about the licensing conditions: http://www.gnu.org/licenses/gpl-2.0.html 16 | Download the code from: http://sourceforge.net/projects/winmtr/ 17 | 18 | ## Installation 19 | 20 | You will get an executable. 21 | Just extract the WinMTR.exe for your platform (x86 or ARM, 32 or 64 bit) and click to run it. 22 | If you don’t know what version you need, just click on 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 | ## Usage 28 | 29 | **Visual:** 30 | 31 | - Start WinMTR. 32 | - Write the name or IP of the host (e.g. google.com) 33 | - Press the Options button to configure ping size, maximum hops and ping interval (the defaults are OK). 34 | - Push the Start button and wait. 35 | - Copy or export the results in text or HTML format. Useful if you want to document or file a complaint with your ISP. 36 | - Click on Clear History to remove the hosts you have previously traced. 37 | 38 | **Command line:** 39 | 40 | Run `winmtr.exe --help` to see what are the options 41 | 42 | Run `winmtr hostname` (e.g. winmtr www.yahoo.com) 43 | 44 | ## Troubleshooting 45 | 46 | 1. I type in the address and nothing happens. 47 | 48 | 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. 49 | 50 | 2. I get an error saying the program cannot be executed. 51 | 52 | You are running the 64 bit version on a 32-bit platform. Try the WinMTR.exe stored in the WinMTR_x32 folder. 53 | 54 | 3. I get an error unspecified here. 55 | 56 | Please report it to us to make sure it’s not a bug in the application. 57 | 58 | ### Bug Reports 59 | 60 | 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. 61 | Before submitting a bug make sure it is not something related to your own specific configurations (e.g. anti-viruses, firewalls). 62 | 63 | ### Feature requests 64 | 65 | 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. 66 | Specific features can be implemented on request under a commercial support agreement. Costs depend on complexity and timing. Contact us for a custom quotation. 67 | 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 68 | 69 | 70 | ## Contact 71 | 72 | Use the form available at https://sctools.cyou or write to us contact AT sctools DOT cyou 73 | 74 | See License.md to read the credits 75 | - -------------------------------------------------------------------------------- /src/WinMTR.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/appstars-dev/WinMTR/cf0bd3b90d564cca9e6e6dbdee2e06e7fb31c484/src/WinMTR.ico -------------------------------------------------------------------------------- /src/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 | ///////////////////////////////////////////////////////////////////////////// 23 | // 24 | // Menu 25 | // 26 | 27 | IDR_MAINMENU MENU 28 | BEGIN 29 | POPUP "File" 30 | BEGIN 31 | POPUP "Export" 32 | BEGIN 33 | MENUITEM "HTML to clipboard", ID_CHTC 34 | MENUITEM "HTML to file", ID_EXPH 35 | MENUITEM "TXT to clipboard", ID_CTTC 36 | MENUITEM "TXT to file", ID_EXPT 37 | END 38 | MENUITEM "Exit", ID_FILE_EXIT 39 | END 40 | POPUP "Help" 41 | BEGIN 42 | MENUITEM "Options", ID_OPTIONS 43 | MENUITEM "About", ID_ABOUT 44 | END 45 | END 46 | 47 | 48 | #ifdef APSTUDIO_INVOKED 49 | ///////////////////////////////////////////////////////////////////////////// 50 | // 51 | // TEXTINCLUDE 52 | // 53 | 54 | 1 TEXTINCLUDE 55 | BEGIN 56 | "resource.h\0" 57 | END 58 | 59 | 2 TEXTINCLUDE 60 | BEGIN 61 | "#include ""afxres.h""\r\n" 62 | "\0" 63 | END 64 | 65 | 3 TEXTINCLUDE 66 | BEGIN 67 | "#define _AFX_NO_SPLITTER_RESOURCES\r\n" 68 | "#define _AFX_NO_OLE_RESOURCES\r\n" 69 | "#define _AFX_NO_TRACKER_RESOURCES\r\n" 70 | "#define _AFX_NO_PROPERTY_RESOURCES\r\n" 71 | "\r\n" 72 | "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" 73 | "#ifdef _WIN32\r\n" 74 | "LANGUAGE 9, 1\r\n" 75 | "#pragma code_page(1252)\r\n" 76 | "#endif //_WIN32\r\n" 77 | "#include ""afxres.rc"" // Standard components\r\n" 78 | "#endif\r\n" 79 | "\0" 80 | END 81 | 82 | #endif // APSTUDIO_INVOKED 83 | 84 | 85 | ///////////////////////////////////////////////////////////////////////////// 86 | // 87 | // Icon 88 | // 89 | 90 | // Icon with lowest ID value placed first to ensure application icon 91 | // remains consistent on all systems. 92 | IDR_MAINFRAME ICON "WinMTR.ico" 93 | 94 | 95 | ///////////////////////////////////////////////////////////////////////////// 96 | // 97 | // Dialog 98 | // 99 | 100 | IDD_WINMTR_DIALOG DIALOGEX 0, 0, 421, 194 101 | STYLE DS_SETFONT | DS_3DLOOK | DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME 102 | EXSTYLE WS_EX_APPWINDOW 103 | MENU IDR_MAINMENU 104 | FONT 8, "MS Sans Serif", 0, 0, 0x1 105 | BEGIN 106 | DEFPUSHBUTTON "&Start",ID_RESTART,315,10,50,14,BS_FLAT 107 | CONTROL "List1",IDC_LIST_MTR,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER | WS_BORDER | WS_TABSTOP,5,32,409,157 108 | LTEXT "Host:",IDC_STATIC,11,10,20,13,SS_CENTERIMAGE 109 | GROUPBOX "",IDC_STATIC,5,0,365,30,BS_FLAT 110 | GROUPBOX "",IDC_STATICS,375,0,40,30,BS_FLAT 111 | COMBOBOX IDC_COMBO_HOST,33,10,277,73,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP 112 | CONTROL "IPv6",IDC_CHECK_IPV6,"Button",BS_AUTO3STATE | WS_TABSTOP,379,14,31,8 113 | END 114 | 115 | IDD_DIALOG_OPTIONS DIALOGEX 0, 0, 251, 164 116 | STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 117 | CAPTION "Options" 118 | FONT 8, "MS Sans Serif", 0, 0, 0x0 119 | BEGIN 120 | DEFPUSHBUTTON "&OK",IDOK,53,143,50,14,BS_FLAT 121 | PUSHBUTTON "&Cancel",IDCANCEL,141,143,50,14,BS_FLAT 122 | GROUPBOX "",IDC_STATIC,7,91,237,46,BS_FLAT 123 | ICON IDR_MAINFRAME,IDC_STATIC,15,12,20,20 124 | LTEXT "Interval (sec):",IDC_STATIC,15,102,45,10,NOT WS_GROUP 125 | EDITTEXT IDC_EDIT_INTERVAL,71,99,34,13,ES_AUTOHSCROLL 126 | LTEXT "Ping size (bytes):",IDC_STATIC,139,102,53,10,NOT WS_GROUP 127 | EDITTEXT IDC_EDIT_SIZE,196,99,34,13,ES_AUTOHSCROLL | ES_NUMBER 128 | CONTROL "Resolve names",IDC_CHECK_DNS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,167,119,63,8 129 | GROUPBOX "",IDC_STATIC,7,7,237,82,BS_FLAT 130 | CTEXT "WinMTR v1.1 is licensed under GNU GPLv2",IDC_STATIC,42,14,194,17 131 | PUSHBUTTON "&License",ID_LICENSE,81,67,94,14,BS_FLAT 132 | LTEXT "Max. hosts in LRU list:",IDC_STATIC,15,119,74,10,NOT WS_GROUP 133 | EDITTEXT IDC_EDIT_MAX_LRU,90,116,34,13,ES_AUTOHSCROLL 134 | LTEXT "Original application by Appnor.com (c) 2000-2001 \nWhite Tiger (c) 2004-2006 \nAUnited LTD (c) 2021",IDC_STATIC,49,34,172,25 135 | END 136 | 137 | IDD_DIALOG_PROPERTIES DIALOG 0, 0, 282, 160 138 | STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU 139 | CAPTION "Host properties" 140 | FONT 8, "MS Sans Serif" 141 | BEGIN 142 | DEFPUSHBUTTON "OK",IDOK,116,140,50,14,BS_FLAT 143 | LTEXT "Name:",IDC_STATIC,15,18,24,8 144 | EDITTEXT IDC_EDIT_PHOST,48,16,219,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY 145 | LTEXT "IP Address:",IDC_STATIC,14,32,40,9 146 | EDITTEXT IDC_EDIT_PIP,58,31,209,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY 147 | GROUPBOX "Packets",IDC_STATIC,46,74,89,60,BS_FLAT 148 | GROUPBOX "Ping time",IDC_STATIC,147,74,86,60,BS_FLAT 149 | GROUPBOX "Host",IDC_STATIC,7,7,267,62,BS_FLAT 150 | LTEXT "Loss (%):",IDC_STATIC,52,117,31,9 151 | LTEXT "Received:",IDC_STATIC,52,101,36,9 152 | LTEXT "Sent:",IDC_STATIC,52,85,21,9 153 | LTEXT "Last:",IDC_STATIC,153,84,18,9 154 | LTEXT "Best:",IDC_STATIC,153,96,20,8 155 | LTEXT "Average:",IDC_STATIC,153,107,32,8 156 | LTEXT "Worst:",IDC_STATIC,153,118,23,8 157 | EDITTEXT IDC_EDIT_PSENT,92,82,35,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER 158 | EDITTEXT IDC_EDIT_PRECV,92,99,35,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER 159 | EDITTEXT IDC_EDIT_PLOSS,92,116,35,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY | ES_NUMBER 160 | EDITTEXT IDC_EDIT_PLAST,189,81,34,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY 161 | EDITTEXT IDC_EDIT_PBEST,189,94,34,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY 162 | EDITTEXT IDC_EDIT_PAVRG,189,106,34,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY 163 | EDITTEXT IDC_EDIT_PWORST,189,118,34,12,ES_RIGHT | ES_AUTOHSCROLL | ES_READONLY 164 | EDITTEXT IDC_EDIT_PCOMMENT,14,50,253,12,ES_AUTOHSCROLL | ES_READONLY 165 | END 166 | 167 | IDD_DIALOG_HELP DIALOGEX 0, 0, 256, 122 168 | STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU 169 | CAPTION "WinMTR" 170 | FONT 8, "MS Shell Dlg", 400, 0, 0x1 171 | BEGIN 172 | DEFPUSHBUTTON "OK",IDOK,144,101,50,14 173 | LTEXT "www.cstools.cyou",IDC_STATIC,187,9,60,11 174 | LTEXT "WinMTR (Live) v1.1 is licensed under GPLv2",IDC_STATIC,7,9,176,10 175 | LTEXT "Usage: WinMTR [options] target_host_name",IDC_STATIC,7,29,144,8 176 | LTEXT "Options:",IDC_STATIC,7,39,28,8 177 | LTEXT " --interval, -i VALUE. Set ping interval.",IDC_STATIC,26,47,131,8 178 | LTEXT " --size, -s VALUE. Set ping size.",IDC_STATIC,26,57,109,8 179 | LTEXT " --maxLRU, -m VALUE. Set max hosts in LRU list.",IDC_STATIC,26,67,163,8 180 | LTEXT " --help, -h. Print this help.",IDC_STATIC,26,89,92,8 181 | LTEXT " --numeric, -n. Do not resolve names.",IDC_STATIC,26,78,129,8 182 | END 183 | 184 | 185 | ///////////////////////////////////////////////////////////////////////////// 186 | // 187 | // Version 188 | // 189 | 190 | VS_VERSION_INFO VERSIONINFO 191 | FILEVERSION 1,1,0,0 192 | PRODUCTVERSION 1,1,0,0 193 | FILEFLAGSMASK 0x3fL 194 | #ifdef _DEBUG 195 | FILEFLAGS 0x1L 196 | #else 197 | FILEFLAGS 0x0L 198 | #endif 199 | FILEOS 0x4L 200 | FILETYPE 0x1L 201 | FILESUBTYPE 0x0L 202 | BEGIN 203 | BLOCK "StringFileInfo" 204 | BEGIN 205 | BLOCK "040904b0" 206 | BEGIN 207 | VALUE "FileDescription", "WinMTR is a GUI MTR implementation for Windows" 208 | VALUE "FileVersion", "1.1.0.0" 209 | VALUE "InternalName", "WinMTR" 210 | VALUE "LegalCopyright", "WinMTR 1.1 (c) 2021" 211 | VALUE "OriginalFilename", "WinMTR.exe" 212 | VALUE "ProductName", "WinMTR" 213 | VALUE "ProductVersion", "1.1.0.0" 214 | END 215 | END 216 | BLOCK "VarFileInfo" 217 | BEGIN 218 | VALUE "Translation", 0x409, 1200 219 | END 220 | END 221 | 222 | 223 | ///////////////////////////////////////////////////////////////////////////// 224 | // 225 | // DESIGNINFO 226 | // 227 | 228 | #ifdef APSTUDIO_INVOKED 229 | GUIDELINES DESIGNINFO 230 | BEGIN 231 | IDD_WINMTR_DIALOG, DIALOG 232 | BEGIN 233 | LEFTMARGIN, 7 234 | RIGHTMARGIN, 415 235 | VERTGUIDE, 270 236 | VERTGUIDE, 321 237 | VERTGUIDE, 328 238 | VERTGUIDE, 377 239 | TOPMARGIN, 7 240 | BOTTOMMARGIN, 189 241 | HORZGUIDE, 12 242 | HORZGUIDE, 39 243 | END 244 | 245 | IDD_DIALOG_OPTIONS, DIALOG 246 | BEGIN 247 | LEFTMARGIN, 7 248 | RIGHTMARGIN, 244 249 | TOPMARGIN, 7 250 | BOTTOMMARGIN, 157 251 | END 252 | 253 | IDD_DIALOG_PROPERTIES, DIALOG 254 | BEGIN 255 | LEFTMARGIN, 7 256 | RIGHTMARGIN, 194 257 | TOPMARGIN, 7 258 | BOTTOMMARGIN, 152 259 | END 260 | 261 | IDD_DIALOG_HELP, DIALOG 262 | BEGIN 263 | LEFTMARGIN, 7 264 | RIGHTMARGIN, 249 265 | VERTGUIDE, 26 266 | TOPMARGIN, 7 267 | BOTTOMMARGIN, 115 268 | END 269 | END 270 | #endif // APSTUDIO_INVOKED 271 | 272 | 273 | ///////////////////////////////////////////////////////////////////////////// 274 | // 275 | // AFX_DIALOG_LAYOUT 276 | // 277 | 278 | IDD_DIALOG_HELP AFX_DIALOG_LAYOUT 279 | BEGIN 280 | 0 281 | END 282 | 283 | IDD_DIALOG_OPTIONS AFX_DIALOG_LAYOUT 284 | BEGIN 285 | 0 286 | END 287 | 288 | IDD_WINMTR_DIALOG AFX_DIALOG_LAYOUT 289 | BEGIN 290 | 0 291 | END 292 | 293 | 294 | ///////////////////////////////////////////////////////////////////////////// 295 | // 296 | // String Table 297 | // 298 | 299 | STRINGTABLE 300 | BEGIN 301 | IDP_SOCKETS_INIT_FAILED "Windows sockets initialization failed." 302 | IDS_STRING_SB_NAME "WinMTR v1.1 under GNU GPLv2" 303 | IDS_STRING_SB_PING "0000000" 304 | IDS_STRING_CLEAR_HISTORY "Clear History" 305 | END 306 | 307 | #endif // English (United States) resources 308 | ///////////////////////////////////////////////////////////////////////////// 309 | 310 | 311 | 312 | #ifndef APSTUDIO_INVOKED 313 | ///////////////////////////////////////////////////////////////////////////// 314 | // 315 | // Generated from the TEXTINCLUDE 3 resource. 316 | // 317 | #define _AFX_NO_SPLITTER_RESOURCES 318 | #define _AFX_NO_OLE_RESOURCES 319 | #define _AFX_NO_TRACKER_RESOURCES 320 | #define _AFX_NO_PROPERTY_RESOURCES 321 | 322 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 323 | #ifdef _WIN32 324 | LANGUAGE 9, 1 325 | #pragma code_page(1252) 326 | #endif //_WIN32 327 | #include "afxres.rc" // Standard components 328 | #endif 329 | 330 | ///////////////////////////////////////////////////////////////////////////// 331 | #endif // not APSTUDIO_INVOKED 332 | 333 | -------------------------------------------------------------------------------- /src/WinMTR.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | ARM 7 | 8 | 9 | Debug 10 | ARM64 11 | 12 | 13 | Debug 14 | Win32 15 | 16 | 17 | Debug 18 | x64 19 | 20 | 21 | Release 22 | ARM 23 | 24 | 25 | Release 26 | ARM64 27 | 28 | 29 | Release 30 | Win32 31 | 32 | 33 | Release 34 | x64 35 | 36 | 37 | 38 | 39 | 40 | {EE7B51B5-96FC-BED3-F2A6-0713CECBB579} 41 | 10.0 42 | 43 | 44 | 45 | Application 46 | false 47 | MultiByte 48 | v143 49 | 50 | 51 | Application 52 | false 53 | MultiByte 54 | v143 55 | 56 | 57 | Application 58 | false 59 | MultiByte 60 | v143 61 | 62 | 63 | Application 64 | false 65 | MultiByte 66 | v143 67 | 68 | 69 | Application 70 | false 71 | MultiByte 72 | v142 73 | 74 | 75 | Application 76 | false 77 | MultiByte 78 | v142 79 | 80 | 81 | Application 82 | false 83 | MultiByte 84 | v143 85 | 86 | 87 | Application 88 | false 89 | MultiByte 90 | v142 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | .\bin\Release_x32\ 130 | .\obj\Release_x32\ 131 | false 132 | 133 | 134 | false 135 | .\bin\Release_ARM\ 136 | .\obj\Release_ARM\ 137 | 138 | 139 | .\bin\Release_x64\ 140 | .\obj\Release_x64\ 141 | false 142 | 143 | 144 | false 145 | .\bin\Release_ARM64\ 146 | .\obj\Release_ARM64\ 147 | 148 | 149 | .\bin\Debug_x32\ 150 | .\obj\Debug_x32\ 151 | true 152 | 153 | 154 | true 155 | .\bin\Debug_ARM\ 156 | .\obj\Debug_ARM\ 157 | 158 | 159 | .\bin\Debug_x64\ 160 | .\obj\Debug_x64\ 161 | true 162 | 163 | 164 | true 165 | .\bin\Debug_ARM64\ 166 | .\obj\Debug_ARM64\ 167 | 168 | 169 | 170 | MultiThreaded 171 | OnlyExplicitInline 172 | true 173 | true 174 | MaxSpeed 175 | true 176 | Level3 177 | WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 178 | .\obj\Release_x32\ 179 | .\obj\Release_x32\WinMTR.pch 180 | .\obj\Release_x32\ 181 | .\obj\Release_x32\ 182 | 183 | 184 | true 185 | NDEBUG;%(PreprocessorDefinitions) 186 | .\Release_x32\WinMTR.tlb 187 | true 188 | Win32 189 | 190 | 191 | 0x0409 192 | NDEBUG;%(PreprocessorDefinitions) 193 | 194 | 195 | true 196 | .\Release_x32\WinMTR.bsc 197 | 198 | 199 | true 200 | Windows 201 | .\bin\Release_x32\WinMTR.exe 202 | odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 203 | AsInvoker 204 | false 205 | true 206 | 207 | 208 | 209 | 210 | MultiThreaded 211 | OnlyExplicitInline 212 | true 213 | true 214 | MaxSpeed 215 | true 216 | Level3 217 | WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 218 | .\obj\Release_ARM\ 219 | .\obj\Release_ARM\WinMTR.pch 220 | .\obj\Release_ARM\ 221 | .\obj\Release_ARM\ 222 | 223 | 224 | true 225 | NDEBUG;%(PreprocessorDefinitions) 226 | .\Release_ARM\WinMTR.tlb 227 | true 228 | 229 | 230 | 0x0409 231 | NDEBUG;%(PreprocessorDefinitions) 232 | 233 | 234 | true 235 | .\Release_ARM\WinMTR.bsc 236 | 237 | 238 | true 239 | Windows 240 | .\bin\Release_ARM\WinMTR.exe 241 | odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 242 | AsInvoker 243 | false 244 | true 245 | 246 | 247 | 248 | 249 | MultiThreaded 250 | OnlyExplicitInline 251 | true 252 | true 253 | MaxSpeed 254 | true 255 | Level3 256 | WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 257 | .\obj\Release_x64\ 258 | .\obj\Release_x64\WinMTR.pch 259 | .\obj\Release_x64\ 260 | .\obj\Release_x64\ 261 | Default 262 | stdc11 263 | 264 | 265 | true 266 | NDEBUG;%(PreprocessorDefinitions) 267 | .\Release_x64\WinMTR.tlb 268 | true 269 | 270 | 271 | 0x0409 272 | NDEBUG;%(PreprocessorDefinitions) 273 | 274 | 275 | true 276 | .\Release_x64\WinMTR.bsc 277 | 278 | 279 | true 280 | Windows 281 | .\bin\Release_x64\WinMTR.exe 282 | odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 283 | AsInvoker 284 | false 285 | true 286 | 287 | 288 | 289 | 290 | MultiThreaded 291 | OnlyExplicitInline 292 | true 293 | true 294 | MaxSpeed 295 | true 296 | Level3 297 | WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 298 | .\obj\Release_ARM64\ 299 | .\obj\Release_ARM64\WinMTR.pch 300 | .\obj\Release_ARM64\ 301 | .\obj\Release_ARM64\ 302 | Default 303 | 304 | 305 | true 306 | NDEBUG;%(PreprocessorDefinitions) 307 | .\Release_ARM64\WinMTR.tlb 308 | true 309 | 310 | 311 | 0x0409 312 | NDEBUG;%(PreprocessorDefinitions) 313 | 314 | 315 | true 316 | .\Release_ARM64\WinMTR.bsc 317 | 318 | 319 | true 320 | Windows 321 | .\bin\Release_ARM64\WinMTR.exe 322 | odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 323 | AsInvoker 324 | false 325 | true 326 | 327 | 328 | 329 | 330 | MultiThreadedDebug 331 | Default 332 | 333 | 334 | Disabled 335 | true 336 | Level3 337 | 338 | 339 | EditAndContinue 340 | WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 341 | .\obj\Debug_x32\ 342 | .\obj\Debug_x32\WinMTR.pch 343 | .\obj\Debug_x32\ 344 | .\obj\Debug_x32\ 345 | EnableFastChecks 346 | 347 | 348 | true 349 | _DEBUG;%(PreprocessorDefinitions) 350 | .\Debug_x32\WinMTR.tlb 351 | true 352 | Win32 353 | 354 | 355 | 0x0409 356 | _DEBUG;%(PreprocessorDefinitions) 357 | 358 | 359 | true 360 | .\Debug_x32\WinMTR.bsc 361 | 362 | 363 | true 364 | true 365 | Windows 366 | .\bin\Debug_x32\WinMTR.exe 367 | odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 368 | AsInvoker 369 | false 370 | true 371 | 372 | 373 | 374 | 375 | MultiThreadedDebug 376 | Default 377 | false 378 | Disabled 379 | true 380 | Level3 381 | true 382 | EditAndContinue 383 | WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 384 | .\obj\Debug_ARM\ 385 | .\obj\Debug_ARM\WinMTR.pch 386 | .\obj\Debug_ARM\ 387 | .\obj\Debug_ARM\ 388 | EnableFastChecks 389 | 390 | 391 | true 392 | _DEBUG;%(PreprocessorDefinitions) 393 | .\Debug_ARM\WinMTR.tlb 394 | true 395 | 396 | 397 | 0x0409 398 | _DEBUG;%(PreprocessorDefinitions) 399 | 400 | 401 | true 402 | .\Debug_ARM\WinMTR.bsc 403 | 404 | 405 | true 406 | true 407 | Windows 408 | .\bin\Debug_ARM\WinMTR.exe 409 | odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 410 | AsInvoker 411 | false 412 | true 413 | 414 | 415 | 416 | 417 | MultiThreadedDebug 418 | Default 419 | false 420 | Disabled 421 | true 422 | Level3 423 | ProgramDatabase 424 | WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 425 | .\obj\Debug_x64\ 426 | .\obj\Debug_x64\WinMTR.pch 427 | .\obj\Debug_x64\ 428 | .\obj\Debug_x64\ 429 | EnableFastChecks 430 | 431 | 432 | true 433 | _DEBUG;%(PreprocessorDefinitions) 434 | .\Debug_x64\WinMTR.tlb 435 | true 436 | 437 | 438 | 0x0409 439 | _DEBUG;%(PreprocessorDefinitions) 440 | 441 | 442 | true 443 | .\Debug_x64\WinMTR.bsc 444 | 445 | 446 | true 447 | true 448 | Windows 449 | .\bin\Debug_x64\WinMTR.exe 450 | odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 451 | AsInvoker 452 | false 453 | true 454 | 455 | 456 | 457 | 458 | MultiThreadedDebug 459 | Default 460 | false 461 | Disabled 462 | true 463 | Level3 464 | ProgramDatabase 465 | WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 466 | .\obj\Debug_ARM64\ 467 | .\obj\Debug_ARM64\WinMTR.pch 468 | .\obj\Debug_ARM64\ 469 | .\obj\Debug_ARM64\ 470 | EnableFastChecks 471 | 472 | 473 | true 474 | _DEBUG;%(PreprocessorDefinitions) 475 | .\Debug_ARM64\WinMTR.tlb 476 | true 477 | 478 | 479 | 0x0409 480 | _DEBUG;%(PreprocessorDefinitions) 481 | 482 | 483 | true 484 | .\Debug_ARM64\WinMTR.bsc 485 | 486 | 487 | true 488 | true 489 | Windows 490 | .\bin\Debug_ARM64\WinMTR.exe 491 | odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 492 | AsInvoker 493 | false 494 | true 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | -------------------------------------------------------------------------------- /src/WinMTRDialog.h: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRDialog.h 3 | //***************************************************************************** 4 | 5 | #ifndef WINMTRDIALOG_H_ 6 | #define WINMTRDIALOG_H_ 7 | 8 | #define WINMTR_DIALOG_TIMER 100 9 | 10 | #include "WinMTRStatusBar.h" 11 | #include "WinMTRNet.h" 12 | #include "afxlinkctrl.h" 13 | 14 | //***************************************************************************** 15 | // CLASS: WinMTRDialog 16 | //***************************************************************************** 17 | 18 | class WinMTRDialog : public CDialog 19 | { 20 | public: 21 | WinMTRDialog(CWnd* pParent = NULL); 22 | ~WinMTRDialog(); 23 | 24 | enum { IDD = IDD_WINMTR_DIALOG }; 25 | 26 | afx_msg BOOL InitRegistry(); 27 | 28 | WinMTRStatusBar statusBar; 29 | 30 | enum STATES { 31 | IDLE, 32 | TRACING, 33 | STOPPING, 34 | EXIT 35 | }; 36 | 37 | enum STATE_TRANSITIONS { 38 | IDLE_TO_IDLE, 39 | IDLE_TO_TRACING, 40 | IDLE_TO_EXIT, 41 | TRACING_TO_TRACING, 42 | TRACING_TO_STOPPING, 43 | TRACING_TO_EXIT, 44 | STOPPING_TO_IDLE, 45 | STOPPING_TO_STOPPING, 46 | STOPPING_TO_EXIT 47 | }; 48 | 49 | CButton m_buttonStart; 50 | CComboBox m_comboHost; 51 | CButton m_checkIPv6; 52 | CListCtrl m_listMTR; 53 | CMFCLinkCtrl m_buttonAppnor; 54 | 55 | CStatic m_staticS; 56 | 57 | int InitMTRNet(); 58 | 59 | int DisplayRedraw(); 60 | void Transit(STATES new_state); 61 | 62 | STATES state; 63 | STATE_TRANSITIONS transition; 64 | HANDLE traceThreadMutex; 65 | double interval; 66 | bool hasIntervalFromCmdLine; 67 | WORD pingsize; 68 | bool hasPingsizeFromCmdLine; 69 | int maxLRU; 70 | bool hasMaxLRUFromCmdLine; 71 | int nrLRU; 72 | BOOL useDNS; 73 | bool hasUseDNSFromCmdLine; 74 | unsigned char useIPv6; 75 | bool hasUseIPv6FromCmdLine; 76 | WinMTRNet* wmtrnet; 77 | 78 | void SetHostName(const char* host); 79 | void SetInterval(float i); 80 | void SetPingSize(WORD ps); 81 | void SetMaxLRU(int mlru); 82 | void SetUseDNS(BOOL udns); 83 | 84 | protected: 85 | virtual void DoDataExchange(CDataExchange* pDX); 86 | 87 | int m_autostart; 88 | char msz_defaulthostname[1000]; 89 | 90 | HICON m_hIcon; 91 | 92 | virtual BOOL OnInitDialog(); 93 | afx_msg void OnPaint(); 94 | afx_msg void OnSize(UINT, int, int); 95 | afx_msg void OnSizing(UINT, LPRECT); 96 | afx_msg HCURSOR OnQueryDragIcon(); 97 | afx_msg void OnRestart(); 98 | afx_msg void OnOptions(); 99 | virtual void OnCancel(); 100 | 101 | afx_msg void OnCTTC(); 102 | afx_msg void OnCHTC(); 103 | afx_msg void OnEXPT(); 104 | afx_msg void OnEXPH(); 105 | 106 | afx_msg void OnDblclkList(NMHDR* pNMHDR, LRESULT* pResult); 107 | 108 | DECLARE_MESSAGE_MAP() 109 | public: 110 | afx_msg void OnCbnSelchangeComboHost(); 111 | afx_msg void OnCbnSelendokComboHost(); 112 | private: 113 | void ClearHistory(); 114 | public: 115 | afx_msg void OnCbnCloseupComboHost(); 116 | afx_msg void OnTimer(UINT_PTR nIDEvent); 117 | afx_msg void OnClose(); 118 | afx_msg void OnBnClickedCancel(); 119 | afx_msg void OnFileExit(); 120 | afx_msg void OnAbout(); 121 | }; 122 | 123 | #endif // ifndef WINMTRDIALOG_H_ 124 | -------------------------------------------------------------------------------- /src/WinMTRGlobal.h: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRGlobal.h 3 | //***************************************************************************** 4 | 5 | #ifndef GLOBAL_H_ 6 | #define GLOBAL_H_ 7 | 8 | #ifndef _WIN64 9 | #define _USE_32BIT_TIME_T 10 | #endif 11 | 12 | #define VC_EXTRALEAN 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #ifndef _AFX_NO_AFXCMN_SUPPORT 20 | #include 21 | #endif 22 | #include 23 | #include //IP_OPTION_INFORMATION32 24 | #include //sockaddr_in6 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include "resource.h" 42 | 43 | #define WINMTR_VERSION "1.0" 44 | #define WINMTR_LICENSE "GPLv2 - GNU General Public License, version 2" 45 | #define WINMTR_HOMEPAGE "https://github.com/White-Tiger/WinMTR" 46 | 47 | #define DEFAULT_PING_SIZE 64 48 | #define DEFAULT_INTERVAL 1.0 49 | #define DEFAULT_MAX_LRU 128 50 | #define DEFAULT_DNS TRUE 51 | 52 | #define SAVED_PINGS 100 53 | #define 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 | 79 | #define MTR_NR_COLS 9 80 | 81 | const char MTR_COLS[ MTR_NR_COLS ][10] = { 82 | "Hostname", 83 | "Nr", 84 | "Loss %", 85 | "Sent", 86 | "Recv", 87 | "Best", 88 | "Avrg", 89 | "Worst", 90 | "Last" 91 | }; 92 | 93 | const int MTR_COL_LENGTH[ MTR_NR_COLS ] = { 94 | 249, 30, 50, 40, 40, 50, 50, 50, 50 95 | }; 96 | 97 | int gettimeofday(struct timeval* tv, struct timezone* tz); 98 | 99 | #endif // ifndef GLOBAL_H_ 100 | -------------------------------------------------------------------------------- /src/WinMTRHelp.cpp: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRHelp.cpp 3 | //***************************************************************************** 4 | 5 | #include "WinMTRGlobal.h" 6 | #include "WinMTRHelp.h" 7 | 8 | 9 | // WinMTRHelp dialog 10 | 11 | IMPLEMENT_DYNAMIC(WinMTRHelp, CDialog) 12 | 13 | WinMTRHelp::WinMTRHelp(CWnd* pParent /*=NULL*/) 14 | : CDialog(WinMTRHelp::IDD, pParent) 15 | { 16 | 17 | } 18 | 19 | WinMTRHelp::~WinMTRHelp() 20 | { 21 | } 22 | 23 | void WinMTRHelp::DoDataExchange(CDataExchange* pDX) 24 | { 25 | CDialog::DoDataExchange(pDX); 26 | } 27 | 28 | 29 | BEGIN_MESSAGE_MAP(WinMTRHelp, CDialog) 30 | ON_BN_CLICKED(IDOK, &WinMTRHelp::OnBnClickedOk) 31 | END_MESSAGE_MAP() 32 | 33 | 34 | // WinMTRHelp message handlers 35 | 36 | 37 | void WinMTRHelp::OnBnClickedOk() 38 | { 39 | // TODO: Add your control notification handler code here 40 | CDialog::OnOK(); 41 | } 42 | -------------------------------------------------------------------------------- /src/WinMTRHelp.h: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRHelp.h 3 | //***************************************************************************** 4 | #pragma once 5 | 6 | // WinMTRHelp dialog 7 | 8 | class WinMTRHelp : public CDialog 9 | { 10 | DECLARE_DYNAMIC(WinMTRHelp); 11 | 12 | public: 13 | WinMTRHelp(CWnd* pParent = NULL); // standard constructor 14 | virtual ~WinMTRHelp(); 15 | 16 | // Dialog Data 17 | enum { IDD = IDD_DIALOG_HELP }; 18 | 19 | protected: 20 | virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 21 | 22 | DECLARE_MESSAGE_MAP(); 23 | public: 24 | afx_msg void OnBnClickedOk(); 25 | }; 26 | -------------------------------------------------------------------------------- /src/WinMTRMain.cpp: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRMain.cpp 3 | //***************************************************************************** 4 | 5 | #include "WinMTRGlobal.h" 6 | #include "WinMTRMain.h" 7 | #include "WinMTRDialog.h" 8 | #include "WinMTRHelp.h" 9 | #include 10 | #include 11 | 12 | #ifdef _DEBUG 13 | #define new DEBUG_NEW 14 | #undef THIS_FILE 15 | static char THIS_FILE[] = __FILE__; 16 | #endif 17 | 18 | WinMTRMain WinMTR; 19 | 20 | //***************************************************************************** 21 | // BEGIN_MESSAGE_MAP 22 | //***************************************************************************** 23 | BEGIN_MESSAGE_MAP(WinMTRMain, CWinApp) 24 | ON_COMMAND(ID_HELP, CWinApp::OnHelp) 25 | END_MESSAGE_MAP() 26 | 27 | //***************************************************************************** 28 | // WinMTRMain::WinMTRMain 29 | //***************************************************************************** 30 | WinMTRMain::WinMTRMain() 31 | { 32 | } 33 | 34 | //***************************************************************************** 35 | // WinMTRMain::InitInstance 36 | //***************************************************************************** 37 | BOOL WinMTRMain::InitInstance() 38 | { 39 | INITCOMMONCONTROLSEX icex= {sizeof(INITCOMMONCONTROLSEX),ICC_STANDARD_CLASSES}; 40 | InitCommonControlsEx(&icex); 41 | if(!AfxSocketInit()) { 42 | AfxMessageBox(IDP_SOCKETS_INIT_FAILED); 43 | return FALSE; 44 | } 45 | 46 | AfxEnableControlContainer(); 47 | 48 | 49 | WinMTRDialog mtrDialog; 50 | m_pMainWnd = &mtrDialog; 51 | 52 | if(strlen(m_lpCmdLine)) { 53 | strcat(m_lpCmdLine," "); 54 | ParseCommandLineParams(m_lpCmdLine, &mtrDialog); 55 | } 56 | 57 | mtrDialog.DoModal(); 58 | 59 | 60 | return FALSE; 61 | } 62 | 63 | 64 | //***************************************************************************** 65 | // WinMTRMain::ParseCommandLineParams 66 | //***************************************************************************** 67 | void WinMTRMain::ParseCommandLineParams(LPTSTR cmd, WinMTRDialog* wmtrdlg) 68 | { 69 | char value[1024]; 70 | std::string host_name = ""; 71 | 72 | if(GetParamValue(cmd, "help",'h', value)) { 73 | WinMTRHelp mtrHelp; 74 | m_pMainWnd = &mtrHelp; 75 | mtrHelp.DoModal(); 76 | exit(0); 77 | } 78 | 79 | if(GetHostNameParamValue(cmd, host_name)) { 80 | wmtrdlg->SetHostName(host_name.c_str()); 81 | } 82 | if(GetParamValue(cmd, "interval",'i', value)) { 83 | wmtrdlg->SetInterval((float)atof(value)); 84 | wmtrdlg->hasIntervalFromCmdLine = true; 85 | } 86 | if(GetParamValue(cmd, "size",'s', value)) { 87 | wmtrdlg->SetPingSize((WORD)atoi(value)); 88 | wmtrdlg->hasPingsizeFromCmdLine = true; 89 | } 90 | if(GetParamValue(cmd, "maxLRU",'m', value)) { 91 | wmtrdlg->SetMaxLRU(atoi(value)); 92 | wmtrdlg->hasMaxLRUFromCmdLine = true; 93 | } 94 | if(GetParamValue(cmd, "numeric",'n', NULL)) { 95 | wmtrdlg->SetUseDNS(FALSE); 96 | wmtrdlg->hasUseDNSFromCmdLine = true; 97 | } 98 | if(GetParamValue(cmd, "ipv6",'6', NULL)) { 99 | wmtrdlg->hasUseIPv6FromCmdLine=true; 100 | wmtrdlg->useIPv6=1; 101 | } 102 | if(GetParamValue(cmd, "ipv4",'4', NULL)) { 103 | wmtrdlg->hasUseIPv6FromCmdLine=true; 104 | wmtrdlg->useIPv6=0; 105 | } 106 | } 107 | 108 | //***************************************************************************** 109 | // WinMTRMain::GetParamValue 110 | //***************************************************************************** 111 | int WinMTRMain::GetParamValue(LPTSTR cmd, char* param, char sparam, char* value) 112 | { 113 | char* p; 114 | 115 | char p_long[1024]; 116 | char p_short[1024]; 117 | 118 | sprintf(p_long,"--%s ", param); 119 | sprintf(p_short,"-%c ", sparam); 120 | 121 | if((p=strstr(cmd, p_long))) ; 122 | else 123 | p=strstr(cmd, p_short); 124 | 125 | if(p == NULL) 126 | return 0; 127 | 128 | if(!value) 129 | return 1; 130 | 131 | while(*p && *p!=' ') 132 | p++; 133 | while(*p==' ') p++; 134 | 135 | int i = 0; 136 | while(*p && *p!=' ') 137 | value[i++] = *p++; 138 | value[i]='\0'; 139 | 140 | return 1; 141 | } 142 | 143 | //***************************************************************************** 144 | // WinMTRMain::GetHostNameParamValue 145 | //***************************************************************************** 146 | int WinMTRMain::GetHostNameParamValue(LPTSTR cmd, std::string& host_name) 147 | { 148 | // WinMTR -h -i 1 -n google.com 149 | size_t size = strlen(cmd); 150 | std::string name = ""; 151 | while(cmd[--size] == ' '); 152 | 153 | size++; 154 | while(size-- && cmd[size] != ' ' && (cmd[size] != '-' || cmd[size - 1] != ' ')) { 155 | name = cmd[size ] + name; 156 | } 157 | 158 | if(size == -1) { 159 | if(name.length() == 0) { 160 | return 0; 161 | } else { 162 | host_name = name; 163 | return 1; 164 | } 165 | } 166 | if(cmd[size] == '-' && cmd[size - 1] == ' ') { 167 | // no target specified 168 | return 0; 169 | } 170 | 171 | std::string possible_argument = ""; 172 | 173 | while(size-- && cmd[size] != ' ') { 174 | possible_argument = cmd[size] + possible_argument; 175 | } 176 | 177 | if(possible_argument.length() && (possible_argument[0] != '-' || possible_argument == "-n" || possible_argument == "--numeric" || possible_argument == "-6" || possible_argument == "--ipv6" || possible_argument == "-4" || possible_argument == "--ipv4")) { 178 | host_name = name; 179 | return 1; 180 | } 181 | 182 | return 0; 183 | } 184 | -------------------------------------------------------------------------------- /src/WinMTRMain.h: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRMain.h 3 | //***************************************************************************** 4 | 5 | #ifndef WINMTRMAIN_H_ 6 | #define WINMTRMAIN_H_ 7 | 8 | #include "WinMTRDialog.h" 9 | #include 10 | 11 | 12 | //***************************************************************************** 13 | // CLASS: WinMTRMain 14 | //***************************************************************************** 15 | 16 | class WinMTRMain : public CWinApp 17 | { 18 | public: 19 | WinMTRMain(); 20 | 21 | virtual BOOL InitInstance(); 22 | 23 | DECLARE_MESSAGE_MAP() 24 | 25 | private: 26 | void ParseCommandLineParams(LPTSTR cmd, WinMTRDialog* wmtrdlg); 27 | int GetParamValue(LPTSTR cmd, char* param, char sparam, char* value); 28 | int GetHostNameParamValue(LPTSTR cmd, std::string& value); 29 | 30 | }; 31 | 32 | #endif // ifndef WINMTRMAIN_H_ 33 | 34 | -------------------------------------------------------------------------------- /src/WinMTRNet.cpp: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRNet.cpp 3 | //***************************************************************************** 4 | #include "WinMTRGlobal.h" 5 | #include "WinMTRNet.h" 6 | #include "WinMTRDialog.h" 7 | #include 8 | #include 9 | 10 | #ifdef _DEBUG 11 | # define TRACE_MSG(msg) \ 12 | { \ 13 | std::ostringstream dbg_msg(std::ostringstream::out); \ 14 | dbg_msg << msg << std::endl; \ 15 | OutputDebugString(dbg_msg.str().c_str()); \ 16 | } 17 | #else 18 | # define TRACE_MSG(msg) 19 | #endif 20 | 21 | #define IPFLAG_DONT_FRAGMENT 0x02 22 | #define MAX_HOPS 30 23 | 24 | struct trace_thread { 25 | WinMTRNet* winmtr; 26 | in_addr address; 27 | int ttl; 28 | }; 29 | struct trace_thread6 { 30 | WinMTRNet* winmtr; 31 | sockaddr_in6 address; 32 | int ttl; 33 | }; 34 | 35 | struct dns_resolver_thread { 36 | WinMTRNet* winmtr; 37 | int index; 38 | }; 39 | 40 | unsigned WINAPI TraceThread(void* p); 41 | unsigned WINAPI TraceThread6(void* p); 42 | void DnsResolverThread(void* p); 43 | 44 | WinMTRNet::WinMTRNet(WinMTRDialog* wp) 45 | { 46 | 47 | ghMutex = CreateMutex(NULL, FALSE, NULL); 48 | hasIPv6=true; 49 | tracing=false; 50 | initialized = false; 51 | wmtrdlg = wp; 52 | WSADATA wsaData; 53 | 54 | if(WSAStartup(MAKEWORD(2, 2), &wsaData)) { 55 | AfxMessageBox("Failed initializing windows sockets library!"); 56 | return; 57 | } 58 | OSVERSIONINFOEX osvi= {0}; 59 | osvi.dwOSVersionInfoSize=sizeof(OSVERSIONINFOEX); 60 | if(!IsWindowsXPOrGreater()) { 61 | AfxMessageBox("Failed to get Windows version!"); 62 | return; 63 | } 64 | if(osvi.dwMajorVersion==5 && osvi.dwMinorVersion==0) { //w2k 65 | hICMP_DLL=LoadLibrary(_T("ICMP.DLL")); 66 | if(!hICMP_DLL) { 67 | AfxMessageBox("Failed: Unable to locate ICMP.DLL!"); 68 | return; 69 | } 70 | } else { 71 | hICMP_DLL=LoadLibrary(_T("Iphlpapi.dll")); 72 | if(!hICMP_DLL) { 73 | AfxMessageBox("Failed: Unable to locate Iphlpapi.dll!"); 74 | return; 75 | } 76 | } 77 | 78 | /* 79 | * Get pointers to ICMP.DLL functions 80 | */ 81 | //IPv4 82 | lpfnIcmpCreateFile = (LPFNICMPCREATEFILE)GetProcAddress(hICMP_DLL,"IcmpCreateFile"); 83 | lpfnIcmpCloseHandle = (LPFNICMPCLOSEHANDLE)GetProcAddress(hICMP_DLL,"IcmpCloseHandle"); 84 | lpfnIcmpSendEcho2 = (LPFNICMPSENDECHO2)GetProcAddress(hICMP_DLL,"IcmpSendEcho2"); 85 | if(!lpfnIcmpCreateFile || !lpfnIcmpCloseHandle || !lpfnIcmpSendEcho2) { 86 | AfxMessageBox("Wrong ICMP system library !"); 87 | return; 88 | } 89 | //IPv6 90 | lpfnIcmp6CreateFile=(LPFNICMP6CREATEFILE)GetProcAddress(hICMP_DLL,"Icmp6CreateFile"); 91 | lpfnIcmp6SendEcho2=(LPFNICMP6SENDECHO2)GetProcAddress(hICMP_DLL,"Icmp6SendEcho2"); 92 | if(!lpfnIcmp6CreateFile || !lpfnIcmp6SendEcho2) { 93 | hasIPv6=false; 94 | AfxMessageBox("IPv6 support not found!"); 95 | return;//@todo : soft fail 96 | } 97 | 98 | /* 99 | * IcmpCreateFile() - Open the ping service 100 | */ 101 | hICMP = (HANDLE) lpfnIcmpCreateFile(); 102 | if(hICMP == INVALID_HANDLE_VALUE) { 103 | AfxMessageBox("Error in ICMP module!"); 104 | return; 105 | } 106 | if(hasIPv6) { 107 | hICMP6=(HANDLE)lpfnIcmp6CreateFile(); 108 | if(hICMP6==INVALID_HANDLE_VALUE) { 109 | AfxMessageBox("Error in ICMPv6 module!"); 110 | return;//@todo : soft fail 111 | } 112 | } 113 | 114 | ResetHops(); 115 | 116 | initialized = true; 117 | return; 118 | } 119 | 120 | WinMTRNet::~WinMTRNet() 121 | { 122 | if(initialized) { 123 | /* 124 | * IcmpCloseHandle - Close the ICMP handle 125 | */ 126 | if(hasIPv6) lpfnIcmpCloseHandle(hICMP6); 127 | lpfnIcmpCloseHandle(hICMP); 128 | 129 | // Shut down... 130 | FreeLibrary(hICMP_DLL); 131 | 132 | WSACleanup(); 133 | 134 | CloseHandle(ghMutex); 135 | } 136 | } 137 | 138 | void WinMTRNet::ResetHops() 139 | { 140 | memset(host,0,sizeof(host)); 141 | } 142 | 143 | void WinMTRNet::DoTrace(sockaddr* sockaddr) 144 | { 145 | HANDLE hThreads[MAX_HOPS]; 146 | unsigned char hops=0; 147 | tracing = true; 148 | ResetHops(); 149 | if(sockaddr->sa_family==AF_INET6) { 150 | host[0].addr6.sin6_family=AF_INET6; 151 | last_remote_addr6=((sockaddr_in6*)sockaddr)->sin6_addr; 152 | for(; hopsaddress=*(sockaddr_in6*)sockaddr; 155 | current->winmtr=this; 156 | current->ttl=hops+1; 157 | hThreads[hops]=(HANDLE)_beginthreadex(NULL,0,TraceThread6,current,0,NULL); 158 | Sleep(30); 159 | if(++hops>this->GetMax()) break; 160 | } 161 | } else { 162 | host[0].addr.sin_family=AF_INET; 163 | last_remote_addr=((sockaddr_in*)sockaddr)->sin_addr; 164 | for(; hopsaddress=((sockaddr_in*)sockaddr)->sin_addr; 167 | current->winmtr=this; 168 | current->ttl=hops+1; 169 | hThreads[hops]=(HANDLE)_beginthreadex(NULL,0,TraceThread,current,0,NULL); 170 | Sleep(30); 171 | if(++hops>this->GetMax()) break; 172 | } 173 | } 174 | WaitForMultipleObjects(hops, hThreads, TRUE, INFINITE); 175 | for(; hops;) CloseHandle(hThreads[--hops]); 176 | } 177 | 178 | void WinMTRNet::StopTrace() 179 | { 180 | tracing = false; 181 | } 182 | 183 | unsigned WINAPI TraceThread(void* p) 184 | { 185 | trace_thread* current = (trace_thread*)p; 186 | WinMTRNet* wmtrnet = current->winmtr; 187 | TRACE_MSG("Thread with TTL=" << (int)current->ttl << " started."); 188 | 189 | IPINFO stIPInfo, *lpstIPInfo; 190 | char achReqData[8192]; 191 | WORD nDataLen = wmtrnet->wmtrdlg->pingsize; 192 | union { 193 | ICMP_ECHO_REPLY icmp_echo_reply; 194 | char achRepData[sizeof(ICMPECHO)+8192]; 195 | }; 196 | 197 | lpstIPInfo = &stIPInfo; 198 | stIPInfo.Ttl = (UCHAR)current->ttl; 199 | stIPInfo.Tos = 0; 200 | stIPInfo.Flags = IPFLAG_DONT_FRAGMENT; 201 | stIPInfo.OptionsSize = 0; 202 | stIPInfo.OptionsData = NULL; 203 | for(int i=0; itracing) { 205 | // For some strange reason, ICMP API is not filling the TTL for icmp echo reply 206 | // Check if the current thread should be closed 207 | if(current->ttl > wmtrnet->GetMax()) break; 208 | // NOTE: some servers does not respond back everytime, if TTL expires in transit; e.g. : 209 | // 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 210 | // but if we are pinging ping -n 20 -w 5000 -l 64 219.80.240.93 we have 0% loss 211 | // A resolution would be: 212 | // - as soon as we get a hop, we start pinging directly that hop, with a greater TTL 213 | // - a drawback would be that, some servers are configured to reply for TTL transit expire, but not to ping requests, so, 214 | // for these servers we'll have 100% loss 215 | DWORD dwReplyCount = wmtrnet->lpfnIcmpSendEcho2(wmtrnet->hICMP, 0,NULL,NULL, current->address, achReqData, nDataLen, lpstIPInfo, achRepData, sizeof(achRepData), ECHO_REPLY_TIMEOUT); 216 | wmtrnet->AddXmit(current->ttl - 1); 217 | if(dwReplyCount) { 218 | TRACE_MSG("TTL " << (int)current->ttl << " reply TTL " << (int)icmp_echo_reply.Options.Ttl << " Status " << icmp_echo_reply.Status << " Reply count " << dwReplyCount); 219 | switch(icmp_echo_reply.Status) { 220 | case IP_SUCCESS: 221 | case IP_TTL_EXPIRED_TRANSIT: 222 | wmtrnet->UpdateRTT(current->ttl - 1, icmp_echo_reply.RoundTripTime); 223 | wmtrnet->AddReturned(current->ttl - 1); 224 | wmtrnet->SetAddr(current->ttl - 1, icmp_echo_reply.Address); 225 | break; 226 | default: 227 | wmtrnet->SetErrorName(current->ttl - 1, icmp_echo_reply.Status); 228 | } 229 | if((DWORD)(wmtrnet->wmtrdlg->interval * 1000) > icmp_echo_reply.RoundTripTime) 230 | Sleep((DWORD)(wmtrnet->wmtrdlg->interval * 1000) - icmp_echo_reply.RoundTripTime); 231 | } else { 232 | DWORD err=GetLastError(); 233 | wmtrnet->SetErrorName(current->ttl - 1, err); 234 | switch(err) { 235 | case IP_REQ_TIMED_OUT: break; 236 | default: 237 | Sleep((DWORD)(wmtrnet->wmtrdlg->interval * 1000)); 238 | } 239 | } 240 | }//end loop 241 | TRACE_MSG("Thread with TTL=" << (int)current->ttl << " stopped."); 242 | delete p; 243 | return 0; 244 | } 245 | 246 | unsigned WINAPI TraceThread6(void* p) 247 | { 248 | static sockaddr_in6 sockaddrfrom= {AF_INET6,0,0,in6addr_any,0}; 249 | trace_thread6* current = (trace_thread6*)p; 250 | WinMTRNet* wmtrnet = current->winmtr; 251 | TRACE_MSG("Thread with TTL=" << (int)current->ttl << " started."); 252 | 253 | IPINFO stIPInfo, *lpstIPInfo; 254 | char achReqData[8192]; 255 | WORD nDataLen = wmtrnet->wmtrdlg->pingsize; 256 | union { 257 | ICMPV6_ECHO_REPLY icmpv6_echo_reply; 258 | char achRepData[sizeof(PICMPV6_ECHO_REPLY) + 8192]; 259 | }; 260 | 261 | lpstIPInfo = &stIPInfo; 262 | stIPInfo.Ttl = (UCHAR)current->ttl; 263 | stIPInfo.Tos = 0; 264 | stIPInfo.Flags = IPFLAG_DONT_FRAGMENT; 265 | stIPInfo.OptionsSize = 0; 266 | stIPInfo.OptionsData = NULL; 267 | for(int i=0; itracing) { 269 | if(current->ttl > wmtrnet->GetMax()) break; 270 | DWORD dwReplyCount = wmtrnet->lpfnIcmp6SendEcho2(wmtrnet->hICMP6, 0,NULL,NULL, &sockaddrfrom, ¤t->address, achReqData, nDataLen, lpstIPInfo, achRepData, sizeof(achRepData), ECHO_REPLY_TIMEOUT); 271 | wmtrnet->AddXmit(current->ttl - 1); 272 | if(dwReplyCount) { 273 | TRACE_MSG("TTL " << (int)current->ttl << " Status " << icmpv6_echo_reply.Status << " Reply count " << dwReplyCount); 274 | switch(icmpv6_echo_reply.Status) { 275 | case IP_SUCCESS: 276 | case IP_TTL_EXPIRED_TRANSIT: 277 | wmtrnet->UpdateRTT(current->ttl - 1, icmpv6_echo_reply.RoundTripTime); 278 | wmtrnet->AddReturned(current->ttl - 1); 279 | wmtrnet->SetAddr6(current->ttl - 1, icmpv6_echo_reply.Address); 280 | break; 281 | default: 282 | wmtrnet->SetErrorName(current->ttl - 1, icmpv6_echo_reply.Status); 283 | } 284 | if((DWORD)(wmtrnet->wmtrdlg->interval * 1000) > icmpv6_echo_reply.RoundTripTime) 285 | Sleep((DWORD)(wmtrnet->wmtrdlg->interval * 1000) - icmpv6_echo_reply.RoundTripTime); 286 | } else { 287 | DWORD err=GetLastError(); 288 | wmtrnet->SetErrorName(current->ttl - 1, err); 289 | switch(err) { 290 | case IP_REQ_TIMED_OUT: break; 291 | default: 292 | Sleep((DWORD)(wmtrnet->wmtrdlg->interval * 1000)); 293 | } 294 | } 295 | }//end loop 296 | TRACE_MSG("Thread with TTL=" << (int)current->ttl << " stopped."); 297 | delete p; 298 | return 0; 299 | } 300 | 301 | sockaddr* WinMTRNet::GetAddr(int at) 302 | { 303 | return (sockaddr*)&host[at].addr; 304 | } 305 | 306 | int WinMTRNet::GetName(int at, char* n) 307 | { 308 | WaitForSingleObject(ghMutex, INFINITE); 309 | strcpy(n, host[at].name); 310 | ReleaseMutex(ghMutex); 311 | return 0; 312 | } 313 | 314 | int WinMTRNet::GetBest(int at) 315 | { 316 | WaitForSingleObject(ghMutex, INFINITE); 317 | int ret = host[at].best; 318 | ReleaseMutex(ghMutex); 319 | return ret; 320 | } 321 | 322 | int WinMTRNet::GetWorst(int at) 323 | { 324 | WaitForSingleObject(ghMutex, INFINITE); 325 | int ret = host[at].worst; 326 | ReleaseMutex(ghMutex); 327 | return ret; 328 | } 329 | 330 | int WinMTRNet::GetAvg(int at) 331 | { 332 | WaitForSingleObject(ghMutex, INFINITE); 333 | int ret = host[at].returned == 0 ? 0 : host[at].total / host[at].returned; 334 | ReleaseMutex(ghMutex); 335 | return ret; 336 | } 337 | 338 | int WinMTRNet::GetPercent(int at) 339 | { 340 | WaitForSingleObject(ghMutex, INFINITE); 341 | int ret = (host[at].xmit == 0) ? 0 : (100 - (100 * host[at].returned / host[at].xmit)); 342 | ReleaseMutex(ghMutex); 343 | return ret; 344 | } 345 | 346 | int WinMTRNet::GetLast(int at) 347 | { 348 | WaitForSingleObject(ghMutex, INFINITE); 349 | int ret = host[at].last; 350 | ReleaseMutex(ghMutex); 351 | return ret; 352 | } 353 | 354 | int WinMTRNet::GetReturned(int at) 355 | { 356 | WaitForSingleObject(ghMutex, INFINITE); 357 | int ret = host[at].returned; 358 | ReleaseMutex(ghMutex); 359 | return ret; 360 | } 361 | 362 | int WinMTRNet::GetXmit(int at) 363 | { 364 | WaitForSingleObject(ghMutex, INFINITE); 365 | int ret = host[at].xmit; 366 | ReleaseMutex(ghMutex); 367 | return ret; 368 | } 369 | 370 | int WinMTRNet::GetMax() 371 | { 372 | // @todo : improve this (last hop guess) 373 | WaitForSingleObject(ghMutex, INFINITE); 374 | int max=0;//first try to find target, if not found, find best guess (doesn't work actually :P) 375 | if(host[0].addr6.sin6_family==AF_INET6) { 376 | for(; max1 && !memcmp(&host[max-1].addr6.sin6_addr,&host[max-2].addr6.sin6_addr,sizeof(in6_addr)) && (host[max-1].addr6.sin6_addr.u.Word[0]|host[max-1].addr6.sin6_addr.u.Word[1]|host[max-1].addr6.sin6_addr.u.Word[2]|host[max-1].addr6.sin6_addr.u.Word[3]|host[max-1].addr6.sin6_addr.u.Word[4]|host[max-1].addr6.sin6_addr.u.Word[5]|host[max-1].addr6.sin6_addr.u.Word[6]|host[max-1].addr6.sin6_addr.u.Word[7])) --max; 379 | } 380 | } else { 381 | for(; max1 && host[max-1].addr.sin_addr.s_addr==host[max-2].addr.sin_addr.s_addr && host[max-1].addr.sin_addr.s_addr) --max; 384 | } 385 | } 386 | ReleaseMutex(ghMutex); 387 | return max; 388 | } 389 | 390 | void WinMTRNet::SetAddr(int at, u_long addr) 391 | { 392 | WaitForSingleObject(ghMutex, INFINITE); 393 | if(host[at].addr.sin_addr.s_addr==0) { 394 | TRACE_MSG("Start DnsResolverThread for new address " << addr << ". Old addr value was " << host[at].addr.sin_addr.s_addr); 395 | host[at].addr.sin_family=AF_INET; 396 | host[at].addr.sin_addr.s_addr=addr; 397 | dns_resolver_thread* dnt=new dns_resolver_thread; 398 | dnt->index=at; 399 | dnt->winmtr=this; 400 | if(wmtrdlg->useDNS) _beginthread(DnsResolverThread, 0, dnt); 401 | else DnsResolverThread(dnt); 402 | } 403 | ReleaseMutex(ghMutex); 404 | } 405 | 406 | void WinMTRNet::SetAddr6(int at, IPV6_ADDRESS_EX addrex) 407 | { 408 | WaitForSingleObject(ghMutex, INFINITE); 409 | if(!(host[at].addr6.sin6_addr.u.Word[0]|host[at].addr6.sin6_addr.u.Word[1]|host[at].addr6.sin6_addr.u.Word[2]|host[at].addr6.sin6_addr.u.Word[3]|host[at].addr6.sin6_addr.u.Word[4]|host[at].addr6.sin6_addr.u.Word[5]|host[at].addr6.sin6_addr.u.Word[6]|host[at].addr6.sin6_addr.u.Word[7])) { 410 | TRACE_MSG("Start DnsResolverThread for new address " << addrex.sin6_addr[0] << ". Old addr value was " << host[at].addr6.sin6_addr.u.Word[0]); 411 | host[at].addr6.sin6_family=AF_INET6; 412 | host[at].addr6.sin6_addr=*(in6_addr*)&addrex.sin6_addr; 413 | dns_resolver_thread* dnt=new dns_resolver_thread; 414 | dnt->index=at; 415 | dnt->winmtr=this; 416 | if(wmtrdlg->useDNS) _beginthread(DnsResolverThread,0,dnt); 417 | else DnsResolverThread(dnt); 418 | } 419 | ReleaseMutex(ghMutex); 420 | } 421 | 422 | void WinMTRNet::SetName(int at, char* n) 423 | { 424 | WaitForSingleObject(ghMutex, INFINITE); 425 | strcpy(host[at].name, n); 426 | ReleaseMutex(ghMutex); 427 | } 428 | 429 | void WinMTRNet::SetErrorName(int at, DWORD errnum) 430 | { 431 | const char* name; 432 | switch(errnum) { 433 | case IP_BUF_TOO_SMALL: 434 | name="Reply buffer too small."; break; 435 | case IP_DEST_NET_UNREACHABLE: 436 | name="Destination network unreachable."; break; 437 | case IP_DEST_HOST_UNREACHABLE: 438 | name="Destination host unreachable."; break; 439 | case IP_DEST_PROT_UNREACHABLE: 440 | name="Destination protocol unreachable."; break; 441 | case IP_DEST_PORT_UNREACHABLE: 442 | name="Destination port unreachable."; break; 443 | case IP_NO_RESOURCES: 444 | name="Insufficient IP resources were available."; break; 445 | case IP_BAD_OPTION: 446 | name="Bad IP option was specified."; break; 447 | case IP_HW_ERROR: 448 | name="Hardware error occurred."; break; 449 | case IP_PACKET_TOO_BIG: 450 | name="Packet was too big."; break; 451 | case IP_REQ_TIMED_OUT: 452 | name="Request timed out."; break; 453 | case IP_BAD_REQ: 454 | name="Bad request."; break; 455 | case IP_BAD_ROUTE: 456 | name="Bad route."; break; 457 | case IP_TTL_EXPIRED_REASSEM: 458 | name="The time to live expired during fragment reassembly."; break; 459 | case IP_PARAM_PROBLEM: 460 | name="Parameter problem."; break; 461 | case IP_SOURCE_QUENCH: 462 | name="Datagrams are arriving too fast to be processed and datagrams may have been discarded."; break; 463 | case IP_OPTION_TOO_BIG: 464 | name="An IP option was too big."; break; 465 | case IP_BAD_DESTINATION: 466 | name="Bad destination."; break; 467 | case IP_GENERAL_FAILURE: 468 | name="General failure."; break; 469 | default: 470 | TRACE_MSG("==UNKNOWN ERROR== " << errnum); 471 | name="Unknown error! (please report)"; break; 472 | } 473 | WaitForSingleObject(ghMutex, INFINITE); 474 | if(!*host[at].name) 475 | strcpy(host[at].name,name); 476 | ReleaseMutex(ghMutex); 477 | } 478 | 479 | void WinMTRNet::UpdateRTT(int at, int rtt) 480 | { 481 | WaitForSingleObject(ghMutex, INFINITE); 482 | host[at].last=rtt; 483 | host[at].total+=rtt; 484 | if(host[at].best>rtt || host[at].xmit==1) 485 | host[at].best=rtt; 486 | if(host[at].worstwinmtr; 509 | char ip[NI_MAXHOST]; 510 | char hostname[NI_MAXHOST]; 511 | if(!getnameinfo(wn->GetAddr(dnt->index),sizeof(sockaddr_in6),ip,NI_MAXHOST,NULL,0,NI_NUMERICHOST)) { 512 | wn->SetName(dnt->index,ip); 513 | } 514 | else { 515 | strcpy(hostname, ""); 516 | } 517 | if(wn->wmtrdlg->useDNS) { 518 | TRACE_MSG("DNS resolver thread started."); 519 | if (!getnameinfo(wn->GetAddr(dnt->index), sizeof(sockaddr_in6), hostname, NI_MAXHOST, NULL, 0, 0)) { 520 | if (strcmp(hostname, ip) != 0) { 521 | // Append IP to hostname 522 | char final_name[NI_MAXHOST]; 523 | snprintf(final_name, NI_MAXHOST - 1, "%s (%s)", hostname, ip); 524 | wn->SetName(dnt->index, final_name); 525 | } 526 | else { 527 | wn->SetName(dnt->index, hostname); 528 | } 529 | } 530 | TRACE_MSG("DNS resolver thread stopped."); 531 | } 532 | delete p; 533 | } 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | -------------------------------------------------------------------------------- /src/WinMTRNet.h: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRNet.h 3 | //***************************************************************************** 4 | 5 | #ifndef WINMTRNET_H_ 6 | #define WINMTRNET_H_ 7 | 8 | 9 | class WinMTRDialog; 10 | 11 | typedef IP_OPTION_INFORMATION IPINFO, *PIPINFO, FAR* LPIPINFO; 12 | #ifdef _WIN64 13 | typedef ICMP_ECHO_REPLY32 ICMPECHO, *PICMPECHO, FAR* LPICMPECHO; 14 | #else 15 | typedef ICMP_ECHO_REPLY ICMPECHO, *PICMPECHO, FAR* LPICMPECHO; 16 | #endif // _WIN64 17 | 18 | #define ECHO_REPLY_TIMEOUT 5000 19 | 20 | struct s_nethost { 21 | union { 22 | sockaddr_in addr; 23 | sockaddr_in6 addr6; 24 | }; 25 | int xmit; // number of PING packets sent 26 | int returned; // number of ICMP echo replies received 27 | unsigned long total; // total time 28 | int last; // last time 29 | int best; // best time 30 | int worst; // worst time 31 | char name[255]; 32 | }; 33 | 34 | //***************************************************************************** 35 | // CLASS: WinMTRNet 36 | //***************************************************************************** 37 | 38 | class WinMTRNet 39 | { 40 | typedef FARPROC PIO_APC_ROUTINE;//not the best way to do it, but works ;) (we do not use it anyway) 41 | //IPv4 42 | typedef HANDLE(WINAPI* LPFNICMPCREATEFILE)(VOID); 43 | typedef BOOL (WINAPI* LPFNICMPCLOSEHANDLE)(HANDLE); 44 | typedef DWORD (WINAPI* LPFNICMPSENDECHO2)(HANDLE IcmpHandle,HANDLE Event,PIO_APC_ROUTINE ApcRoutine,PVOID ApcContext,in_addr DestinationAddress,LPVOID RequestData,WORD RequestSize,PIP_OPTION_INFORMATION RequestOptions,LPVOID ReplyBuffer,DWORD ReplySize,DWORD Timeout); 45 | //IPv6 46 | typedef HANDLE(WINAPI* LPFNICMP6CREATEFILE)(VOID); 47 | typedef BOOL (WINAPI* LPFNICMP6CLOSEHANDLE)(HANDLE); 48 | typedef DWORD (WINAPI* LPFNICMP6SENDECHO2)(HANDLE IcmpHandle,HANDLE Event,PIO_APC_ROUTINE ApcRoutine,PVOID ApcContext,sockaddr_in6* SourceAddress,sockaddr_in6* DestinationAddress,LPVOID RequestData,WORD RequestSize,PIP_OPTION_INFORMATION RequestOptions,LPVOID ReplyBuffer,DWORD ReplySize,DWORD Timeout); 49 | 50 | public: 51 | 52 | WinMTRNet(WinMTRDialog* wp); 53 | ~WinMTRNet(); 54 | void DoTrace(sockaddr* sockaddr); 55 | void ResetHops(); 56 | void StopTrace(); 57 | 58 | sockaddr* GetAddr(int at); 59 | int GetName(int at, char* n); 60 | int GetBest(int at); 61 | int GetWorst(int at); 62 | int GetAvg(int at); 63 | int GetPercent(int at); 64 | int GetLast(int at); 65 | int GetReturned(int at); 66 | int GetXmit(int at); 67 | int GetMax(); 68 | 69 | void SetAddr(int at, u_long addr); 70 | void SetAddr6(int at, IPV6_ADDRESS_EX addrex); 71 | void SetName(int at, char* n); 72 | void SetErrorName(int at,DWORD errnum); 73 | void UpdateRTT(int at, int rtt); 74 | void AddReturned(int at); 75 | void AddXmit(int at); 76 | 77 | WinMTRDialog* wmtrdlg; 78 | union { 79 | in_addr last_remote_addr; 80 | in6_addr last_remote_addr6; 81 | }; 82 | bool hasIPv6; 83 | bool tracing; 84 | bool initialized; 85 | HANDLE hICMP; 86 | HANDLE hICMP6; 87 | //IPv4 88 | LPFNICMPCREATEFILE lpfnIcmpCreateFile; 89 | LPFNICMPCLOSEHANDLE lpfnIcmpCloseHandle; 90 | LPFNICMPSENDECHO2 lpfnIcmpSendEcho2; 91 | //IPv6 92 | LPFNICMP6CREATEFILE lpfnIcmp6CreateFile; 93 | LPFNICMP6SENDECHO2 lpfnIcmp6SendEcho2; 94 | private: 95 | HINSTANCE hICMP_DLL; 96 | 97 | struct s_nethost host[MaxHost]; 98 | HANDLE ghMutex; 99 | }; 100 | 101 | #endif // ifndef WINMTRNET_H_ 102 | -------------------------------------------------------------------------------- /src/WinMTROptions.cpp: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTROptions.cpp 3 | //***************************************************************************** 4 | 5 | #include "WinMTRGlobal.h" 6 | #include "WinMTROptions.h" 7 | 8 | #ifdef _DEBUG 9 | #define new DEBUG_NEW 10 | #undef THIS_FILE 11 | static char THIS_FILE[] = __FILE__; 12 | #endif 13 | 14 | 15 | //***************************************************************************** 16 | // BEGIN_MESSAGE_MAP 17 | //***************************************************************************** 18 | BEGIN_MESSAGE_MAP(WinMTROptions, CDialog) 19 | ON_BN_CLICKED(ID_LICENSE, OnLicense) 20 | END_MESSAGE_MAP() 21 | 22 | 23 | //***************************************************************************** 24 | // WinMTROptions::DoDataExchange 25 | //***************************************************************************** 26 | void WinMTROptions::DoDataExchange(CDataExchange* pDX) 27 | { 28 | CDialog::DoDataExchange(pDX); 29 | DDX_Control(pDX, IDC_EDIT_SIZE, m_editSize); 30 | DDX_Control(pDX, IDC_EDIT_INTERVAL, m_editInterval); 31 | DDX_Control(pDX, IDC_EDIT_MAX_LRU, m_editMaxLRU); 32 | DDX_Control(pDX, IDC_CHECK_DNS, m_checkDNS); 33 | } 34 | 35 | 36 | //***************************************************************************** 37 | // WinMTROptions::OnInitDialog 38 | //***************************************************************************** 39 | BOOL WinMTROptions::OnInitDialog() 40 | { 41 | CDialog::OnInitDialog(); 42 | 43 | char strtmp[20]; 44 | 45 | sprintf(strtmp, "%.1f", interval); 46 | m_editInterval.SetWindowText(strtmp); 47 | 48 | sprintf(strtmp, "%d", pingsize); 49 | m_editSize.SetWindowText(strtmp); 50 | 51 | sprintf(strtmp, "%d", maxLRU); 52 | m_editMaxLRU.SetWindowText(strtmp); 53 | 54 | m_checkDNS.SetCheck(useDNS); 55 | 56 | m_editInterval.SetFocus(); 57 | return FALSE; 58 | } 59 | 60 | 61 | //***************************************************************************** 62 | // WinMTROptions::OnOK 63 | //***************************************************************************** 64 | void WinMTROptions::OnOK() 65 | { 66 | char tmpstr[20]; 67 | 68 | useDNS = m_checkDNS.GetCheck(); 69 | 70 | m_editInterval.GetWindowText(tmpstr, 20); 71 | interval = atof(tmpstr); 72 | 73 | m_editSize.GetWindowText(tmpstr, 20); 74 | pingsize = atoi(tmpstr); 75 | 76 | m_editMaxLRU.GetWindowText(tmpstr, 20); 77 | maxLRU = atoi(tmpstr); 78 | 79 | CDialog::OnOK(); 80 | } 81 | 82 | //***************************************************************************** 83 | // WinMTROptions::OnLicense 84 | //***************************************************************************** 85 | void WinMTROptions::OnLicense() 86 | { 87 | ShellExecute (NULL, "open", "https://www.gnu.org/licenses/gpl-2.0.html", 0, 0, SW_SHOWNORMAL); 88 | } 89 | -------------------------------------------------------------------------------- /src/WinMTROptions.h: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTROptions.h 3 | //***************************************************************************** 4 | 5 | #ifndef WINMTROPTIONS_H_ 6 | #define WINMTROPTIONS_H_ 7 | 8 | //***************************************************************************** 9 | // CLASS: WinMTROptions 10 | //***************************************************************************** 11 | 12 | class WinMTROptions : public CDialog 13 | { 14 | public: 15 | WinMTROptions(double interval,int pingsize,int maxLRU,BOOL useDNS,CWnd* pParent=NULL) : 16 | interval(interval),pingsize(pingsize),maxLRU(maxLRU),useDNS(useDNS),CDialog(WinMTROptions::IDD, pParent) {}; 17 | 18 | double GetInterval() { return interval; }; 19 | int GetPingSize() { return pingsize; }; 20 | int GetMaxLRU() { return maxLRU; }; 21 | BOOL GetUseDNS() { return useDNS; }; 22 | 23 | enum { IDD = IDD_DIALOG_OPTIONS }; 24 | CEdit m_editSize; 25 | CEdit m_editInterval; 26 | CEdit m_editMaxLRU; 27 | CButton m_checkDNS; 28 | 29 | protected: 30 | virtual void DoDataExchange(CDataExchange* pDX); 31 | 32 | virtual BOOL OnInitDialog(); 33 | virtual void OnOK(); 34 | 35 | afx_msg void OnLicense(); 36 | 37 | DECLARE_MESSAGE_MAP(); 38 | 39 | private: 40 | double interval; 41 | int pingsize; 42 | int maxLRU; 43 | BOOL useDNS; 44 | }; 45 | 46 | #endif // ifndef WINMTROPTIONS_H_ 47 | -------------------------------------------------------------------------------- /src/WinMTRProperties.cpp: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRProperties.cpp 3 | //***************************************************************************** 4 | 5 | #include "WinMTRGlobal.h" 6 | #include "WinMTRProperties.h" 7 | 8 | #ifdef _DEBUG 9 | #define new DEBUG_NEW 10 | #undef THIS_FILE 11 | static char THIS_FILE[] = __FILE__; 12 | #endif 13 | 14 | //***************************************************************************** 15 | // BEGIN_MESSAGE_MAP 16 | //***************************************************************************** 17 | BEGIN_MESSAGE_MAP(WinMTRProperties, CDialog) 18 | END_MESSAGE_MAP() 19 | 20 | 21 | //***************************************************************************** 22 | // WinMTRProperties::WinMTRProperties 23 | //***************************************************************************** 24 | WinMTRProperties::WinMTRProperties(CWnd* pParent) : CDialog(WinMTRProperties::IDD, pParent) 25 | { 26 | } 27 | 28 | //***************************************************************************** 29 | // WinMTRroperties::DoDataExchange 30 | //***************************************************************************** 31 | void WinMTRProperties::DoDataExchange(CDataExchange* pDX) 32 | { 33 | CDialog::DoDataExchange(pDX); 34 | DDX_Control(pDX, IDC_EDIT_PHOST, m_editHost); 35 | DDX_Control(pDX, IDC_EDIT_PIP, m_editIP); 36 | DDX_Control(pDX, IDC_EDIT_PCOMMENT, m_editComment); 37 | 38 | DDX_Control(pDX, IDC_EDIT_PLOSS, m_editLoss); 39 | DDX_Control(pDX, IDC_EDIT_PSENT, m_editSent); 40 | DDX_Control(pDX, IDC_EDIT_PRECV, m_editRecv); 41 | 42 | DDX_Control(pDX, IDC_EDIT_PLAST, m_editLast); 43 | DDX_Control(pDX, IDC_EDIT_PBEST, m_editBest); 44 | DDX_Control(pDX, IDC_EDIT_PWORST, m_editWorst); 45 | DDX_Control(pDX, IDC_EDIT_PAVRG, m_editAvrg); 46 | } 47 | 48 | 49 | //***************************************************************************** 50 | // WinMTRProperties::OnInitDialog 51 | //***************************************************************************** 52 | BOOL WinMTRProperties::OnInitDialog() 53 | { 54 | CDialog::OnInitDialog(); 55 | char buf[255]; 56 | 57 | m_editIP.SetWindowText(ip); 58 | m_editHost.SetWindowText(host); 59 | m_editComment.SetWindowText(comment); 60 | 61 | sprintf(buf, "%d", pck_loss); 62 | m_editLoss.SetWindowText(buf); 63 | sprintf(buf, "%d", pck_sent); 64 | m_editSent.SetWindowText(buf); 65 | sprintf(buf, "%d", pck_recv); 66 | m_editRecv.SetWindowText(buf); 67 | 68 | sprintf(buf, "%.1f", ping_last); 69 | m_editLast.SetWindowText(buf); 70 | sprintf(buf, "%.1f", ping_best); 71 | m_editBest.SetWindowText(buf); 72 | sprintf(buf, "%.1f", ping_worst); 73 | m_editWorst.SetWindowText(buf); 74 | sprintf(buf, "%.1f", ping_avrg); 75 | m_editAvrg.SetWindowText(buf); 76 | 77 | return FALSE; 78 | } 79 | 80 | -------------------------------------------------------------------------------- /src/WinMTRProperties.h: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRProperties.h 3 | //***************************************************************************** 4 | 5 | #ifndef WINMTRPROPERTIES_H_ 6 | #define WINMTRPROPERTIES_H_ 7 | 8 | //***************************************************************************** 9 | // CLASS: WinMTRLicense 10 | //***************************************************************************** 11 | 12 | class WinMTRProperties : public CDialog 13 | { 14 | public: 15 | WinMTRProperties(CWnd* pParent = NULL); 16 | 17 | enum { IDD = IDD_DIALOG_PROPERTIES }; 18 | 19 | char host[255]; 20 | char ip[40]; 21 | char comment[255]; 22 | 23 | float ping_last; 24 | float ping_best; 25 | float ping_avrg; 26 | float ping_worst; 27 | 28 | int pck_sent; 29 | int pck_recv; 30 | int pck_loss; 31 | 32 | CEdit m_editHost, 33 | m_editIP, 34 | m_editComment, 35 | m_editSent, 36 | m_editRecv, 37 | m_editLoss, 38 | m_editLast, 39 | m_editBest, 40 | m_editWorst, 41 | m_editAvrg; 42 | 43 | protected: 44 | virtual void DoDataExchange(CDataExchange* pDX); 45 | 46 | virtual BOOL OnInitDialog(); 47 | 48 | DECLARE_MESSAGE_MAP(); 49 | }; 50 | 51 | #endif // WINMTRPROPERTIES_H_ 52 | -------------------------------------------------------------------------------- /src/WinMTRStatusBar.cpp: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRStatusBar.cpp 3 | //***************************************************************************** 4 | #include "WinMTRGlobal.h" 5 | #include "WinMTRStatusBar.h" 6 | 7 | #ifdef _DEBUG 8 | #define new DEBUG_NEW 9 | #undef THIS_FILE 10 | static char THIS_FILE[] = __FILE__; 11 | #endif 12 | 13 | WinMTRStatusBar::WinMTRStatusBar() 14 | { 15 | } 16 | 17 | WinMTRStatusBar::~WinMTRStatusBar() 18 | { 19 | for(int i = 0; i < m_arrPaneControls.GetSize(); i++) { 20 | if(m_arrPaneControls[i]->hWnd && ::IsWindow(m_arrPaneControls[i]->hWnd)) { 21 | ::ShowWindow(m_arrPaneControls[i]->hWnd, SW_HIDE); 22 | if(m_arrPaneControls[i]->bAutoDestroy) { 23 | ::DestroyWindow(m_arrPaneControls[i]->hWnd); 24 | } 25 | } 26 | _STATUSBAR_PANE_CTRL_ *pPaneCtrl = m_arrPaneControls[i]; 27 | if(pPaneCtrl) 28 | delete pPaneCtrl; 29 | } 30 | } 31 | 32 | BEGIN_MESSAGE_MAP(WinMTRStatusBar, CStatusBar) 33 | //{{AFX_MSG_MAP(WinMTRStatusBar) 34 | ON_WM_CREATE() 35 | //}}AFX_MSG_MAP 36 | END_MESSAGE_MAP() 37 | 38 | // WinMTRStatusBar message handlers 39 | 40 | int WinMTRStatusBar::OnCreate(LPCREATESTRUCT lpCreateStruct) 41 | { 42 | if(CStatusBar::OnCreate(lpCreateStruct) == -1) 43 | return -1; 44 | 45 | return 0; 46 | } 47 | 48 | LRESULT WinMTRStatusBar::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 49 | { 50 | LRESULT lResult =CStatusBar::WindowProc(message, wParam, lParam); 51 | if(message == WM_SIZE) { 52 | RepositionControls(); 53 | } 54 | return lResult; 55 | } 56 | 57 | void WinMTRStatusBar::RepositionControls() 58 | { 59 | HDWP _hDWP = ::BeginDeferWindowPos((int)m_arrPaneControls.GetSize()); 60 | 61 | CRect rcClient; 62 | GetClientRect(&rcClient); 63 | for(int i = 0; i < m_arrPaneControls.GetSize(); i++) { 64 | int iIndex = CommandToIndex(m_arrPaneControls[i]->nID); 65 | HWND hWnd = m_arrPaneControls[i]->hWnd; 66 | 67 | CRect rcPane; 68 | GetItemRect(iIndex, &rcPane); 69 | 70 | // CStatusBar::GetItemRect() sometimes returns invalid size 71 | // of the last pane - we will re-compute it 72 | int cx = ::GetSystemMetrics(SM_CXEDGE); 73 | DWORD dwPaneStyle = GetPaneStyle(iIndex); 74 | if(iIndex == (m_nCount-1)) { 75 | if((dwPaneStyle & SBPS_STRETCH) == 0) { 76 | UINT nID, nStyle; 77 | int cxWidth; 78 | GetPaneInfo(iIndex, nID, nStyle, cxWidth); 79 | rcPane.right = rcPane.left + cxWidth + cx*3; 80 | } // if( (dwPaneStyle & SBPS_STRETCH ) == 0 ) 81 | else { 82 | CRect rcClient; 83 | GetClientRect(&rcClient); 84 | rcPane.right = rcClient.right; 85 | if((GetStyle() & SBARS_SIZEGRIP) == SBARS_SIZEGRIP) { 86 | int cxSmIcon = ::GetSystemMetrics(SM_CXSMICON); 87 | rcPane.right -= cxSmIcon + cx; 88 | } // if( (GetStyle() & SBARS_SIZEGRIP) == SBARS_SIZEGRIP ) 89 | } // else from if( (dwPaneStyle & SBPS_STRETCH ) == 0 ) 90 | } // if( iIndex == (m_nCount-1) ) 91 | 92 | if((GetPaneStyle(iIndex) & SBPS_NOBORDERS) == 0) { 93 | rcPane.DeflateRect(cx,cx); 94 | } else { 95 | rcPane.DeflateRect(cx,1,cx,1); 96 | } 97 | 98 | if(hWnd && ::IsWindow(hWnd)) { 99 | _hDWP = ::DeferWindowPos( 100 | _hDWP, 101 | hWnd, 102 | NULL, 103 | rcPane.left, 104 | rcPane.top, 105 | rcPane.Width(), 106 | rcPane.Height(), 107 | SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_SHOWWINDOW 108 | ); 109 | 110 | ::RedrawWindow( 111 | hWnd, 112 | NULL, 113 | NULL, 114 | RDW_INVALIDATE|RDW_UPDATENOW 115 | |RDW_ERASE|RDW_ERASENOW 116 | ); 117 | 118 | } // if (hWnd && ::IsWindow(hWnd)){ 119 | } 120 | 121 | VERIFY(::EndDeferWindowPos(_hDWP)); 122 | }; 123 | 124 | BOOL WinMTRStatusBar::AddPane( 125 | UINT nID, // ID of the pane 126 | int nIndex // index of the pane 127 | ) 128 | { 129 | if(nIndex < 0 || nIndex > m_nCount) { 130 | ASSERT(FALSE); 131 | return FALSE; 132 | } 133 | 134 | if(CommandToIndex(nID) != -1) { 135 | ASSERT(FALSE); 136 | return FALSE; 137 | } 138 | 139 | CArray<_STATUSBAR_PANE_*,_STATUSBAR_PANE_*> arrPanesTmp; 140 | int iIndex = 0; 141 | for(iIndex = 0; iIndex < m_nCount+1; iIndex++) { 142 | _STATUSBAR_PANE_* pNewPane = new _STATUSBAR_PANE_; 143 | 144 | if(iIndex == nIndex) { 145 | pNewPane->nID = nID; 146 | pNewPane->nStyle = SBPS_NORMAL; 147 | } else { 148 | int idx = iIndex; 149 | if(iIndex > nIndex) idx--; 150 | 151 | _STATUSBAR_PANE_* pOldPane = GetPanePtr(idx); 152 | pNewPane->cxText = pOldPane->cxText; 153 | pNewPane->nFlags = pOldPane->nFlags; 154 | pNewPane->nID = pOldPane->nID; 155 | pNewPane->nStyle = pOldPane->nStyle; 156 | pNewPane->strText = pOldPane->strText; 157 | } 158 | arrPanesTmp.Add(pNewPane); 159 | } 160 | 161 | int nPanesCount = (int)arrPanesTmp.GetSize(); 162 | UINT* lpIDArray = new UINT[ nPanesCount ]; 163 | for(iIndex = 0; iIndex < nPanesCount; iIndex++) { 164 | lpIDArray[iIndex] = arrPanesTmp[iIndex]->nID; 165 | } 166 | 167 | // set the indicators 168 | SetIndicators(lpIDArray, nPanesCount); 169 | // free memory 170 | for(iIndex = 0; iIndex < nPanesCount; iIndex++) { 171 | _STATUSBAR_PANE_* pPane = arrPanesTmp[iIndex]; 172 | if(iIndex != nIndex) 173 | PaneInfoSet(iIndex, pPane); 174 | if(pPane) 175 | delete pPane; 176 | } 177 | 178 | arrPanesTmp.RemoveAll(); 179 | if(lpIDArray) 180 | delete []lpIDArray; 181 | 182 | RepositionControls(); 183 | 184 | return TRUE; 185 | } 186 | 187 | BOOL WinMTRStatusBar::RemovePane( 188 | UINT nID // ID of the pane 189 | ) 190 | { 191 | if(CommandToIndex(nID) == -1 || m_nCount == 1) { 192 | ASSERT(FALSE); 193 | return FALSE; 194 | } 195 | 196 | CArray<_STATUSBAR_PANE_*,_STATUSBAR_PANE_*> arrPanesTmp; 197 | int nIndex; 198 | for(nIndex = 0; nIndex < m_nCount; nIndex++) { 199 | _STATUSBAR_PANE_* pOldPane = GetPanePtr(nIndex); 200 | 201 | if(pOldPane->nID == nID) 202 | continue; 203 | 204 | _STATUSBAR_PANE_* pNewPane = new _STATUSBAR_PANE_; 205 | 206 | pNewPane->cxText = pOldPane->cxText; 207 | pNewPane->nFlags = pOldPane->nFlags; 208 | pNewPane->nID = pOldPane->nID; 209 | pNewPane->nStyle = pOldPane->nStyle; 210 | pNewPane->strText = pOldPane->strText; 211 | arrPanesTmp.Add(pNewPane); 212 | } 213 | 214 | UINT* lpIDArray = new UINT[arrPanesTmp.GetSize()]; 215 | for(nIndex = 0; nIndex < arrPanesTmp.GetSize(); nIndex++) { 216 | lpIDArray[nIndex] = arrPanesTmp[nIndex]->nID; 217 | } 218 | 219 | // set the indicators 220 | SetIndicators(lpIDArray, (int)arrPanesTmp.GetSize()); 221 | // free memory 222 | for(nIndex = 0; nIndex < arrPanesTmp.GetSize(); nIndex++) { 223 | _STATUSBAR_PANE_* pPane = arrPanesTmp[nIndex]; 224 | PaneInfoSet(nIndex, pPane); 225 | if(pPane) 226 | delete pPane; 227 | } 228 | 229 | for(int i = 0; i < m_arrPaneControls.GetSize(); i++) { 230 | if(m_arrPaneControls[i]->nID == nID) { 231 | if(m_arrPaneControls[i]->hWnd && ::IsWindow(m_arrPaneControls[i]->hWnd)) { 232 | ::ShowWindow(m_arrPaneControls[i]->hWnd, SW_HIDE); 233 | if(m_arrPaneControls[i]->bAutoDestroy) { 234 | ::DestroyWindow(m_arrPaneControls[i]->hWnd); 235 | } 236 | } 237 | _STATUSBAR_PANE_CTRL_ *pPaneCtrl = m_arrPaneControls[i]; 238 | if(pPaneCtrl) 239 | delete pPaneCtrl; 240 | m_arrPaneControls.RemoveAt(i); 241 | break; 242 | } 243 | } 244 | 245 | arrPanesTmp.RemoveAll(); 246 | if(lpIDArray) 247 | delete []lpIDArray; 248 | 249 | RepositionControls(); 250 | 251 | return TRUE; 252 | } 253 | 254 | BOOL WinMTRStatusBar::AddPaneControl(HWND hWnd, UINT nID, BOOL bAutoDestroy) 255 | { 256 | if(CommandToIndex(nID) == -1) { 257 | return FALSE; 258 | } 259 | 260 | _STATUSBAR_PANE_CTRL_* pPaneCtrl = new _STATUSBAR_PANE_CTRL_; 261 | pPaneCtrl->nID = nID; 262 | pPaneCtrl->hWnd = hWnd; 263 | pPaneCtrl->bAutoDestroy = bAutoDestroy; 264 | 265 | m_arrPaneControls.Add(pPaneCtrl); 266 | 267 | RepositionControls(); 268 | return TRUE; 269 | } 270 | 271 | BOOL WinMTRStatusBar::PaneInfoGet(int nIndex, _STATUSBAR_PANE_* pPane) 272 | { 273 | if(nIndex < m_nCount && nIndex >= 0) { 274 | GetPaneInfo(nIndex, pPane->nID, pPane->nStyle, pPane->cxText); 275 | CString strPaneText; 276 | GetPaneText(nIndex , strPaneText); 277 | pPane->strText = LPCTSTR(strPaneText); 278 | return TRUE; 279 | } 280 | return FALSE; 281 | } 282 | 283 | BOOL WinMTRStatusBar::PaneInfoSet(int nIndex, _STATUSBAR_PANE_* pPane) 284 | { 285 | if(nIndex < m_nCount && nIndex >= 0) { 286 | SetPaneInfo(nIndex, pPane->nID, pPane->nStyle, pPane->cxText); 287 | SetPaneText(nIndex, LPCTSTR(pPane->strText)); 288 | return TRUE; 289 | } 290 | return FALSE; 291 | } 292 | -------------------------------------------------------------------------------- /src/WinMTRStatusBar.h: -------------------------------------------------------------------------------- 1 | //***************************************************************************** 2 | // FILE: WinMTRStatusBar.h 3 | //***************************************************************************** 4 | #ifndef WINMTRSTATUSBAR_H_ 5 | #define WINMTRSTATUSBAR_H_ 6 | 7 | class WinMTRStatusBar : public CStatusBar 8 | { 9 | // Construction 10 | public: 11 | 12 | WinMTRStatusBar(); 13 | 14 | // Attributes 15 | public: 16 | 17 | // Operations 18 | public: 19 | 20 | int GetPanesCount() const 21 | { 22 | return m_nCount; 23 | } 24 | 25 | void SetPaneWidth(int nIndex, int nWidth) 26 | { 27 | _STATUSBAR_PANE_ pane; 28 | PaneInfoGet(nIndex, &pane); 29 | pane.cxText = nWidth; 30 | PaneInfoSet(nIndex, &pane); 31 | } 32 | 33 | BOOL AddPane( 34 | UINT nID, // ID of the pane 35 | int nIndex // index of the pane 36 | ); 37 | 38 | BOOL RemovePane( 39 | UINT nID // ID of the pane 40 | ); 41 | 42 | BOOL AddPaneControl(CWnd* pWnd, UINT nID, BOOL bAutoDestroy) 43 | { 44 | return AddPaneControl(pWnd->GetSafeHwnd(), nID, bAutoDestroy); 45 | } 46 | 47 | BOOL AddPaneControl(HWND hWnd, UINT nID, BOOL bAutoDestroy); 48 | 49 | void DisableControl(int nIndex, BOOL bDisable=TRUE) 50 | { 51 | UINT uItemID = GetItemID(nIndex); 52 | for(int i = 0; i < m_arrPaneControls.GetSize(); i++) { 53 | if(uItemID == m_arrPaneControls[i]->nID) { 54 | if(m_arrPaneControls[i]->hWnd && ::IsWindow(m_arrPaneControls[i]->hWnd)) { 55 | ::EnableWindow(m_arrPaneControls[i]->hWnd, bDisable); 56 | } 57 | } 58 | } 59 | } 60 | 61 | void SetPaneInfo(int nIndex, UINT nID, UINT nStyle, int cxWidth) 62 | { 63 | CStatusBar::SetPaneInfo(nIndex, nID, nStyle, cxWidth); 64 | BOOL bDisabled = ((nStyle&SBPS_DISABLED) == 0); 65 | DisableControl(nIndex, bDisabled); 66 | } 67 | 68 | void SetPaneStyle(int nIndex, UINT nStyle) 69 | { 70 | CStatusBar::SetPaneStyle(nIndex, nStyle); 71 | BOOL bDisabled = ((nStyle&SBPS_DISABLED) == 0); 72 | DisableControl(nIndex, bDisabled); 73 | } 74 | 75 | // Overrides 76 | // ClassWizard generated virtual function overrides 77 | //{{AFX_VIRTUAL(WinMTRStatusBar) 78 | //}}AFX_VIRTUAL 79 | 80 | // Implementation 81 | public: 82 | virtual ~WinMTRStatusBar(); 83 | 84 | protected: 85 | 86 | struct _STATUSBAR_PANE_ { 87 | _STATUSBAR_PANE_() 88 | { 89 | nID = cxText = nStyle = nFlags = 0; 90 | } 91 | 92 | UINT nID; // IDC of indicator: 0 => normal text area 93 | int cxText; // width of string area in pixels 94 | // on both sides there is a 3 pixel gap and 95 | // a one pixel border, making a pane 6 pixels wider 96 | UINT nStyle; // style flags (SBPS_*) 97 | UINT nFlags; // state flags (SBPF_*) 98 | CString strText; // text in the pane 99 | }; 100 | 101 | struct _STATUSBAR_PANE_CTRL_ { 102 | HWND hWnd; 103 | UINT nID; 104 | BOOL bAutoDestroy; 105 | }; 106 | 107 | CArray < _STATUSBAR_PANE_CTRL_*, _STATUSBAR_PANE_CTRL_* > m_arrPaneControls; 108 | 109 | _STATUSBAR_PANE_* GetPanePtr(int nIndex) const 110 | { 111 | ASSERT((nIndex >= 0 && nIndex < m_nCount) || m_nCount == 0); 112 | return ((_STATUSBAR_PANE_*)m_pData) + nIndex; 113 | } 114 | 115 | BOOL PaneInfoGet(int nIndex, _STATUSBAR_PANE_* pPane); 116 | BOOL PaneInfoSet(int nIndex, _STATUSBAR_PANE_* pPane); 117 | 118 | void RepositionControls(); 119 | 120 | // Generated message map functions 121 | protected: 122 | //{{AFX_MSG(WinMTRStatusBar) 123 | afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); 124 | //}}AFX_MSG 125 | DECLARE_MESSAGE_MAP() 126 | virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); 127 | }; 128 | 129 | #endif // WINMTRSTATUSBAR_H_ 130 | -------------------------------------------------------------------------------- /src/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 IDR_MAINFRAME 128 11 | #define IDD_DIALOG_OPTIONS 129 12 | #define IDD_DIALOG_PROPERTIES 131 13 | #define IDD_DIALOG_HELP 132 14 | #define IDR_MAINMENU 138 15 | #define IDC_EDIT_HOST 1000 16 | #define IDC_LIST_MTR 1001 17 | #define ID_RESTART 1002 18 | #define ID_OPTIONS 1003 19 | #define IDC_EDIT_INTERVAL 1004 20 | #define ID_CTTC 1004 21 | #define IDC_EDIT_SIZE 1005 22 | #define ID_CHTC 1005 23 | #define IDC_CHECK_DNS 1006 24 | #define ID_EXPT 1006 25 | #define ID_EXPH 1007 26 | #define ID_LICENSE 1008 27 | #define IDC_EDIT_LICENSE 1011 28 | #define IDC_EDIT_PHOST 1012 29 | #define IDC_EDIT_PIP 1013 30 | #define IDC_EDIT_PSENT 1014 31 | #define IDC_EDIT_PRECV 1015 32 | #define IDC_EDIT_PLOSS 1016 33 | #define IDC_EDIT_PLAST 1017 34 | #define IDC_EDIT_PBEST 1018 35 | #define IDC_EDIT_PAVRG 1019 36 | #define IDC_EDIT_PWORST 1020 37 | #define IDC_EDIT_PCOMMENT 1021 38 | #define IDC_STATICS 1022 39 | #define IDC_COMBO_HOST 1024 40 | #define IDC_EDIT_MAX_LRU 1025 41 | #define IDC_CHECK_IPV6 1026 42 | #define ID_FILE_EXIT 32773 43 | #define ID_ABOUT 32779 44 | 45 | // Next default values for new objects 46 | // 47 | #ifdef APSTUDIO_INVOKED 48 | #ifndef APSTUDIO_READONLY_SYMBOLS 49 | #define _APS_NEXT_RESOURCE_VALUE 140 50 | #define _APS_NEXT_COMMAND_VALUE 32780 51 | #define _APS_NEXT_CONTROL_VALUE 1028 52 | #define _APS_NEXT_SYMED_VALUE 101 53 | #endif 54 | #endif 55 | --------------------------------------------------------------------------------