server: Allow completion object to be attached to an fd object.
This commit is contained in:
parent
f6ebeba5a2
commit
d1a8155882
|
@ -1658,6 +1658,23 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FileCompletionInformation:
|
||||||
|
if (len >= sizeof(FILE_COMPLETION_INFORMATION))
|
||||||
|
{
|
||||||
|
FILE_COMPLETION_INFORMATION *info = (FILE_COMPLETION_INFORMATION *)ptr;
|
||||||
|
|
||||||
|
SERVER_START_REQ( set_completion_info )
|
||||||
|
{
|
||||||
|
req->handle = handle;
|
||||||
|
req->chandle = info->CompletionPort;
|
||||||
|
req->ckey = info->CompletionKey;
|
||||||
|
io->u.Status = wine_server_call( req );
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
} else
|
||||||
|
io->u.Status = STATUS_INVALID_PARAMETER_3;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
FIXME("Unsupported class (%d)\n", class);
|
FIXME("Unsupported class (%d)\n", class);
|
||||||
io->u.Status = STATUS_NOT_IMPLEMENTED;
|
io->u.Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
|
|
@ -4156,6 +4156,20 @@ struct query_completion_reply
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct set_completion_info_request
|
||||||
|
{
|
||||||
|
struct request_header __header;
|
||||||
|
obj_handle_t handle;
|
||||||
|
obj_handle_t chandle;
|
||||||
|
unsigned long ckey;
|
||||||
|
};
|
||||||
|
struct set_completion_info_reply
|
||||||
|
{
|
||||||
|
struct reply_header __header;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
enum request
|
enum request
|
||||||
{
|
{
|
||||||
REQ_new_process,
|
REQ_new_process,
|
||||||
|
@ -4383,6 +4397,7 @@ enum request
|
||||||
REQ_add_completion,
|
REQ_add_completion,
|
||||||
REQ_remove_completion,
|
REQ_remove_completion,
|
||||||
REQ_query_completion,
|
REQ_query_completion,
|
||||||
|
REQ_set_completion_info,
|
||||||
REQ_NB_REQUESTS
|
REQ_NB_REQUESTS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4615,6 +4630,7 @@ union generic_request
|
||||||
struct add_completion_request add_completion_request;
|
struct add_completion_request add_completion_request;
|
||||||
struct remove_completion_request remove_completion_request;
|
struct remove_completion_request remove_completion_request;
|
||||||
struct query_completion_request query_completion_request;
|
struct query_completion_request query_completion_request;
|
||||||
|
struct set_completion_info_request set_completion_info_request;
|
||||||
};
|
};
|
||||||
union generic_reply
|
union generic_reply
|
||||||
{
|
{
|
||||||
|
@ -4845,8 +4861,9 @@ union generic_reply
|
||||||
struct add_completion_reply add_completion_reply;
|
struct add_completion_reply add_completion_reply;
|
||||||
struct remove_completion_reply remove_completion_reply;
|
struct remove_completion_reply remove_completion_reply;
|
||||||
struct query_completion_reply query_completion_reply;
|
struct query_completion_reply query_completion_reply;
|
||||||
|
struct set_completion_info_reply set_completion_info_reply;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 314
|
#define SERVER_PROTOCOL_VERSION 315
|
||||||
|
|
||||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
|
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
|
#include "file.h"
|
||||||
#include "handle.h"
|
#include "handle.h"
|
||||||
#include "request.h"
|
#include "request.h"
|
||||||
|
|
||||||
|
@ -124,7 +125,7 @@ static struct completion *create_completion( struct directory *root, const struc
|
||||||
return completion;
|
return completion;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct completion *get_completion_obj( struct process *process, obj_handle_t handle, unsigned int access )
|
struct completion *get_completion_obj( struct process *process, obj_handle_t handle, unsigned int access )
|
||||||
{
|
{
|
||||||
return (struct completion *) get_handle_obj( process, handle, access, &completion_ops );
|
return (struct completion *) get_handle_obj( process, handle, access, &completion_ops );
|
||||||
}
|
}
|
||||||
|
|
22
server/fd.c
22
server/fd.c
|
@ -180,6 +180,8 @@ struct fd
|
||||||
struct async_queue *read_q; /* async readers of this fd */
|
struct async_queue *read_q; /* async readers of this fd */
|
||||||
struct async_queue *write_q; /* async writers of this fd */
|
struct async_queue *write_q; /* async writers of this fd */
|
||||||
struct async_queue *wait_q; /* other async waiters of this fd */
|
struct async_queue *wait_q; /* other async waiters of this fd */
|
||||||
|
struct completion *completion; /* completion object attached to this fd */
|
||||||
|
unsigned long comp_key; /* completion key to set in completion events */
|
||||||
};
|
};
|
||||||
|
|
||||||
static void fd_dump( struct object *obj, int verbose );
|
static void fd_dump( struct object *obj, int verbose );
|
||||||
|
@ -1329,6 +1331,7 @@ static void fd_destroy( struct object *obj )
|
||||||
free_async_queue( fd->write_q );
|
free_async_queue( fd->write_q );
|
||||||
free_async_queue( fd->wait_q );
|
free_async_queue( fd->wait_q );
|
||||||
|
|
||||||
|
if (fd->completion) release_object( fd->completion );
|
||||||
remove_fd_locks( fd );
|
remove_fd_locks( fd );
|
||||||
list_remove( &fd->inode_entry );
|
list_remove( &fd->inode_entry );
|
||||||
if (fd->poll_index != -1) remove_poll_user( fd, fd->poll_index );
|
if (fd->poll_index != -1) remove_poll_user( fd, fd->poll_index );
|
||||||
|
@ -1406,6 +1409,7 @@ static struct fd *alloc_fd_object(void)
|
||||||
fd->read_q = NULL;
|
fd->read_q = NULL;
|
||||||
fd->write_q = NULL;
|
fd->write_q = NULL;
|
||||||
fd->wait_q = NULL;
|
fd->wait_q = NULL;
|
||||||
|
fd->completion = NULL;
|
||||||
list_init( &fd->inode_entry );
|
list_init( &fd->inode_entry );
|
||||||
list_init( &fd->locks );
|
list_init( &fd->locks );
|
||||||
|
|
||||||
|
@ -1438,6 +1442,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
|
||||||
fd->read_q = NULL;
|
fd->read_q = NULL;
|
||||||
fd->write_q = NULL;
|
fd->write_q = NULL;
|
||||||
fd->wait_q = NULL;
|
fd->wait_q = NULL;
|
||||||
|
fd->completion = NULL;
|
||||||
fd->no_fd_status = STATUS_BAD_DEVICE_TYPE;
|
fd->no_fd_status = STATUS_BAD_DEVICE_TYPE;
|
||||||
list_init( &fd->inode_entry );
|
list_init( &fd->inode_entry );
|
||||||
list_init( &fd->locks );
|
list_init( &fd->locks );
|
||||||
|
@ -2009,3 +2014,20 @@ DECL_HANDLER(cancel_async)
|
||||||
release_object( fd );
|
release_object( fd );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* attach completion object to a fd */
|
||||||
|
DECL_HANDLER(set_completion_info)
|
||||||
|
{
|
||||||
|
struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
|
||||||
|
|
||||||
|
if (fd)
|
||||||
|
{
|
||||||
|
if (!fd->completion)
|
||||||
|
{
|
||||||
|
fd->completion = get_completion_obj( current->process, req->chandle, IO_COMPLETION_MODIFY_STATE );
|
||||||
|
fd->comp_key = req->ckey;
|
||||||
|
}
|
||||||
|
else set_error( STATUS_INVALID_PARAMETER );
|
||||||
|
release_object( fd );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
struct fd;
|
struct fd;
|
||||||
struct async_queue;
|
struct async_queue;
|
||||||
|
struct completion;
|
||||||
|
|
||||||
typedef unsigned __int64 file_pos_t;
|
typedef unsigned __int64 file_pos_t;
|
||||||
|
|
||||||
|
@ -120,6 +121,10 @@ extern void do_change_notify( int unix_fd );
|
||||||
extern void sigio_callback(void);
|
extern void sigio_callback(void);
|
||||||
extern struct object *create_dir_obj( struct fd *fd );
|
extern struct object *create_dir_obj( struct fd *fd );
|
||||||
|
|
||||||
|
/* completion */
|
||||||
|
|
||||||
|
struct completion *get_completion_obj( struct process *process, obj_handle_t handle, unsigned int access );
|
||||||
|
|
||||||
/* serial port functions */
|
/* serial port functions */
|
||||||
|
|
||||||
extern int is_serial_fd( struct fd *fd );
|
extern int is_serial_fd( struct fd *fd );
|
||||||
|
|
|
@ -2983,3 +2983,11 @@ enum message_type
|
||||||
@REPLY
|
@REPLY
|
||||||
unsigned int depth; /* completion queue depth */
|
unsigned int depth; /* completion queue depth */
|
||||||
@END
|
@END
|
||||||
|
|
||||||
|
|
||||||
|
/* associate object with completion port */
|
||||||
|
@REQ(set_completion_info)
|
||||||
|
obj_handle_t handle; /* object handle */
|
||||||
|
obj_handle_t chandle; /* port handle */
|
||||||
|
unsigned long ckey; /* completion key */
|
||||||
|
@END
|
||||||
|
|
|
@ -335,6 +335,7 @@ DECL_HANDLER(open_completion);
|
||||||
DECL_HANDLER(add_completion);
|
DECL_HANDLER(add_completion);
|
||||||
DECL_HANDLER(remove_completion);
|
DECL_HANDLER(remove_completion);
|
||||||
DECL_HANDLER(query_completion);
|
DECL_HANDLER(query_completion);
|
||||||
|
DECL_HANDLER(set_completion_info);
|
||||||
|
|
||||||
#ifdef WANT_REQUEST_HANDLERS
|
#ifdef WANT_REQUEST_HANDLERS
|
||||||
|
|
||||||
|
@ -566,6 +567,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
||||||
(req_handler)req_add_completion,
|
(req_handler)req_add_completion,
|
||||||
(req_handler)req_remove_completion,
|
(req_handler)req_remove_completion,
|
||||||
(req_handler)req_query_completion,
|
(req_handler)req_query_completion,
|
||||||
|
(req_handler)req_set_completion_info,
|
||||||
};
|
};
|
||||||
#endif /* WANT_REQUEST_HANDLERS */
|
#endif /* WANT_REQUEST_HANDLERS */
|
||||||
|
|
||||||
|
|
|
@ -3628,6 +3628,13 @@ static void dump_query_completion_reply( const struct query_completion_reply *re
|
||||||
fprintf( stderr, " depth=%08x", req->depth );
|
fprintf( stderr, " depth=%08x", req->depth );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dump_set_completion_info_request( const struct set_completion_info_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle=%p,", req->handle );
|
||||||
|
fprintf( stderr, " chandle=%p,", req->chandle );
|
||||||
|
fprintf( stderr, " ckey=%lx", req->ckey );
|
||||||
|
}
|
||||||
|
|
||||||
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)dump_new_process_request,
|
(dump_func)dump_new_process_request,
|
||||||
(dump_func)dump_get_new_process_info_request,
|
(dump_func)dump_get_new_process_info_request,
|
||||||
|
@ -3854,6 +3861,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)dump_add_completion_request,
|
(dump_func)dump_add_completion_request,
|
||||||
(dump_func)dump_remove_completion_request,
|
(dump_func)dump_remove_completion_request,
|
||||||
(dump_func)dump_query_completion_request,
|
(dump_func)dump_query_completion_request,
|
||||||
|
(dump_func)dump_set_completion_info_request,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
||||||
|
@ -4082,6 +4090,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)0,
|
(dump_func)0,
|
||||||
(dump_func)dump_remove_completion_reply,
|
(dump_func)dump_remove_completion_reply,
|
||||||
(dump_func)dump_query_completion_reply,
|
(dump_func)dump_query_completion_reply,
|
||||||
|
(dump_func)0,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const req_names[REQ_NB_REQUESTS] = {
|
static const char * const req_names[REQ_NB_REQUESTS] = {
|
||||||
|
@ -4310,6 +4319,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
||||||
"add_completion",
|
"add_completion",
|
||||||
"remove_completion",
|
"remove_completion",
|
||||||
"query_completion",
|
"query_completion",
|
||||||
|
"set_completion_info",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct
|
static const struct
|
||||||
|
|
Loading…
Reference in New Issue