server: Infrastructure to return a wait handle for blocking ioctls.

This commit is contained in:
Alexandre Julliard 2007-05-03 17:43:18 +02:00
parent 017480d4e2
commit fd59e158a7
7 changed files with 45 additions and 28 deletions

View File

@ -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;
}

View File

@ -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 */

View File

@ -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 );
}
}

View File

@ -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 );

View File

@ -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 );
}
}

View File

@ -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

View File

@ -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 );
}