Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 14 +++++------ server/async.c | 39 ++++++++++++++++++------------ 2 files changed, 30 insertions(+), 23 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index f0e8021aa17..fb91783779b 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -729,7 +729,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) todo_wine ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status); todo_wine ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information); ret = WaitForSingleObject(event, 0); - todo_wine ok(ret == WAIT_TIMEOUT, "got %d\n", ret); + ok(ret == WAIT_TIMEOUT, "got %d\n", ret); } else { @@ -753,7 +753,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) ret = NtRemoveIoCompletion(port, &key, &value, &io, &zero); if (!params->pending && NT_ERROR(params->iosb_status)) { - todo_wine ok(ret == STATUS_TIMEOUT, "got %#x\n", ret); + ok(ret == STATUS_TIMEOUT, "got %#x\n", ret); } else { @@ -781,7 +781,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) todo_wine ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status); todo_wine ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information); ret = WaitForSingleObject(event, 0); - todo_wine ok(ret == WAIT_TIMEOUT, "got %d\n", ret); + ok(ret == WAIT_TIMEOUT, "got %d\n", ret); } else { @@ -813,7 +813,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) todo_wine ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status); todo_wine ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information); ret = WaitForSingleObject(file, 0); - todo_wine ok(ret == WAIT_TIMEOUT, "got %d\n", ret); + ok(ret == WAIT_TIMEOUT, "got %d\n", ret); } else { @@ -849,7 +849,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) todo_wine ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status); todo_wine ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information); ret = WaitForSingleObject(event, 0); - todo_wine ok(ret == WAIT_TIMEOUT, "got %d\n", ret); + ok(ret == WAIT_TIMEOUT, "got %d\n", ret); } else { @@ -932,8 +932,8 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) ret = SleepEx(0, TRUE); if (!params->pending && NT_ERROR(params->iosb_status)) { - todo_wine ok(!ret, "got %d\n", ret); - todo_wine ok(!got_return_status_apc, "got %u APC calls\n", got_return_status_apc); + ok(!ret, "got %d\n", ret); + ok(!got_return_status_apc, "got %u APC calls\n", got_return_status_apc); } else { diff --git a/server/async.c b/server/async.c index df30ae3c7da..7cffd24a18b 100644 --- a/server/async.c +++ b/server/async.c @@ -465,25 +465,32 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota async->terminated = 1; if (async->iosb) async->iosb->status = status;
- if (async->data.apc) + /* don't signal completion if the async failed synchronously + * this can happen if the initial status was unknown (i.e. for device files) + * note that we check the IOSB status here, not the initial status */ + if (async->pending || !NT_ERROR( status )) { - apc_call_t data; - memset( &data, 0, sizeof(data) ); - data.type = APC_USER; - data.user.func = async->data.apc; - data.user.args[0] = async->data.apc_context; - data.user.args[1] = async->data.iosb; - data.user.args[2] = 0; - thread_queue_apc( NULL, async->thread, NULL, &data ); - } - else if (async->data.apc_context && (async->pending || - !(async->comp_flags & FILE_SKIP_COMPLETION_PORT_ON_SUCCESS))) - { - add_async_completion( async, async->data.apc_context, status, total ); + if (async->data.apc) + { + apc_call_t data; + memset( &data, 0, sizeof(data) ); + data.type = APC_USER; + data.user.func = async->data.apc; + data.user.args[0] = async->data.apc_context; + data.user.args[1] = async->data.iosb; + data.user.args[2] = 0; + thread_queue_apc( NULL, async->thread, NULL, &data ); + } + else if (async->data.apc_context && (async->pending || + !(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 ); }
- if (async->event) set_event( async->event ); - else if (async->fd) set_fd_signaled( async->fd, 1 ); if (!async->signaled) { async->signaled = 1;