Added ICMP DLL implementation.
diff --git a/Makefile.in b/Makefile.in
index 6f8cfe5..0dfd0b6 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -38,6 +38,7 @@
dlls/dciman32 \
dlls/dplayx \
dlls/dsound \
+ dlls/icmp \
dlls/imagehlp \
dlls/imm32 \
dlls/lzexpand \
@@ -143,6 +144,7 @@
dlls/commdlg/commdlg.o \
dlls/crtdll/crtdll.o \
dlls/dciman32/dciman32.o \
+ dlls/icmp/icmp.o \
dlls/dplayx/dplayx.o \
dlls/dsound/dsound.o \
dlls/imagehlp/imagehlp.o \
diff --git a/configure b/configure
index 63b7bea..139ff44 100755
--- a/configure
+++ b/configure
@@ -5643,6 +5643,7 @@
dlls/dciman32/Makefile
dlls/dplayx/Makefile
dlls/dsound/Makefile
+dlls/icmp/Makefile
dlls/imagehlp/Makefile
dlls/imm32/Makefile
dlls/lzexpand/Makefile
@@ -5846,6 +5847,7 @@
dlls/dciman32/Makefile
dlls/dplayx/Makefile
dlls/dsound/Makefile
+dlls/icmp/Makefile
dlls/imagehlp/Makefile
dlls/imm32/Makefile
dlls/lzexpand/Makefile
diff --git a/configure.in b/configure.in
index d42a0f1..3f05ff1 100644
--- a/configure.in
+++ b/configure.in
@@ -850,6 +850,7 @@
dlls/dciman32/Makefile
dlls/dplayx/Makefile
dlls/dsound/Makefile
+dlls/icmp/Makefile
dlls/imagehlp/Makefile
dlls/imm32/Makefile
dlls/lzexpand/Makefile
diff --git a/dlls/Makefile.in b/dlls/Makefile.in
index 0efcaf5..fe659bc 100644
--- a/dlls/Makefile.in
+++ b/dlls/Makefile.in
@@ -7,6 +7,7 @@
dciman32 \
dplayx \
dsound \
+ icmp \
imagehlp \
imm32 \
lzexpand \
diff --git a/dlls/icmp/.cvsignore b/dlls/icmp/.cvsignore
new file mode 100644
index 0000000..f540160
--- /dev/null
+++ b/dlls/icmp/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+icmp.spec.c
diff --git a/dlls/icmp/Makefile.in b/dlls/icmp/Makefile.in
new file mode 100644
index 0000000..a65a090
--- /dev/null
+++ b/dlls/icmp/Makefile.in
@@ -0,0 +1,19 @@
+DEFS = @DLLFLAGS@ -D__WINE__
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR = @srcdir@
+VPATH = @srcdir@
+MODULE = icmp
+
+SPEC_SRCS = icmp.spec
+
+C_SRCS = icmp_main.c
+
+all: $(MODULE).o
+
+@MAKE_RULES@
+
+### Dependencies:
+
+
+
diff --git a/dlls/icmp/icmp.spec b/dlls/icmp/icmp.spec
new file mode 100644
index 0000000..e394f68
--- /dev/null
+++ b/dlls/icmp/icmp.spec
@@ -0,0 +1,13 @@
+name icmp
+type win32
+
+1 stdcall IcmpCloseHandle(ptr) IcmpCloseHandle
+2 stdcall IcmpCreateFile() IcmpCreateFile
+3 stub IcmpParseReplies
+4 stub IcmpSendEcho2
+5 stdcall IcmpSendEcho(ptr long ptr long ptr ptr long long) IcmpSendEcho
+6 stub do_echo_rep
+7 stub do_echo_req
+8 stub register_icmp
+
+
diff --git a/dlls/icmp/icmp_main.c b/dlls/icmp/icmp_main.c
new file mode 100644
index 0000000..93e20ea
--- /dev/null
+++ b/dlls/icmp/icmp_main.c
@@ -0,0 +1,472 @@
+/*
+ * ICMP
+ *
+ * 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.
+ */
+
+/* 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.
+ * - Is it correct to use malloc for the internal buffer, for allocating the
+ * handle's structure?
+ * - This API should probably be thread safe. Is it really?
+ * - Using the winsock functions has not been tested.
+ */
+
+
+#define __USE_BSD
+
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <sys/time.h>
+#include <malloc.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+
+#include "windef.h"
+#include "winbase.h"
+#ifdef ICMP_WIN
+#include "winsock.h"
+#endif
+
+#include "winerror.h"
+#include "wine/ipexport.h"
+#include "wine/icmpapi.h"
+#include "debugtools.h"
+
+DEFAULT_DEBUG_CHANNEL(icmp)
+
+/* Define the following macro to use the winsock functions */
+/*#define ICMP_WIN*/
+
+#ifdef ICMP_WIN
+/* FIXME: should we include winsock.h ???*/
+SOCKET WINAPI WINSOCK_socket(INT af, INT type, INT protocol);
+INT WINAPI WINSOCK_sendto(SOCKET s, char *buf, INT len, INT flags, struct sockaddr *to, INT tolen);
+INT WINAPI WINSOCK_recvfrom(SOCKET s, char *buf,INT len, INT flags, struct sockaddr *from, INT *fromlen32);
+INT WINAPI WINSOCK_shutdown(SOCKET s, INT how);
+#endif
+
+
+#ifdef ICMP_WIN
+#define ISOCK_SOCKET SOCKET
+#define ISOCK_ISVALID(a) ((a)!=INVALID_SOCKET)
+#define ISOCK_getsockopt(a,b,c,d,e) WINSOCK_getsockopt(a,b,c,d,e)
+#define ISOCK_recvfrom(a,b,c,d,e,f) WINSOCK_recvfrom(a,b,c,d,e,f)
+#define ISOCK_select(a,b,c,d,e) WINSOCK_select(a,b,c,d,e)
+#define ISOCK_sendto(a,b,c,d,e,f) WINSOCK_sendto(a,b,c,d,e,f)
+#define ISOCK_setsockopt(a,b,c,d,e) WINSOCK_setsockopt(a,b,c,d,e)
+#define ISOCK_shutdown(a,b) WINSOCK_shutdown(a,b)
+#define ISOCK_socket(a,b,c) WINSOCK_socket(a,b,c)
+#else
+#define ISOCK_SOCKET int
+#define ISOCK_ISVALID(a) ((a)>=0)
+#define ISOCK_getsockopt(a,b,c,d,e) getsockopt(a,b,c,d,e)
+#define ISOCK_recvfrom(a,b,c,d,e,f) recvfrom(a,b,c,d,e,f)
+#define ISOCK_select(a,b,c,d,e) select(a,b,c,d,e)
+#define ISOCK_setsockopt(a,b,c,d,e) setsockopt(a,b,c,d,e)
+#define ISOCK_sendto(a,b,c,d,e,f) sendto(a,b,c,d,e,f)
+#define ISOCK_shutdown(a,b) shutdown(a,b)
+#define ISOCK_socket(a,b,c) socket(a,b,c)
+#endif
+
+typedef struct {
+ ISOCK_SOCKET sid;
+ IP_OPTION_INFORMATION default_opts;
+} icmp_t;
+
+#define IP_OPTS_UNKNOWN 0
+#define IP_OPTS_DEFAULT 1
+#define IP_OPTS_CUSTOM 2
+
+/* 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)
+{
+ int nleft=len;
+ u_short *w = addr;
+ int sum = 0;
+ u_short answer = 0;
+
+ while (nleft > 1) {
+ sum += *w++;
+ nleft -= 2;
+ }
+
+ if (nleft == 1) {
+ *(u_char *)(&answer) = *(u_char *)w;
+ sum += answer;
+ }
+
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16);
+ answer = ~sum;
+ return(answer);
+}
+
+
+
+/*
+ * Exported Routines.
+ */
+
+HANDLE WINAPI IcmpCreateFile(VOID)
+{
+ icmp_t* icp;
+
+ ISOCK_SOCKET sid=ISOCK_socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
+ if (!ISOCK_ISVALID(sid)) {
+ MESSAGE("WARNING: Trying to use ICMP will fail unless running as root\n");
+ SetLastError(ERROR_ACCESS_DENIED);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ icp=malloc(sizeof(*icp));
+ if (icp==NULL) {
+ SetLastError(IP_NO_RESOURCES);
+ return INVALID_HANDLE_VALUE;
+ }
+ icp->sid=sid;
+ icp->default_opts.OptionsSize=IP_OPTS_UNKNOWN;
+ return (HANDLE)icp;
+}
+
+
+BOOL WINAPI IcmpCloseHandle(HANDLE IcmpHandle)
+{
+ icmp_t* icp=(icmp_t*)IcmpHandle;
+
+ ISOCK_shutdown(icp->sid,2);
+ free(icp);
+ return TRUE;
+}
+
+
+DWORD WINAPI IcmpSendEcho(
+ HANDLE IcmpHandle,
+ IPAddr DestinationAddress,
+ LPVOID RequestData,
+ WORD RequestSize,
+ PIP_OPTION_INFORMATION RequestOptions,
+ LPVOID ReplyBuffer,
+ DWORD ReplySize,
+ DWORD Timeout
+ )
+{
+ icmp_t* icp=(icmp_t*)IcmpHandle;
+ unsigned char* reqbuf;
+ int reqsize;
+
+ struct icmp_echo_reply* ier;
+ struct ip* ip_header;
+ struct icmp* icmp_header;
+ char* endbuf;
+ int ip_header_len;
+ int maxlen;
+ fd_set fdr;
+ struct timeval timeout,send_time,recv_time;
+ struct sockaddr_in addr;
+ int addrlen;
+ unsigned short id,seq,cksum;
+ int res;
+
+ if (ReplySize<sizeof(ICMP_ECHO_REPLY)+ICMP_MINLEN) {
+ SetLastError(IP_BUF_TOO_SMALL);
+ return 0;
+ }
+ /* check the request size against SO_MAX_MSG_SIZE using getsockopt */
+
+ /* Prepare the request */
+ id=getpid() & 0xFFFF;
+ seq=InterlockedIncrement(&icmp_sequence) & 0xFFFF;
+
+ reqsize=ICMP_MINLEN+RequestSize;
+ reqbuf=malloc(reqsize);
+ if (reqbuf==NULL) {
+ SetLastError(ERROR_OUTOFMEMORY);
+ 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);
+
+ addr.sin_family=AF_INET;
+ addr.sin_addr.s_addr=DestinationAddress;
+ addr.sin_port=0;
+
+ if (RequestOptions!=NULL) {
+ int val;
+ if (icp->default_opts.OptionsSize==IP_OPTS_UNKNOWN) {
+ int len;
+ /* Before we mess with the options, get the default values */
+ len=sizeof(val);
+ ISOCK_getsockopt(icp->sid,SOL_IP,IP_TTL,&val,&len);
+ icp->default_opts.Ttl=val;
+
+ len=sizeof(val);
+ ISOCK_getsockopt(icp->sid,SOL_IP,IP_TOS,&val,&len);
+ icp->default_opts.Tos=val;
+ /* FIXME: missing: handling of IP 'flags', and all the other options */
+ }
+
+ val=RequestOptions->Ttl;
+ ISOCK_setsockopt(icp->sid,SOL_IP,IP_TTL,&val,sizeof(val));
+ val=RequestOptions->Tos;
+ ISOCK_setsockopt(icp->sid,SOL_IP,IP_TOS,&val,sizeof(val));
+ /* FIXME: missing: handling of IP 'flags', and all the other options */
+
+ icp->default_opts.OptionsSize=IP_OPTS_CUSTOM;
+ } else if (icp->default_opts.OptionsSize==IP_OPTS_CUSTOM) {
+ int val;
+
+ /* Restore the default options */
+ val=icp->default_opts.Ttl;
+ ISOCK_setsockopt(icp->sid,SOL_IP,IP_TTL,&val,sizeof(val));
+ val=icp->default_opts.Tos;
+ ISOCK_setsockopt(icp->sid,SOL_IP,IP_TOS,&val,sizeof(val));
+ /* FIXME: missing: handling of IP 'flags', and all the other options */
+
+ icp->default_opts.OptionsSize=IP_OPTS_DEFAULT;
+ }
+
+ /* Get ready for receiving the reply
+ * Do it before we send the request to minimize the risk of introducing delays
+ */
+ FD_ZERO(&fdr);
+ FD_SET(icp->sid,&fdr);
+ timeout.tv_sec=Timeout/1000;
+ timeout.tv_usec=(Timeout % 1000)*1000;
+ addrlen=sizeof(addr);
+ ier=ReplyBuffer;
+ ip_header=ReplyBuffer+sizeof(ICMP_ECHO_REPLY);
+ endbuf=ReplyBuffer+ReplySize;
+ maxlen=ReplySize-sizeof(ICMP_ECHO_REPLY);
+
+ /* 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;i<reqsize;i++)
+ printf("%2x,", buf[i]);
+ printf("\n");
+ }
+#endif
+
+ gettimeofday(&send_time,NULL);
+ res=ISOCK_sendto(icp->sid, reqbuf, reqsize, 0, (struct sockaddr*)&addr, sizeof(addr));
+ free(reqbuf);
+ if (res<0) {
+ if (errno==EMSGSIZE)
+ SetLastError(IP_PACKET_TOO_BIG);
+ else {
+ switch (errno) {
+ case ENETUNREACH:
+ SetLastError(IP_DEST_NET_UNREACHABLE);
+ break;
+ case EHOSTUNREACH:
+ SetLastError(IP_DEST_NET_UNREACHABLE);
+ break;
+ default:
+ TRACE("unknown error: errno=%d\n",errno);
+ SetLastError(ERROR_UNKNOWN);
+ }
+ }
+ return 0;
+ }
+
+ /* Get the reply */
+ ip_header_len=0; /* because gcc was complaining */
+ while ((res=ISOCK_select(icp->sid+1,&fdr,NULL,NULL,&timeout))>0) {
+ gettimeofday(&recv_time,NULL);
+ res=ISOCK_recvfrom(icp->sid, (char*)ip_header, maxlen, 0, (struct sockaddr*)&addr,&addrlen);
+ TRACE("received %d bytes from %s\n",res, inet_ntoa(addr.sin_addr));
+ ier->Status=IP_REQ_TIMED_OUT;
+
+ /* 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:
+ case ICMP_UNREACH_HOST_UNKNOWN:
+ case ICMP_UNREACH_ISOLATED:
+ case ICMP_UNREACH_HOST_PROHIB:
+ case ICMP_UNREACH_TOSHOST:
+ 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));
+
+ /* 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) ||
+ (rep_icmp_header->icmp_seq!=seq) ||
+ (rep_icmp_header->icmp_cksum!=cksum)) {
+ /* 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;
+ }
+ }
+ }
+ }
+
+ 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.
+ */
+ timeout.tv_sec=Timeout/1000-(recv_time.tv_sec-send_time.tv_sec);
+ timeout.tv_usec=(Timeout % 1000)*1000+send_time.tv_usec-(recv_time.tv_usec-send_time.tv_usec);
+ if (timeout.tv_usec<0) {
+ timeout.tv_usec+=1000000;
+ timeout.tv_sec--;
+ }
+ 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.tv_sec-send_time.tv_sec)*1000+(recv_time.tv_usec-send_time.tv_usec)/1000;
+ 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=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=ier->Options.OptionsData;
+ } else {
+ ier->Options.OptionsData=NULL;
+ endbuf=ier->Data;
+ }
+
+ /* Prepare for the next packet */
+ ier++;
+ ip_header=(struct ip*)(((char*)ip_header)+sizeof(ICMP_ECHO_REPLY));
+ maxlen=endbuf-(char*)ip_header;
+
+ /* Check out whether there is more but don't wait this time */
+ timeout.tv_sec=0;
+ timeout.tv_usec=0;
+ }
+ FD_ZERO(&fdr);
+ FD_SET(icp->sid,&fdr);
+ }
+ res=ier-(ICMP_ECHO_REPLY*)ReplyBuffer;
+ if (res==0)
+ SetLastError(IP_REQ_TIMED_OUT);
+ TRACE("received %d replies\n",res);
+ return res;
+}
+
+/*
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. 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.
+ *
+ */
diff --git a/include/debugdefs.h b/include/debugdefs.h
index 818041e..f92a39e 100644
--- a/include/debugdefs.h
+++ b/include/debugdefs.h
@@ -59,114 +59,115 @@
const int dbch_heap = 48;
const int dbch_hook = 49;
const int dbch_hotkey = 50;
-const int dbch_icon = 51;
-const int dbch_imagehlp = 52;
-const int dbch_imagelist = 53;
-const int dbch_imm = 54;
-const int dbch_int = 55;
-const int dbch_int10 = 56;
-const int dbch_int16 = 57;
-const int dbch_int17 = 58;
-const int dbch_int19 = 59;
-const int dbch_int21 = 60;
-const int dbch_int31 = 61;
-const int dbch_io = 62;
-const int dbch_ipaddress = 63;
-const int dbch_key = 64;
-const int dbch_keyboard = 65;
-const int dbch_ldt = 66;
-const int dbch_listbox = 67;
-const int dbch_listview = 68;
-const int dbch_local = 69;
-const int dbch_mci = 70;
-const int dbch_mcianim = 71;
-const int dbch_mciavi = 72;
-const int dbch_mcimidi = 73;
-const int dbch_mciwave = 74;
-const int dbch_mdi = 75;
-const int dbch_menu = 76;
-const int dbch_message = 77;
-const int dbch_metafile = 78;
-const int dbch_midi = 79;
-const int dbch_mmaux = 80;
-const int dbch_mmio = 81;
-const int dbch_mmsys = 82;
-const int dbch_mmtime = 83;
-const int dbch_module = 84;
-const int dbch_monthcal = 85;
-const int dbch_mpr = 86;
-const int dbch_msacm = 87;
-const int dbch_msg = 88;
-const int dbch_msvideo = 89;
-const int dbch_nativefont = 90;
-const int dbch_nonclient = 91;
-const int dbch_ntdll = 92;
-const int dbch_ole = 93;
-const int dbch_pager = 94;
-const int dbch_palette = 95;
-const int dbch_pidl = 96;
-const int dbch_print = 97;
-const int dbch_process = 98;
-const int dbch_profile = 99;
-const int dbch_progress = 100;
-const int dbch_prop = 101;
-const int dbch_propsheet = 102;
-const int dbch_psapi = 103;
-const int dbch_psdrv = 104;
-const int dbch_ras = 105;
-const int dbch_rebar = 106;
-const int dbch_reg = 107;
-const int dbch_region = 108;
-const int dbch_relay = 109;
-const int dbch_resource = 110;
-const int dbch_scroll = 111;
-const int dbch_security = 112;
-const int dbch_segment = 113;
-const int dbch_seh = 114;
-const int dbch_selector = 115;
-const int dbch_sendmsg = 116;
-const int dbch_server = 117;
-const int dbch_shell = 118;
-const int dbch_snoop = 119;
-const int dbch_sound = 120;
-const int dbch_static = 121;
-const int dbch_statusbar = 122;
-const int dbch_storage = 123;
-const int dbch_stress = 124;
-const int dbch_string = 125;
-const int dbch_syscolor = 126;
-const int dbch_system = 127;
-const int dbch_tab = 128;
-const int dbch_tapi = 129;
-const int dbch_task = 130;
-const int dbch_text = 131;
-const int dbch_thread = 132;
-const int dbch_thunk = 133;
-const int dbch_timer = 134;
-const int dbch_toolbar = 135;
-const int dbch_toolhelp = 136;
-const int dbch_tooltips = 137;
-const int dbch_trackbar = 138;
-const int dbch_treeview = 139;
-const int dbch_ttydrv = 140;
-const int dbch_tweak = 141;
-const int dbch_typelib = 142;
-const int dbch_updown = 143;
-const int dbch_ver = 144;
-const int dbch_virtual = 145;
-const int dbch_vxd = 146;
-const int dbch_wave = 147;
-const int dbch_win = 148;
-const int dbch_win16drv = 149;
-const int dbch_win32 = 150;
-const int dbch_wing = 151;
-const int dbch_winsock = 152;
-const int dbch_winspool = 153;
-const int dbch_wnet = 154;
-const int dbch_x11 = 155;
-const int dbch_x11drv = 156;
+const int dbch_icmp = 51;
+const int dbch_icon = 52;
+const int dbch_imagehlp = 53;
+const int dbch_imagelist = 54;
+const int dbch_imm = 55;
+const int dbch_int = 56;
+const int dbch_int10 = 57;
+const int dbch_int16 = 58;
+const int dbch_int17 = 59;
+const int dbch_int19 = 60;
+const int dbch_int21 = 61;
+const int dbch_int31 = 62;
+const int dbch_io = 63;
+const int dbch_ipaddress = 64;
+const int dbch_key = 65;
+const int dbch_keyboard = 66;
+const int dbch_ldt = 67;
+const int dbch_listbox = 68;
+const int dbch_listview = 69;
+const int dbch_local = 70;
+const int dbch_mci = 71;
+const int dbch_mcianim = 72;
+const int dbch_mciavi = 73;
+const int dbch_mcimidi = 74;
+const int dbch_mciwave = 75;
+const int dbch_mdi = 76;
+const int dbch_menu = 77;
+const int dbch_message = 78;
+const int dbch_metafile = 79;
+const int dbch_midi = 80;
+const int dbch_mmaux = 81;
+const int dbch_mmio = 82;
+const int dbch_mmsys = 83;
+const int dbch_mmtime = 84;
+const int dbch_module = 85;
+const int dbch_monthcal = 86;
+const int dbch_mpr = 87;
+const int dbch_msacm = 88;
+const int dbch_msg = 89;
+const int dbch_msvideo = 90;
+const int dbch_nativefont = 91;
+const int dbch_nonclient = 92;
+const int dbch_ntdll = 93;
+const int dbch_ole = 94;
+const int dbch_pager = 95;
+const int dbch_palette = 96;
+const int dbch_pidl = 97;
+const int dbch_print = 98;
+const int dbch_process = 99;
+const int dbch_profile = 100;
+const int dbch_progress = 101;
+const int dbch_prop = 102;
+const int dbch_propsheet = 103;
+const int dbch_psapi = 104;
+const int dbch_psdrv = 105;
+const int dbch_ras = 106;
+const int dbch_rebar = 107;
+const int dbch_reg = 108;
+const int dbch_region = 109;
+const int dbch_relay = 110;
+const int dbch_resource = 111;
+const int dbch_scroll = 112;
+const int dbch_security = 113;
+const int dbch_segment = 114;
+const int dbch_seh = 115;
+const int dbch_selector = 116;
+const int dbch_sendmsg = 117;
+const int dbch_server = 118;
+const int dbch_shell = 119;
+const int dbch_snoop = 120;
+const int dbch_sound = 121;
+const int dbch_static = 122;
+const int dbch_statusbar = 123;
+const int dbch_storage = 124;
+const int dbch_stress = 125;
+const int dbch_string = 126;
+const int dbch_syscolor = 127;
+const int dbch_system = 128;
+const int dbch_tab = 129;
+const int dbch_tapi = 130;
+const int dbch_task = 131;
+const int dbch_text = 132;
+const int dbch_thread = 133;
+const int dbch_thunk = 134;
+const int dbch_timer = 135;
+const int dbch_toolbar = 136;
+const int dbch_toolhelp = 137;
+const int dbch_tooltips = 138;
+const int dbch_trackbar = 139;
+const int dbch_treeview = 140;
+const int dbch_ttydrv = 141;
+const int dbch_tweak = 142;
+const int dbch_typelib = 143;
+const int dbch_updown = 144;
+const int dbch_ver = 145;
+const int dbch_virtual = 146;
+const int dbch_vxd = 147;
+const int dbch_wave = 148;
+const int dbch_win = 149;
+const int dbch_win16drv = 150;
+const int dbch_win32 = 151;
+const int dbch_wing = 152;
+const int dbch_winsock = 153;
+const int dbch_winspool = 154;
+const int dbch_wnet = 155;
+const int dbch_x11 = 156;
+const int dbch_x11drv = 157;
-#define DEBUG_CHANNEL_COUNT 157
+#define DEBUG_CHANNEL_COUNT 158
char __debug_msg_enabled[DEBUG_CHANNEL_COUNT][DEBUG_CLASS_COUNT] = {
{1, 1, 0, 0},
@@ -325,6 +326,7 @@
{1, 1, 0, 0},
{1, 1, 0, 0},
{1, 1, 0, 0},
+{1, 1, 0, 0},
{1, 1, 0, 0}
};
@@ -380,6 +382,7 @@
"heap",
"hook",
"hotkey",
+"icmp",
"icon",
"imagehlp",
"imagelist",
diff --git a/include/wine/icmpapi.h b/include/wine/icmpapi.h
new file mode 100644
index 0000000..df2717f
--- /dev/null
+++ b/include/wine/icmpapi.h
@@ -0,0 +1,33 @@
+/*
+ * Interface to the ICMP functions.
+ *
+ * This header is not part of the standard headers, it is usually
+ * delivered separately and this is why it is not directly in 'include'.
+ *
+ * Depends on ipexport.h (there is no include directive in the original)
+ */
+
+#ifndef __WINE_ICMPAPI_H
+#define __WINE_ICMPAPI_H
+
+HANDLE WINAPI IcmpCreateFile(
+ VOID
+ );
+
+BOOL WINAPI IcmpCloseHandle(
+ HANDLE IcmpHandle
+ );
+
+DWORD WINAPI IcmpSendEcho(
+ HANDLE IcmpHandle,
+ IPAddr DestinationAddress,
+ LPVOID RequestData,
+ WORD RequestSize,
+ PIP_OPTION_INFORMATION RequestOptions,
+ LPVOID ReplyBuffer,
+ DWORD ReplySize,
+ DWORD Timeout
+ );
+
+
+#endif /* __WINE_ICMPAPI_H */
diff --git a/include/wine/ipexport.h b/include/wine/ipexport.h
new file mode 100644
index 0000000..c383d7c0
--- /dev/null
+++ b/include/wine/ipexport.h
@@ -0,0 +1,86 @@
+/*
+ * Defines the types and macros used by the ICMP API, see icmpapi.h.
+ *
+ * This header is not part of the standard headers, it is usually
+ * delivered separately and this is why it is not directly in 'include'.
+ */
+
+#ifndef __WINE_IPEXPORT_H
+#define __WINE_IPEXPORT_H
+
+typedef unsigned long IPAddr;
+typedef unsigned long IPMask;
+typedef unsigned long IP_STATUS;
+
+struct ip_option_information
+{
+ unsigned char Ttl;
+ unsigned char Tos;
+ unsigned char Flags;
+ unsigned char OptionsSize;
+ unsigned char* OptionsData;
+};
+
+#define IP_FLAG_DF 0x2
+
+#define IP_OPT_EOL 0
+#define IP_OPT_NOP 1
+#define IP_OPT_SECURITY 0x82
+#define IP_OPT_LSRR 0x83
+#define IP_OPT_SSRR 0x89
+#define IP_OPT_RR 0x7
+#define IP_OPT_TS 0x44
+#define IP_OPT_SID 0x88
+
+#define MAX_OPT_SIZE 40
+
+
+struct icmp_echo_reply
+{
+ IPAddr Address;
+ unsigned long Status;
+ unsigned long RoundTripTime;
+ unsigned short DataSize;
+ unsigned short Reserved;
+ void* Data;
+ struct ip_option_information Options;
+};
+
+typedef struct ip_option_information IP_OPTION_INFORMATION, *PIP_OPTION_INFORMATION;
+
+typedef struct icmp_echo_reply ICMP_ECHO_REPLY, *PICMP_ECHO_REPLY;
+
+
+#define IP_STATUS_BASE 11000
+
+#define IP_SUCCESS 0
+#define IP_BUF_TOO_SMALL (IP_STATUS_BASE + 1)
+#define IP_DEST_NET_UNREACHABLE (IP_STATUS_BASE + 2)
+#define IP_DEST_HOST_UNREACHABLE (IP_STATUS_BASE + 3)
+#define IP_DEST_PROT_UNREACHABLE (IP_STATUS_BASE + 4)
+#define IP_DEST_PORT_UNREACHABLE (IP_STATUS_BASE + 5)
+#define IP_NO_RESOURCES (IP_STATUS_BASE + 6)
+#define IP_BAD_OPTION (IP_STATUS_BASE + 7)
+#define IP_HW_ERROR (IP_STATUS_BASE + 8)
+#define IP_PACKET_TOO_BIG (IP_STATUS_BASE + 9)
+#define IP_REQ_TIMED_OUT (IP_STATUS_BASE + 10)
+#define IP_BAD_REQ (IP_STATUS_BASE + 11)
+#define IP_BAD_ROUTE (IP_STATUS_BASE + 12)
+#define IP_TTL_EXPIRED_TRANSIT (IP_STATUS_BASE + 13)
+#define IP_TTL_EXPIRED_REASSEM (IP_STATUS_BASE + 14)
+#define IP_PARAM_PROBLEM (IP_STATUS_BASE + 15)
+#define IP_SOURCE_QUENCH (IP_STATUS_BASE + 16)
+#define IP_OPTION_TOO_BIG (IP_STATUS_BASE + 17)
+#define IP_BAD_DESTINATION (IP_STATUS_BASE + 18)
+
+#define IP_ADDR_DELETED (IP_STATUS_BASE + 19)
+#define IP_SPEC_MTU_CHANGE (IP_STATUS_BASE + 20)
+#define IP_MTU_CHANGE (IP_STATUS_BASE + 21)
+#define IP_UNLOAD (IP_STATUS_BASE + 22)
+
+#define IP_GENERAL_FAILURE (IP_STATUS_BASE + 50)
+#define MAX_IP_STATUS IP_GENERAL_FAILURE
+#define IP_PENDING (IP_STATUS_BASE + 255)
+
+
+#endif /* __WINE_IPEXPORT_H */
diff --git a/loader/loadorder.c b/loader/loadorder.c
index a340c8b..101a8b2 100644
--- a/loader/loadorder.c
+++ b/loader/loadorder.c
@@ -56,6 +56,7 @@
{"wnaspi32,wow32", "builtin"},
{"system,display,wprocs ", "builtin"},
{"wineps", "builtin"},
+ {"icmp", "builtin"},
/* we have to use libglide2x.so instead of glide2x.dll ... */
{"glide2x", "so,native"},
{NULL,NULL},
diff --git a/relay32/builtin32.c b/relay32/builtin32.c
index 92c8df1..2d52b5c 100644
--- a/relay32/builtin32.c
+++ b/relay32/builtin32.c
@@ -60,6 +60,7 @@
extern const BUILTIN32_DESCRIPTOR DPLAYX_Descriptor;
extern const BUILTIN32_DESCRIPTOR DSOUND_Descriptor;
extern const BUILTIN32_DESCRIPTOR GDI32_Descriptor;
+extern const BUILTIN32_DESCRIPTOR ICMP_Descriptor;
extern const BUILTIN32_DESCRIPTOR IMAGEHLP_Descriptor;
extern const BUILTIN32_DESCRIPTOR IMM32_Descriptor;
extern const BUILTIN32_DESCRIPTOR KERNEL32_Descriptor;
@@ -116,6 +117,7 @@
{ &DPLAYX_Descriptor, 0, 0, NULL },
{ &DSOUND_Descriptor, 0, 0, NULL },
{ &GDI32_Descriptor, 0, 0, NULL },
+ { &ICMP_Descriptor, 0, 0, NULL },
{ &IMAGEHLP_Descriptor, BI32_DANGER, 0, NULL },
{ &IMM32_Descriptor, 0, 0, NULL },
{ &KERNEL32_Descriptor, 0, 0, NULL },
diff --git a/wine.ini b/wine.ini
index 6f55056..ada10dd 100644
--- a/wine.ini
+++ b/wine.ini
@@ -61,7 +61,7 @@
DefaultLoadOrder = native, elfdll, so, builtin
[DllPairs]
-kernel = kernel32
+krnl386 = kernel32
gdi = gdi32
user = user32
commdlg = comdlg32
@@ -96,6 +96,7 @@
wnaspi32, wow32 = builtin
system, display, wprocs = builtin
wineps = builtin
+icmp = builtin
[options]
AllocSystemColors=100