winsock ipx improvements

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

The following three patches improve wine's winsock ipx support. With these 
patches various games work now using IPX. For example C&C Red Alert (v 3.x) 
and Tiberian Sun, I expect other games to work too (Red Alert II ...).

First I'll start describing all patches. The patch wsnwlink.h.diff adds a new 
header to wine which is needed for the winsock improvements.

The patch called winsock.diff adds various new ipx stuff (IPX_PTYPE, 
IPX_ADDRESS ..) to the winsock dll. One new feature (IPX_PTYPE) needs a patch 
to the wineserver.

Inside the functions WS_getsockopt/WS_setsockopt the option IPX_PTYPE was 
missing. On windows this option can get/set the ipx packet type. The unix way 
to change the packet type is to change one of the members of the unix 
sockaddr_ipx structure. The winsock sockaddr_ipx structure lacks this member. 
:( Just adding the variable can't be done ofcourse since this structure is 
part of the official winsock api's. Mike McCormack advised me to add a 
wineserver call to get/set the packet type value. This new wineserver call 
can be found in wineserver.diff. I'm using the new call in 3 different places 
inside winsock: in WS_getsockopt, WS_setsockopt and in WS2_send.

There is one thing I don't like about my work. That part is quite hacky and 
because of this I didn't clean it up since it will likely be rejected. Inside 
ws2_send the winsock sockaddr structure is converted to its unix equivalent 
before sending the data by ws_sockaddr_ws2u. The packet type needs to be set 
to a variable of the unix sockaddr_ipx structure. Because of this I need my 
new wineserver call. The problem more is that my call needs the socket and I 
only have the fd. I tried using wine_server_fd_to_handle but I don't think 
that is the correct function to convert the fd back to the socket/handle. 
(didn't get good results) In the end I added the socket as a hack to the 
prototype of the function. Because I don't think it is the correct way, I 
didn't clean this part up. I hope we can find a more correct solution.

ChangeLog:
- implement getsockopt/setsockopt's IPX_PTYPE, IPX_ADDRESS and 
IPX_MAD_ADAPATER_NUM

Roderick

Index: dlls/winsock/socket.c
===================================================================
RCS file: /home/wine/wine/dlls/winsock/socket.c,v
retrieving revision 1.130
diff -u -r1.130 socket.c
--- dlls/winsock/socket.c	30 Jun 2003 20:53:48 -0000	1.130
+++ dlls/winsock/socket.c	12 Jul 2003 13:12:22 -0000
@@ -182,6 +182,11 @@
     DWORD                               flags;
 } ws2_async;
 
+#ifdef HAVE_IPX
+# include "wsnwlink.h"
+#endif
+
+
 /****************************************************************/
 
 /* ----------------------------------- internal data */
@@ -1247,7 +1252,7 @@
  * Work horse for both synchronous and asynchronous send() operations.
  */
 static int WS2_send ( int fd, struct iovec* iov, int count,
-                      const struct WS_sockaddr *to, INT tolen, DWORD dwFlags )
+                      const struct WS_sockaddr *to, INT tolen, DWORD dwFlags, SOCKET s)
 {
     struct msghdr hdr;
     int n = -1;
@@ -1261,6 +1266,25 @@
 #if DEBUG_SOCKADDR
         dump_sockaddr (to);
 #endif
+
+#ifdef HAVE_IPX
+	if(to->sa_family == WS_AF_IPX)
+	{
+            struct sockaddr_ipx* uipx;
+	    uipx = (struct sockaddr_ipx*) ws_sockaddr_ws2u ( to, tolen, &hdr.msg_namelen );
+
+	    SERVER_START_REQ(packet_type )
+	    {
+		req->flags = IPX_GET_PTYPE;
+		req->handle = SOCKET2HANDLE(s);
+    		wine_server_call( req );
+    		uipx->sipx_type=reply->ptype;
+	    }
+	    SERVER_END_REQ;
+	    hdr.msg_name = (struct sockaddr*) uipx;
+	}    
+	else
+#endif
         hdr.msg_name = (struct sockaddr*) ws_sockaddr_ws2u ( to, tolen, &hdr.msg_namelen );
         if ( !hdr.msg_name )
         {
@@ -1308,7 +1332,7 @@
     }
 
     result = WS2_send ( wsa->async.fd, wsa->iovec, wsa->n_iovecs,
-                        wsa->addr, wsa->addrlen.val, wsa->flags );
+                        wsa->addr, wsa->addrlen.val, wsa->flags, 0 );
 
     if (result >= 0)
     {
@@ -1826,6 +1850,55 @@
         return 0;
     }
 
+#ifdef HAVE_IPX
+    if(level == NSPROTO_IPX)
+    {
+    	struct WS_sockaddr_ipx addr;
+	IPX_ADDRESS_DATA *data;
+	int namelen;
+	switch(optname)
+	{
+	    case IPX_PTYPE:
+		SERVER_START_REQ(packet_type )
+		{
+		    req->flags = IPX_GET_PTYPE;
+		    req->handle = SOCKET2HANDLE (s);
+
+    		    wine_server_call( req );
+    		    *(int*)optval = reply->ptype;
+		    *optlen = sizeof(int);
+		}
+		SERVER_END_REQ;
+		return 0;
+		break;	    
+	    case IPX_ADDRESS:
+		namelen = sizeof(struct WS_sockaddr);
+		memset(&addr, 0, sizeof(struct WS_sockaddr));
+		WS_getsockname(s, (struct WS_sockaddr*)&addr, &namelen);
+
+		data = (IPX_ADDRESS_DATA*)optval;
+                memcpy(data->nodenum,&addr.sa_nodenum,sizeof(data->nodenum));
+                memcpy(data->netnum,&addr.sa_netnum,sizeof(data->netnum));
+		data->adapternum = 0;
+		data->wan = FALSE; /* We are not on a wan for now .. */
+		data->status = FALSE; /* Since we are not on a wan, the wan link isn't up */
+		data->maxpkt = 1500; /* Is this value correct, I found it on a IPX page */
+		data->linkspeed = 13107; /* Set the line speed to 10 Mbit / 1.25 MB for now */
+		FIXME("IPX_ADDRESS\n");
+		return 0;	
+		break;
+	    case IPX_MAX_ADAPTER_NUM:
+    		*(int*)optval = 1; /* Only one card for the moment .. */
+		FIXME("IPX_MAX_ADAPTER_NUM\n");
+		return 0;
+		break;
+	    default:
+		FIXME("opt_name:%x\n", optname);
+		return SOCKET_ERROR;
+	}
+    }
+#endif
+
     fd = _get_sock_fd(s);
     if (fd != -1)
     {
@@ -2476,7 +2549,7 @@
         do_block(fd, 2);
     }
 
-    n = WS2_send ( fd, iovec, dwBufferCount, to, tolen, dwFlags );
+    n = WS2_send ( fd, iovec, dwBufferCount, to, tolen, dwFlags, s );
     if ( n == -1 )
     {
         err = wsaErrno();
@@ -2572,6 +2645,44 @@
         return 0;
     }
 
+#ifdef HAVE_IPX
+    if(level == NSPROTO_IPX)
+    {
+    	struct WS_sockaddr addr;
+	struct sockaddr_ipx* sipx;
+	int namelen, uaddrlen;
+	switch(optname)
+	{
+	    case IPX_PTYPE:
+		namelen = sizeof(struct WS_sockaddr);
+		memset(&addr, 0, sizeof(struct WS_sockaddr));
+		WS_getsockname(s, &addr, &namelen);
+		sipx = (struct sockaddr_ipx*)ws_sockaddr_ws2u(&addr, sizeof(addr), &uaddrlen);
+
+		SERVER_START_REQ(packet_type )
+		{
+		    req->flags = IPX_SET_PTYPE;
+		    req->handle = SOCKET2HANDLE (s);
+	
+		    req->value = *optval;
+    		    wine_server_call( req );
+		}
+		SERVER_END_REQ;
+		return 0;
+		break;
+	    case IPX_FILTERPTYPE:
+		/* sets the receive filter packet type */
+		/* SO_ATTACH_FILTER ??*/
+		FIXME("IPX_FILTERPTYPE: %x\n", *optval);
+		return 0;
+		break;
+	    default:
+		FIXME("opt_name:%x\n", optname);
+		return SOCKET_ERROR;
+	}
+	return 0;
+    }
+#endif
 
     fd = _get_sock_fd(s);
     if (fd != -1)
--- /dev/null	2003-01-18 20:54:32.000000000 +0100
+++ ./include/wsnwlink.h	2003-07-12 14:21:34.000000000 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2003 Roderick Colenbrander
+ *
+ * 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.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _WSNWLINK_
+#define _WSNWLINK_
+
+#include "wtypes.h"
+
+#define IPX_PTYPE 0x4000
+#define IPX_FILTERPTYPE 0x4001
+#define IPX_DSTYPE 0x4002
+#define IPX_STOPFILTERPTYPE 0x4003
+#define IPX_EXTENDED_ADDRESS 0x4004
+#define IPX_RECVHDR 0x4005
+#define IPX_MAXSIZE 0x4006
+#define IPX_ADDRESS 0x4007
+#define IPX_GETNETINFO 0x4008
+#define IPX_GETNETINFO_NORIP 0x4009
+#define IPX_SPXGETCONNECTIONSTATUS 0x400b
+#define IPX_ADDRESS_NOTIFY 0x400c
+#define IPX_MAX_ADAPTER_NUM 0x400d
+#define IPX_RERIPNETNUMBER 0x400e
+#define IPX_RECEIVE_BROADCAST 0x400f
+#define IPX_IMMEDIATESPXACK 0x4010
+
+typedef struct _IPX_ADDRESS_DATA {
+    INT   adapternum;
+    UCHAR netnum[4];
+    UCHAR nodenum[6];
+    BOOLEAN wan;
+    BOOLEAN status;
+    INT maxpkt;
+    ULONG linkspeed;
+} IPX_ADDRESS_DATA, *PIPX_ADDRESS_DATA;
+
+#endif
+
Index: include/wine/server_protocol.h
===================================================================
RCS file: /home/wine/wine/include/wine/server_protocol.h,v
retrieving revision 1.76
diff -u -r1.76 server_protocol.h
--- include/wine/server_protocol.h	11 Jul 2003 21:55:59 -0000	1.76
+++ include/wine/server_protocol.h	12 Jul 2003 13:12:23 -0000
@@ -3081,6 +3081,22 @@
 #define CB_OPEN          0x040
 #define CB_OWNER         0x080
 
+struct packet_type_request
+{
+    struct request_header __header;
+    obj_handle_t handle;
+    unsigned int flags;
+    int value;
+};
+struct packet_type_reply
+{
+    struct reply_header __header;
+    int ptype;
+};
+
+#define IPX_GET_PTYPE 0x1
+#define IPX_SET_PTYPE 0x2
+
 
 enum request
 {
@@ -3260,6 +3276,7 @@
     REQ_finish_hook_chain,
     REQ_get_next_hook,
     REQ_set_clipboard_info,
+    REQ_packet_type,
     REQ_NB_REQUESTS
 };
 
@@ -3443,6 +3460,7 @@
     struct finish_hook_chain_request finish_hook_chain_request;
     struct get_next_hook_request get_next_hook_request;
     struct set_clipboard_info_request set_clipboard_info_request;
+    struct packet_type_request packet_type_request;
 };
 union generic_reply
 {
@@ -3624,8 +3642,9 @@
     struct finish_hook_chain_reply finish_hook_chain_reply;
     struct get_next_hook_reply get_next_hook_reply;
     struct set_clipboard_info_reply set_clipboard_info_reply;
+    struct packet_type_reply packet_type_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 116
+#define SERVER_PROTOCOL_VERSION 117
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
Index: server/protocol.def
===================================================================
RCS file: /home/wine/wine/server/protocol.def,v
retrieving revision 1.76
diff -u -r1.76 protocol.def
--- server/protocol.def	11 Jul 2003 21:55:58 -0000	1.76
+++ server/protocol.def	12 Jul 2003 13:12:25 -0000
@@ -2160,3 +2160,14 @@
 #define SET_CB_CLOSE     0x020
 #define CB_OPEN          0x040
 #define CB_OWNER         0x080
+
+@REQ(packet_type)
+    obj_handle_t handle;        /* handle to the socket */
+    unsigned int flags;		/* get/set packet type */
+    int value;			/* packet type */
+@REPLY
+    int ptype;
+@END
+
+#define IPX_GET_PTYPE 0x1	/* get ipx packet type */
+#define IPX_SET_PTYPE 0x2	/* set ipx packet type */
Index: server/request.h
===================================================================
RCS file: /home/wine/wine/server/request.h,v
retrieving revision 1.86
diff -u -r1.86 request.h
--- server/request.h	23 Jun 2003 23:02:03 -0000	1.86
+++ server/request.h	12 Jul 2003 13:12:25 -0000
@@ -279,6 +279,7 @@
 DECL_HANDLER(finish_hook_chain);
 DECL_HANDLER(get_next_hook);
 DECL_HANDLER(set_clipboard_info);
+DECL_HANDLER(packet_type);
 
 #ifdef WANT_REQUEST_HANDLERS
 
@@ -461,6 +462,7 @@
     (req_handler)req_finish_hook_chain,
     (req_handler)req_get_next_hook,
     (req_handler)req_set_clipboard_info,
+    (req_handler)req_packet_type,
 };
 #endif  /* WANT_REQUEST_HANDLERS */
 
Index: server/sock.c
===================================================================
RCS file: /home/wine/wine/server/sock.c,v
retrieving revision 1.45
diff -u -r1.45 sock.c
--- server/sock.c	12 Mar 2003 22:38:14 -0000	1.45
+++ server/sock.c	12 Jul 2003 13:12:25 -0000
@@ -1,7 +1,7 @@
 /*
  * Server-side socket management
  *
- * Copyright (C) 1999 Marcus Meissner, Ove Kåven
+ * Copyright (C) 1999 Marcus Meissner, Ove KÃ¥ven
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -82,6 +82,7 @@
     struct sock*        deferred;    /* socket that waits for a deferred accept */
     struct async_queue  read_q;      /* Queue for asynchronous reads */
     struct async_queue  write_q;     /* Queue for asynchronous writes */
+    int 		ptype;       /* packet type, only used for ipx */
 };
 
 static void sock_dump( struct object *obj, int verbose );
@@ -616,6 +617,7 @@
     sock->message = 0;
     sock->wparam  = 0;
     sock->deferred = NULL;
+    sock->ptype   = 0;
     if (!(sock->fd = create_anonymous_fd( &sock_fd_ops, sockfd, &sock->obj )))
     {
         release_object( sock );
@@ -921,5 +923,24 @@
         return;
     }
     sock->deferred = acceptsock;
+    release_object ( sock );
+}
+
+DECL_HANDLER(packet_type)
+{
+    struct sock *sock;
+
+    sock=(struct sock*)get_handle_obj( current->process,req->handle,
+                                       GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,&sock_ops );
+    if(!sock)
+    {
+        return;
+    }
+
+    if(req->flags == IPX_GET_PTYPE)
+	reply->ptype = sock->ptype;
+    else
+	sock->ptype = req->value;
+
     release_object ( sock );
 }
Index: server/trace.c
===================================================================
RCS file: /home/wine/wine/server/trace.c,v
retrieving revision 1.173
diff -u -r1.173 trace.c
--- server/trace.c	11 Jul 2003 21:55:58 -0000	1.173
+++ server/trace.c	12 Jul 2003 13:12:26 -0000
@@ -2486,6 +2486,18 @@
     fprintf( stderr, " seqno=%08x", req->seqno );
 }
 
+static void dump_packet_type_request( const struct packet_type_request *req )
+{
+    fprintf( stderr, " handle=%p,", req->handle );
+    fprintf( stderr, " flags=%08x,", req->flags );
+    fprintf( stderr, " value=%d", req->value );
+}
+
+static void dump_packet_type_reply( const struct packet_type_reply *req )
+{
+    fprintf( stderr, " ptype=%d", req->ptype );
+}
+
 static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
     (dump_func)dump_new_process_request,
     (dump_func)dump_get_new_process_info_request,
@@ -2663,6 +2675,7 @@
     (dump_func)dump_finish_hook_chain_request,
     (dump_func)dump_get_next_hook_request,
     (dump_func)dump_set_clipboard_info_request,
+    (dump_func)dump_packet_type_request,
 };
 
 static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
@@ -2842,6 +2855,7 @@
     (dump_func)0,
     (dump_func)dump_get_next_hook_reply,
     (dump_func)dump_set_clipboard_info_reply,
+    (dump_func)dump_packet_type_reply,
 };
 
 static const char * const req_names[REQ_NB_REQUESTS] = {
@@ -3021,6 +3035,7 @@
     "finish_hook_chain",
     "get_next_hook",
     "set_clipboard_info",
+    "packet_type",
 };
 
 /* ### make_requests end ### */

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux