server: Infrastructure to return a wait handle for blocking ioctls.
This commit is contained in:
parent
017480d4e2
commit
fd59e158a7
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
12
server/fd.c
12
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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue