server: Support FILE_SKIP_COMPLETION_PORT_ON_SUCCESS on server-side asyncs.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=38960
Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Sebastian Lackner 2018-10-25 14:56:08 +02:00 committed by Alexandre Julliard
parent 4be482bc82
commit c0996553a1
4 changed files with 13 additions and 12 deletions

View File

@ -1287,7 +1287,6 @@ static void test_completion(void)
ret = WriteFile(client, buf, sizeof(buf), &num_bytes, &ov);
ok(ret, "WriteFile failed, error %u\n", GetLastError());
ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
todo_wine
test_no_queued_completion(port);
ret = WriteFile(pipe, buf, sizeof(buf), &num_bytes, &ov);
@ -1301,14 +1300,12 @@ static void test_completion(void)
if(status == STATUS_PENDING) /* win8+ */
test_queued_completion(port, &io, STATUS_BUFFER_OVERFLOW, 1);
else
todo_wine
test_no_queued_completion(port);
status = NtReadFile(client, NULL, NULL, &io, &io, read_buf, sizeof(read_buf), NULL, NULL);
ok(status == STATUS_SUCCESS, "status = %x\n", status);
ok(io.Status == STATUS_SUCCESS, "Status = %x\n", io.Status);
ok(io.Information == sizeof(buf)-1, "Information = %lu\n", io.Information);
todo_wine
test_no_queued_completion(port);
status = NtFsControlFile(client, NULL, NULL, &io, &io, FSCTL_PIPE_PEEK,
@ -1317,7 +1314,6 @@ static void test_completion(void)
if(status == STATUS_PENDING) /* win8+ */
test_queued_completion(port, &io, STATUS_SUCCESS, FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data));
else
todo_wine
test_no_queued_completion(port);
memset(&io, 0xcc, sizeof(io));
@ -1339,7 +1335,6 @@ static void test_completion(void)
if(status == STATUS_PENDING) /* win8+ */
test_queued_completion(port, &io, STATUS_BUFFER_OVERFLOW, sizeof(peek_buf));
else
todo_wine
test_no_queued_completion(port);
CloseHandle(ov.hEvent);

View File

@ -53,6 +53,7 @@ struct async
int direct_result; /* a flag if we're passing result directly from request instead of APC */
struct completion *completion; /* completion associated with fd */
apc_param_t comp_key; /* completion key associated with fd */
unsigned int comp_flags; /* completion flags */
};
static void async_dump( struct object *obj, int verbose );
@ -239,6 +240,7 @@ struct async *create_async( struct fd *fd, struct thread *thread, const async_da
async->wait_handle = 0;
async->direct_result = 0;
async->completion = fd_get_completion( fd, &async->comp_key );
async->comp_flags = 0;
if (iosb) async->iosb = (struct iosb *)grab_object( iosb );
else async->iosb = NULL;
@ -258,7 +260,7 @@ struct async *create_async( struct fd *fd, struct thread *thread, const async_da
/* create an async associated with iosb for async-based requests
* returned async must be passed to async_handoff */
struct async *create_request_async( struct fd *fd, const async_data_t *data )
struct async *create_request_async( struct fd *fd, unsigned int comp_flags, const async_data_t *data )
{
struct async *async;
struct iosb *iosb;
@ -276,6 +278,7 @@ struct async *create_request_async( struct fd *fd, const async_data_t *data )
return NULL;
}
async->direct_result = 1;
async->comp_flags = comp_flags;
}
return async;
}
@ -377,8 +380,11 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
data.user.args[2] = 0;
thread_queue_apc( NULL, async->thread, NULL, &data );
}
else if (async->data.apc_context)
else if (async->data.apc_context && (!async->direct_result ||
!(async->comp_flags & FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)))
{
add_async_completion( async, async->data.apc_context, status, total );
}
if (async->event) set_event( async->event );
else if (async->fd) set_fd_signaled( async->fd, 1 );

View File

@ -2414,7 +2414,7 @@ DECL_HANDLER(flush)
if (!fd) return;
if ((async = create_request_async( fd, &req->async )))
if ((async = create_request_async( fd, fd->comp_flags, &req->async )))
{
reply->event = async_handoff( async, fd->fd_ops->flush( fd, async ), NULL );
release_object( async );
@ -2513,7 +2513,7 @@ DECL_HANDLER(read)
if (!fd) return;
if ((async = create_request_async( fd, &req->async )))
if ((async = create_request_async( fd, fd->comp_flags, &req->async )))
{
reply->wait = async_handoff( async, fd->fd_ops->read( fd, async, req->pos ), NULL );
reply->options = fd->options;
@ -2530,7 +2530,7 @@ DECL_HANDLER(write)
if (!fd) return;
if ((async = create_request_async( fd, &req->async )))
if ((async = create_request_async( fd, fd->comp_flags, &req->async )))
{
reply->wait = async_handoff( async, fd->fd_ops->write( fd, async, req->pos ), &reply->size );
reply->options = fd->options;
@ -2548,7 +2548,7 @@ DECL_HANDLER(ioctl)
if (!fd) return;
if ((async = create_request_async( fd, &req->async )))
if ((async = create_request_async( fd, fd->comp_flags, &req->async )))
{
reply->wait = async_handoff( async, fd->fd_ops->ioctl( fd, req->code, async ), NULL );
reply->options = fd->options;

View File

@ -185,7 +185,7 @@ extern struct object *create_serial( struct fd *fd );
/* async I/O functions */
extern void free_async_queue( struct async_queue *queue );
extern struct async *create_async( struct fd *fd, struct thread *thread, const async_data_t *data, struct iosb *iosb );
extern struct async *create_request_async( struct fd *fd, const async_data_t *data );
extern struct async *create_request_async( struct fd *fd, unsigned int comp_flags, const async_data_t *data );
extern obj_handle_t async_handoff( struct async *async, int success, data_size_t *result );
extern void queue_async( struct async_queue *queue, struct async *async );
extern void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status );