Implement an arping tool. Some portions of code are just plain copy/paste from ping tool code (booh, it's bad!).
It was designed and tested on W2K3.

It's in RosApps for two major reasons: such a tool doesn't exist by default in Windows 2K3.
And it doesn't work in ReactOS.

svn path=/trunk/; revision=70212
This commit is contained in:
Pierre Schweitzer 2015-11-29 19:44:29 +00:00
parent fedd88382f
commit 575842c05c
6 changed files with 492 additions and 0 deletions

View File

@ -1,4 +1,5 @@
add_subdirectory(appwiz)
add_subdirectory(arping)
add_subdirectory(cat)
add_subdirectory(hackssign)
add_subdirectory(ntfsinfo)

View File

@ -0,0 +1,11 @@
add_definitions(-D__USE_W32_SOCKETS)
add_executable(arping arping.c arping.rc)
set_module_type(arping win32cui UNICODE)
add_importlibs(arping user32 ws2_32 iphlpapi msvcrt kernel32)
if(MSVC)
add_importlibs(arping ntdll)
endif()
add_cd_file(TARGET arping DESTINATION reactos/system32 FOR all)

View File

@ -0,0 +1,424 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS ping utility
* FILE: applications/cmdutils/arping/arping.c
* PURPOSE: Network test utility
* PROGRAMMERS: Pierre Schweitzer <pierre@reactos.org>
*/
#define WIN32_NO_STATUS
#include <stdarg.h>
#include <windef.h>
#include <winbase.h>
#include <winuser.h>
#include <winnls.h>
#include <wincon.h>
#define _INC_WINDOWS
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <ws2def.h>
#include <stdio.h>
#include <stdlib.h>
#include "resource.h"
BOOL NeverStop;
UINT PingCount;
WCHAR TargetName[256];
WCHAR SourceName[256];
DWORD SourceAddr;
DWORD TargetAddr;
WCHAR TargetIP[16];
WCHAR SourceIP[16];
SOCKADDR_IN Target;
HANDLE hStdOutput;
ULONG Timeout;
LARGE_INTEGER TicksPerMs;
LARGE_INTEGER TicksPerUs;
BOOL UsePerformanceCounter;
UINT Sent;
UINT Received;
void FormatOutput(UINT uID, ...)
{
va_list valist;
WCHAR Buf[1024];
CHAR AnsiBuf[1024];
LPWSTR pBuf = Buf;
PCHAR pAnsiBuf = AnsiBuf;
WCHAR Format[1024];
DWORD written;
UINT DataLength;
int AnsiLength;
if (!LoadString(GetModuleHandle(NULL), uID,
Format, sizeof(Format) / sizeof(WCHAR)))
{
return;
}
va_start(valist, uID);
DataLength = FormatMessage(FORMAT_MESSAGE_FROM_STRING, Format, 0, 0, Buf,\
sizeof(Buf) / sizeof(WCHAR), &valist);
if(!DataLength)
{
if(GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
va_end(valist);
return;
}
DataLength = FormatMessage(FORMAT_MESSAGE_FROM_STRING |\
FORMAT_MESSAGE_ALLOCATE_BUFFER,\
Format, 0, 0, (LPWSTR)&pBuf, 0, &valist);
}
if(!DataLength)
{
va_end(valist);
return;
}
if(GetFileType(hStdOutput) == FILE_TYPE_CHAR)
{
/* Is a console or a printer */
WriteConsole(hStdOutput, pBuf, DataLength, &written, NULL);
}
else
{
/* Is a pipe, socket, file or other */
AnsiLength = WideCharToMultiByte(CP_ACP, 0, pBuf, DataLength,\
NULL, 0, NULL, NULL);
if(AnsiLength >= sizeof(AnsiBuf))
pAnsiBuf = (PCHAR)HeapAlloc(GetProcessHeap(), 0, AnsiLength);
AnsiLength = WideCharToMultiByte(CP_OEMCP, 0, pBuf, DataLength,\
pAnsiBuf, AnsiLength, " ", NULL);
WriteFile(hStdOutput, pAnsiBuf, AnsiLength, &written, NULL);
if(pAnsiBuf != AnsiBuf)
HeapFree(NULL, 0, pAnsiBuf);
}
if(pBuf != Buf)
LocalFree(pBuf);
}
static VOID Usage(VOID)
{
FormatOutput(IDS_USAGE);
}
static BOOL ParseCmdline(int argc, LPWSTR argv[])
{
INT i;
if (argc < 3)
{
Usage();
return FALSE;
}
for (i = 1; i < argc; i++)
{
if (argv[i][0] == L'-' || argv[i][0] == L'/')
{
switch (argv[i][1])
{
case L't': NeverStop = TRUE; break;
case L'n':
if (i + 1 < argc)
{
PingCount = wcstoul(argv[++i], NULL, 0);
if (PingCount == 0)
{
FormatOutput(IDS_BAD_VALUE_OPTION_N, UINT_MAX);
return FALSE;
}
}
else
{
FormatOutput(IDS_BAD_OPTION_FORMAT, argv[i]);
return FALSE;
}
break;
case L's':
if (SourceName[0] != 0)
{
FormatOutput(IDS_BAD_PARAMETER, argv[i]);
return FALSE;
}
if (i + 1 < argc)
{
wcscpy(SourceName, argv[++i]);
}
else
{
FormatOutput(IDS_BAD_OPTION_FORMAT, argv[i]);
return FALSE;
}
break;
case '?':
Usage();
return FALSE;
default:
FormatOutput(IDS_BAD_OPTION, argv[i]);
return FALSE;
}
}
else
{
if (TargetName[0] != 0)
{
FormatOutput(IDS_BAD_PARAMETER, argv[i]);
return FALSE;
}
else
{
wcscpy(TargetName, argv[i]);
}
}
}
if (TargetName[0] == 0)
{
FormatOutput(IDS_DEST_MUST_BE_SPECIFIED);
return FALSE;
}
if (SourceName[0] == 0)
{
FormatOutput(IDS_SRC_MUST_BE_SPECIFIED);
return FALSE;
}
return TRUE;
}
static BOOL WINAPI StopLoop(DWORD dwCtrlType)
{
NeverStop = FALSE;
PingCount = 0;
return TRUE;
}
static BOOL Setup(VOID)
{
WORD wVersionRequested;
WSADATA WsaData;
INT Status;
PHOSTENT phe;
CHAR aTargetName[256];
IN_ADDR Target;
wVersionRequested = MAKEWORD(2, 2);
Status = WSAStartup(wVersionRequested, &WsaData);
if (Status != 0)
{
FormatOutput(IDS_COULD_NOT_INIT_WINSOCK);
return FALSE;
}
if (!WideCharToMultiByte(CP_ACP, 0, TargetName, -1, aTargetName,
sizeof(aTargetName), NULL, NULL))
{
FormatOutput(IDS_UNKNOWN_HOST, TargetName);
return FALSE;
}
phe = NULL;
TargetAddr = inet_addr(aTargetName);
if (TargetAddr == INADDR_NONE)
{
phe = gethostbyname(aTargetName);
if (phe == NULL)
{
FormatOutput(IDS_UNKNOWN_HOST, TargetName);
return FALSE;
}
CopyMemory(&TargetAddr, phe->h_addr, phe->h_length);
}
Target.S_un.S_addr = TargetAddr;
swprintf(TargetIP, L"%d.%d.%d.%d", Target.S_un.S_un_b.s_b1,
Target.S_un.S_un_b.s_b2,
Target.S_un.S_un_b.s_b3,
Target.S_un.S_un_b.s_b4);
if (!WideCharToMultiByte(CP_ACP, 0, SourceName, -1, aTargetName,
sizeof(aTargetName), NULL, NULL))
{
FormatOutput(IDS_UNKNOWN_HOST, SourceName);
return FALSE;
}
SourceAddr = inet_addr(aTargetName);
if (SourceAddr == INADDR_NONE)
{
FormatOutput(IDS_UNKNOWN_HOST, SourceName);
return FALSE;
}
SetConsoleCtrlHandler(StopLoop, TRUE);
return TRUE;
}
static VOID Cleanup(VOID)
{
WSACleanup();
}
static VOID QueryTime(PLARGE_INTEGER Time)
{
if (UsePerformanceCounter)
{
if (QueryPerformanceCounter(Time) == 0)
{
/* This should not happen, but we fall
back to GetCurrentTick() if it does */
Time->u.LowPart = (ULONG)GetTickCount();
Time->u.HighPart = 0;
/* 1 tick per millisecond for GetCurrentTick() */
TicksPerMs.QuadPart = 1;
/* GetCurrentTick() cannot handle microseconds */
TicksPerUs.QuadPart = 1;
UsePerformanceCounter = FALSE;
}
}
else
{
Time->u.LowPart = (ULONG)GetTickCount();
Time->u.HighPart = 0;
}
}
static VOID TimeToMsString(LPWSTR String, ULONG Length, LARGE_INTEGER Time)
{
WCHAR Convstr[40];
LARGE_INTEGER LargeTime;
LPWSTR ms;
LargeTime.QuadPart = Time.QuadPart / TicksPerMs.QuadPart;
_i64tow(LargeTime.QuadPart, Convstr, 10);
wcscpy(String, Convstr);
ms = String + wcslen(String);
LoadString(GetModuleHandle(NULL), IDS_MS, ms, Length - (ms - String));
}
static BOOL Ping(VOID)
{
LARGE_INTEGER RelativeTime;
LARGE_INTEGER LargeTime;
LARGE_INTEGER SentTime;
DWORD Ret;
BYTE TargetHW[6];
ULONG Size;
WCHAR Sign[2];
WCHAR Time[100];
WCHAR StrHwAddr[18];
QueryTime(&SentTime);
Size = sizeof(TargetHW);
memset(TargetHW, 0xff, Size);
++Sent;
Ret = SendARP(TargetAddr, SourceAddr, (PULONG)TargetHW, &Size);
if (Ret == ERROR_SUCCESS)
{
QueryTime(&LargeTime);
RelativeTime.QuadPart = (LargeTime.QuadPart - SentTime.QuadPart);
if ((RelativeTime.QuadPart / TicksPerMs.QuadPart) < 1)
{
wcscpy(Sign, L"<");
LoadString(GetModuleHandle(NULL), IDS_1MS, Time, sizeof(Time) / sizeof(WCHAR));
}
else
{
wcscpy(Sign, L"=");
TimeToMsString(Time, sizeof(Time) / sizeof(WCHAR), RelativeTime);
}
swprintf(StrHwAddr, L"%02x:%02x:%02x:%02x:%02x:%02x", TargetHW[0], TargetHW[1],
TargetHW[2], TargetHW[3],
TargetHW[4], TargetHW[5]);
FormatOutput(IDS_REPLY_FROM, TargetIP, StrHwAddr, Sign, Time);
Received++;
return TRUE;
}
return FALSE;
}
int wmain(int argc, LPWSTR argv[])
{
UINT Count;
LARGE_INTEGER PerformanceCounterFrequency;
PingCount = 4;
Timeout = 1000;
hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
UsePerformanceCounter = QueryPerformanceFrequency(&PerformanceCounterFrequency);
if (UsePerformanceCounter)
{
/* Performance counters may return incorrect results on some multiprocessor
platforms so we restrict execution on the first processor. This may fail
on Windows NT so we fall back to GetCurrentTick() for timing */
if (SetThreadAffinityMask (GetCurrentThread(), 1) == 0)
UsePerformanceCounter = FALSE;
/* Convert frequency to ticks per millisecond */
TicksPerMs.QuadPart = PerformanceCounterFrequency.QuadPart / 1000;
/* And to ticks per microsecond */
TicksPerUs.QuadPart = PerformanceCounterFrequency.QuadPart / 1000000;
}
if (!UsePerformanceCounter)
{
/* 1 tick per millisecond for GetCurrentTick() */
TicksPerMs.QuadPart = 1;
/* GetCurrentTick() cannot handle microseconds */
TicksPerUs.QuadPart = 1;
}
if (!ParseCmdline(argc, argv) || !Setup())
{
return 1;
}
FormatOutput(IDS_ARPING_TO_FROM, TargetIP, SourceName);
Count = 0;
while (Count < PingCount || NeverStop)
{
Ping();
Count++;
if (Count < PingCount || NeverStop)
Sleep(Timeout);
}
Cleanup();
FormatOutput(IDS_ARPING_STATISTICS, Sent, Received);
return 0;
}

View File

@ -0,0 +1,15 @@
#include <windef.h>
#include "resource.h"
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS TCP/IPv4 Win32 ARP Ping"
#define REACTOS_STR_INTERNAL_NAME "arpping"
#define REACTOS_STR_ORIGINAL_FILENAME "arpping.exe"
#include <reactos/version.rc>
/* UTF-8 */
#pragma code_page(65001)
#ifdef LANGUAGE_EN_US
#include "lang/en-US.rc"
#endif

View File

@ -0,0 +1,25 @@
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
STRINGTABLE
BEGIN
IDS_USAGE "\nUsage: arping [-t] [-n count] -s source-ip destination-host\n\n\
Options:\n\
-t Ping the specified host until stopped.\n\
To stop - type Control-C.\n\
-n count Number of probes to send.\n\
-s Use this source IP.\n\n\0"
IDS_BAD_OPTION_FORMAT "Bad option format %1.\n\0"
IDS_BAD_OPTION "Bad option %1.\n\0"
IDS_BAD_PARAMETER "Bad parameter %1.\n\0"
IDS_DEST_MUST_BE_SPECIFIED "Name or IP address of destination host must be specified.\n\0"
IDS_COULD_NOT_INIT_WINSOCK "Could not initialize winsock dll.\n\0"
IDS_UNKNOWN_HOST "Unknown host %1.\n\0"
IDS_SRC_MUST_BE_SPECIFIED "IP address of source host must be specified.\n\0"
IDS_BAD_VALUE_OPTION_N "Bad value for option -n, valid range is from 1 to %1!u!.\n\0"
IDS_ARPING_TO_FROM "ARPING %1 from %2\n\0"
IDS_MS "ms\0"
IDS_1MS "1ms\0"
IDS_REPLY_FROM "Unicast reply from %1 [%2] %3%4\n\0"
IDS_ARPING_STATISTICS "Sent %1!u! probes\n\
Received %2!u! response(s)\n\0"
END

View File

@ -0,0 +1,16 @@
#pragma once
#define IDS_USAGE 0
#define IDS_BAD_OPTION_FORMAT 1
#define IDS_BAD_OPTION 2
#define IDS_BAD_PARAMETER 3
#define IDS_DEST_MUST_BE_SPECIFIED 4
#define IDS_COULD_NOT_INIT_WINSOCK 5
#define IDS_UNKNOWN_HOST 6
#define IDS_SRC_MUST_BE_SPECIFIED 7
#define IDS_BAD_VALUE_OPTION_N 8
#define IDS_ARPING_TO_FROM 9
#define IDS_MS 10
#define IDS_1MS 11
#define IDS_REPLY_FROM 12
#define IDS_ARPING_STATISTICS 13