Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenping.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS ping utility 00004 * FILE: base/applications/network/ping/ping.c 00005 * PURPOSE: Network test utility 00006 * PROGRAMMERS: 00007 */ 00008 00009 #include <winsock2.h> 00010 #include <ws2tcpip.h> 00011 #include <tchar.h> 00012 #include <stdarg.h> 00013 #include <string.h> 00014 #include <stdio.h> 00015 #include "resource.h" 00016 00017 #define NDEBUG 00018 00019 /* General ICMP constants */ 00020 #define ICMP_MINSIZE 8 /* Minimum ICMP packet size */ 00021 #define ICMP_MAXSIZE 65535 /* Maximum ICMP packet size */ 00022 00023 /* ICMP message types */ 00024 #define ICMPMSG_ECHOREQUEST 8 /* ICMP ECHO request message */ 00025 #define ICMPMSG_ECHOREPLY 0 /* ICMP ECHO reply message */ 00026 00027 #pragma pack(4) 00028 00029 /* IPv4 header structure */ 00030 typedef struct _IPv4_HEADER 00031 { 00032 unsigned char IHL:4; 00033 unsigned char Version:4; 00034 unsigned char TOS; 00035 unsigned short Length; 00036 unsigned short Id; 00037 unsigned short FragFlags; 00038 unsigned char TTL; 00039 unsigned char Protocol; 00040 unsigned short Checksum; 00041 unsigned int SrcAddress; 00042 unsigned int DstAddress; 00043 } IPv4_HEADER, *PIPv4_HEADER; 00044 00045 /* ICMP echo request/reply header structure */ 00046 typedef struct _ICMP_HEADER 00047 { 00048 unsigned char Type; 00049 unsigned char Code; 00050 unsigned short Checksum; 00051 unsigned short Id; 00052 unsigned short SeqNum; 00053 } ICMP_HEADER, *PICMP_HEADER; 00054 00055 typedef struct _ICMP_ECHO_PACKET 00056 { 00057 ICMP_HEADER Icmp; 00058 } ICMP_ECHO_PACKET, *PICMP_ECHO_PACKET; 00059 00060 #pragma pack(1) 00061 00062 BOOL NeverStop; 00063 BOOL ResolveAddresses; 00064 UINT PingCount; 00065 UINT DataSize; /* ICMP echo request data size */ 00066 BOOL DontFragment; 00067 ULONG TTLValue; 00068 ULONG TOSValue; 00069 ULONG Timeout; 00070 WCHAR TargetName[256]; 00071 SOCKET IcmpSock; 00072 SOCKADDR_IN Target; 00073 WCHAR TargetIP[16]; 00074 FD_SET Fds; 00075 TIMEVAL Timeval; 00076 UINT CurrentSeqNum; 00077 UINT SentCount; 00078 UINT LostCount; 00079 BOOL MinRTTSet; 00080 LARGE_INTEGER MinRTT; /* Minimum round trip time in microseconds */ 00081 LARGE_INTEGER MaxRTT; 00082 LARGE_INTEGER SumRTT; 00083 LARGE_INTEGER AvgRTT; 00084 LARGE_INTEGER TicksPerMs; /* Ticks per millisecond */ 00085 LARGE_INTEGER TicksPerUs; /* Ticks per microsecond */ 00086 LARGE_INTEGER SentTime; 00087 BOOL UsePerformanceCounter; 00088 HANDLE hStdOutput; 00089 00090 #ifndef NDEBUG 00091 /* Display the contents of a buffer */ 00092 static VOID DisplayBuffer( 00093 PVOID Buffer, 00094 DWORD Size) 00095 { 00096 UINT i; 00097 PCHAR p; 00098 00099 printf("Buffer (0x%p) Size (0x%lX).\n", Buffer, Size); 00100 00101 p = (PCHAR)Buffer; 00102 for (i = 0; i < Size; i++) 00103 { 00104 if (i % 16 == 0) 00105 printf("\n"); 00106 printf("%02X ", (p[i]) & 0xFF); 00107 } 00108 } 00109 #endif /* !NDEBUG */ 00110 00111 LPWSTR 00112 MyLoadString(UINT uID) 00113 { 00114 HRSRC hres; 00115 HGLOBAL hResData; 00116 WCHAR *pwsz; 00117 UINT string_num, i; 00118 00119 hres = FindResourceW(NULL, MAKEINTRESOURCEW((LOWORD(uID) >> 4) + 1), RT_STRING); 00120 if (!hres) return NULL; 00121 00122 hResData = LoadResource(NULL, hres); 00123 if (!hResData) return NULL; 00124 00125 pwsz = LockResource(hResData); 00126 if (!pwsz) return NULL; 00127 00128 string_num = uID & 15; 00129 for (i = 0; i < string_num; i++) 00130 pwsz += *pwsz + 1; 00131 00132 return pwsz + 1; 00133 } 00134 00135 void FormatOutput(UINT uID, ...) 00136 { 00137 va_list valist; 00138 00139 WCHAR Buf[1024]; 00140 LPWSTR pBuf = Buf; 00141 LPWSTR Format; 00142 DWORD written; 00143 UINT DataLength; 00144 00145 va_start(valist, uID); 00146 00147 Format = MyLoadString(uID); 00148 if (!Format) return; 00149 00150 DataLength = FormatMessage(FORMAT_MESSAGE_FROM_STRING, Format, 0, 0, Buf,\ 00151 sizeof(Buf) / sizeof(WCHAR), &valist); 00152 00153 if(!DataLength) 00154 { 00155 if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) 00156 return; 00157 00158 DataLength = FormatMessage(FORMAT_MESSAGE_FROM_STRING |\ 00159 FORMAT_MESSAGE_ALLOCATE_BUFFER,\ 00160 Format, 0, 0, (LPWSTR)&pBuf, 0, &valist); 00161 00162 if(!DataLength) 00163 return; 00164 } 00165 00166 WriteConsole(hStdOutput, pBuf, DataLength, &written, NULL); 00167 00168 if(pBuf != Buf) 00169 LocalFree(pBuf); 00170 } 00171 00172 /* Display usage information on screen */ 00173 static VOID Usage(VOID) 00174 { 00175 FormatOutput(IDS_USAGE); 00176 } 00177 00178 /* Reset configuration to default values */ 00179 static VOID Reset(VOID) 00180 { 00181 LARGE_INTEGER PerformanceCounterFrequency; 00182 00183 NeverStop = FALSE; 00184 ResolveAddresses = FALSE; 00185 PingCount = 4; 00186 DataSize = 32; 00187 DontFragment = FALSE; 00188 TTLValue = 128; 00189 TOSValue = 0; 00190 Timeout = 1000; 00191 UsePerformanceCounter = QueryPerformanceFrequency(&PerformanceCounterFrequency); 00192 00193 if (UsePerformanceCounter) 00194 { 00195 /* Performance counters may return incorrect results on some multiprocessor 00196 platforms so we restrict execution on the first processor. This may fail 00197 on Windows NT so we fall back to GetCurrentTick() for timing */ 00198 if (SetThreadAffinityMask (GetCurrentThread(), 1) == 0) 00199 UsePerformanceCounter = FALSE; 00200 00201 /* Convert frequency to ticks per millisecond */ 00202 TicksPerMs.QuadPart = PerformanceCounterFrequency.QuadPart / 1000; 00203 /* And to ticks per microsecond */ 00204 TicksPerUs.QuadPart = PerformanceCounterFrequency.QuadPart / 1000000; 00205 } 00206 if (!UsePerformanceCounter) 00207 { 00208 /* 1 tick per millisecond for GetCurrentTick() */ 00209 TicksPerMs.QuadPart = 1; 00210 /* GetCurrentTick() cannot handle microseconds */ 00211 TicksPerUs.QuadPart = 1; 00212 } 00213 } 00214 00215 /* Parse command line parameters */ 00216 static BOOL ParseCmdline(int argc, LPWSTR argv[]) 00217 { 00218 INT i; 00219 BOOL FoundTarget = FALSE, InvalidOption = FALSE; 00220 00221 if (argc < 2) 00222 { 00223 Usage(); 00224 return FALSE; 00225 } 00226 00227 for (i = 1; i < argc; i++) 00228 { 00229 if (argv[i][0] == L'-' || argv[i][0] == L'/') 00230 { 00231 switch (argv[i][1]) 00232 { 00233 case L't': NeverStop = TRUE; break; 00234 case L'a': ResolveAddresses = TRUE; break; 00235 case L'n': 00236 if (i + 1 < argc) 00237 PingCount = wcstoul(argv[++i], NULL, 0); 00238 else 00239 InvalidOption = TRUE; 00240 break; 00241 case L'l': 00242 if (i + 1 < argc) 00243 { 00244 DataSize = wcstoul(argv[++i], NULL, 0); 00245 00246 if (DataSize > ICMP_MAXSIZE - sizeof(ICMP_ECHO_PACKET) - sizeof(IPv4_HEADER)) 00247 { 00248 FormatOutput(IDS_BAD_VALUE_OPTION_L, ICMP_MAXSIZE - \ 00249 (int)sizeof(ICMP_ECHO_PACKET) - \ 00250 (int)sizeof(IPv4_HEADER)); 00251 return FALSE; 00252 } 00253 } else 00254 InvalidOption = TRUE; 00255 break; 00256 case L'f': DontFragment = TRUE; break; 00257 case L'i': 00258 if (i + 1 < argc) 00259 TTLValue = wcstoul(argv[++i], NULL, 0); 00260 else 00261 InvalidOption = TRUE; 00262 break; 00263 case L'v': 00264 if (i + 1 < argc) 00265 TOSValue = wcstoul(argv[++i], NULL, 0); 00266 else 00267 InvalidOption = TRUE; 00268 break; 00269 case L'w': 00270 if (i + 1 < argc) 00271 Timeout = wcstoul(argv[++i], NULL, 0); 00272 else 00273 InvalidOption = TRUE; 00274 break; 00275 case '?': 00276 Usage(); 00277 return FALSE; 00278 default: 00279 FormatOutput(IDS_BAD_OPTION, argv[i]); 00280 return FALSE; 00281 } 00282 if (InvalidOption) 00283 { 00284 FormatOutput(IDS_BAD_OPTION_FORMAT, argv[i]); 00285 return FALSE; 00286 } 00287 } 00288 else 00289 { 00290 if (FoundTarget) 00291 { 00292 FormatOutput(IDS_BAD_PARAMETER, argv[i]); 00293 return FALSE; 00294 } 00295 else 00296 { 00297 wcscpy(TargetName, argv[i]); 00298 FoundTarget = TRUE; 00299 } 00300 } 00301 } 00302 00303 if (!FoundTarget) 00304 { 00305 FormatOutput(IDS_DEST_MUST_BE_SPECIFIED); 00306 return FALSE; 00307 } 00308 00309 return TRUE; 00310 } 00311 00312 /* Calculate checksum of data */ 00313 static WORD Checksum(PUSHORT data, UINT size) 00314 { 00315 ULONG sum = 0; 00316 00317 while (size > 1) 00318 { 00319 sum += *data++; 00320 size -= sizeof(USHORT); 00321 } 00322 00323 if (size) 00324 sum += *(UCHAR*)data; 00325 00326 sum = (sum >> 16) + (sum & 0xFFFF); 00327 sum += (sum >> 16); 00328 00329 return (USHORT)(~sum); 00330 } 00331 00332 /* Prepare to ping target */ 00333 static BOOL Setup(VOID) 00334 { 00335 WORD wVersionRequested; 00336 WSADATA WsaData; 00337 INT Status; 00338 ULONG Addr; 00339 PHOSTENT phe; 00340 CHAR aTargetName[256]; 00341 00342 wVersionRequested = MAKEWORD(2, 2); 00343 00344 Status = WSAStartup(wVersionRequested, &WsaData); 00345 if (Status != 0) 00346 { 00347 FormatOutput(IDS_COULD_NOT_INIT_WINSOCK); 00348 return FALSE; 00349 } 00350 00351 IcmpSock = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, 0); 00352 if (IcmpSock == INVALID_SOCKET) 00353 { 00354 FormatOutput(IDS_COULD_NOT_CREATE_SOCKET, WSAGetLastError()); 00355 return FALSE; 00356 } 00357 00358 if (setsockopt(IcmpSock, 00359 IPPROTO_IP, 00360 IP_DONTFRAGMENT, 00361 (const char *)&DontFragment, 00362 sizeof(DontFragment)) == SOCKET_ERROR) 00363 { 00364 FormatOutput(IDS_SETSOCKOPT_FAILED, WSAGetLastError()); 00365 return FALSE; 00366 } 00367 00368 if (setsockopt(IcmpSock, 00369 IPPROTO_IP, 00370 IP_TTL, 00371 (const char *)&TTLValue, 00372 sizeof(TTLValue)) == SOCKET_ERROR) 00373 { 00374 FormatOutput(IDS_SETSOCKOPT_FAILED, WSAGetLastError()); 00375 return FALSE; 00376 } 00377 00378 00379 if(!WideCharToMultiByte(CP_ACP, 0, TargetName, -1, aTargetName,\ 00380 sizeof(aTargetName), NULL, NULL)) 00381 { 00382 FormatOutput(IDS_UNKNOWN_HOST, TargetName); 00383 return FALSE; 00384 } 00385 00386 ZeroMemory(&Target, sizeof(Target)); 00387 phe = NULL; 00388 Addr = inet_addr(aTargetName); 00389 if (Addr == INADDR_NONE) 00390 { 00391 phe = gethostbyname(aTargetName); 00392 if (phe == NULL) 00393 { 00394 FormatOutput(IDS_UNKNOWN_HOST, TargetName); 00395 return FALSE; 00396 } 00397 00398 CopyMemory(&Target.sin_addr, phe->h_addr, phe->h_length); 00399 Target.sin_family = phe->h_addrtype; 00400 } 00401 else 00402 { 00403 Target.sin_addr.s_addr = Addr; 00404 Target.sin_family = AF_INET; 00405 } 00406 00407 00408 swprintf(TargetIP, L"%d.%d.%d.%d", Target.sin_addr.S_un.S_un_b.s_b1,\ 00409 Target.sin_addr.S_un.S_un_b.s_b2,\ 00410 Target.sin_addr.S_un.S_un_b.s_b3,\ 00411 Target.sin_addr.S_un.S_un_b.s_b4); 00412 CurrentSeqNum = 1; 00413 SentCount = 0; 00414 LostCount = 0; 00415 MinRTT.QuadPart = 0; 00416 MaxRTT.QuadPart = 0; 00417 SumRTT.QuadPart = 0; 00418 MinRTTSet = FALSE; 00419 return TRUE; 00420 } 00421 00422 /* Close socket */ 00423 static VOID Cleanup(VOID) 00424 { 00425 if (IcmpSock != INVALID_SOCKET) 00426 closesocket(IcmpSock); 00427 00428 WSACleanup(); 00429 } 00430 00431 static VOID QueryTime(PLARGE_INTEGER Time) 00432 { 00433 if (UsePerformanceCounter) 00434 { 00435 if (QueryPerformanceCounter(Time) == 0) 00436 { 00437 /* This should not happen, but we fall 00438 back to GetCurrentTick() if it does */ 00439 Time->u.LowPart = (ULONG)GetTickCount(); 00440 Time->u.HighPart = 0; 00441 00442 /* 1 tick per millisecond for GetCurrentTick() */ 00443 TicksPerMs.QuadPart = 1; 00444 /* GetCurrentTick() cannot handle microseconds */ 00445 TicksPerUs.QuadPart = 1; 00446 00447 UsePerformanceCounter = FALSE; 00448 } 00449 } 00450 else 00451 { 00452 Time->u.LowPart = (ULONG)GetTickCount(); 00453 Time->u.HighPart = 0; 00454 } 00455 } 00456 00457 static VOID TimeToMsString(LPWSTR String, LARGE_INTEGER Time) 00458 { 00459 WCHAR Convstr[40]; 00460 LARGE_INTEGER LargeTime; 00461 LPWSTR ms; 00462 00463 LargeTime.QuadPart = Time.QuadPart / TicksPerMs.QuadPart; 00464 00465 _i64tow(LargeTime.QuadPart, Convstr, 10); 00466 wcscpy(String, Convstr); 00467 ms = MyLoadString(IDS_MS); 00468 wcscat(String, ms); 00469 } 00470 00471 /* Locate the ICMP data and print it. Returns TRUE if the packet was good, 00472 FALSE if not */ 00473 static BOOL DecodeResponse(PCHAR buffer, UINT size, PSOCKADDR_IN from) 00474 { 00475 PIPv4_HEADER IpHeader; 00476 PICMP_ECHO_PACKET Icmp; 00477 UINT IphLength; 00478 WCHAR Time[100]; 00479 LARGE_INTEGER RelativeTime; 00480 LARGE_INTEGER LargeTime; 00481 WCHAR Sign[2]; 00482 WCHAR wfromIP[16]; 00483 00484 IpHeader = (PIPv4_HEADER)buffer; 00485 00486 IphLength = IpHeader->IHL * 4; 00487 00488 if (size < IphLength + ICMP_MINSIZE) 00489 { 00490 #ifndef NDEBUG 00491 printf("Bad size (0x%X < 0x%X)\n", size, IphLength + ICMP_MINSIZE); 00492 #endif /* !NDEBUG */ 00493 return FALSE; 00494 } 00495 00496 Icmp = (PICMP_ECHO_PACKET)(buffer + IphLength); 00497 00498 if (Icmp->Icmp.Type != ICMPMSG_ECHOREPLY) 00499 { 00500 #ifndef NDEBUG 00501 printf("Bad ICMP type (0x%X should be 0x%X)\n", Icmp->Icmp.Type, ICMPMSG_ECHOREPLY); 00502 #endif /* !NDEBUG */ 00503 return FALSE; 00504 } 00505 00506 if (Icmp->Icmp.Id != (USHORT)GetCurrentProcessId()) 00507 { 00508 #ifndef NDEBUG 00509 printf("Bad ICMP id (0x%X should be 0x%X)\n", Icmp->Icmp.Id, (USHORT)GetCurrentProcessId()); 00510 #endif /* !NDEBUG */ 00511 return FALSE; 00512 } 00513 00514 if (from->sin_addr.s_addr != Target.sin_addr.s_addr) 00515 { 00516 #ifndef NDEBUG 00517 printf("Bad source address (%s should be %s)\n", inet_ntoa(from->sin_addr), inet_ntoa(Target.sin_addr)); 00518 #endif /* !NDEBUG */ 00519 return FALSE; 00520 } 00521 00522 QueryTime(&LargeTime); 00523 00524 RelativeTime.QuadPart = (LargeTime.QuadPart - SentTime.QuadPart); 00525 00526 if ((RelativeTime.QuadPart / TicksPerMs.QuadPart) < 1) 00527 { 00528 LPWSTR ms1; 00529 00530 wcscpy(Sign, L"<"); 00531 ms1 = MyLoadString(IDS_1MS); 00532 wcscpy(Time, ms1); 00533 } 00534 else 00535 { 00536 wcscpy(Sign, L"="); 00537 TimeToMsString(Time, RelativeTime); 00538 } 00539 00540 00541 swprintf(wfromIP, L"%d.%d.%d.%d", from->sin_addr.S_un.S_un_b.s_b1,\ 00542 from->sin_addr.S_un.S_un_b.s_b2,\ 00543 from->sin_addr.S_un.S_un_b.s_b3,\ 00544 from->sin_addr.S_un.S_un_b.s_b4); 00545 FormatOutput(IDS_REPLY_FROM, wfromIP,\ 00546 size - IphLength - (int)sizeof(ICMP_ECHO_PACKET),\ 00547 Sign, Time, IpHeader->TTL); 00548 00549 if (RelativeTime.QuadPart < MinRTT.QuadPart || !MinRTTSet) 00550 { 00551 MinRTT.QuadPart = RelativeTime.QuadPart; 00552 MinRTTSet = TRUE; 00553 } 00554 if (RelativeTime.QuadPart > MaxRTT.QuadPart) 00555 MaxRTT.QuadPart = RelativeTime.QuadPart; 00556 00557 SumRTT.QuadPart += RelativeTime.QuadPart; 00558 00559 return TRUE; 00560 } 00561 00562 /* Send and receive one ping */ 00563 static BOOL Ping(VOID) 00564 { 00565 INT Status; 00566 SOCKADDR From; 00567 INT Length; 00568 PVOID Buffer; 00569 UINT Size; 00570 PICMP_ECHO_PACKET Packet; 00571 00572 /* Account for extra space for IP header when packet is received */ 00573 Size = DataSize + 128; 00574 Buffer = GlobalAlloc(0, Size); 00575 if (!Buffer) 00576 { 00577 FormatOutput(IDS_NOT_ENOUGH_RESOURCES); 00578 return FALSE; 00579 } 00580 00581 ZeroMemory(Buffer, Size); 00582 Packet = (PICMP_ECHO_PACKET)Buffer; 00583 00584 /* Assemble ICMP echo request packet */ 00585 Packet->Icmp.Type = ICMPMSG_ECHOREQUEST; 00586 Packet->Icmp.Code = 0; 00587 Packet->Icmp.Id = (USHORT)GetCurrentProcessId(); 00588 Packet->Icmp.SeqNum = htons((USHORT)CurrentSeqNum); 00589 Packet->Icmp.Checksum = 0; 00590 00591 /* Calculate checksum for ICMP header and data area */ 00592 Packet->Icmp.Checksum = Checksum((PUSHORT)&Packet->Icmp, sizeof(ICMP_ECHO_PACKET) + DataSize); 00593 00594 CurrentSeqNum++; 00595 00596 /* Send ICMP echo request */ 00597 00598 FD_ZERO(&Fds); 00599 FD_SET(IcmpSock, &Fds); 00600 Timeval.tv_sec = Timeout / 1000; 00601 Timeval.tv_usec = Timeout % 1000; 00602 Status = select(0, NULL, &Fds, NULL, &Timeval); 00603 if ((Status != SOCKET_ERROR) && (Status != 0)) 00604 { 00605 00606 #ifndef NDEBUG 00607 printf("Sending packet\n"); 00608 DisplayBuffer(Buffer, sizeof(ICMP_ECHO_PACKET) + DataSize); 00609 printf("\n"); 00610 #endif /* !NDEBUG */ 00611 00612 Status = sendto(IcmpSock, Buffer, sizeof(ICMP_ECHO_PACKET) + DataSize, 00613 0, (SOCKADDR*)&Target, sizeof(Target)); 00614 QueryTime(&SentTime); 00615 SentCount++; 00616 } 00617 if (Status == SOCKET_ERROR) 00618 { 00619 if (WSAGetLastError() == WSAEHOSTUNREACH) 00620 FormatOutput(IDS_DEST_UNREACHABLE); 00621 else 00622 FormatOutput(IDS_COULD_NOT_TRANSMIT, WSAGetLastError()); 00623 GlobalFree(Buffer); 00624 return FALSE; 00625 } 00626 00627 /* Expect to receive ICMP echo reply */ 00628 FD_ZERO(&Fds); 00629 FD_SET(IcmpSock, &Fds); 00630 Timeval.tv_sec = Timeout / 1000; 00631 Timeval.tv_usec = Timeout % 1000; 00632 00633 do { 00634 Status = select(0, &Fds, NULL, NULL, &Timeval); 00635 if ((Status != SOCKET_ERROR) && (Status != 0)) 00636 { 00637 Length = sizeof(From); 00638 Status = recvfrom(IcmpSock, Buffer, Size, 0, &From, &Length); 00639 00640 #ifndef NDEBUG 00641 printf("Received packet\n"); 00642 DisplayBuffer(Buffer, Status); 00643 printf("\n"); 00644 #endif /* !NDEBUG */ 00645 } 00646 else 00647 LostCount++; 00648 if (Status == SOCKET_ERROR) 00649 { 00650 if (WSAGetLastError() != WSAETIMEDOUT) 00651 { 00652 FormatOutput(IDS_COULD_NOT_RECV, WSAGetLastError()); 00653 GlobalFree(Buffer); 00654 return FALSE; 00655 } 00656 Status = 0; 00657 } 00658 00659 if (Status == 0) 00660 { 00661 FormatOutput(IDS_REQUEST_TIMEOUT); 00662 GlobalFree(Buffer); 00663 return TRUE; 00664 } 00665 00666 } while (!DecodeResponse(Buffer, Status, (PSOCKADDR_IN)&From)); 00667 00668 GlobalFree(Buffer); 00669 return TRUE; 00670 } 00671 00672 00673 /* Program entry point */ 00674 int wmain(int argc, LPWSTR argv[]) 00675 { 00676 UINT Count; 00677 WCHAR MinTime[20]; 00678 WCHAR MaxTime[20]; 00679 WCHAR AvgTime[20]; 00680 00681 hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); 00682 00683 Reset(); 00684 00685 if ((ParseCmdline(argc, argv)) && (Setup())) 00686 { 00687 00688 FormatOutput(IDS_PING_WITH_BYTES, TargetName, TargetIP, DataSize); 00689 00690 Count = 0; 00691 while ((NeverStop) || (Count < PingCount)) 00692 { 00693 Ping(); 00694 Count++; 00695 if((NeverStop) || (Count < PingCount)) 00696 Sleep(Timeout); 00697 }; 00698 00699 Cleanup(); 00700 00701 /* Calculate avarage round trip time */ 00702 if ((SentCount - LostCount) > 0) 00703 AvgRTT.QuadPart = SumRTT.QuadPart / (SentCount - LostCount); 00704 else 00705 AvgRTT.QuadPart = 0; 00706 00707 /* Calculate loss percent */ 00708 Count = SentCount ? (LostCount * 100) / SentCount : 0; 00709 00710 if (!MinRTTSet) 00711 MinRTT = MaxRTT; 00712 00713 TimeToMsString(MinTime, MinRTT); 00714 TimeToMsString(MaxTime, MaxRTT); 00715 TimeToMsString(AvgTime, AvgRTT); 00716 00717 /* Print statistics */ 00718 FormatOutput(IDS_PING_STATISTICS, TargetIP); 00719 FormatOutput(IDS_PACKETS_SENT_RECEIVED_LOST,\ 00720 SentCount, SentCount - LostCount, LostCount, Count); 00721 00722 00723 /* Print approximate times or NO approximate times if 100% loss */ 00724 if ((SentCount - LostCount) > 0) 00725 { 00726 FormatOutput(IDS_APPROXIMATE_ROUND_TRIP); 00727 FormatOutput(IDS_MIN_MAX_AVERAGE, MinTime, MaxTime, AvgTime); 00728 } 00729 } 00730 else 00731 { 00732 return 1; 00733 } 00734 return 0; 00735 } 00736 00737 /* EOF */ Generated on Sat May 26 2012 04:16:10 for ReactOS by
1.7.6.1
|