In particular, don't mark asyncs with output data as "alerted", i.e. restartable.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 48 +++++++++++++++++++----------- server/async.c | 17 +++++++---- 2 files changed, 41 insertions(+), 24 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 8ede0e55513..b85c0078620 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -663,11 +663,12 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) size = 0xdeadf00d; SetLastError(0xdeadf00d); ret = DeviceIoControl(device, ioctl, params, sizeof(*params), buffer, sizeof(buffer), &size, NULL); - todo_wine_if (NT_SUCCESS(expect_status) != NT_SUCCESS(params->iosb_status)) + todo_wine_if ((params->iosb_status != STATUS_PENDING && NT_SUCCESS(expect_status) != NT_SUCCESS(params->iosb_status)) + || (params->iosb_status == STATUS_PENDING && NT_SUCCESS(expect_status))) ok(ret == NT_SUCCESS(expect_status), "got %d\n", ret); if (NT_SUCCESS(expect_status)) { - todo_wine_if (!NT_SUCCESS(params->iosb_status)) + todo_wine_if (!NT_SUCCESS(params->iosb_status) || params->iosb_status == STATUS_PENDING) ok(GetLastError() == 0xdeadf00d, "got error %u\n", GetLastError()); } else @@ -679,7 +680,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) if (NT_ERROR(expect_status)) todo_wine ok(size == 0xdeadf00d, "got size %u\n", size); else if (!NT_ERROR(params->iosb_status)) - ok(size == 3, "got size %u\n", size); + todo_wine_if (params->iosb_status == STATUS_PENDING) ok(size == 3, "got size %u\n", size); /* size is garbage if !NT_ERROR(expect_status) && NT_ERROR(iosb_status) */ todo_wine_if (ioctl != IOCTL_WINETEST_RETURN_STATUS_BUFFERED) ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer); @@ -689,8 +690,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) io.Information = 0xdeadf00d; ret = NtDeviceIoControlFile(device, NULL, NULL, NULL, &io, ioctl, params, sizeof(*params), buffer, sizeof(buffer)); - todo_wine_if ((params->ret_status != params->iosb_status && params->ret_status != STATUS_PENDING) - || params->iosb_status == STATUS_PENDING) + todo_wine_if (params->ret_status != params->iosb_status && params->ret_status != STATUS_PENDING) ok(ret == expect_status, "got %#x\n", ret); if (NT_ERROR(params->iosb_status)) { @@ -700,8 +700,10 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) else { todo_wine_if (params->iosb_status == STATUS_PENDING) + { ok(io.Status == params->iosb_status, "got %#x\n", io.Status); - ok(io.Information == 3, "got size %Iu\n", io.Information); + ok(io.Information == 3, "got size %Iu\n", io.Information); + } } todo_wine_if (ioctl != IOCTL_WINETEST_RETURN_STATUS_BUFFERED) ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer); @@ -723,7 +725,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) io.Information = 0xdeadf00d; ret = NtDeviceIoControlFile(file, event, NULL, (void *)456, &io, ioctl, params, sizeof(*params), buffer, sizeof(buffer)); - todo_wine_if (params->ret_status != params->iosb_status || params->ret_status == STATUS_PENDING) + todo_wine_if (params->ret_status != params->iosb_status) ok(ret == params->ret_status || broken(NT_WARNING(params->ret_status) && ret == STATUS_PENDING), /* win10 */ "got %#x\n", ret); @@ -737,8 +739,10 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) else { todo_wine_if (params->iosb_status == STATUS_PENDING) + { ok(io.Status == params->iosb_status, "got %#x\n", io.Status); - ok(io.Information == 3, "got size %Iu\n", io.Information); + ok(io.Information == 3, "got size %Iu\n", io.Information); + } ret = WaitForSingleObject(event, 0); ok(!ret, "got %d\n", ret); } @@ -761,9 +765,9 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) ok(!ret, "got %#x\n", ret); ok(key == 123, "got key %Iu\n", key); ok(value == 456, "got value %Iu\n", value); + ok(io.Status == params->iosb_status, "got iosb status %#x\n", io.Status); todo_wine_if (params->iosb_status == STATUS_PENDING) - ok(io.Status == params->iosb_status, "got iosb status %#x\n", io.Status); - ok(io.Information == 3, "got information %Iu\n", io.Information); + ok(io.Information == 3, "got information %Iu\n", io.Information); }
/* As above, but set the event first, to show that the event is always @@ -774,7 +778,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) io.Information = 0xdeadf00d; ret = NtDeviceIoControlFile(file, event, NULL, NULL, &io, ioctl, params, sizeof(*params), buffer, sizeof(buffer)); - todo_wine_if (params->ret_status != params->iosb_status || params->ret_status == STATUS_PENDING) + todo_wine_if (params->ret_status != params->iosb_status) ok(ret == params->ret_status || broken(NT_WARNING(params->ret_status) && ret == STATUS_PENDING), /* win10 */ "got %#x\n", ret); @@ -788,8 +792,10 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) else { todo_wine_if (params->iosb_status == STATUS_PENDING) + { ok(io.Status == params->iosb_status, "got %#x\n", io.Status); - ok(io.Information == 3, "got size %Iu\n", io.Information); + ok(io.Information == 3, "got size %Iu\n", io.Information); + } ret = WaitForSingleObject(event, 0); ok(!ret, "got %d\n", ret); } @@ -805,7 +811,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) io.Information = 0xdeadf00d; ret = NtDeviceIoControlFile(file, NULL, NULL, NULL, &io, ioctl, params, sizeof(*params), buffer, sizeof(buffer)); - todo_wine_if (params->ret_status != params->iosb_status || params->ret_status == STATUS_PENDING) + todo_wine_if (params->ret_status != params->iosb_status) ok(ret == params->ret_status || broken(NT_WARNING(params->ret_status) && ret == STATUS_PENDING), /* win10 */ "got %#x\n", ret); @@ -819,8 +825,10 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) else { todo_wine_if (params->iosb_status == STATUS_PENDING) + { ok(io.Status == params->iosb_status, "got %#x\n", io.Status); - ok(io.Information == 3, "got size %Iu\n", io.Information); + ok(io.Information == 3, "got size %Iu\n", io.Information); + } ret = WaitForSingleObject(file, 0); ok(!ret, "got %d\n", ret); } @@ -840,7 +848,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) io.Information = 0xdeadf00d; ret = NtDeviceIoControlFile(file, event, NULL, (void *)456, &io, ioctl, params, sizeof(*params), buffer, sizeof(buffer)); - todo_wine_if (params->ret_status != params->iosb_status || params->ret_status == STATUS_PENDING) + todo_wine_if (params->ret_status != params->iosb_status) ok(ret == params->ret_status || broken(NT_WARNING(params->ret_status) && ret == STATUS_PENDING), /* win10 */ "got %#x\n", ret); @@ -854,8 +862,10 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) else { todo_wine_if (params->iosb_status == STATUS_PENDING) + { ok(io.Status == params->iosb_status, "got %#x\n", io.Status); - ok(io.Information == 3, "got size %Iu\n", io.Information); + ok(io.Information == 3, "got size %Iu\n", io.Information); + } ret = WaitForSingleObject(event, 0); ok(!ret, "got %d\n", ret); } @@ -909,7 +919,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) io.Information = 0xdeadf00d; ret = NtDeviceIoControlFile(file, NULL, return_status_apc, (void *)456, &io, ioctl, params, sizeof(*params), buffer, sizeof(buffer)); - todo_wine_if (params->ret_status != params->iosb_status || params->ret_status == STATUS_PENDING) + todo_wine_if (params->ret_status != params->iosb_status) ok(ret == params->ret_status, "got %#x\n", ret); if (!params->pending && NT_ERROR(params->iosb_status)) { @@ -919,8 +929,10 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) else { todo_wine_if (params->iosb_status == STATUS_PENDING) + { ok(io.Status == params->iosb_status, "got %#x\n", io.Status); - ok(io.Information == 3, "got size %Iu\n", io.Information); + ok(io.Information == 3, "got size %Iu\n", io.Information); + } } todo_wine_if (ioctl != IOCTL_WINETEST_RETURN_STATUS_BUFFERED) ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer); diff --git a/server/async.c b/server/async.c index 17ef709f89e..e8d95a62d4b 100644 --- a/server/async.c +++ b/server/async.c @@ -156,6 +156,8 @@ static void async_destroy( struct object *obj ) /* notifies client thread of new status of its async request */ void async_terminate( struct async *async, unsigned int status ) { + struct iosb *iosb = async->iosb; + if (async->terminated) return;
async->terminated = 1; @@ -176,7 +178,15 @@ void async_terminate( struct async *async, unsigned int status ) data.type = APC_ASYNC_IO; data.async_io.user = async->data.user; data.async_io.sb = async->data.iosb; - data.async_io.status = status; + + /* if the result is nonzero or there is output data, the client needs to + * make an extra request to retrieve them; use STATUS_ALERTED to signal + * this case */ + if (iosb && (iosb->result || iosb->out_data)) + data.async_io.status = STATUS_ALERTED; + else + data.async_io.status = status; + thread_queue_apc( async->thread->process, async->thread, &async->obj, &data ); }
@@ -353,11 +363,6 @@ void async_request_complete( struct async *async, unsigned int status, data_size
release_object( iosb );
- /* if the result is nonzero or there is output data, the client needs to - * make an extra request to retrieve them; use STATUS_ALERTED to signal - * this case */ - if (result || out_data) - status = STATUS_ALERTED; async_terminate( async, status ); }