Author: tkreuzer Date: Wed Jan 12 14:57:22 2011 New Revision: 50371
URL: http://svn.reactos.org/svn/reactos?rev=50371&view=rev Log: [PING] Add localization support to ping. Patch by "none" (menone7 at gmail dot com)
See issue #5500 for more details.
Added: trunk/reactos/base/applications/network/ping/lang/ trunk/reactos/base/applications/network/ping/lang/en-US.rc (with props) trunk/reactos/base/applications/network/ping/resource.h (with props) Modified: trunk/reactos/base/applications/network/ping/ping.c trunk/reactos/base/applications/network/ping/ping.rbuild trunk/reactos/base/applications/network/ping/ping.rc
Added: trunk/reactos/base/applications/network/ping/lang/en-US.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/network/p... ============================================================================== --- trunk/reactos/base/applications/network/ping/lang/en-US.rc (added) +++ trunk/reactos/base/applications/network/ping/lang/en-US.rc [iso-8859-1] Wed Jan 12 14:57:22 2011 @@ -1,0 +1,35 @@ +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +STRINGTABLE DISCARDABLE +BEGIN + IDS_USAGE "\nUsage: ping [-t] [-n count] [-l size] [-w timeout] destination-host\n\n" \ + "Options:\n" \ + " -t Ping the specified host until stopped.\n" \ + " To stop - type Control-C.\n" \ + " -n count Number of echo requests to send.\n" \ + " -l size Send buffer size.\n" \ + " -w timeout Timeout in milliseconds to wait for each reply.\n\n\0" + + IDS_PING_WITH_BYTES "\nPinging %1 [%2] with %3!d! bytes of data:\n\n\0" + IDS_PING_STATISTICS "\nPing statistics for %1:\n\0" + IDS_PACKETS_SENT_RECEIVED_LOST " Packets: Sent = %1!d!, Received = %2!d!, Lost = %3!d! (%4!d!%% loss),\n\0" + IDS_APPROXIMATE_ROUND_TRIP "Approximate round trip times in milli-seconds:\n\0" + IDS_MIN_MAX_AVERAGE " Minimum = %1, Maximum = %2, Average = %3\n\0" + IDS_NOT_ENOUGH_RESOURCES "Not enough free resources available.\n\0" + IDS_UNKNOWN_HOST "Unknown host %1.\n\0" + IDS_SETSOCKOPT_FAILED "setsockopt failed (%1!d!).\n\0" + IDS_COULD_NOT_CREATE_SOCKET "Could not create socket (#%1!d!).\n\0" + IDS_COULD_NOT_INIT_WINSOCK "Could not initialize winsock dll.\n\0" + IDS_DEST_MUST_BE_SPECIFIED "Name or IP address of destination host must be specified.\n\0" + IDS_BAD_PARAMETER "Bad parameter %1.\n\0" + IDS_BAD_OPTION_FORMAT "Bad option format %1.\n\0" + IDS_BAD_OPTION "Bad option %1.\n\0" + IDS_BAD_VALUE_OPTION_L "Bad value for option -l, valid range is from 0 to %1!d!.\n\0" + IDS_REPLY_FROM "Reply from %1: bytes=%2!d! time%3%4 TTL=%5!d!\n\0" + IDS_DEST_UNREACHABLE "Destination host unreachable.\n\0" + IDS_COULD_NOT_TRANSMIT "Could not transmit data (%1!d!).\n\0" + IDS_COULD_NOT_RECV "Could not receive data (%1!d!).\n\0" + IDS_REQUEST_TIMEOUT "Request timed out.\n\0" + IDS_MS "ms\0" + IDS_1MS "1ms\0" +END
Propchange: trunk/reactos/base/applications/network/ping/lang/en-US.rc ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/base/applications/network/ping/ping.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/network/p... ============================================================================== --- trunk/reactos/base/applications/network/ping/ping.c [iso-8859-1] (original) +++ trunk/reactos/base/applications/network/ping/ping.c [iso-8859-1] Wed Jan 12 14:57:22 2011 @@ -12,6 +12,7 @@ #include <stdarg.h> #include <string.h> #include <stdio.h> +#include "resource.h"
#define NDEBUG
@@ -67,10 +68,10 @@ ULONG TTLValue; ULONG TOSValue; ULONG Timeout; -CHAR TargetName[256]; +WCHAR TargetName[256]; SOCKET IcmpSock; SOCKADDR_IN Target; -LPSTR TargetIP; +WCHAR TargetIP[16]; FD_SET Fds; TIMEVAL Timeval; UINT CurrentSeqNum; @@ -85,6 +86,7 @@ LARGE_INTEGER TicksPerUs; /* Ticks per microsecond */ LARGE_INTEGER SentTime; BOOL UsePerformanceCounter; +HANDLE hStdOutput;
#ifndef NDEBUG /* Display the contents of a buffer */ @@ -107,16 +109,47 @@ } #endif /* !NDEBUG */
+void FormatOutput(UINT uID, ...) +{ + va_list valist; + + WCHAR Buf[1024]; + LPWSTR pBuf = Buf; + LPWSTR Format; + DWORD written; + UINT DataLength; + + va_start(valist, uID); + + if(!LoadString(NULL, uID, (LPWSTR)&Format, 0)) + return; + + DataLength = FormatMessage(FORMAT_MESSAGE_FROM_STRING, Format, 0, 0, Buf,\ + sizeof(Buf) / sizeof(WCHAR), &valist); + + if(!DataLength) + { + if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return; + + DataLength = FormatMessage(FORMAT_MESSAGE_FROM_STRING |\ + FORMAT_MESSAGE_ALLOCATE_BUFFER,\ + Format, 0, 0, (LPWSTR)&pBuf, 0, &valist); + + if(!DataLength) + return; + } + + WriteConsole(hStdOutput, pBuf, DataLength, &written, NULL); + + if(pBuf != Buf) + LocalFree(pBuf); +} + /* Display usage information on screen */ static VOID Usage(VOID) { - printf("\nUsage: ping [-t] [-n count] [-l size] [-w timeout] destination-host\n\n"); - printf("Options:\n"); - printf(" -t Ping the specified host until stopped.\n"); - printf(" To stop - type Control-C.\n"); - printf(" -n count Number of echo requests to send.\n"); - printf(" -l size Send buffer size.\n"); - printf(" -w timeout Timeout in milliseconds to wait for each reply.\n\n"); + FormatOutput(IDS_USAGE); }
/* Reset configuration to default values */ @@ -157,26 +190,26 @@ }
/* Return ULONG in a string */ -static ULONG GetULONG(LPSTR String) +static ULONG GetULONG(LPWSTR String) { UINT i, Length; ULONG Value; - LPSTR StopString; + LPWSTR StopString; i = 0; - Length = (UINT)_tcslen(String); - while ((i < Length) && ((String[i] < '0') || (String[i] > '9'))) i++; - if ((i >= Length) || ((String[i] < '0') || (String[i] > '9'))) + Length = (UINT)wcslen(String); + while ((i < Length) && ((String[i] < L'0') || (String[i] > L'9'))) i++; + if ((i >= Length) || ((String[i] < L'0') || (String[i] > L'9'))) { InvalidOption = TRUE; return 0; } - Value = strtoul(&String[i], &StopString, 10); + Value = wcstoul(&String[i], &StopString, 10);
return Value; }
/* Return ULONG in a string. Try next paramter if not successful */ -static ULONG GetULONG2(LPSTR String1, LPSTR String2, PINT i) +static ULONG GetULONG2(LPWSTR String1, LPWSTR String2, PINT i) { ULONG Value;
@@ -184,7 +217,7 @@ if (InvalidOption) { InvalidOption = FALSE; - if (String2[0] != '-') + if (String2[0] != L'-') { Value = GetULONG(String2); if (!InvalidOption) @@ -196,7 +229,7 @@ }
/* Parse command line parameters */ -static BOOL ParseCmdline(int argc, char* argv[]) +static BOOL ParseCmdline(int argc, LPWSTR argv[]) { INT i; BOOL ShowUsage; @@ -210,34 +243,35 @@
for (i = 1; i < argc; i++) { - if (argv[i][0] == '-') + if (argv[i][0] == L'-') { switch (argv[i][1]) { - case 't': NeverStop = TRUE; break; - case 'a': ResolveAddresses = TRUE; break; - case 'n': PingCount = GetULONG2(&argv[i][2], argv[i + 1], &i); break; - case 'l': + case L't': NeverStop = TRUE; break; + case L'a': ResolveAddresses = TRUE; break; + case L'n': PingCount = GetULONG2(&argv[i][2], argv[i + 1], &i); break; + case L'l': DataSize = GetULONG2(&argv[i][2], argv[i + 1], &i); if (DataSize > ICMP_MAXSIZE - sizeof(ICMP_ECHO_PACKET) - sizeof(IPv4_HEADER)) { - printf("Bad value for option -l, valid range is from 0 to %d.\n", - ICMP_MAXSIZE - (int)sizeof(ICMP_ECHO_PACKET) - (int)sizeof(IPv4_HEADER)); + FormatOutput(IDS_BAD_VALUE_OPTION_L, ICMP_MAXSIZE - \ + (int)sizeof(ICMP_ECHO_PACKET) - \ + (int)sizeof(IPv4_HEADER)); return FALSE; } break; - case 'f': DontFragment = TRUE; break; - case 'i': TTLValue = GetULONG2(&argv[i][2], argv[i + 1], &i); break; - case 'v': TOSValue = GetULONG2(&argv[i][2], argv[i + 1], &i); break; - case 'w': Timeout = GetULONG2(&argv[i][2], argv[i + 1], &i); break; + case L'f': DontFragment = TRUE; break; + case L'i': TTLValue = GetULONG2(&argv[i][2], argv[i + 1], &i); break; + case L'v': TOSValue = GetULONG2(&argv[i][2], argv[i + 1], &i); break; + case L'w': Timeout = GetULONG2(&argv[i][2], argv[i + 1], &i); break; default: - printf("Bad option %s.\n", argv[i]); + FormatOutput(IDS_BAD_OPTION, argv[i]); Usage(); return FALSE; } if (InvalidOption) { - printf("Bad option format %s.\n", argv[i]); + FormatOutput(IDS_BAD_OPTION_FORMAT, argv[i]); return FALSE; } } @@ -245,12 +279,12 @@ { if (FoundTarget) { - printf("Bad parameter %s.\n", argv[i]); + FormatOutput(IDS_BAD_PARAMETER, argv[i]); return FALSE; } else { - lstrcpy(TargetName, argv[i]); + wcscpy(TargetName, argv[i]); FoundTarget = TRUE; } } @@ -258,7 +292,7 @@
if ((!ShowUsage) && (!FoundTarget)) { - printf("Name or IP address of destination host must be specified.\n"); + FormatOutput(IDS_DEST_MUST_BE_SPECIFIED); return FALSE; }
@@ -298,20 +332,21 @@ INT Status; ULONG Addr; PHOSTENT phe; + CHAR aTargetName[256];
wVersionRequested = MAKEWORD(2, 2);
Status = WSAStartup(wVersionRequested, &WsaData); if (Status != 0) { - printf("Could not initialize winsock dll.\n"); + FormatOutput(IDS_COULD_NOT_INIT_WINSOCK); return FALSE; }
IcmpSock = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, 0); if (IcmpSock == INVALID_SOCKET) { - printf("Could not create socket (#%d).\n", WSAGetLastError()); + FormatOutput(IDS_COULD_NOT_CREATE_SOCKET, WSAGetLastError()); return FALSE; }
@@ -321,8 +356,8 @@ (const char *)&DontFragment, sizeof(DontFragment)) == SOCKET_ERROR) { - printf("setsockopt failed (%d).\n", WSAGetLastError()); - return FALSE; + FormatOutput(IDS_SETSOCKOPT_FAILED, WSAGetLastError()); + return FALSE; }
if (setsockopt(IcmpSock, @@ -331,35 +366,44 @@ (const char *)&TTLValue, sizeof(TTLValue)) == SOCKET_ERROR) { - printf("setsockopt failed (%d).\n", WSAGetLastError()); - return FALSE; - } - + FormatOutput(IDS_SETSOCKOPT_FAILED, WSAGetLastError()); + return FALSE; + } + + + if(!WideCharToMultiByte(CP_ACP, 0, TargetName, -1, aTargetName,\ + sizeof(aTargetName), NULL, NULL)) + { + FormatOutput(IDS_UNKNOWN_HOST, TargetName); + return FALSE; + }
ZeroMemory(&Target, sizeof(Target)); phe = NULL; - Addr = inet_addr(TargetName); + Addr = inet_addr(aTargetName); if (Addr == INADDR_NONE) { - phe = gethostbyname(TargetName); + phe = gethostbyname(aTargetName); if (phe == NULL) { - printf("Unknown host %s.\n", TargetName); + FormatOutput(IDS_UNKNOWN_HOST, TargetName); return FALSE; } - } - - if (phe != NULL) + CopyMemory(&Target.sin_addr, phe->h_addr, phe->h_length); + Target.sin_family = phe->h_addrtype; + } else + { Target.sin_addr.s_addr = Addr; - - if (phe != NULL) - Target.sin_family = phe->h_addrtype; - else Target.sin_family = AF_INET; - - TargetIP = inet_ntoa(Target.sin_addr); + } + + + swprintf(TargetIP, L"%d.%d.%d.%d", Target.sin_addr.S_un.S_un_b.s_b1,\ + Target.sin_addr.S_un.S_un_b.s_b2,\ + Target.sin_addr.S_un.S_un_b.s_b3,\ + Target.sin_addr.S_un.S_un_b.s_b4); CurrentSeqNum = 1; SentCount = 0; LostCount = 0; @@ -405,16 +449,18 @@ } }
-static VOID TimeToMsString(LPSTR String, LARGE_INTEGER Time) -{ - CHAR Convstr[40]; +static VOID TimeToMsString(LPWSTR String, LARGE_INTEGER Time) +{ + WCHAR Convstr[40]; LARGE_INTEGER LargeTime; + LPWSTR ms;
LargeTime.QuadPart = Time.QuadPart / TicksPerMs.QuadPart;
- _i64toa(LargeTime.QuadPart, Convstr, 10); - strcpy(String, Convstr); - strcat(String, "ms"); + _i64tow(LargeTime.QuadPart, Convstr, 10); + wcscpy(String, Convstr); + LoadString(NULL, IDS_MS, (LPWSTR)&ms, 0); + wcscat(String, ms); }
/* Locate the ICMP data and print it. Returns TRUE if the packet was good, @@ -424,10 +470,11 @@ PIPv4_HEADER IpHeader; PICMP_ECHO_PACKET Icmp; UINT IphLength; - CHAR Time[100]; + WCHAR Time[100]; LARGE_INTEGER RelativeTime; LARGE_INTEGER LargeTime; - CHAR Sign[2]; + WCHAR Sign[2]; + WCHAR wfromIP[16];
IpHeader = (PIPv4_HEADER)buffer;
@@ -473,18 +520,27 @@
if ((RelativeTime.QuadPart / TicksPerMs.QuadPart) < 1) { - strcpy(Sign, "<"); - strcpy(Time, "1ms"); + LPWSTR ms1; + + wcscpy(Sign, L"<"); + LoadString(NULL, IDS_1MS, (LPWSTR)&ms1, 0); + wcscpy(Time, ms1); } else { - strcpy(Sign, "="); + wcscpy(Sign, L"="); TimeToMsString(Time, RelativeTime); }
- printf("Reply from %s: bytes=%d time%s%s TTL=%d\n", inet_ntoa(from->sin_addr), - size - IphLength - (int)sizeof(ICMP_ECHO_PACKET), Sign, Time, IpHeader->TTL); + swprintf(wfromIP, L"%d.%d.%d.%d", from->sin_addr.S_un.S_un_b.s_b1,\ + from->sin_addr.S_un.S_un_b.s_b2,\ + from->sin_addr.S_un.S_un_b.s_b3,\ + from->sin_addr.S_un.S_un_b.s_b4); + FormatOutput(IDS_REPLY_FROM, wfromIP,\ + size - IphLength - (int)sizeof(ICMP_ECHO_PACKET),\ + Sign, Time, IpHeader->TTL); + if (RelativeTime.QuadPart < MinRTT.QuadPart || !MinRTTSet) { MinRTT.QuadPart = RelativeTime.QuadPart; @@ -513,7 +569,7 @@ Buffer = GlobalAlloc(0, Size); if (!Buffer) { - printf("Not enough free resources available.\n"); + FormatOutput(IDS_NOT_ENOUGH_RESOURCES); return FALSE; }
@@ -556,9 +612,9 @@ if (Status == SOCKET_ERROR) { if (WSAGetLastError() == WSAEHOSTUNREACH) - printf("Destination host unreachable.\n"); + FormatOutput(IDS_DEST_UNREACHABLE); else - printf("Could not transmit data (%d).\n", WSAGetLastError()); + FormatOutput(IDS_COULD_NOT_TRANSMIT, WSAGetLastError()); GlobalFree(Buffer); return FALSE; } @@ -588,7 +644,7 @@ { if (WSAGetLastError() != WSAETIMEDOUT) { - printf("Could not receive data (%d).\n", WSAGetLastError()); + FormatOutput(IDS_COULD_NOT_RECV, WSAGetLastError()); GlobalFree(Buffer); return FALSE; } @@ -597,7 +653,7 @@
if (Status == 0) { - printf("Request timed out.\n"); + FormatOutput(IDS_REQUEST_TIMEOUT); GlobalFree(Buffer); return TRUE; } @@ -610,20 +666,21 @@
/* Program entry point */ -int main(int argc, char* argv[]) +int wmain(int argc, LPWSTR argv[]) { UINT Count; - CHAR MinTime[20]; - CHAR MaxTime[20]; - CHAR AvgTime[20]; + WCHAR MinTime[20]; + WCHAR MaxTime[20]; + WCHAR AvgTime[20]; + + hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
Reset();
if ((ParseCmdline(argc, argv)) && (Setup())) {
- printf("\nPinging %s [%s] with %d bytes of data:\n\n", - TargetName, TargetIP, DataSize); + FormatOutput(IDS_PING_WITH_BYTES, TargetName, TargetIP, DataSize);
Count = 0; while ((NeverStop) || (Count < PingCount)) @@ -653,15 +710,15 @@ TimeToMsString(AvgTime, AvgRTT);
/* Print statistics */ - printf("\nPing statistics for %s:\n", TargetIP); - printf(" Packets: Sent = %d, Received = %d, Lost = %d (%d%% loss),\n", - SentCount, SentCount - LostCount, LostCount, Count); + FormatOutput(IDS_PING_STATISTICS, TargetIP); + FormatOutput(IDS_PACKETS_SENT_RECEIVED_LOST,\ + SentCount, SentCount - LostCount, LostCount, Count); + /* Print approximate times or NO approximate times if 100% loss */ if ((SentCount - LostCount) > 0) { - printf("Approximate round trip times in milli-seconds:\n"); - printf(" Minimum = %s, Maximum = %s, Average = %s\n", - MinTime, MaxTime, AvgTime); + FormatOutput(IDS_APPROXIMATE_ROUND_TRIP); + FormatOutput(IDS_MIN_MAX_AVERAGE, MinTime, MaxTime, AvgTime); } } return 0;
Modified: trunk/reactos/base/applications/network/ping/ping.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/network/p... ============================================================================== --- trunk/reactos/base/applications/network/ping/ping.rbuild [iso-8859-1] (original) +++ trunk/reactos/base/applications/network/ping/ping.rbuild [iso-8859-1] Wed Jan 12 14:57:22 2011 @@ -1,9 +1,10 @@ <?xml version="1.0"?> <!DOCTYPE module SYSTEM "../../../../tools/rbuild/project.dtd"> -<module name="ping" type="win32cui" installbase="system32" installname="ping.exe"> +<module name="ping" type="win32cui" installbase="system32" installname="ping.exe" unicode="true"> <include base="ping">.</include> <define name="__USE_W32_SOCKETS" /> <library>ws2_32</library> + <library>user32</library> <file>ping.c</file> <file>ping.rc</file> </module>
Modified: trunk/reactos/base/applications/network/ping/ping.rc URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/network/p... ============================================================================== --- trunk/reactos/base/applications/network/ping/ping.rc [iso-8859-1] (original) +++ trunk/reactos/base/applications/network/ping/ping.rc [iso-8859-1] Wed Jan 12 14:57:22 2011 @@ -1,7 +1,12 @@ /* $Id$ */ +#include <windows.h> +#include "resource.h" + +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS TCP/IPv4 Win32 Ping\0" +#define REACTOS_STR_INTERNAL_NAME "ping\0" +#define REACTOS_STR_ORIGINAL_FILENAME "ping.exe\0" +#define REACTOS_STR_ORIGINAL_COPYRIGHT "Casper S. Hornstrup (chorns@users.sourceforge.net)\0" +#include <reactos/version.rc>
-#define REACTOS_STR_FILE_DESCRIPTION "ReactOS TCP/IPv4 Win32 Ping\0" -#define REACTOS_STR_INTERNAL_NAME "ping\0" -#define REACTOS_STR_ORIGINAL_FILENAME "ping.exe\0" -#define REACTOS_STR_ORIGINAL_COPYRIGHT "Casper S. Hornstrup (chorns@users.sourceforge.net)\0" -#include <reactos/version.rc> +#include "lang/en-US.rc" +
Added: trunk/reactos/base/applications/network/ping/resource.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/network/p... ============================================================================== --- trunk/reactos/base/applications/network/ping/resource.h (added) +++ trunk/reactos/base/applications/network/ping/resource.h [iso-8859-1] Wed Jan 12 14:57:22 2011 @@ -1,0 +1,24 @@ +#define IDS_USAGE 0 +#define IDS_PING_WITH_BYTES 1 +#define IDS_PING_STATISTICS 2 +#define IDS_PACKETS_SENT_RECEIVED_LOST 3 +#define IDS_APPROXIMATE_ROUND_TRIP 4 +#define IDS_MIN_MAX_AVERAGE 5 +#define IDS_NOT_ENOUGH_RESOURCES 6 +#define IDS_UNKNOWN_HOST 7 +#define IDS_SETSOCKOPT_FAILED 8 +#define IDS_COULD_NOT_CREATE_SOCKET 9 +#define IDS_COULD_NOT_INIT_WINSOCK 10 +#define IDS_DEST_MUST_BE_SPECIFIED 11 +#define IDS_BAD_PARAMETER 12 +#define IDS_BAD_OPTION_FORMAT 13 +#define IDS_BAD_OPTION 14 +#define IDS_BAD_VALUE_OPTION_L 15 +#define IDS_REPLY_FROM 16 +#define IDS_DEST_UNREACHABLE 17 +#define IDS_COULD_NOT_TRANSMIT 18 +#define IDS_COULD_NOT_RECV 19 +#define IDS_REQUEST_TIMEOUT 20 +#define IDS_MS 21 +#define IDS_1MS 22 +
Propchange: trunk/reactos/base/applications/network/ping/resource.h ------------------------------------------------------------------------------ svn:eol-style = native