Updated SIO_ADDRESS_LIST_CHANGE patches.

This commit is contained in:
Erich E. Hoover 2014-05-06 15:43:52 -06:00
parent 94813ecf3c
commit bfb7d535af
4 changed files with 120 additions and 81 deletions

4
debian/changelog vendored
View File

@ -1,3 +1,7 @@
wine-compholio (1.7.19) unstable; urgency=low
* Updated SIO_ADDRESS_LIST_CHANGE patches.
-- Erich E. Hoover <erich.e.hoover@gmail.com> Tue, 06 May 2014 15:42:32 -0600
wine-compholio (1.7.18-1) unstable; urgency=low
* Fix some issues on BSD systems.
* Add additional patches to silence a few FIXMEs.

View File

@ -1,15 +1,15 @@
From 69e77bd226057f486d1c076ccbebb963d3b750ee Mon Sep 17 00:00:00 2001
From 864781654bfbb059a351fdcda6773e2857019278 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 3 Apr 2014 09:25:48 -0600
Date: Tue, 6 May 2014 08:39:18 -0600
Subject: server: Add socket-side support for the interface change
notification object.
---
server/sock.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 91 insertions(+), 1 deletion(-)
server/sock.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 86 insertions(+), 1 deletion(-)
diff --git a/server/sock.c b/server/sock.c
index 05fc38b..20d022f 100644
index 3eb1bdf..ad20a69 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -106,12 +106,18 @@ struct sock
@ -22,26 +22,26 @@ index 05fc38b..20d022f 100644
};
static void sock_dump( struct object *obj, int verbose );
+static int sock_add_ifchange( struct sock *sock, const async_data_t *async_data );
+static void sock_add_ifchange( struct sock *sock, const async_data_t *async_data );
static int sock_signaled( struct object *obj, struct wait_queue_entry *entry );
static struct fd *sock_get_fd( struct object *obj );
static void sock_destroy( struct object *obj );
+static int sock_get_ifchange_q( struct sock *sock, struct async_queue **async_queue );
+static struct async_queue *sock_get_ifchange_q( struct sock *sock );
+static void sock_destroy_ifchange_q( struct sock *sock );
static int sock_get_poll_events( struct fd *fd );
static void sock_poll_event( struct fd *fd, int event );
@@ -539,7 +545,8 @@ obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *a
@@ -529,7 +535,8 @@ obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *a
switch(code)
{
case WS_SIO_ADDRESS_LIST_CHANGE:
- /* intentional fallthrough, not yet supported */
+ error = sock_add_ifchange( sock, async_data );
+ break;
+ sock_add_ifchange( sock, async_data );
+ return 0;
default:
error = STATUS_NOT_SUPPORTED;
break;
@@ -625,6 +632,7 @@ static void sock_destroy( struct object *obj )
set_error( STATUS_NOT_SUPPORTED );
return 0;
@@ -610,6 +617,7 @@ static void sock_destroy( struct object *obj )
free_async_queue( sock->read_q );
free_async_queue( sock->write_q );
@ -49,7 +49,7 @@ index 05fc38b..20d022f 100644
if (sock->event) release_object( sock->event );
if (sock->fd)
{
@@ -651,6 +659,8 @@ static void init_sock(struct sock *sock)
@@ -636,6 +644,8 @@ static void init_sock(struct sock *sock)
sock->deferred = NULL;
sock->read_q = NULL;
sock->write_q = NULL;
@ -58,37 +58,37 @@ index 05fc38b..20d022f 100644
memset( sock->errors, 0, sizeof(sock->errors) );
}
@@ -939,6 +949,86 @@ static void sock_set_error(void)
@@ -924,6 +934,81 @@ static void sock_set_error(void)
set_error( sock_get_ntstatus( errno ) );
}
+/* add interface change notification to a socket */
+static int sock_add_ifchange( struct sock *sock, const async_data_t *async_data )
+static void sock_add_ifchange( struct sock *sock, const async_data_t *async_data )
+{
+ struct async_queue *ifchange_q = NULL;
+ struct async *async;
+ int error;
+
+ error = sock_get_ifchange_q( sock, &ifchange_q );
+ if (error != STATUS_PENDING)
+ return error;
+ if (!(ifchange_q = sock_get_ifchange_q( sock )))
+ return;
+
+ if (!(async = create_async( current, ifchange_q, async_data )))
+ {
+ if (!async_queued( ifchange_q ))
+ sock_destroy_ifchange_q( sock );
+
+ return STATUS_NO_MEMORY;
+ set_error( STATUS_NO_MEMORY );
+ return;
+ }
+
+ release_object( async );
+ return error;
+ set_error( STATUS_PENDING );
+}
+
+/* stub ifchange object */
+static int get_ifchange( struct object **obj )
+static struct object *get_ifchange( void )
+{
+ return STATUS_NOT_SUPPORTED;
+ set_error( STATUS_NOT_SUPPORTED );
+ return NULL;
+}
+
+/* stub ifchange add socket to list */
@ -97,21 +97,16 @@ index 05fc38b..20d022f 100644
+}
+
+/* create a new ifchange queue for a specific socket or, if one already exists, reuse the existing one */
+static int sock_get_ifchange_q( struct sock *sock, struct async_queue **async_queue )
+static struct async_queue *sock_get_ifchange_q( struct sock *sock )
+{
+ struct object *ifchange = NULL;
+ struct fd *fd;
+ int error;
+
+ if (sock->ifchange_q) /* reuse existing ifchange_q for this socket */
+ {
+ *async_queue = sock->ifchange_q;
+ return STATUS_PENDING;
+ }
+ return sock->ifchange_q;
+
+ error = get_ifchange( &ifchange );
+ if (error != STATUS_PENDING)
+ return error;
+ if (!(ifchange = get_ifchange()))
+ return NULL;
+
+ /* create the ifchange notification queue */
+ fd = ifchange->ops->get_fd( ifchange );
@ -120,14 +115,14 @@ index 05fc38b..20d022f 100644
+ if (!sock->ifchange_q)
+ {
+ release_object( ifchange );
+ return STATUS_NO_MEMORY;
+ set_error( STATUS_NO_MEMORY );
+ return NULL;
+ }
+
+ /* add the socket to the ifchange notification list */
+ ifchange_add_sock( ifchange, sock );
+ sock->ifchange_obj = ifchange;
+ *async_queue = sock->ifchange_q;
+ return error;
+ return sock->ifchange_q;
+}
+
+/* destroy an existing ifchange queue for a specific socket */

View File

@ -1,14 +1,14 @@
From 45dfbd2ddb5ca2c64fcfd56392be9c55513abc4b Mon Sep 17 00:00:00 2001
From c93a05ca0114b76c542f251de60b8c009e4a72b0 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 3 Apr 2014 09:23:02 -0600
Subject: server: Add delayed processing for socket-specific ioctl().
Date: Tue, 6 May 2014 08:44:59 -0600
Subject: server: Add blocked support for SIO_ADDRESS_LIST_CHANGE ioctl().
---
server/event.c | 13 +++++++++++++
server/named_pipe.c | 13 -------------
server/object.h | 1 +
server/sock.c | 19 +++++++++++++++++--
4 files changed, 31 insertions(+), 15 deletions(-)
server/sock.c | 26 ++++++++++++++++++++------
4 files changed, 34 insertions(+), 19 deletions(-)
diff --git a/server/event.c b/server/event.c
index 4d3c562..0daa5b2 100644
@ -71,44 +71,78 @@ index bb3ff21..bad162f 100644
extern struct keyed_event *get_keyed_event_obj( struct process *process, obj_handle_t handle, unsigned int access );
extern void pulse_event( struct event *event );
diff --git a/server/sock.c b/server/sock.c
index 3eb1bdf..05fc38b 100644
index ad20a69..a8a5ac3 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -523,17 +523,32 @@ obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *a
@@ -112,7 +112,7 @@ struct sock
};
static void sock_dump( struct object *obj, int verbose );
-static void sock_add_ifchange( struct sock *sock, const async_data_t *async_data );
+static int sock_add_ifchange( struct sock *sock, const async_data_t *async_data );
static int sock_signaled( struct object *obj, struct wait_queue_entry *entry );
static struct fd *sock_get_fd( struct object *obj );
static void sock_destroy( struct object *obj );
@@ -529,14 +529,27 @@ obj_handle_t sock_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *a
int blocking, const void *data, data_size_t size )
{
struct sock *sock = get_fd_user( fd );
+ obj_handle_t wait_handle = 0;
+ async_data_t new_data;
+ int error;
assert( sock->obj.ops == &sock_ops );
+ if (blocking)
+ {
+ if (!(wait_handle = alloc_wait_event( current->process ))) return 0;
+ new_data = *async_data;
+ new_data.event = wait_handle;
+ async_data = &new_data;
+ }
switch(code)
{
case WS_SIO_ADDRESS_LIST_CHANGE:
/* intentional fallthrough, not yet supported */
default:
- set_error( STATUS_NOT_SUPPORTED );
- sock_add_ifchange( sock, async_data );
- return 0;
+ error = STATUS_NOT_SUPPORTED;
+ break;
}
+ set_error( error );
+ if (error == STATUS_PENDING)
+ if (blocking)
+ {
+ if (!(wait_handle = alloc_wait_event( current->process ))) return 0;
+ new_data = *async_data;
+ new_data.event = wait_handle;
+ async_data = &new_data;
+ }
+ if (!sock_add_ifchange( sock, async_data ) && wait_handle)
+ {
+ close_handle( current->process, wait_handle );
+ return 0;
+ }
+ return wait_handle;
+ close_handle( current->process, wait_handle );
+ return 0;
default:
set_error( STATUS_NOT_SUPPORTED );
return 0;
@@ -935,13 +948,13 @@ static void sock_set_error(void)
}
static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, int count )
/* add interface change notification to a socket */
-static void sock_add_ifchange( struct sock *sock, const async_data_t *async_data )
+static int sock_add_ifchange( struct sock *sock, const async_data_t *async_data )
{
struct async_queue *ifchange_q = NULL;
struct async *async;
if (!(ifchange_q = sock_get_ifchange_q( sock )))
- return;
+ return FALSE;
if (!(async = create_async( current, ifchange_q, async_data )))
{
@@ -949,11 +962,12 @@ static void sock_add_ifchange( struct sock *sock, const async_data_t *async_data
sock_destroy_ifchange_q( sock );
set_error( STATUS_NO_MEMORY );
- return;
+ return FALSE;
}
release_object( async );
set_error( STATUS_PENDING );
+ return TRUE;
}
/* stub ifchange object */
--
1.7.9.5

View File

@ -1,14 +1,14 @@
From 85d0475a493be336c340f25cab9895846e202f26 Mon Sep 17 00:00:00 2001
From 55c83dc866e2d0e2cdc15b976b6d818a03ef4b89 Mon Sep 17 00:00:00 2001
From: "Erich E. Hoover" <erich.e.hoover@gmail.com>
Date: Thu, 3 Apr 2014 09:26:34 -0600
Date: Tue, 6 May 2014 08:49:52 -0600
Subject: server: Implement the interface change notification object.
---
server/sock.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 198 insertions(+), 2 deletions(-)
server/sock.c | 206 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 203 insertions(+), 3 deletions(-)
diff --git a/server/sock.c b/server/sock.c
index 20d022f..82464f2 100644
index a8a5ac3..2af9acc 100644
--- a/server/sock.c
+++ b/server/sock.c
@@ -43,6 +43,10 @@
@ -22,11 +22,12 @@ index 20d022f..82464f2 100644
#include "ntstatus.h"
#define WIN32_NO_STATUS
@@ -972,15 +976,207 @@ static int sock_add_ifchange( struct sock *sock, const async_data_t *async_data
return error;
@@ -970,16 +974,212 @@ static int sock_add_ifchange( struct sock *sock, const async_data_t *async_data
return TRUE;
}
-/* stub ifchange object */
-static struct object *get_ifchange( void )
+#ifdef HAVE_LINUX_RTNETLINK_H
+
+/* only keep one ifchange object around, all sockets waiting for wakeups will look to it */
@ -162,7 +163,7 @@ index 20d022f..82464f2 100644
+}
+
+static void ifchange_reselect_async( struct fd *fd, struct async_queue *queue )
+{
{
+ /* do nothing, this object is about to disappear */
+}
+
@ -170,8 +171,8 @@ index 20d022f..82464f2 100644
+
+/* we only need one of these interface notification objects, all of the sockets dependent upon
+ * it will wake up when a notification event occurs */
static int get_ifchange( struct object **obj )
{
+ static struct object *get_ifchange( void )
+ {
+#ifdef HAVE_LINUX_RTNETLINK_H
+ struct ifchange *ifchange;
+ struct sockaddr_nl addr;
@ -180,14 +181,16 @@ index 20d022f..82464f2 100644
+ if (ifchange_object)
+ {
+ /* increment the refcount for each socket that uses the ifchange object */
+ *obj = grab_object( ifchange_object );
+ return STATUS_PENDING;
+ return grab_object( ifchange_object );
+ }
+
+ /* create the socket we need for processing interface change notifications */
+ unix_fd = socket( PF_NETLINK, SOCK_RAW, NETLINK_ROUTE );
+ if (unix_fd == -1)
+ return sock_get_ntstatus( errno );
+ {
+ sock_set_error();
+ return NULL;
+ }
+ fcntl( unix_fd, F_SETFL, O_NONBLOCK ); /* make socket nonblocking */
+ memset( &addr, 0, sizeof(addr) );
+ addr.nl_family = AF_NETLINK;
@ -196,27 +199,30 @@ index 20d022f..82464f2 100644
+ if (bind( unix_fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1)
+ {
+ close( unix_fd );
+ return sock_get_ntstatus( errno );
+ sock_set_error();
+ return NULL;
+ }
+ if (!(ifchange = alloc_object( &ifchange_ops )))
+ {
+ close( unix_fd );
+ return STATUS_NO_MEMORY;
+ set_error( STATUS_NO_MEMORY );
+ return NULL;
+ }
+ list_init( &ifchange->sockets );
+ if (!(ifchange->fd = create_anonymous_fd( &ifchange_fd_ops, unix_fd, &ifchange->obj, 0 )))
+ {
+ release_object( ifchange );
+ return STATUS_NO_MEMORY;
+ set_error( STATUS_NO_MEMORY );
+ return NULL;
+ }
+ set_fd_events( ifchange->fd, POLLIN ); /* enable read wakeup on the file descriptor */
+
+ /* the ifchange object is now successfully configured */
+ ifchange_object = &ifchange->obj;
+ *obj = &ifchange->obj;
+ return STATUS_PENDING;
+ return &ifchange->obj;
+#else
return STATUS_NOT_SUPPORTED;
set_error( STATUS_NOT_SUPPORTED );
return NULL;
+#endif
}