ReactOS  0.4.10-dev-234-g15c29d0
arping.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS ping utility
4  * FILE: applications/cmdutils/arping/arping.c
5  * PURPOSE: Network test utility
6  * PROGRAMMERS: Pierre Schweitzer <pierre@reactos.org>
7  */
8 
9 #define WIN32_NO_STATUS
10 #include <stdarg.h>
11 #include <windef.h>
12 #include <winbase.h>
13 #include <winuser.h>
14 #include <winnls.h>
15 #include <wincon.h>
16 #define _INC_WINDOWS
17 #include <ws2tcpip.h>
18 #include <iphlpapi.h>
19 #include <ws2def.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 
23 #include "resource.h"
24 
41 
42 void FormatOutput(UINT uID, ...)
43 {
45 
46  WCHAR Buf[1024];
47  CHAR AnsiBuf[1024];
48  LPWSTR pBuf = Buf;
49  PCHAR pAnsiBuf = AnsiBuf;
50  WCHAR Format[1024];
51  DWORD written;
53  int AnsiLength;
54 
55  if (!LoadString(GetModuleHandle(NULL), uID,
56  Format, sizeof(Format) / sizeof(WCHAR)))
57  {
58  return;
59  }
60 
61  va_start(valist, uID);
62  DataLength = FormatMessage(FORMAT_MESSAGE_FROM_STRING, Format, 0, 0, Buf,\
63  sizeof(Buf) / sizeof(WCHAR), &valist);
64  va_end(valist);
65 
66  if(!DataLength)
67  {
69  {
70  return;
71  }
72 
73  va_start(valist, uID);
76  Format, 0, 0, (LPWSTR)&pBuf, 0, &valist);
77  va_end(valist);
78  }
79 
80  if(!DataLength)
81  {
82  return;
83  }
84 
86  {
87  /* Is a console or a printer */
88  WriteConsole(hStdOutput, pBuf, DataLength, &written, NULL);
89  }
90  else
91  {
92  /* Is a pipe, socket, file or other */
93  AnsiLength = WideCharToMultiByte(CP_ACP, 0, pBuf, DataLength,\
94  NULL, 0, NULL, NULL);
95 
96  if(AnsiLength >= sizeof(AnsiBuf))
97  pAnsiBuf = (PCHAR)HeapAlloc(GetProcessHeap(), 0, AnsiLength);
98 
99  AnsiLength = WideCharToMultiByte(CP_OEMCP, 0, pBuf, DataLength,\
100  pAnsiBuf, AnsiLength, " ", NULL);
101 
102  WriteFile(hStdOutput, pAnsiBuf, AnsiLength, &written, NULL);
103 
104  if(pAnsiBuf != AnsiBuf)
105  HeapFree(NULL, 0, pAnsiBuf);
106  }
107 
108  if(pBuf != Buf)
109  LocalFree(pBuf);
110 }
111 
112 static VOID Usage(VOID)
113 {
115 }
116 
118 {
119  INT i;
120 
121  if (argc < 3)
122  {
123  Usage();
124  return FALSE;
125  }
126 
127  for (i = 1; i < argc; i++)
128  {
129  if (argv[i][0] == L'-' || argv[i][0] == L'/')
130  {
131  switch (argv[i][1])
132  {
133  case L't': NeverStop = TRUE; break;
134  case L'n':
135  if (i + 1 < argc)
136  {
137  PingCount = wcstoul(argv[++i], NULL, 0);
138 
139  if (PingCount == 0)
140  {
142  return FALSE;
143  }
144  }
145  else
146  {
148  return FALSE;
149  }
150  break;
151 
152  case L's':
153  if (SourceName[0] != 0)
154  {
156  return FALSE;
157  }
158 
159  if (i + 1 < argc)
160  {
161  wcscpy(SourceName, argv[++i]);
162  }
163  else
164  {
166  return FALSE;
167  }
168  break;
169 
170  case '?':
171  Usage();
172  return FALSE;
173 
174  default:
175  FormatOutput(IDS_BAD_OPTION, argv[i]);
176  return FALSE;
177  }
178  }
179  else
180  {
181  if (TargetName[0] != 0)
182  {
184  return FALSE;
185  }
186  else
187  {
188  wcscpy(TargetName, argv[i]);
189  }
190  }
191  }
192 
193  if (TargetName[0] == 0)
194  {
196  return FALSE;
197  }
198 
199  if (SourceName[0] == 0)
200  {
202  return FALSE;
203  }
204 
205  return TRUE;
206 }
207 
208 static BOOL WINAPI StopLoop(DWORD dwCtrlType)
209 {
210  NeverStop = FALSE;
211  PingCount = 0;
212 
213  return TRUE;
214 }
215 
216 static BOOL Setup(VOID)
217 {
218  WORD wVersionRequested;
219  WSADATA WsaData;
220  INT Status;
221  PHOSTENT phe;
222  CHAR aTargetName[256];
223  IN_ADDR Target;
224 
225  wVersionRequested = MAKEWORD(2, 2);
226 
227  Status = WSAStartup(wVersionRequested, &WsaData);
228  if (Status != 0)
229  {
231  return FALSE;
232  }
233 
234  if (!WideCharToMultiByte(CP_ACP, 0, TargetName, -1, aTargetName,
235  sizeof(aTargetName), NULL, NULL))
236  {
238  return FALSE;
239  }
240 
241  phe = NULL;
242  TargetAddr = inet_addr(aTargetName);
243  if (TargetAddr == INADDR_NONE)
244  {
245  phe = gethostbyname(aTargetName);
246  if (phe == NULL)
247  {
249  return FALSE;
250  }
251 
252  CopyMemory(&TargetAddr, phe->h_addr, phe->h_length);
253  }
254 
255  Target.S_un.S_addr = TargetAddr;
256  swprintf(TargetIP, L"%d.%d.%d.%d", Target.S_un.S_un_b.s_b1,
257  Target.S_un.S_un_b.s_b2,
258  Target.S_un.S_un_b.s_b3,
259  Target.S_un.S_un_b.s_b4);
260 
261  if (!WideCharToMultiByte(CP_ACP, 0, SourceName, -1, aTargetName,
262  sizeof(aTargetName), NULL, NULL))
263  {
265  return FALSE;
266  }
267 
268  SourceAddr = inet_addr(aTargetName);
269  if (SourceAddr == INADDR_NONE)
270  {
272  return FALSE;
273  }
274 
276 
277  return TRUE;
278 }
279 
281 {
282  WSACleanup();
283 }
284 
286 {
288  {
289  if (QueryPerformanceCounter(Time) == 0)
290  {
291  /* This should not happen, but we fall
292  back to GetCurrentTick() if it does */
293  Time->u.LowPart = (ULONG)GetTickCount();
294  Time->u.HighPart = 0;
295 
296  /* 1 tick per millisecond for GetCurrentTick() */
297  TicksPerMs.QuadPart = 1;
298  /* GetCurrentTick() cannot handle microseconds */
299  TicksPerUs.QuadPart = 1;
300 
302  }
303  }
304  else
305  {
306  Time->u.LowPart = (ULONG)GetTickCount();
307  Time->u.HighPart = 0;
308  }
309 }
310 
312 {
313  WCHAR Convstr[40];
314  LARGE_INTEGER LargeTime;
315  LPWSTR ms;
316 
317  LargeTime.QuadPart = Time.QuadPart / TicksPerMs.QuadPart;
318 
319  _i64tow(LargeTime.QuadPart, Convstr, 10);
320  wcscpy(String, Convstr);
321  ms = String + wcslen(String);
322  LoadString(GetModuleHandle(NULL), IDS_MS, ms, Length - (ms - String));
323 }
324 
325 static BOOL Ping(VOID)
326 {
327  LARGE_INTEGER RelativeTime;
328  LARGE_INTEGER LargeTime;
329  LARGE_INTEGER SentTime;
330  DWORD Ret;
331  BYTE TargetHW[6];
332  ULONG Size;
333  WCHAR Sign[2];
334  WCHAR Time[100];
335  WCHAR StrHwAddr[18];
336 
337  QueryTime(&SentTime);
338  Size = sizeof(TargetHW);
339  memset(TargetHW, 0xff, Size);
340  ++Sent;
341  Ret = SendARP(TargetAddr, SourceAddr, (PULONG)TargetHW, &Size);
342  if (Ret == ERROR_SUCCESS)
343  {
344  QueryTime(&LargeTime);
345 
346  RelativeTime.QuadPart = (LargeTime.QuadPart - SentTime.QuadPart);
347 
348  if ((RelativeTime.QuadPart / TicksPerMs.QuadPart) < 1)
349  {
350  wcscpy(Sign, L"<");
351  LoadString(GetModuleHandle(NULL), IDS_1MS, Time, sizeof(Time) / sizeof(WCHAR));
352  }
353  else
354  {
355  wcscpy(Sign, L"=");
356  TimeToMsString(Time, sizeof(Time) / sizeof(WCHAR), RelativeTime);
357  }
358 
359  swprintf(StrHwAddr, L"%02x:%02x:%02x:%02x:%02x:%02x", TargetHW[0], TargetHW[1],
360  TargetHW[2], TargetHW[3],
361  TargetHW[4], TargetHW[5]);
362  FormatOutput(IDS_REPLY_FROM, TargetIP, StrHwAddr, Sign, Time);
363  Received++;
364 
365  return TRUE;
366  }
367 
368  return FALSE;
369 }
370 
371 int wmain(int argc, LPWSTR argv[])
372 {
373  UINT Count;
374  LARGE_INTEGER PerformanceCounterFrequency;
375 
376  PingCount = 4;
377  Timeout = 1000;
379 
380  UsePerformanceCounter = QueryPerformanceFrequency(&PerformanceCounterFrequency);
381 
383  {
384  /* Performance counters may return incorrect results on some multiprocessor
385  platforms so we restrict execution on the first processor. This may fail
386  on Windows NT so we fall back to GetCurrentTick() for timing */
387  if (SetThreadAffinityMask (GetCurrentThread(), 1) == 0)
389 
390  /* Convert frequency to ticks per millisecond */
391  TicksPerMs.QuadPart = PerformanceCounterFrequency.QuadPart / 1000;
392  /* And to ticks per microsecond */
393  TicksPerUs.QuadPart = PerformanceCounterFrequency.QuadPart / 1000000;
394  }
396  {
397  /* 1 tick per millisecond for GetCurrentTick() */
398  TicksPerMs.QuadPart = 1;
399  /* GetCurrentTick() cannot handle microseconds */
400  TicksPerUs.QuadPart = 1;
401  }
402 
403  if (!ParseCmdline(argc, argv) || !Setup())
404  {
405  return 1;
406  }
407 
409 
410  Count = 0;
411  while (Count < PingCount || NeverStop)
412  {
413  Ping();
414  Count++;
415  if (Count < PingCount || NeverStop)
416  Sleep(Timeout);
417  }
418 
419  Cleanup();
420 
422 
423  return 0;
424 }
signed char * PCHAR
Definition: retypes.h:7
static int argc
Definition: ServiceArgs.c:12
HANDLE hStdOutput
Definition: arping.c:34
BOOL UsePerformanceCounter
Definition: arping.c:38
unsigned short WORD
Definition: ntddk_ex.h:93
#define TRUE
Definition: types.h:120
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:736
#define IDS_BAD_VALUE_OPTION_N
Definition: resource.h:11
#define inet_addr(cp)
Definition: inet.h:98
#define ERROR_SUCCESS
Definition: deptool.c:10
#define WideCharToMultiByte
Definition: compat.h:101
static VOID Cleanup(VOID)
Definition: arping.c:280
#define MAKEWORD(a, b)
Definition: typedefs.h:247
__wchar_t WCHAR
Definition: xmlstorage.h:180
BOOL NeverStop
Definition: arping.c:25
#define CP_ACP
Definition: compat.h:99
#define FORMAT_MESSAGE_FROM_STRING
Definition: winbase.h:402
int wmain(int argc, LPWSTR argv[])
Definition: arping.c:371
char CHAR
Definition: xmlstorage.h:175
#define INADDR_NONE
Definition: tcp.c:42
INT WSAAPI WSACleanup(VOID)
Definition: startup.c:60
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:445
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1056
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:137
#define IDS_USAGE
Definition: resource.h:3
Definition: msg.c:1051
DWORD WINAPI GetFileType(HANDLE hFile)
Definition: fileinfo.c:419
_Check_return_ unsigned long __cdecl wcstoul(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
struct _LARGE_INTEGER::@2136 u
int32_t INT
Definition: typedefs.h:56
DWORD DWORD
Definition: winlogon.h:75
static char ** argv
Definition: ServiceArgs.c:11
#define IDS_SRC_MUST_BE_SPECIFIED
Definition: resource.h:10
static BOOL Ping(VOID)
Definition: arping.c:325
__MINGW_EXTENSION _CRTIMP wchar_t *__cdecl _i64tow(_In_ __int64 _Val, _Pre_notnull_ _Post_z_ wchar_t *_DstBuf, _In_ int _Radix)
WCHAR SourceIP[16]
Definition: arping.c:32
static BOOL ParseCmdline(int argc, LPWSTR argv[])
Definition: arping.c:117
CHAR16 * String
Definition: acefiex.h:201
GLenum GLclampf GLint i
Definition: glfuncs.h:14
#define va_end(ap)
Definition: acmsvcex.h:90
#define FALSE
Definition: types.h:117
HANDLE WINAPI GetCurrentThread(VOID)
Definition: proc.c:1205
#define FILE_TYPE_CHAR
Definition: winbase.h:257
UINT PingCount
Definition: arping.c:26
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add)
Definition: console.c:2111
#define FORMAT_MESSAGE_ALLOCATE_BUFFER
Definition: winbase.h:400
short h_length
Definition: winsock.h:137
BOOL WINAPI QueryPerformanceFrequency(OUT PLARGE_INTEGER lpFrequency)
Definition: perfcnt.c:45
INT WINAPI WSAStartup(IN WORD wVersionRequested, OUT LPWSADATA lpWSAData)
Definition: startup.c:113
smooth NULL
Definition: ftsmooth.c:416
DWORD_PTR WINAPI SetThreadAffinityMask(IN HANDLE hThread, IN DWORD_PTR dwThreadAffinityMask)
Definition: thread.c:646
char * va_list
Definition: acmsvcex.h:78
UINTN Size
Definition: acefiex.h:555
#define PCHAR
Definition: match.c:90
DWORD TargetAddr
Definition: arping.c:30
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
PHOSTENT WSAAPI gethostbyname(IN const char FAR *name)
Definition: getxbyxx.c:221
#define IDS_ARPING_STATISTICS
Definition: resource.h:16
unsigned int BOOL
Definition: ntddk_ex.h:94
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
void FormatOutput(UINT uID,...)
Definition: arping.c:42
static VOID Usage(VOID)
Definition: arping.c:112
Definition: tcpip.h:125
LARGE_INTEGER TicksPerMs
Definition: arping.c:36
#define swprintf(buf, format,...)
Definition: sprintf.c:56
#define CopyMemory
Definition: winbase.h:1633
#define IDS_UNKNOWN_HOST
Definition: resource.h:13
static BOOL Setup(VOID)
Definition: arping.c:216
#define FormatMessage
Definition: winbase.h:3609
BOOL WINAPI QueryPerformanceCounter(OUT PLARGE_INTEGER lpPerformanceCount)
Definition: perfcnt.c:23
#define IDS_BAD_OPTION_FORMAT
Definition: resource.h:4
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
static const WCHAR L[]
Definition: oid.c:1087
VOID UINTN Length
Definition: acefiex.h:744
#define IDS_COULD_NOT_INIT_WINSOCK
Definition: resource.h:8
WCHAR TargetName[256]
Definition: arping.c:27
#define STD_OUTPUT_HANDLE
Definition: winbase.h:265
#define IDS_BAD_PARAMETER
Definition: resource.h:10
#define IDS_MS
Definition: resource.h:13
#define WINAPI
Definition: msvc.h:20
#define IDS_DEST_MUST_BE_SPECIFIED
Definition: resource.h:7
unsigned char BYTE
Definition: ntddk_ex.h:96
Status
Definition: gdiplustypes.h:24
u_long S_addr
Definition: tcpip.h:131
WCHAR TargetIP[16]
Definition: arping.c:31
#define UINT_MAX
Definition: limits.h:41
DWORD *typedef HANDLE
Definition: winlogon.h:52
#define GetModuleHandle
Definition: winbase.h:3641
struct in_addr::@986::@987 S_un_b
#define IDS_REPLY_FROM
Definition: resource.h:18
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1577
DWORD SourceAddr
Definition: arping.c:29
ULONG Timeout
Definition: arping.c:35
unsigned int * PULONG
Definition: retypes.h:1
#define va_start(ap, A)
Definition: acmsvcex.h:91
unsigned int UINT
Definition: ndis.h:50
WCHAR SourceName[256]
Definition: arping.c:28
UINT Sent
Definition: arping.c:39
#define WriteConsole
Definition: wincon.h:772
static BOOL WINAPI StopLoop(DWORD dwCtrlType)
Definition: arping.c:208
#define IDS_ARPING_TO_FROM
Definition: resource.h:12
unsigned int ULONG
Definition: retypes.h:1
static VOID QueryTime(PLARGE_INTEGER Time)
Definition: arping.c:285
static __ms_va_list valist
Definition: printf.c:59
union in_addr::@986 S_un
#define IDS_BAD_OPTION
Definition: resource.h:9
static VOID TimeToMsString(LPWSTR String, ULONG Length, LARGE_INTEGER Time)
Definition: arping.c:311
_Must_inspect_result_ _Out_writes_to_ DataLength PHIDP_DATA _Inout_ PULONG DataLength
Definition: hidpi.h:333
#define memset(x, y, z)
Definition: compat.h:39
WCHAR * LPWSTR
Definition: xmlstorage.h:184
UINT Received
Definition: arping.c:40
#define CP_OEMCP
Definition: winnls.h:219
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define HeapFree(x, y, z)
Definition: compat.h:394
#define LoadString
Definition: winuser.h:5680
static PLARGE_INTEGER Time
Definition: time.c:105
SOCKADDR_IN Target
Definition: arping.c:33
DWORD WINAPI SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen)
LONGLONG QuadPart
Definition: typedefs.h:112
LARGE_INTEGER TicksPerUs
Definition: arping.c:37
#define IDS_1MS
Definition: resource.h:14
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10