Index: dll/win32/iphlpapi/icmp.c =================================================================== --- dll/win32/iphlpapi/icmp.c (revision 70511) +++ dll/win32/iphlpapi/icmp.c (working copy) @@ -1,918 +1,630 @@ /* - * ICMP + * Copyright (c) 2016 Tim Crawford * - * Francois Gouget, 1999, based on the work of - * RW Hall, 1999, based on public domain code PING.C by Mike Muus (1983) - * and later works (c) 1989 Regents of Univ. of California - see copyright - * notice at end of source-code. - * Copyright 2015 Sebastian Lackner + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. */ -/* Future work: - * - Systems like FreeBSD don't seem to support the IP_TTL option and maybe others. - * But using IP_HDRINCL and building the IP header by hand might work. - * - Not all IP options are supported. - * - Are ICMP handles real handles, i.e. inheritable and all? There might be some - * more work to do here, including server side stuff with synchronization. - * - This API should probably be thread safe. Is it really? - * - Using the winsock functions has not been tested. +/* + * PROJECT: ReactOS IP Helper API + * LICENSE: MIT + * FILE: dll/win32/iphlpapi/icmp.c + * PURPOSE: ICMP functions + * PROGRAMMERS: Tim Crawford */ -#include "iphlpapi_private.h" +/* +#define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H -/* Set up endianness macros for the ip and ip_icmp BSD headers */ -#ifndef BIG_ENDIAN -#define BIG_ENDIAN 4321 -#endif -#ifndef LITTLE_ENDIAN -#define LITTLE_ENDIAN 1234 -#endif -#ifndef BYTE_ORDER -#ifdef WORDS_BIGENDIAN -#define BYTE_ORDER BIG_ENDIAN -#else -#define BYTE_ORDER LITTLE_ENDIAN -#endif -#endif /* BYTE_ORDER */ +#include +#include -#define u_int16_t WORD -#define u_int32_t DWORD +#define NTOS_MODE_USER +#include +#include +#include -/* These are BSD headers. We use these here because they are needed on - * libc5 Linux systems. On other platforms they are usually simply more - * complete than the native stuff, and cause less portability problems - * so we use them anyway. - */ -#include "ip.h" -#include "ip_icmp.h" +#include +#include +#include +*/ -WINE_DEFAULT_DEBUG_CHANNEL(icmp); -WINE_DECLARE_DEBUG_CHANNEL(winediag); +#include "iphlpapi_private.h" +WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi); -typedef struct { - int sid; - IP_OPTION_INFORMATION default_opts; -} icmp_t; -#define IP_OPTS_UNKNOWN 0 -#define IP_OPTS_DEFAULT 1 -#define IP_OPTS_CUSTOM 2 +// XXX: Only reference I've found says ICMP uses 0x120000. +#define IOCTL_ICMP_ECHO_REQUEST \ + CTL_CODE(FILE_DEVICE_NETWORK, 0, METHOD_BUFFERED, FILE_ANY_ACCESS) -/* The sequence number is unique process wide, so that all threads - * have a distinct sequence number. - */ -static LONG icmp_sequence=0; -static int in_cksum(u_short *addr, int len) +typedef struct _ICMP_ECHO_REQUEST { - int nleft=len; - u_short *w = addr; - int sum = 0; - u_short answer = 0; + IPAddr Address; + ULONG Timeout; + USHORT DataOffset; + USHORT DataSize; + UCHAR HasOptions; + UCHAR Ttl; + UCHAR Tos; + UCHAR Flags; + USHORT OptionsOffset; + USHORT OptionsSize; +} ICMP_ECHO_REQUEST, *PICMP_ECHO_REQUEST; - while (nleft > 1) { - sum += *w++; - nleft -= 2; - } +typedef struct _ICMPV6_ECHO_REQUEST +{ + IPV6_ADDRESS_EX DestinationAddress; + IPV6_ADDRESS_EX SourceAddress; + ULONG Timeout; + USHORT Unknown1; + USHORT Ttl; // XXX: These seem unnecessarily large. + ULONG Flags; // Is something else in the struct? +} ICMPV6_ECHO_REQUEST, *PICMPV6_ECHO_REQUEST; - if (nleft == 1) { - *(u_char *)(&answer) = *(u_char *)w; - sum += answer; - } +/** + * Icmp6CreateFile + * @implemented + */ +HANDLE +WINAPI +Icmp6CreateFile(void) +{ + HANDLE IcmpFile; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\Ip6"); + NTSTATUS Status; - sum = (sum >> 16) + (sum & 0xffff); - sum += (sum >> 16); - answer = ~sum; - return(answer); -} + InitializeObjectAttributes( + &ObjectAttributes, + &DeviceName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtCreateFile( + &IcmpFile, + GENERIC_EXECUTE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN_IF, + 0, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return INVALID_HANDLE_VALUE; + } -/* - * Exported Routines. - */ + return IcmpFile; +} -/*********************************************************************** - * Icmp6CreateFile (IPHLPAPI.@) +/** + * Icmp6ParseReplies + * @implemented */ -HANDLE WINAPI Icmp6CreateFile(VOID) +DWORD +WINAPI +Icmp6ParseReplies( + _In_ LPVOID ReplyBuffer, + _In_ DWORD ReplySize) { - icmp_t* icp; + PICMPV6_ECHO_REPLY pEcho; - int sid=socket(AF_INET6,SOCK_RAW,IPPROTO_ICMPV6); -#ifndef __REACTOS__ - if (sid < 0) + if (ReplyBuffer == NULL || ReplySize == 0) + return 0; + + pEcho = (PICMPV6_ECHO_REPLY)ReplyBuffer; + + // XXX: MSDN also says IP_TTL_EXPIRED_TRANSIT. + if (pEcho->Status == IP_SUCCESS) { - /* Mac OS X supports non-privileged ICMP via SOCK_DGRAM type. */ - sid=socket(AF_INET6,SOCK_DGRAM,IPPROTO_ICMPV6); + return 1; } -#endif - if (sid < 0) { - ERR_(winediag)("Failed to use ICMPV6 (network ping), this requires special permissions.\n"); - SetLastError(ERROR_ACCESS_DENIED); - return INVALID_HANDLE_VALUE; - } - icp=HeapAlloc(GetProcessHeap(), 0, sizeof(*icp)); - if (icp==NULL) { -#ifdef __REACTOS__ - closesocket(sid); -#else - close(sid); -#endif - SetLastError(IP_NO_RESOURCES); - return INVALID_HANDLE_VALUE; - } - icp->sid=sid; - icp->default_opts.OptionsSize=IP_OPTS_UNKNOWN; - return (HANDLE)icp; + SetLastError(pEcho->Status); + return 0; } - -/*********************************************************************** - * Icmp6SendEcho2 (IPHLPAPI.@) +/** + * Icmp6SendEcho2 + * @implemented */ -DWORD WINAPI Icmp6SendEcho2( - HANDLE IcmpHandle, - HANDLE Event, - PIO_APC_ROUTINE ApcRoutine, - PVOID ApcContext, - struct sockaddr_in6* SourceAddress, - struct sockaddr_in6* DestinationAddress, - LPVOID RequestData, - WORD RequestSize, - PIP_OPTION_INFORMATION RequestOptions, - LPVOID ReplyBuffer, - DWORD ReplySize, - DWORD Timeout - ) +DWORD +WINAPI +Icmp6SendEcho2( + _In_ HANDLE IcmpHandle, + _In_opt_ HANDLE Event, + _In_opt_ PIO_APC_ROUTINE ApcRoutine, + _In_opt_ PVOID ApcContext, + _In_ struct sockaddr_in6 *SourceAddress, + _In_ struct sockaddr_in6 *DestinationAddress, + _In_ LPVOID RequestData, + _In_ WORD RequestSize, + _In_ PIP_OPTION_INFORMATION RequestOptions, + _Out_ LPVOID ReplyBuffer, + _In_ DWORD ReplySize, + _In_ DWORD Timeout) { - FIXME("(%p, %p, %p, %p, %p, %p, %p, %d, %p, %p, %d, %d): stub\n", IcmpHandle, Event, - ApcRoutine, ApcContext, SourceAddress, DestinationAddress, RequestData, - RequestSize, RequestOptions, ReplyBuffer, ReplySize, Timeout); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; -} + HANDLE hEvent; + IO_STATUS_BLOCK IoStatusBlock; + PVOID InputBuffer; + ULONG InputBufferLength; + //ULONG OutputBufferLength; + PICMPV6_ECHO_REQUEST Request; + NTSTATUS Status; + InputBufferLength = sizeof(ICMPV6_ECHO_REQUEST) + RequestSize; -/*********************************************************************** - * IcmpCreateFile (IPHLPAPI.@) - */ -HANDLE WINAPI IcmpCreateFile(VOID) -{ -#ifndef __REACTOS__ - static int once; -#endif - icmp_t* icp; - - int sid=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); -#ifdef __REACTOS__ - if (sid < 0) { - ERR_(winediag)("Failed to use ICMP (network ping), this requires special permissions.\n"); - SetLastError(ERROR_ACCESS_DENIED); - return INVALID_HANDLE_VALUE; - } -#else - if (sid < 0) + // XXX: What is the extra 8 bytes it needs? + if (ReplySize < sizeof(ICMPV6_ECHO_REPLY) + 8) { - /* Mac OS X supports non-privileged ICMP via SOCK_DGRAM type. */ - sid=socket(AF_INET,SOCK_DGRAM,IPPROTO_ICMP); + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; } - if (sid < 0 && !once++) { - FIXME_(winediag)("Failed to use ICMP (network ping), this requires special permissions.\n"); - FIXME_(winediag)("Falling back to system 'ping' command as a workaround.\n"); - } -#endif - icp=HeapAlloc(GetProcessHeap(), 0, sizeof(*icp)); - if (icp==NULL) { -#ifdef __REACTOS__ - closesocket(sid); -#else - if (sid >= 0) close(sid); -#endif - SetLastError(IP_NO_RESOURCES); - return INVALID_HANDLE_VALUE; + InputBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, InputBufferLength); + if (InputBuffer == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; } - icp->sid=sid; - icp->default_opts.OptionsSize=IP_OPTS_UNKNOWN; - return (HANDLE)icp; -} + Request = (PICMPV6_ECHO_REQUEST)InputBuffer; -/*********************************************************************** - * IcmpCloseHandle (IPHLPAPI.@) - */ -BOOL WINAPI IcmpCloseHandle(HANDLE IcmpHandle) -{ - icmp_t* icp=(icmp_t*)IcmpHandle; - if (IcmpHandle==INVALID_HANDLE_VALUE) { - /* FIXME: in fact win98 seems to ignore the handle value !!! */ - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } + Request->DestinationAddress.sin6_port = DestinationAddress->sin6_port; + Request->DestinationAddress.sin6_flowinfo = DestinationAddress->sin6_flowinfo; + CopyMemory(&(Request->DestinationAddress.sin6_addr), &(DestinationAddress->sin6_addr), sizeof(Request->DestinationAddress.sin6_addr)); + Request->DestinationAddress.sin6_scope_id = DestinationAddress->sin6_scope_id; -#ifdef __REACTOS__ - shutdown(icp->sid,2); -#else - if (icp->sid >= 0) close(icp->sid); -#endif - HeapFree(GetProcessHeap (), 0, icp); - return TRUE; -} + Request->SourceAddress.sin6_port = SourceAddress->sin6_port; + Request->SourceAddress.sin6_flowinfo = SourceAddress->sin6_flowinfo; + CopyMemory(&(Request->SourceAddress.sin6_addr), &(SourceAddress->sin6_addr), sizeof(Request->SourceAddress.sin6_addr)); + Request->SourceAddress.sin6_scope_id = SourceAddress->sin6_scope_id; -#ifndef __REACTOS__ -static DWORD system_icmp( - IPAddr DestinationAddress, - LPVOID RequestData, - WORD RequestSize, - PIP_OPTION_INFORMATION RequestOptions, - LPVOID ReplyBuffer, - DWORD ReplySize, - DWORD Timeout - ) -{ -#ifdef HAVE_FORK - ICMP_ECHO_REPLY *reply = ReplyBuffer; - char ntoa_buffer[16]; /* 4*3 digits + 3 '.' + 1 '\0' */ - char size_buffer[6]; /* 5 digits + '\0' */ - char tos_buffer[4]; /* 3 digits + '\0' */ - char ttl_buffer[4]; /* 3 digits + '\0' */ - char time_buffer[11]; /* 10 digits + '\0' */ - int i, pos, res, status, argc; - const char *argv[20]; - struct in_addr addr; - int pipe_out[2]; - pid_t pid, wpid; - char *ptr, *eol; - char buf[127]; + // XXX: What is this and why is it sometimes 0x72? + Request->Unknown1 = 0x72; - /* Assemble the ping commandline */ - argc = 0; - argv[argc++] = "ping"; - argv[argc++] = "-c"; /* only send a single ping */ - argv[argc++] = "1"; - argv[argc++] = "-n"; /* numeric output only */ - argv[argc++] = "-s"; /* request size */ - sprintf(size_buffer, "%u", (RequestSize >= 16) ? RequestSize : 16); - argv[argc++] = size_buffer; - argv[argc++] = "-W"; /* timeout */ -#ifdef __linux__ - /* The linux 'ping' utlity expects a time in seconds */ - Timeout = (Timeout + 999) / 1000; -#endif - sprintf(time_buffer, "%u", Timeout); - argv[argc++] = time_buffer; + Request->Timeout = Timeout; + Request->Ttl = RequestOptions->Ttl; + Request->Flags = RequestOptions->Flags; - if (RequestOptions) + if (RequestSize > 0) { - #ifdef __linux__ - argv[argc++] = "-Q"; /* tos option */ - #else - argv[argc++] = "-z"; /* tos option */ - #endif - sprintf(tos_buffer, "%u", RequestOptions->Tos); - argv[argc++] = tos_buffer; - #ifdef __linux__ - /* TTL can only be specified for multicast addresses on FreeBSD/MacOS */ - argv[argc++] = "-t"; /* ttl option */ - sprintf(ttl_buffer, "%u", RequestOptions->Ttl); - argv[argc++] = ttl_buffer; - #endif + CopyMemory((PBYTE)InputBuffer + sizeof(ICMPV6_ECHO_REQUEST), RequestData, RequestSize); } - addr.s_addr = DestinationAddress; - if (!(ptr = inet_ntoa(addr))) + if (Event == NULL && ApcRoutine == NULL) { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; + hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); } - strcpy(ntoa_buffer, ptr); - argv[argc++] = ntoa_buffer; - argv[argc] = NULL; + else + { + hEvent = Event; + } - /* Dump commandline for debugging purposes */ - TRACE("Ping commandline: "); - for (i = 0; i < argc; i++) + Status = NtDeviceIoControlFile( + IcmpHandle, + hEvent, + ApcRoutine, + ApcContext, + &IoStatusBlock, + IOCTL_ICMP_ECHO_REQUEST, + InputBuffer, + InputBufferLength, + ReplyBuffer, + ReplySize); // TODO: Determine how Windows calculates OutputBufferLength. + + if (Event != NULL || ApcRoutine != NULL) { - TRACE("%s ", debugstr_a(argv[i])); + SetLastError(RtlNtStatusToDosError(Status)); + HeapFree(GetProcessHeap(), 0, InputBuffer); + return 0; } - TRACE("\n"); - /* Prefill the reply struct with fallback values */ - memset(reply, 0, sizeof(*reply)); - reply->Address = DestinationAddress; - reply->RoundTripTime = 40; - reply->Options.Ttl = 120; + if (Status == STATUS_PENDING) + { + Status = NtWaitForSingleObject(hEvent, FALSE, NULL); - /* Create communication pipes */ -#ifdef HAVE_PIPE2 - if (pipe2(pipe_out, O_CLOEXEC) < 0) -#endif - { - if (pipe(pipe_out) < 0) + if (NT_SUCCESS(Status)) { - SetLastError(ERROR_OUTOFMEMORY); - return 0; + Status = IoStatusBlock.Status; } - fcntl(pipe_out[0], F_SETFD, FD_CLOEXEC); - fcntl(pipe_out[1], F_SETFD, FD_CLOEXEC); } - /* Fork child process */ - pid = fork(); - if (pid == -1) + CloseHandle(hEvent); + HeapFree(GetProcessHeap(), 0, InputBuffer); + + if (!NT_SUCCESS(Status)) { - close(pipe_out[0]); - close(pipe_out[1]); - SetLastError(ERROR_OUTOFMEMORY); + SetLastError(RtlNtStatusToDosError(Status)); return 0; } - /* Child process */ - if (pid == 0) + Status = ((PICMPV6_ECHO_REPLY)ReplyBuffer)->Status; + if (Status != IP_SUCCESS) { - static char lang_env[] = "LANG=C"; + SetLastError(Status); + return 0; + } - dup2(pipe_out[1], 1); - close(pipe_out[0]); - close(pipe_out[1]); - close(0); - close(2); + return 1; +} - putenv(lang_env); - execvp(argv[0], (char **)argv); - _exit(1); +/** + * IcmpCloseHandle + * @implemented + */ +BOOL +WINAPI +IcmpCloseHandle( + _In_ HANDLE IcmpHandle) +{ + NTSTATUS Status; + + Status = NtClose(IcmpHandle); + if (!NT_SUCCESS(Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return FALSE; } - close(pipe_out[1]); + return TRUE; +} - /* Wait for child and read output */ - pos = 0; - do - { - if (pos >= sizeof(buf) - 1) - { - ERR("line too long, dropping buffer\n"); - pos = 0; - } +/** + * IcmpCreateFile + * @implemented + */ +HANDLE +WINAPI +IcmpCreateFile(void) +{ + HANDLE IcmpFile; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\Ip"); + NTSTATUS Status; - /* read next block */ - do - { - res = read(pipe_out[0], &buf[pos], (sizeof(buf) - 1) - pos); - } - while (res < 0 && errno == EINTR); - if (res < 0) - { - ERR("read failed: %s\n", strerror(errno)); - break; - } + InitializeObjectAttributes( + &ObjectAttributes, + &DeviceName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); - pos += res; - while (pos) - { - eol = memchr(buf, '\n', pos); - if (!eol) break; - *eol = 0; + Status = NtCreateFile( + &IcmpFile, + GENERIC_EXECUTE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + FILE_ATTRIBUTE_NORMAL, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN_IF, + 0, + NULL, + 0); - TRACE("Received line: %s\n", debugstr_a(buf)); + if (!NT_SUCCESS(Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return INVALID_HANDLE_VALUE; + } - /* Interpret address */ - if ((ptr = strstr(buf, "from "))) - { - int a, b, c, d; - if (sscanf(ptr + 5, "%u.%u.%u.%u", &a, &b, &c, &d) >= 4) - { - reply->Address = a | (b << 8) | (c << 16) | (d << 24); - addr.s_addr = reply->Address; - TRACE("Got address %s\n", inet_ntoa(addr)); - } - } + return IcmpFile; +} - /* Interpret ttl */ - if ((ptr = strstr(buf, "ttl="))) - { - int val; - if (sscanf(ptr + 4, "%u", &val) >= 1) - { - reply->Options.Ttl = val; - TRACE("Got ttl %u\n", val); - } - } +/** + * IcmpParseReplies + * @implemented + */ +DWORD +WINAPI +IcmpParseReplies( + _In_ LPVOID ReplyBuffer, + _In_ DWORD ReplySize) +{ + PICMP_ECHO_REPLY pEcho; + DWORD nReplies; - /* Interpret time */ - if ((ptr = strstr(buf, "time="))) - { - float val; - if (sscanf(ptr + 5, "%f", &val) >= 1) - { - reply->RoundTripTime = (unsigned int)(val + 0.5); - TRACE("Got rtt = %u\n", reply->RoundTripTime); - } - } + if (ReplyBuffer == NULL || ReplySize == 0) + return 0; - memmove(buf, eol + 1, pos - (eol + 1 - buf)); - pos -= (eol + 1 - buf); - } - } - while (res > 0); - close(pipe_out[0]); + // TODO: Handle ReplyBuffer having more than 1 ICMP_ECHO_REPLY. - /* reap the child process */ - do - { - wpid = waitpid(pid, &status, 0); - } - while (wpid < 0 && errno == EINTR); + pEcho = (PICMP_ECHO_REPLY)ReplyBuffer; - /* fill out remaining struct fields */ - if (wpid >= 0 && WIFEXITED(status) && WEXITSTATUS(status) == 0) + if (pEcho->Reserved == 0) { - if (ReplySize < RequestSize + sizeof(*reply)) - { - reply->Status = IP_BUF_TOO_SMALL; - reply->DataSize = 0; - reply->Data = NULL; - } - else - { - reply->Status = 0; - reply->DataSize = RequestSize; - reply->Data = (char *)reply + sizeof(*reply); - memcpy(reply->Data, RequestData, RequestSize); - } - return 1; + SetLastError(pEcho->Status); } - SetLastError(IP_REQ_TIMED_OUT); - return 0; -#else - ERR("no fork support on this platform\n"); - SetLastError(ERROR_NOT_SUPPORTED); - return 0; -#endif + nReplies = pEcho->Reserved; + pEcho->Reserved = 0; + + return nReplies; } -#endif -/*********************************************************************** - * IcmpSendEcho (IPHLPAPI.@) +/** + * IcmpSendEcho2 + * @implemented */ -DWORD WINAPI IcmpSendEcho( - HANDLE IcmpHandle, - IPAddr DestinationAddress, - LPVOID RequestData, - WORD RequestSize, - PIP_OPTION_INFORMATION RequestOptions, - LPVOID ReplyBuffer, - DWORD ReplySize, - DWORD Timeout - ) +DWORD +WINAPI +IcmpSendEcho2( + _In_ HANDLE IcmpHandle, + _In_opt_ HANDLE Event, + _In_opt_ PIO_APC_ROUTINE ApcRoutine, + _In_opt_ PVOID ApcContext, + _In_ IPAddr DestinationAddress, + _In_ LPVOID RequestData, + _In_ WORD RequestSize, + _In_opt_ PIP_OPTION_INFORMATION RequestOptions, + _Out_ LPVOID ReplyBuffer, + _In_ DWORD ReplySize, + _In_ DWORD Timeout) { - icmp_t* icp=(icmp_t*)IcmpHandle; - unsigned char* reqbuf; - int reqsize; + HANDLE hEvent; + IO_STATUS_BLOCK IoStatusBlock; + PVOID InputBuffer; + PICMP_ECHO_REQUEST Request; + DWORD nReplies; + NTSTATUS Status; - struct icmp_echo_reply* ier; - struct ip* ip_header; - struct icmp* icmp_header; - char* endbuf; - int ip_header_len; - int maxlen; -#ifdef __REACTOS__ - fd_set fdr; - struct timeval timeout; -#else - struct pollfd fdr; -#endif - DWORD send_time,recv_time; - struct sockaddr_in addr; - socklen_t addrlen; - unsigned short id,seq,cksum; - int res; - - if (IcmpHandle==INVALID_HANDLE_VALUE) { - /* FIXME: in fact win98 seems to ignore the handle value !!! */ - SetLastError(ERROR_INVALID_HANDLE); + // XXX: What is the extra 8 bytes it needs? + if (ReplySize < sizeof(ICMP_ECHO_REPLY) + 8) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); return 0; } - if (ReplySizeAddress = DestinationAddress; + Request->Timeout = Timeout; + Request->OptionsOffset = sizeof(ICMP_ECHO_REQUEST); + Request->DataOffset = sizeof(ICMP_ECHO_REQUEST); + + if (RequestOptions != NULL) + { + Request->HasOptions = TRUE; + Request->Ttl = RequestOptions->Ttl; + Request->Tos = RequestOptions->Tos; + Request->Flags = RequestOptions->Flags; + + if (RequestOptions->OptionsSize > 0) + { + Request->OptionsSize = RequestOptions->OptionsSize; + Request->DataOffset += Request->OptionsSize; + + CopyMemory( + (PBYTE)InputBuffer + sizeof(ICMP_ECHO_REQUEST), + RequestOptions->OptionsData, + Request->OptionsSize); + } } -#ifndef __REACTOS__ - if (icp->sid < 0) { - WARN("using system ping command since SOCK_RAW was not supported.\n"); - return system_icmp(DestinationAddress, RequestData, RequestSize, - RequestOptions, ReplyBuffer, ReplySize, Timeout); -#endif + if (RequestSize > 0) + { + Request->DataSize = RequestSize; + CopyMemory((PBYTE)InputBuffer + Request->DataOffset, RequestData, RequestSize); + } - /* Prepare the request */ -#ifdef __REACTOS__ - id = GetCurrentProcessId() & 0xFFFF; -#else - id=getpid() & 0xFFFF; -#endif - seq=InterlockedIncrement(&icmp_sequence) & 0xFFFF; + if (Event == NULL && ApcRoutine == NULL) + { + hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + } + else + { + hEvent = Event; + } - reqsize=ICMP_MINLEN+RequestSize; - reqbuf=HeapAlloc(GetProcessHeap(), 0, reqsize); - if (reqbuf==NULL) { - SetLastError(ERROR_OUTOFMEMORY); + Status = NtDeviceIoControlFile( + IcmpHandle, + hEvent, + ApcRoutine, + ApcContext, + &IoStatusBlock, + IOCTL_ICMP_ECHO_REQUEST, + InputBuffer, + ReplySize, + ReplyBuffer, + ReplySize); // TODO: Determine how Windows calculates OutputBufferLength. + + // If called asynchronously, return for the caller to handle. + if (Event != NULL || ApcRoutine != NULL) + { + SetLastError(RtlNtStatusToDosError(Status)); + HeapFree(GetProcessHeap(), 0, InputBuffer); return 0; } - icmp_header=(struct icmp*)reqbuf; - icmp_header->icmp_type=ICMP_ECHO; - icmp_header->icmp_code=0; - icmp_header->icmp_cksum=0; - icmp_header->icmp_id=id; - icmp_header->icmp_seq=seq; - memcpy(reqbuf+ICMP_MINLEN, RequestData, RequestSize); - icmp_header->icmp_cksum=cksum=in_cksum((u_short*)reqbuf,reqsize); + // Otherwise handle it like IcmpSendEcho. - addr.sin_family=AF_INET; - addr.sin_addr.s_addr=DestinationAddress; - addr.sin_port=0; + if (Status == STATUS_PENDING) + { + Status = NtWaitForSingleObject(hEvent, FALSE, NULL); - if (RequestOptions!=NULL) { - int val; - if (icp->default_opts.OptionsSize==IP_OPTS_UNKNOWN) { - socklen_t len; - /* Before we mess with the options, get the default values */ - len=sizeof(val); - getsockopt(icp->sid,IPPROTO_IP,IP_TTL,(char *)&val,&len); - icp->default_opts.Ttl=val; - - len=sizeof(val); - getsockopt(icp->sid,IPPROTO_IP,IP_TOS,(char *)&val,&len); - icp->default_opts.Tos=val; - /* FIXME: missing: handling of IP 'flags', and all the other options */ + if (NT_SUCCESS(Status)) + { + Status = IoStatusBlock.Status; } + } - val=RequestOptions->Ttl; - setsockopt(icp->sid,IPPROTO_IP,IP_TTL,(char *)&val,sizeof(val)); - val=RequestOptions->Tos; - setsockopt(icp->sid,IPPROTO_IP,IP_TOS,(char *)&val,sizeof(val)); - /* FIXME: missing: handling of IP 'flags', and all the other options */ + CloseHandle(hEvent); + HeapFree(GetProcessHeap(), 0, InputBuffer); - icp->default_opts.OptionsSize=IP_OPTS_CUSTOM; - } else if (icp->default_opts.OptionsSize==IP_OPTS_CUSTOM) { - int val; + if (!NT_SUCCESS(Status)) + { + SetLastError(RtlNtStatusToDosError(Status)); + return 0; + } - /* Restore the default options */ - val=icp->default_opts.Ttl; - setsockopt(icp->sid,IPPROTO_IP,IP_TTL,(char *)&val,sizeof(val)); - val=icp->default_opts.Tos; - setsockopt(icp->sid,IPPROTO_IP,IP_TOS,(char *)&val,sizeof(val)); - /* FIXME: missing: handling of IP 'flags', and all the other options */ - - icp->default_opts.OptionsSize=IP_OPTS_DEFAULT; + Status = ((PICMP_ECHO_REPLY)ReplyBuffer)->Status; + if (Status != IP_SUCCESS) + { + SetLastError(Status); } - /* Get ready for receiving the reply - * Do it before we send the request to minimize the risk of introducing delays - */ -#ifdef __REACTOS__ - FD_ZERO(&fdr); - FD_SET(icp->sid,&fdr); - timeout.tv_sec=Timeout/1000; - timeout.tv_usec=(Timeout % 1000)*1000; -#else - fdr.fd = icp->sid; - fdr.events = POLLIN; -#endif - addrlen=sizeof(addr); - ier=ReplyBuffer; - ip_header=(struct ip *) ((char *) ReplyBuffer+sizeof(ICMP_ECHO_REPLY)); - endbuf=(char *) ReplyBuffer+ReplySize; - maxlen=ReplySize-sizeof(ICMP_ECHO_REPLY); + nReplies = ((PICMP_ECHO_REPLY)ReplyBuffer)->Reserved; + ((PICMP_ECHO_REPLY)ReplyBuffer)->Reserved = 0; - /* Send the packet */ - TRACE("Sending %d bytes (RequestSize=%d) to %s\n", reqsize, RequestSize, inet_ntoa(addr.sin_addr)); -#if 0 - if (TRACE_ON(icmp)){ - unsigned char* buf=(unsigned char*)reqbuf; - int i; - printf("Output buffer:\n"); - for (i=0;isid, (const char*)reqbuf, reqsize, 0, (struct sockaddr*)&addr, sizeof(addr)); - HeapFree(GetProcessHeap (), 0, reqbuf); - if (res<0) { - if (WSAGetLastError()==WSAEMSGSIZE) - SetLastError(IP_PACKET_TOO_BIG); - else { - switch (WSAGetLastError()) { - case WSAENETUNREACH: - SetLastError(IP_DEST_NET_UNREACHABLE); - break; - case WSAEHOSTUNREACH: - SetLastError(IP_DEST_HOST_UNREACHABLE); - break; - default: - TRACE("unknown error: errno=%d\n",WSAGetLastError()); - SetLastError(IP_GENERAL_FAILURE); - } - } +/** + * IcmpSendEcho + * @implemented + */ +DWORD +WINAPI +IcmpSendEcho( + _In_ HANDLE IcmpHandle, + _In_ IPAddr DestinationAddress, + _In_ LPVOID RequestData, + _In_ WORD RequestSize, + _In_opt_ PIP_OPTION_INFORMATION RequestOptions, + _Out_ LPVOID ReplyBuffer, + _In_ DWORD ReplySize, + _In_ DWORD Timeout) +{ + HANDLE hEvent; + IO_STATUS_BLOCK IoStatusBlock; + PVOID InputBuffer; + ULONG InputBufferLength; + PICMP_ECHO_REQUEST Request; + DWORD nReplies; + NTSTATUS Status; + + if (ReplySize < sizeof(ICMP_ECHO_REPLY)) + { + SetLastError(ERROR_INSUFFICIENT_BUFFER); return 0; } - /* Get the reply */ - ip_header_len=0; /* because gcc was complaining */ -#ifdef __REACTOS__ - while ((res=select(icp->sid+1,&fdr,NULL,NULL,&timeout))>0) { -#else - while (poll(&fdr,1,Timeout)>0) { -#endif - recv_time = GetTickCount(); - res=recvfrom(icp->sid, (char*)ip_header, maxlen, 0, (struct sockaddr*)&addr,(int*)&addrlen); - TRACE("received %d bytes from %s\n",res, inet_ntoa(addr.sin_addr)); - ier->Status=IP_REQ_TIMED_OUT; + InputBufferLength = sizeof(ICMP_ECHO_REQUEST) + RequestSize; + if (RequestOptions != NULL) + InputBufferLength += RequestOptions->OptionsSize; - /* Check whether we should ignore this packet */ - if ((ip_header->ip_p==IPPROTO_ICMP) && (res>=sizeof(struct ip)+ICMP_MINLEN)) { - ip_header_len=ip_header->ip_hl << 2; - icmp_header=(struct icmp*)(((char*)ip_header)+ip_header_len); - TRACE("received an ICMP packet of type,code=%d,%d\n",icmp_header->icmp_type,icmp_header->icmp_code); - if (icmp_header->icmp_type==ICMP_ECHOREPLY) { - if ((icmp_header->icmp_id==id) && (icmp_header->icmp_seq==seq)) - ier->Status=IP_SUCCESS; - } else { - switch (icmp_header->icmp_type) { - case ICMP_UNREACH: - switch (icmp_header->icmp_code) { - case ICMP_UNREACH_HOST: -#ifdef ICMP_UNREACH_HOST_UNKNOWN - case ICMP_UNREACH_HOST_UNKNOWN: -#endif -#ifdef ICMP_UNREACH_ISOLATED - case ICMP_UNREACH_ISOLATED: -#endif -#ifdef ICMP_UNREACH_HOST_PROHIB - case ICMP_UNREACH_HOST_PROHIB: -#endif -#ifdef ICMP_UNREACH_TOSHOST - case ICMP_UNREACH_TOSHOST: -#endif - ier->Status=IP_DEST_HOST_UNREACHABLE; - break; - case ICMP_UNREACH_PORT: - ier->Status=IP_DEST_PORT_UNREACHABLE; - break; - case ICMP_UNREACH_PROTOCOL: - ier->Status=IP_DEST_PROT_UNREACHABLE; - break; - case ICMP_UNREACH_SRCFAIL: - ier->Status=IP_BAD_ROUTE; - break; - default: - ier->Status=IP_DEST_NET_UNREACHABLE; - } - break; - case ICMP_TIMXCEED: - if (icmp_header->icmp_code==ICMP_TIMXCEED_REASS) - ier->Status=IP_TTL_EXPIRED_REASSEM; - else - ier->Status=IP_TTL_EXPIRED_TRANSIT; - break; - case ICMP_PARAMPROB: - ier->Status=IP_PARAM_PROBLEM; - break; - case ICMP_SOURCEQUENCH: - ier->Status=IP_SOURCE_QUENCH; - break; - } - if (ier->Status!=IP_REQ_TIMED_OUT) { - struct ip* rep_ip_header; - struct icmp* rep_icmp_header; - /* The ICMP header size of all the packets we accept is the same */ - rep_ip_header=(struct ip*)(((char*)icmp_header)+ICMP_MINLEN); - rep_icmp_header=(struct icmp*)(((char*)rep_ip_header)+(rep_ip_header->ip_hl << 2)); + if (InputBufferLength < ReplySize) + InputBufferLength = ReplySize; - /* Make sure that this is really a reply to our packet */ - if (ip_header_len+ICMP_MINLEN+(rep_ip_header->ip_hl << 2)+ICMP_MINLEN>ip_header->ip_len) { - ier->Status=IP_REQ_TIMED_OUT; - } else if ((rep_icmp_header->icmp_type!=ICMP_ECHO) || - (rep_icmp_header->icmp_code!=0) || - (rep_icmp_header->icmp_id!=id) || - /* windows doesn't check this checksum, else tracert */ - /* behind a Linux 2.2 masquerading firewall would fail*/ - /* (rep_icmp_header->icmp_cksum!=cksum) || */ - (rep_icmp_header->icmp_seq!=seq)) { - /* This was not a reply to one of our packets after all */ - TRACE("skipping type,code=%d,%d id,seq=%d,%d cksum=%d\n", - rep_icmp_header->icmp_type,rep_icmp_header->icmp_code, - rep_icmp_header->icmp_id,rep_icmp_header->icmp_seq, - rep_icmp_header->icmp_cksum); - TRACE("expected type,code=8,0 id,seq=%d,%d cksum=%d\n", - id,seq, - cksum); - ier->Status=IP_REQ_TIMED_OUT; - } - } - } - } + InputBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, InputBufferLength); + if (InputBuffer == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } - if (ier->Status==IP_REQ_TIMED_OUT) { - /* This packet was not for us. - * Decrease the timeout so that we don't enter an endless loop even - * if we get flooded with ICMP packets that are not for us. - */ -#ifdef __REACTOS__ - int t = Timeout - (recv_time - send_time); - if (t < 0) t = 0; - timeout.tv_sec = t / 1000; - timeout.tv_usec = (t % 1000) * 1000; -#else - DWORD t = (recv_time - send_time); - if (Timeout > t) Timeout -= t; - else Timeout = 0; -#endif - continue; - } else { - /* This is a reply to our packet */ - memcpy(&ier->Address,&ip_header->ip_src,sizeof(IPAddr)); - /* Status is already set */ - ier->RoundTripTime= recv_time - send_time; - ier->DataSize=res-ip_header_len-ICMP_MINLEN; - ier->Reserved=0; - ier->Data=endbuf-ier->DataSize; - memmove(ier->Data,((char*)ip_header)+ip_header_len+ICMP_MINLEN,ier->DataSize); - ier->Options.Ttl=ip_header->ip_ttl; - ier->Options.Tos=ip_header->ip_tos; - ier->Options.Flags=ip_header->ip_off >> 13; - ier->Options.OptionsSize=ip_header_len-sizeof(struct ip); - if (ier->Options.OptionsSize!=0) { - ier->Options.OptionsData=(unsigned char *) ier->Data-ier->Options.OptionsSize; - /* FIXME: We are supposed to rearrange the option's 'source route' data */ - memmove(ier->Options.OptionsData,((char*)ip_header)+ip_header_len,ier->Options.OptionsSize); - endbuf=(char*)ier->Options.OptionsData; - } else { - ier->Options.OptionsData=NULL; - endbuf=ier->Data; - } + Request = (PICMP_ECHO_REQUEST)InputBuffer; + Request->Address = DestinationAddress; + Request->Timeout = Timeout; + Request->OptionsOffset = sizeof(ICMP_ECHO_REQUEST); + Request->DataOffset = sizeof(ICMP_ECHO_REQUEST); - /* Prepare for the next packet */ - ier++; - ip_header=(struct ip*)(((char*)ip_header)+sizeof(ICMP_ECHO_REPLY)); - maxlen=endbuf-(char*)ip_header; + if (RequestOptions != NULL) + { + Request->HasOptions = TRUE; + Request->Ttl = RequestOptions->Ttl; + Request->Tos = RequestOptions->Tos; + Request->Flags = RequestOptions->Flags; - /* Check out whether there is more but don't wait this time */ -#ifdef __REACTOS__ - timeout.tv_sec=0; - timeout.tv_usec=0; -#else - Timeout=0; -#endif + if (RequestOptions->OptionsSize > 0) + { + Request->OptionsSize = RequestOptions->OptionsSize; + Request->DataOffset += Request->OptionsSize; + + CopyMemory( + (PBYTE)InputBuffer + sizeof(ICMP_ECHO_REQUEST), + RequestOptions->OptionsData, + Request->OptionsSize); } -#ifdef __REACTOS__ - FD_ZERO(&fdr); - FD_SET(icp->sid,&fdr); -#endif } - res=ier-(ICMP_ECHO_REPLY*)ReplyBuffer; - if (res==0) - SetLastError(IP_REQ_TIMED_OUT); - TRACE("received %d replies\n",res); - return res; -} -/*********************************************************************** - * IcmpSendEcho2 (IPHLPAPI.@) - */ -DWORD WINAPI IcmpSendEcho2( - HANDLE IcmpHandle, - HANDLE Event, - PIO_APC_ROUTINE ApcRoutine, - PVOID ApcContext, - IPAddr DestinationAddress, - LPVOID RequestData, - WORD RequestSize, - PIP_OPTION_INFORMATION RequestOptions, - LPVOID ReplyBuffer, - DWORD ReplySize, - DWORD Timeout - ) -{ - TRACE("(%p, %p, %p, %p, %08x, %p, %d, %p, %p, %d, %d): stub\n", IcmpHandle, - Event, ApcRoutine, ApcContext, DestinationAddress, RequestData, - RequestSize, RequestOptions, ReplyBuffer, ReplySize, Timeout); - - if (Event) + if (RequestSize > 0) { - FIXME("unsupported for events\n"); - return 0; + Request->DataSize = RequestSize; + CopyMemory((PBYTE)InputBuffer + Request->DataOffset, RequestData, RequestSize); } - if (ApcRoutine) + + hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + if (hEvent == NULL) { - FIXME("unsupported for APCs\n"); + HeapFree(GetProcessHeap(), 0, InputBuffer); return 0; } - return IcmpSendEcho(IcmpHandle, DestinationAddress, RequestData, - RequestSize, RequestOptions, ReplyBuffer, ReplySize, Timeout); -} -/*********************************************************************** - * IcmpSendEcho2Ex (IPHLPAPI.@) - */ -DWORD WINAPI IcmpSendEcho2Ex( - HANDLE IcmpHandle, - HANDLE Event, - PIO_APC_ROUTINE ApcRoutine, - PVOID ApcContext, - IPAddr SourceAddress, - IPAddr DestinationAddress, - LPVOID RequestData, - WORD RequestSize, - PIP_OPTION_INFORMATION RequestOptions, - LPVOID ReplyBuffer, - DWORD ReplySize, - DWORD Timeout - ) -{ - TRACE("(%p, %p, %p, %p, %08x, %08x, %p, %d, %p, %p, %d, %d): stub\n", IcmpHandle, - Event, ApcRoutine, ApcContext, SourceAddress, DestinationAddress, RequestData, - RequestSize, RequestOptions, ReplyBuffer, ReplySize, Timeout); + Status = NtDeviceIoControlFile( + IcmpHandle, + hEvent, + NULL, + NULL, + &IoStatusBlock, + IOCTL_ICMP_ECHO_REQUEST, + InputBuffer, + InputBufferLength, + ReplyBuffer, + ReplySize); - if (Event) + if (Status == STATUS_PENDING) { - FIXME("unsupported for events\n"); - return 0; + Status = NtWaitForSingleObject(hEvent, FALSE, NULL); + + if (NT_SUCCESS(Status)) + { + Status = IoStatusBlock.Status; + } } - if (ApcRoutine) + + CloseHandle(hEvent); + HeapFree(GetProcessHeap(), 0, InputBuffer); + + if (!NT_SUCCESS(Status)) { - FIXME("unsupported for APCs\n"); + SetLastError(RtlNtStatusToDosError(Status)); return 0; } - if (SourceAddress) + + Status = ((PICMP_ECHO_REPLY)ReplyBuffer)->Status; + if (Status != IP_SUCCESS) { - FIXME("unsupported for source addresses\n"); - return 0; + SetLastError(Status); } - return IcmpSendEcho(IcmpHandle, DestinationAddress, RequestData, - RequestSize, RequestOptions, ReplyBuffer, ReplySize, Timeout); + nReplies = ((PICMP_ECHO_REPLY)ReplyBuffer)->Reserved; + ((PICMP_ECHO_REPLY)ReplyBuffer)->Reserved = 0; + + return nReplies; } - -/* - * Copyright (c) 1989 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Mike Muuss. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ Index: dll/win32/iphlpapi/iphlpapi.spec =================================================================== --- dll/win32/iphlpapi/iphlpapi.spec (revision 70511) +++ dll/win32/iphlpapi/iphlpapi.spec (working copy) @@ -80,11 +80,11 @@ @ stub GetUdpTableFromStack @ stdcall GetUniDirectionalAdapterInfo( ptr ptr ) @ stdcall Icmp6CreateFile() -@ stub Icmp6ParseReplies +@ stdcall Icmp6ParseReplies(ptr long) @ stdcall Icmp6SendEcho2(ptr ptr ptr ptr ptr ptr ptr long ptr ptr long long) @ stdcall IcmpCloseHandle(ptr) @ stdcall IcmpCreateFile() -@ stdcall -stub IcmpParseReplies(ptr long) +@ stdcall IcmpParseReplies(ptr long) @ stdcall IcmpSendEcho2(ptr ptr ptr ptr long ptr long ptr ptr long long) @ stdcall IcmpSendEcho(ptr long ptr long ptr ptr long long) @ stub InternalCreateIpForwardEntry Index: dll/win32/iphlpapi/iphlpapi_main.c =================================================================== --- dll/win32/iphlpapi/iphlpapi_main.c (revision 70511) +++ dll/win32/iphlpapi/iphlpapi_main.c (working copy) @@ -35,17 +35,13 @@ BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { - WSADATA wsaData; - switch (fdwReason) { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls( hinstDLL ); interfaceMapInit(); - WSAStartup(MAKEWORD(2, 2), &wsaData); break; case DLL_PROCESS_DETACH: - WSACleanup(); interfaceMapFree(); break; } Index: media/doc/README.WINE =================================================================== --- media/doc/README.WINE (revision 70511) +++ media/doc/README.WINE (working copy) @@ -267,7 +267,7 @@ reactos/dll/win32/gdi32/objects/linedda.c # Synced at 20090410 iphlpapi - - reactos/dll/win32/iphlpapi/icmp.c # Partially synced to WineStaging-1.7.55 + reactos/dll/win32/iphlpapi/icmp.c # Forked kernel32 - reactos/dll/win32/kernel32/wine/actctx.c # Partly synced with Wine 1.7.55