├── .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 |
--------------------------------------------------------------------------------