diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index b1e22095249..cb09e964c50 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -933,6 +933,8 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event, PVOID out_buffer, ULONG out_size ) { NTSTATUS status; + HANDLE wait_handle; + ULONG options; SERVER_START_REQ( ioctl ) { @@ -948,6 +950,8 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event, wine_server_set_reply( req, out_buffer, out_size ); if (!(status = wine_server_call( req ))) io->Information = wine_server_reply_size( reply ); + wait_handle = reply->wait; + options = reply->options; } SERVER_END_REQ; @@ -955,6 +959,13 @@ static NTSTATUS server_ioctl_file( HANDLE handle, HANDLE event, FIXME("Unsupported ioctl %x (device=%x access=%x func=%x method=%x)\n", code, code >> 16, (code >> 14) & 3, (code >> 2) & 0xfff, code & 3); + if (wait_handle) + { + NtWaitForSingleObject( wait_handle, (options & FILE_SYNCHRONOUS_IO_ALERT), NULL ); + status = io->u.Status; + NtClose( wait_handle ); + } + return status; } diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 5a1c721aa97..7f6def05cd0 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2677,6 +2677,8 @@ struct ioctl_request struct ioctl_reply { struct reply_header __header; + obj_handle_t wait; + unsigned int options; /* VARARG(out_data,bytes); */ }; @@ -4626,6 +4628,6 @@ union generic_reply struct allocate_locally_unique_id_reply allocate_locally_unique_id_reply; }; -#define SERVER_PROTOCOL_VERSION 299 +#define SERVER_PROTOCOL_VERSION 300 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/fd.c b/server/fd.c index c4a0288dffd..11cf294a68c 100644 --- a/server/fd.c +++ b/server/fd.c @@ -1858,17 +1858,17 @@ static void unmount_device( struct fd *device_fd ) } /* 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 @@ DECL_HANDLER(ioctl) 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 df5988dd5cf..4884c72f7c6 100644 --- a/server/file.h +++ b/server/file.h @@ -40,8 +40,8 @@ struct fd_ops /* 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 void default_poll_event( struct fd *fd, int event ); 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 801b4d78180..9137bf6cfc0 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -139,8 +139,8 @@ static struct fd *pipe_server_get_fd( struct object *obj ); 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 @@ static struct object *named_pipe_device_open_file( struct object *obj, unsigned 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 @@ static enum server_fd_type pipe_client_get_fd_type( struct fd *fd ) 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 @@ static void pipe_server_ioctl( struct fd *fd, ioctl_code_t code, const async_dat set_error( STATUS_INVALID_HANDLE ); break; } - break; + return 0; case FSCTL_PIPE_DISCONNECT: switch(server->state) @@ -634,11 +634,10 @@ static void pipe_server_ioctl( struct fd *fd, ioctl_code_t code, const async_dat 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 @@ static struct object *named_pipe_open_file( struct object *obj, unsigned int acc 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 @@ static void named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, const asy 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 @@ static void named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, const asy 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 @@ static void named_pipe_device_ioctl( struct fd *fd, ioctl_code_t code, const asy 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 8e501191d5d..dd59acb9c61 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1973,6 +1973,8 @@ enum message_type 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 09af4419eeb..71e5cb05696 100644 --- a/server/trace.c +++ b/server/trace.c @@ -2418,6 +2418,8 @@ static void dump_ioctl_request( const struct ioctl_request *req ) 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 ); }