Commit c0996553 authored by Sebastian Lackner's avatar Sebastian Lackner Committed by Alexandre Julliard

server: Support FILE_SKIP_COMPLETION_PORT_ON_SUCCESS on server-side asyncs.

parent 4be482bc
...@@ -1287,7 +1287,6 @@ static void test_completion(void) ...@@ -1287,7 +1287,6 @@ static void test_completion(void)
ret = WriteFile(client, buf, sizeof(buf), &num_bytes, &ov); ret = WriteFile(client, buf, sizeof(buf), &num_bytes, &ov);
ok(ret, "WriteFile failed, error %u\n", GetLastError()); ok(ret, "WriteFile failed, error %u\n", GetLastError());
ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes); ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
todo_wine
test_no_queued_completion(port); test_no_queued_completion(port);
ret = WriteFile(pipe, buf, sizeof(buf), &num_bytes, &ov); ret = WriteFile(pipe, buf, sizeof(buf), &num_bytes, &ov);
...@@ -1301,14 +1300,12 @@ static void test_completion(void) ...@@ -1301,14 +1300,12 @@ static void test_completion(void)
if(status == STATUS_PENDING) /* win8+ */ if(status == STATUS_PENDING) /* win8+ */
test_queued_completion(port, &io, STATUS_BUFFER_OVERFLOW, 1); test_queued_completion(port, &io, STATUS_BUFFER_OVERFLOW, 1);
else else
todo_wine
test_no_queued_completion(port); test_no_queued_completion(port);
status = NtReadFile(client, NULL, NULL, &io, &io, read_buf, sizeof(read_buf), NULL, NULL); status = NtReadFile(client, NULL, NULL, &io, &io, read_buf, sizeof(read_buf), NULL, NULL);
ok(status == STATUS_SUCCESS, "status = %x\n", status); ok(status == STATUS_SUCCESS, "status = %x\n", status);
ok(io.Status == STATUS_SUCCESS, "Status = %x\n", io.Status); ok(io.Status == STATUS_SUCCESS, "Status = %x\n", io.Status);
ok(io.Information == sizeof(buf)-1, "Information = %lu\n", io.Information); ok(io.Information == sizeof(buf)-1, "Information = %lu\n", io.Information);
todo_wine
test_no_queued_completion(port); test_no_queued_completion(port);
status = NtFsControlFile(client, NULL, NULL, &io, &io, FSCTL_PIPE_PEEK, status = NtFsControlFile(client, NULL, NULL, &io, &io, FSCTL_PIPE_PEEK,
...@@ -1317,7 +1314,6 @@ static void test_completion(void) ...@@ -1317,7 +1314,6 @@ static void test_completion(void)
if(status == STATUS_PENDING) /* win8+ */ if(status == STATUS_PENDING) /* win8+ */
test_queued_completion(port, &io, STATUS_SUCCESS, FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data)); test_queued_completion(port, &io, STATUS_SUCCESS, FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data));
else else
todo_wine
test_no_queued_completion(port); test_no_queued_completion(port);
memset(&io, 0xcc, sizeof(io)); memset(&io, 0xcc, sizeof(io));
...@@ -1339,7 +1335,6 @@ static void test_completion(void) ...@@ -1339,7 +1335,6 @@ static void test_completion(void)
if(status == STATUS_PENDING) /* win8+ */ if(status == STATUS_PENDING) /* win8+ */
test_queued_completion(port, &io, STATUS_BUFFER_OVERFLOW, sizeof(peek_buf)); test_queued_completion(port, &io, STATUS_BUFFER_OVERFLOW, sizeof(peek_buf));
else else
todo_wine
test_no_queued_completion(port); test_no_queued_completion(port);
CloseHandle(ov.hEvent); CloseHandle(ov.hEvent);
......
...@@ -53,6 +53,7 @@ struct async ...@@ -53,6 +53,7 @@ struct async
int direct_result; /* a flag if we're passing result directly from request instead of APC */ int direct_result; /* a flag if we're passing result directly from request instead of APC */
struct completion *completion; /* completion associated with fd */ struct completion *completion; /* completion associated with fd */
apc_param_t comp_key; /* completion key 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 ); 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 ...@@ -239,6 +240,7 @@ struct async *create_async( struct fd *fd, struct thread *thread, const async_da
async->wait_handle = 0; async->wait_handle = 0;
async->direct_result = 0; async->direct_result = 0;
async->completion = fd_get_completion( fd, &async->comp_key ); async->completion = fd_get_completion( fd, &async->comp_key );
async->comp_flags = 0;
if (iosb) async->iosb = (struct iosb *)grab_object( iosb ); if (iosb) async->iosb = (struct iosb *)grab_object( iosb );
else async->iosb = NULL; else async->iosb = NULL;
...@@ -258,7 +260,7 @@ struct async *create_async( struct fd *fd, struct thread *thread, const async_da ...@@ -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 /* create an async associated with iosb for async-based requests
* returned async must be passed to async_handoff */ * 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 async *async;
struct iosb *iosb; struct iosb *iosb;
...@@ -276,6 +278,7 @@ struct async *create_request_async( struct fd *fd, const async_data_t *data ) ...@@ -276,6 +278,7 @@ struct async *create_request_async( struct fd *fd, const async_data_t *data )
return NULL; return NULL;
} }
async->direct_result = 1; async->direct_result = 1;
async->comp_flags = comp_flags;
} }
return async; return async;
} }
...@@ -377,8 +380,11 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota ...@@ -377,8 +380,11 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
data.user.args[2] = 0; data.user.args[2] = 0;
thread_queue_apc( NULL, async->thread, NULL, &data ); 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 ); add_async_completion( async, async->data.apc_context, status, total );
}
if (async->event) set_event( async->event ); if (async->event) set_event( async->event );
else if (async->fd) set_fd_signaled( async->fd, 1 ); else if (async->fd) set_fd_signaled( async->fd, 1 );
......
...@@ -2414,7 +2414,7 @@ DECL_HANDLER(flush) ...@@ -2414,7 +2414,7 @@ DECL_HANDLER(flush)
if (!fd) return; 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 ); reply->event = async_handoff( async, fd->fd_ops->flush( fd, async ), NULL );
release_object( async ); release_object( async );
...@@ -2513,7 +2513,7 @@ DECL_HANDLER(read) ...@@ -2513,7 +2513,7 @@ DECL_HANDLER(read)
if (!fd) return; 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->wait = async_handoff( async, fd->fd_ops->read( fd, async, req->pos ), NULL );
reply->options = fd->options; reply->options = fd->options;
...@@ -2530,7 +2530,7 @@ DECL_HANDLER(write) ...@@ -2530,7 +2530,7 @@ DECL_HANDLER(write)
if (!fd) return; 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->wait = async_handoff( async, fd->fd_ops->write( fd, async, req->pos ), &reply->size );
reply->options = fd->options; reply->options = fd->options;
...@@ -2548,7 +2548,7 @@ DECL_HANDLER(ioctl) ...@@ -2548,7 +2548,7 @@ DECL_HANDLER(ioctl)
if (!fd) return; 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->wait = async_handoff( async, fd->fd_ops->ioctl( fd, req->code, async ), NULL );
reply->options = fd->options; reply->options = fd->options;
......
...@@ -185,7 +185,7 @@ extern struct object *create_serial( struct fd *fd ); ...@@ -185,7 +185,7 @@ extern struct object *create_serial( struct fd *fd );
/* async I/O functions */ /* async I/O functions */
extern void free_async_queue( struct async_queue *queue ); 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_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 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 queue_async( struct async_queue *queue, struct async *async );
extern void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status ); extern void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment