server: Infrastructure to return a wait handle for blocking ioctls.
diff --git a/server/fd.c b/server/fd.c
index c4a0288..11cf294 100644
--- a/server/fd.c
+++ b/server/fd.c
@@ -1858,17 +1858,17 @@
 }
 
 /* default ioctl() routine */
-void default_fd_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async,
-                       const void *data, data_size_t size )
+obj_handle_t default_fd_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async,
+                               const void *data, data_size_t size )
 {
     switch(code)
     {
     case FSCTL_DISMOUNT_VOLUME:
         unmount_device( fd );
-        break;
+        return 0;
     default:
         set_error( STATUS_NOT_SUPPORTED );
-        break;
+        return 0;
     }
 }
 
@@ -1956,7 +1956,9 @@
 
     if (fd)
     {
-        fd->fd_ops->ioctl( fd, req->code, &req->async, get_req_data(), get_req_data_size() );
+        reply->wait = fd->fd_ops->ioctl( fd, req->code, &req->async,
+                                         get_req_data(), get_req_data_size() );
+        reply->options = fd->options;
         release_object( fd );
     }
 }
diff --git a/server/file.h b/server/file.h
index df5988d..4884c72 100644
--- a/server/file.h
+++ b/server/file.h
@@ -40,8 +40,8 @@
     /* get file information */
     enum server_fd_type (*get_fd_type)(struct fd *fd);
     /* perform an ioctl on the file */
-    void (*ioctl)(struct fd *fd, ioctl_code_t code, const async_data_t *async,
-                  const void *data, data_size_t size);
+    obj_handle_t (*ioctl)(struct fd *fd, ioctl_code_t code, const async_data_t *async,
+                          const void *data, data_size_t size);
     /* queue an async operation */
     void (*queue_async)(struct fd *, const async_data_t *data, int type, int count);
     /* selected events for async i/o need an update */
@@ -79,8 +79,8 @@
 extern struct async *fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
 extern void fd_async_wake_up( struct fd *fd, int type, unsigned int status );
 extern void fd_reselect_async( struct fd *fd, struct async_queue *queue );
-extern void default_fd_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async,
-                              const void *data, data_size_t size );
+extern obj_handle_t default_fd_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async,
+                                      const void *data, data_size_t size );
 extern void default_fd_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
 extern void default_fd_reselect_async( struct fd *fd, struct async_queue *queue );
 extern void default_fd_cancel_async( struct fd *fd );
diff --git a/server/named_pipe.c b/server/named_pipe.c
index 801b4d7..9137bf6 100644
--- a/server/named_pipe.c
+++ b/server/named_pipe.c
@@ -139,8 +139,8 @@
 static void pipe_server_destroy( struct object *obj);
 static void pipe_server_flush( struct fd *fd, struct event **event );
 static enum server_fd_type pipe_server_get_fd_type( struct fd *fd );
-static void pipe_server_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async,
-                               const void *data, data_size_t size );
+static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async,
+                                       const void *data, data_size_t size );
 
 static const struct object_ops pipe_server_ops =
 {
@@ -215,8 +215,8 @@
                                                    unsigned int sharing, unsigned int options );
 static void named_pipe_device_destroy( struct object *obj );
 static enum server_fd_type named_pipe_device_get_fd_type( struct fd *fd );
-static void named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data,
-                                     const void *data, data_size_t size );
+static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data,
+                                             const void *data, data_size_t size );
 
 static const struct object_ops named_pipe_device_ops =
 {
@@ -570,8 +570,8 @@
     return FD_TYPE_PIPE;
 }
 
-static void pipe_server_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data,
-                               const void *data, data_size_t size )
+static obj_handle_t pipe_server_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data,
+                                       const void *data, data_size_t size )
 {
     struct pipe_server *server = get_fd_user( fd );
     struct async *async;
@@ -604,7 +604,7 @@
             set_error( STATUS_INVALID_HANDLE );
             break;
         }
-        break;
+        return 0;
 
     case FSCTL_PIPE_DISCONNECT:
         switch(server->state)
@@ -634,11 +634,10 @@
             set_error( STATUS_PIPE_DISCONNECTED );
             break;
         }
-        break;
+        return 0;
 
     default:
-        default_fd_ioctl( fd, code, async_data, data, size );
-        break;
+        return default_fd_ioctl( fd, code, async_data, data, size );
     }
 }
 
@@ -809,8 +808,8 @@
     return &client->obj;
 }
 
-static void named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data,
-                                     const void *data, data_size_t size )
+static obj_handle_t named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data,
+                                             const void *data, data_size_t size )
 {
     struct named_pipe_device *device = get_fd_user( fd );
 
@@ -827,14 +826,14 @@
                 size < FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name[buffer->NameLength/sizeof(WCHAR)]))
             {
                 set_error( STATUS_INVALID_PARAMETER );
-                break;
+                return 0;
             }
             name.str = buffer->Name;
             name.len = (buffer->NameLength / sizeof(WCHAR)) * sizeof(WCHAR);
             if (!(pipe = (struct named_pipe *)find_object( device->pipes, &name, OBJ_CASE_INSENSITIVE )))
             {
                 set_error( STATUS_PIPE_NOT_AVAILABLE );
-                break;
+                return 0;
             }
             if (!(server = find_available_server( pipe )))
             {
@@ -843,7 +842,7 @@
                 if (!pipe->waiters && !(pipe->waiters = create_async_queue( NULL )))
                 {
                     release_object( pipe );
-                    break;
+                    return 0;
                 }
 
                 if ((async = create_async( current, pipe->waiters, async_data )))
@@ -857,12 +856,11 @@
             else release_object( server );
 
             release_object( pipe );
-            break;
+            return 0;
         }
 
     default:
-        default_fd_ioctl( fd, code, async_data, data, size );
-        break;
+        return default_fd_ioctl( fd, code, async_data, data, size );
     }
 }
 
diff --git a/server/protocol.def b/server/protocol.def
index 8e50119..dd59acb 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1973,6 +1973,8 @@
     async_data_t   async;         /* async I/O parameters */
     VARARG(in_data,bytes);        /* ioctl input data */
 @REPLY
+    obj_handle_t   wait;          /* handle to wait on for blocking ioctl */
+    unsigned int   options;       /* device open options */
     VARARG(out_data,bytes);       /* ioctl output data */
 @END
 
diff --git a/server/trace.c b/server/trace.c
index 09af441..71e5cb0 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -2418,6 +2418,8 @@
 
 static void dump_ioctl_reply( const struct ioctl_reply *req )
 {
+    fprintf( stderr, " wait=%p,", req->wait );
+    fprintf( stderr, " options=%08x,", req->options );
     fprintf( stderr, " out_data=" );
     dump_varargs_bytes( cur_size );
 }