Only really an optimization (plus it makes the code a little conceptually simpler).
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ntdll/unix/file.c | 1 - dlls/ntdll/unix/server.c | 2 +- dlls/ntdll/unix/socket.c | 15 ++++----------- server/async.c | 9 ++++----- server/protocol.def | 2 +- server/trace.c | 2 +- 6 files changed, 11 insertions(+), 20 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 712f94ec43f..5da9ca560f6 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -4690,7 +4690,6 @@ static NTSTATUS irp_completion( void *user, ULONG_PTR *info, NTSTATUS status ) req->user_arg = wine_server_client_ptr( async ); wine_server_set_reply( req, async->buffer, async->size ); status = virtual_locked_server_call( req ); - *info = reply->size; } SERVER_END_REQ; } diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 986eb6c3250..d0cfd4cd46c 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -378,7 +378,7 @@ static void invoke_system_apc( const apc_call_t *call, apc_result_t *result, BOO case APC_ASYNC_IO: { struct async_fileio *user = wine_server_get_ptr( call->async_io.user ); - ULONG_PTR info = 0; + ULONG_PTR info = call->async_io.result;
result->type = call->type; result->async_io.status = user->callback( user, &info, call->async_io.status ); diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index 8469def786a..db58d2e5b12 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -565,7 +565,6 @@ static NTSTATUS try_recv( int fd, struct async_recv_ioctl *async, ULONG_PTR *siz static NTSTATUS async_recv_proc( void *user, ULONG_PTR *info, NTSTATUS status ) { struct async_recv_ioctl *async = user; - ULONG_PTR information = 0; int fd, needs_close;
TRACE( "%#x\n", status ); @@ -575,19 +574,15 @@ static NTSTATUS async_recv_proc( void *user, ULONG_PTR *info, NTSTATUS status ) if ((status = server_get_unix_fd( async->io.handle, 0, &fd, &needs_close, NULL, NULL ))) return status;
- status = try_recv( fd, async, &information ); - TRACE( "got status %#x, %#lx bytes read\n", status, information ); + status = try_recv( fd, async, info ); + TRACE( "got status %#x, %#lx bytes read\n", status, *info );
if (status == STATUS_DEVICE_NOT_READY) status = STATUS_PENDING;
if (needs_close) close( fd ); } - if (status != STATUS_PENDING) - { - *info = information; - release_fileio( &async->io ); - } + if (status != STATUS_PENDING) release_fileio( &async->io ); return status; }
@@ -704,7 +699,6 @@ static ULONG_PTR fill_poll_output( struct async_poll_ioctl *async, NTSTATUS stat static NTSTATUS async_poll_proc( void *user, ULONG_PTR *info, NTSTATUS status ) { struct async_poll_ioctl *async = user; - ULONG_PTR information = 0;
if (status == STATUS_ALERTED) { @@ -716,12 +710,11 @@ static NTSTATUS async_poll_proc( void *user, ULONG_PTR *info, NTSTATUS status ) } SERVER_END_REQ;
- information = fill_poll_output( async, status ); + *info = fill_poll_output( async, status ); }
if (status != STATUS_PENDING) { - *info = information; free( async->input ); release_fileio( &async->io ); } diff --git a/server/async.c b/server/async.c index 7cffd24a18b..bdc7620e9a1 100644 --- a/server/async.c +++ b/server/async.c @@ -185,11 +185,11 @@ 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.result = iosb ? iosb->result : 0;
- /* 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)) + /* if there is output data, the client needs to make an extra request + * to retrieve it; use STATUS_ALERTED to signal this case */ + if (iosb && iosb->out_data) data.async_io.status = STATUS_ALERTED; else data.async_io.status = status; @@ -719,6 +719,5 @@ DECL_HANDLER(get_async_result) iosb->out_data = NULL; } } - reply->size = iosb->result; set_error( iosb->status ); } diff --git a/server/protocol.def b/server/protocol.def index 02c1f269be7..cc1887dae2d 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -508,6 +508,7 @@ typedef union unsigned int status; /* I/O status */ client_ptr_t user; /* user pointer */ client_ptr_t sb; /* status block */ + data_size_t result; /* result size */ } async_io; struct { @@ -2156,7 +2157,6 @@ enum message_type @REQ(get_async_result) client_ptr_t user_arg; /* user arg used to identify async */ @REPLY - data_size_t size; /* result size (input or output depending on the operation) */ VARARG(out_data,bytes); /* iosb output data */ @END
diff --git a/server/trace.c b/server/trace.c index da8c74cea2b..b11e51e6d81 100644 --- a/server/trace.c +++ b/server/trace.c @@ -181,7 +181,7 @@ static void dump_apc_call( const char *prefix, const apc_call_t *call ) case APC_ASYNC_IO: dump_uint64( "APC_ASYNC_IO,user=", &call->async_io.user ); dump_uint64( ",sb=", &call->async_io.sb ); - fprintf( stderr, ",status=%s", get_status_name(call->async_io.status) ); + fprintf( stderr, ",status=%s,result=%u", get_status_name(call->async_io.status), call->async_io.result ); break; case APC_VIRTUAL_ALLOC: dump_uint64( "APC_VIRTUAL_ALLOC,addr==", &call->virtual_alloc.addr );
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/kernel32/tests/volume.c | 16 ++++++++-------- dlls/ntdll/unix/server.c | 1 + dlls/ntoskrnl.exe/tests/ntoskrnl.c | 28 ++++++++++++++-------------- server/async.c | 10 +++++++++- 4 files changed, 32 insertions(+), 23 deletions(-)
diff --git a/dlls/kernel32/tests/volume.c b/dlls/kernel32/tests/volume.c index cb35de6add1..723dfabb817 100644 --- a/dlls/kernel32/tests/volume.c +++ b/dlls/kernel32/tests/volume.c @@ -1641,8 +1641,8 @@ static void test_mountmgr_query_points(void) status = NtDeviceIoControlFile( file, NULL, NULL, NULL, &io, IOCTL_MOUNTMGR_QUERY_POINTS, NULL, 0, NULL, 0 ); ok(status == STATUS_INVALID_PARAMETER, "got %#x\n", status); - todo_wine ok(io.Status == 0xdeadf00d, "got status %#x\n", io.Status); - todo_wine ok(io.Information == 0xdeadf00d, "got information %#Ix\n", io.Information); + ok(io.Status == 0xdeadf00d, "got status %#x\n", io.Status); + ok(io.Information == 0xdeadf00d, "got information %#Ix\n", io.Information);
memset( input, 0, sizeof(*input) );
@@ -1651,16 +1651,16 @@ static void test_mountmgr_query_points(void) status = NtDeviceIoControlFile( file, NULL, NULL, NULL, &io, IOCTL_MOUNTMGR_QUERY_POINTS, input, sizeof(*input) - 1, NULL, 0 ); ok(status == STATUS_INVALID_PARAMETER, "got %#x\n", status); - todo_wine ok(io.Status == 0xdeadf00d, "got status %#x\n", io.Status); - todo_wine ok(io.Information == 0xdeadf00d, "got information %#Ix\n", io.Information); + ok(io.Status == 0xdeadf00d, "got status %#x\n", io.Status); + ok(io.Information == 0xdeadf00d, "got information %#Ix\n", io.Information);
io.Status = 0xdeadf00d; io.Information = 0xdeadf00d; status = NtDeviceIoControlFile( file, NULL, NULL, NULL, &io, IOCTL_MOUNTMGR_QUERY_POINTS, input, sizeof(*input), NULL, 0 ); ok(status == STATUS_INVALID_PARAMETER, "got %#x\n", status); - todo_wine ok(io.Status == 0xdeadf00d, "got status %#x\n", io.Status); - todo_wine ok(io.Information == 0xdeadf00d, "got information %#Ix\n", io.Information); + ok(io.Status == 0xdeadf00d, "got status %#x\n", io.Status); + ok(io.Information == 0xdeadf00d, "got information %#Ix\n", io.Information);
io.Status = 0xdeadf00d; io.Information = 0xdeadf00d; @@ -1668,8 +1668,8 @@ static void test_mountmgr_query_points(void) status = NtDeviceIoControlFile( file, NULL, NULL, NULL, &io, IOCTL_MOUNTMGR_QUERY_POINTS, input, sizeof(*input), output, sizeof(*output) - 1 ); ok(status == STATUS_INVALID_PARAMETER, "got %#x\n", status); - todo_wine ok(io.Status == 0xdeadf00d, "got status %#x\n", io.Status); - todo_wine ok(io.Information == 0xdeadf00d, "got information %#Ix\n", io.Information); + ok(io.Status == 0xdeadf00d, "got status %#x\n", io.Status); + ok(io.Information == 0xdeadf00d, "got information %#Ix\n", io.Information); ok(output->Size == 0xcccccccc, "got size %u\n", output->Size); ok(output->NumberOfMountPoints == 0xcccccccc, "got count %u\n", output->NumberOfMountPoints);
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index d0cfd4cd46c..08733fba710 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -385,6 +385,7 @@ static void invoke_system_apc( const apc_call_t *call, apc_result_t *result, BOO if (result->async_io.status != STATUS_PENDING) { result->async_io.total = info; + /* the server will pass us NULL if a call failed synchronously */ set_async_iosb( call->async_io.sb, result->async_io.status, info ); } break; diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index fb91783779b..ff61ff847ab 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -690,8 +690,8 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) ok(ret == expect_status, "got %#x\n", ret); if (NT_ERROR(params->iosb_status)) { - todo_wine ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status); - todo_wine ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information); + ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status); + ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information); } else { @@ -726,8 +726,8 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) "got %#x\n", ret); if (!params->pending && NT_ERROR(params->iosb_status)) { - todo_wine ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status); - todo_wine ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information); + ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status); + ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information); ret = WaitForSingleObject(event, 0); ok(ret == WAIT_TIMEOUT, "got %d\n", ret); } @@ -778,8 +778,8 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) "got %#x\n", ret); if (!params->pending && NT_ERROR(params->iosb_status)) { - todo_wine ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status); - todo_wine ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information); + ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status); + ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information); ret = WaitForSingleObject(event, 0); ok(ret == WAIT_TIMEOUT, "got %d\n", ret); } @@ -810,8 +810,8 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) "got %#x\n", ret); if (!params->pending && NT_ERROR(params->iosb_status)) { - todo_wine ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status); - todo_wine ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information); + ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status); + ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information); ret = WaitForSingleObject(file, 0); ok(ret == WAIT_TIMEOUT, "got %d\n", ret); } @@ -846,8 +846,8 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) "got %#x\n", ret); if (!params->pending && NT_ERROR(params->iosb_status)) { - todo_wine ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status); - todo_wine ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information); + ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status); + ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information); ret = WaitForSingleObject(event, 0); ok(ret == WAIT_TIMEOUT, "got %d\n", ret); } @@ -915,8 +915,8 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) ok(ret == params->ret_status, "got %#x\n", ret); if (!params->pending && NT_ERROR(params->iosb_status)) { - todo_wine ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status); - todo_wine ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information); + ok(io.Status == 0xdeadf00d, "got %#x\n", io.Status); + ok(io.Information == 0xdeadf00d, "got size %Iu\n", io.Information); } else { @@ -1151,8 +1151,8 @@ static void test_blocking_irp(void) io.Information = 0xdeadf00d; status = NtQueryVolumeInformationFile(file, &io, buffer, sizeof(buffer), FileFsFullSizeInformation); ok(status == STATUS_DEVICE_NOT_READY, "got %#x\n", status); - todo_wine ok(io.Status == 0xdeadf00d, "got iosb status %#x\n", io.Status); - todo_wine ok(io.Information == 0xdeadf00d, "got information %#Ix\n", io.Information); + ok(io.Status == 0xdeadf00d, "got iosb status %#x\n", io.Status); + ok(io.Information == 0xdeadf00d, "got information %#Ix\n", io.Information);
CloseHandle(file);
diff --git a/server/async.c b/server/async.c index bdc7620e9a1..1a564ff1a69 100644 --- a/server/async.c +++ b/server/async.c @@ -184,9 +184,17 @@ void async_terminate( struct async *async, unsigned int status ) memset( &data, 0, sizeof(data) ); data.type = APC_ASYNC_IO; data.async_io.user = async->data.user; - data.async_io.sb = async->data.iosb; data.async_io.result = iosb ? iosb->result : 0;
+ /* this can happen if the initial status was unknown (i.e. for device + * files). the client should not fill the IOSB in this case; pass it as + * NULL to communicate that. + * note that we check the IOSB status and not the initial status */ + if (NT_ERROR( status ) && (!is_fd_overlapped( async->fd ) || !async->pending)) + data.async_io.sb = 0; + else + data.async_io.sb = async->data.iosb; + /* if there is output data, the client needs to make an extra request * to retrieve it; use STATUS_ALERTED to signal this case */ if (iosb && iosb->out_data)
From: Chip Davis cdavis@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=30155 Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ntoskrnl.exe/ntoskrnl.c | 51 ++++++++++++++++++++++-------- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 21 ++++-------- 2 files changed, 44 insertions(+), 28 deletions(-)
diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c index 1bd5d6fb351..f2fb0a6d66e 100644 --- a/dlls/ntoskrnl.exe/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/ntoskrnl.c @@ -440,15 +440,43 @@ static void free_dispatch_irp( struct irp_data *irp_data ) free( irp_data ); }
+static ULONG get_irp_output_size( IRP *irp ) +{ + IO_STACK_LOCATION *stack = IoGetNextIrpStackLocation( irp ); + + if (!irp->UserBuffer || (irp->Flags & IRP_WRITE_OPERATION)) + return 0; + + /* For IRPs not using buffered I/O, the driver is supposed to have direct + * access to the user's output buffer, either via an MDL (direct I/O) or + * with the raw user VA (neither). We can't fully support this, but we + * should at least copy the entire buffer back to the caller. */ + switch (stack->MajorFunction) + { + case IRP_MJ_FILE_SYSTEM_CONTROL: + case IRP_MJ_DEVICE_CONTROL: + case IRP_MJ_INTERNAL_DEVICE_CONTROL: + if ((stack->Parameters.DeviceIoControl.IoControlCode & 3) != METHOD_BUFFERED) + return stack->Parameters.DeviceIoControl.OutputBufferLength; + break; + + case IRP_MJ_READ: + /* FIXME: Handle non-buffered reads. */ + default: + break; + } + + if (NT_ERROR(irp->IoStatus.u.Status)) + return 0; + return irp->IoStatus.Information; +} + /* transfer result of IRP back to wineserver */ static NTSTATUS WINAPI dispatch_irp_completion( DEVICE_OBJECT *device, IRP *irp, void *context ) { struct irp_data *irp_data = context; - void *out_buff = irp->UserBuffer; NTSTATUS status; - - if (irp->Flags & IRP_WRITE_OPERATION) - out_buff = NULL; /* do not transfer back input buffer */ + ULONG out_size;
EnterCriticalSection( &irp_completion_cs );
@@ -460,15 +488,14 @@ static NTSTATUS WINAPI dispatch_irp_completion( DEVICE_OBJECT *device, IRP *irp, return STATUS_MORE_PROCESSING_REQUIRED; }
+ out_size = get_irp_output_size( irp ); + SERVER_START_REQ( set_irp_result ) { req->handle = wine_server_obj_handle( irp_data->handle ); req->status = irp->IoStatus.u.Status; req->size = irp->IoStatus.Information; - if (!NT_ERROR(irp->IoStatus.u.Status)) - { - if (out_buff) wine_server_add_data( req, out_buff, irp->IoStatus.Information ); - } + if (out_size) wine_server_add_data( req, irp->UserBuffer, out_size ); status = wine_server_call( req ); } SERVER_END_REQ; @@ -943,17 +970,13 @@ NTSTATUS CDECL wine_ntoskrnl_main_loop( HANDLE stop_event ) if (context.irp_data->complete) { /* IRP completed even before we got here; we can report completion now */ - void *out_buff = irp->UserBuffer; - - if (irp->Flags & IRP_WRITE_OPERATION) - out_buff = NULL; /* do not transfer back input buffer */ + unsigned int out_size = get_irp_output_size( irp );
req->prev = wine_server_obj_handle( context.irp_data->handle ); req->pending = irp->PendingReturned; req->iosb_status = irp->IoStatus.u.Status; req->result = irp->IoStatus.Information; - if (!NT_ERROR(irp->IoStatus.u.Status) && out_buff) - wine_server_add_data( req, out_buff, irp->IoStatus.Information ); + if (out_size) wine_server_add_data( req, irp->UserBuffer, out_size ); } else { diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index ff61ff847ab..8825c7e69e8 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -679,8 +679,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) else if (!NT_ERROR(params->iosb_status)) 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); + ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer);
strcpy(buffer, "abcdef"); io.Status = 0xdeadf00d; @@ -701,8 +700,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) 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); + ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer);
/* Test the overlapped case. */
@@ -741,8 +739,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) ret = WaitForSingleObject(event, 0); ok(!ret, "got %d\n", ret); } - todo_wine_if (ioctl != IOCTL_WINETEST_RETURN_STATUS_BUFFERED) - ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer); + ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer);
ret = WaitForSingleObject(file, 0); ok(ret == WAIT_TIMEOUT, "got %d\n", ret); @@ -793,8 +790,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) ret = WaitForSingleObject(event, 0); ok(!ret, "got %d\n", ret); } - todo_wine_if (ioctl != IOCTL_WINETEST_RETURN_STATUS_BUFFERED) - ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer); + ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer);
/* As above, but use the file handle instead of an event. */ ret = WaitForSingleObject(file, 0); @@ -825,8 +821,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) ret = WaitForSingleObject(file, 0); ok(!ret, "got %d\n", ret); } - todo_wine_if (ioctl != IOCTL_WINETEST_RETURN_STATUS_BUFFERED) - ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer); + ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer);
/* Test FILE_SKIP_COMPLETION_PORT_ON_SUCCESS. */
@@ -861,8 +856,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) ret = WaitForSingleObject(event, 0); ok(!ret, "got %d\n", ret); } - todo_wine_if (ioctl != IOCTL_WINETEST_RETURN_STATUS_BUFFERED) - ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer); + ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer);
key = 0xdeadf00d; value = 0xdeadf00d; @@ -926,8 +920,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) 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); + ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer);
ret = SleepEx(0, TRUE); if (!params->pending && NT_ERROR(params->iosb_status))
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 2 +- server/fd.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 8825c7e69e8..30868db3e98 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -711,7 +711,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) ok(port != NULL, "failed to create port, error %u\n", GetLastError());
ret = WaitForSingleObject(file, 0); - todo_wine ok(!ret, "got %d\n", ret); + ok(!ret, "got %d\n", ret);
ResetEvent(event); strcpy(buffer, "abcdef"); diff --git a/server/fd.c b/server/fd.c index 9486a1c3c7c..ad1b7a1bd4a 100644 --- a/server/fd.c +++ b/server/fd.c @@ -1742,7 +1742,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use fd->nt_namelen = 0; fd->unix_fd = -1; fd->cacheable = 0; - fd->signaled = 0; + fd->signaled = 1; fd->fs_locks = 0; fd->poll_index = -1; fd->completion = NULL;
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/kernelbase/file.c | 2 +- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index a4d26c2a1be..5c7b649d805 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -4115,7 +4115,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH DeviceIoControl( HANDLE handle, DWORD code, void * status = NtDeviceIoControlFile( handle, event, NULL, cvalue, piosb, code, in_buff, in_count, out_buff, out_count );
- if (returned) *returned = piosb->Information; + if (returned && !NT_ERROR(status)) *returned = piosb->Information; if (status == STATUS_PENDING || !NT_SUCCESS( status )) return set_ntstatus( status ); return TRUE; } diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 30868db3e98..2484479efc3 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -675,7 +675,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) ok(GetLastError() == RtlNtStatusToDosError(expect_status), "got error %u\n", GetLastError()); } if (NT_ERROR(expect_status)) - todo_wine ok(size == 0xdeadf00d, "got size %u\n", size); + ok(size == 0xdeadf00d, "got size %u\n", size); else if (!NT_ERROR(params->iosb_status)) 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) */
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ntdll/unix/file.c | 92 ++++++++++++------------- dlls/ntdll/unix/server.c | 6 +- dlls/ntdll/unix/socket.c | 104 +++++++++++++---------------- dlls/ntdll/unix/unix_private.h | 3 +- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 50 +++++--------- 5 files changed, 112 insertions(+), 143 deletions(-)
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c index 5da9ca560f6..bcd74c9d6aa 100644 --- a/dlls/ntdll/unix/file.c +++ b/dlls/ntdll/unix/file.c @@ -4679,34 +4679,34 @@ struct async_fileio *alloc_fileio( DWORD size, async_callback_t callback, HANDLE }
/* callback for irp async I/O completion */ -static NTSTATUS irp_completion( void *user, ULONG_PTR *info, NTSTATUS status ) +static BOOL irp_completion( void *user, ULONG_PTR *info, NTSTATUS *status ) { struct async_irp *async = user;
- if (status == STATUS_ALERTED) + if (*status == STATUS_ALERTED) { SERVER_START_REQ( get_async_result ) { req->user_arg = wine_server_client_ptr( async ); wine_server_set_reply( req, async->buffer, async->size ); - status = virtual_locked_server_call( req ); + *status = virtual_locked_server_call( req ); } SERVER_END_REQ; } - if (status != STATUS_PENDING) release_fileio( &async->io ); - return status; + release_fileio( &async->io ); + return TRUE; }
-static NTSTATUS async_read_proc( void *user, ULONG_PTR *info, NTSTATUS status ) +static BOOL async_read_proc( void *user, ULONG_PTR *info, NTSTATUS *status ) { struct async_fileio_read *fileio = user; int fd, needs_close, result;
- switch (status) + switch (*status) { case STATUS_ALERTED: /* got some new data */ /* check to see if the data is ready (non-blocking) */ - if ((status = server_get_unix_fd( fileio->io.handle, FILE_READ_DATA, &fd, + if ((*status = server_get_unix_fd( fileio->io.handle, FILE_READ_DATA, &fd, &needs_close, NULL, NULL ))) break;
@@ -4716,48 +4716,48 @@ static NTSTATUS async_read_proc( void *user, ULONG_PTR *info, NTSTATUS status ) if (result < 0) { if (errno == EAGAIN || errno == EINTR) - status = STATUS_PENDING; - else /* check to see if the transfer is complete */ - status = errno_to_status( errno ); + return FALSE; + + /* check to see if the transfer is complete */ + *status = errno_to_status( errno ); } else if (result == 0) { - status = fileio->already ? STATUS_SUCCESS : STATUS_PIPE_BROKEN; + *status = fileio->already ? STATUS_SUCCESS : STATUS_PIPE_BROKEN; } else { fileio->already += result; - if (fileio->already >= fileio->count || fileio->avail_mode) - status = STATUS_SUCCESS; - else - status = STATUS_PENDING; + + if (fileio->already < fileio->count && !fileio->avail_mode) + return FALSE; + + *status = STATUS_SUCCESS; } break;
case STATUS_TIMEOUT: case STATUS_IO_TIMEOUT: - if (fileio->already) status = STATUS_SUCCESS; + if (fileio->already) *status = STATUS_SUCCESS; break; } - if (status != STATUS_PENDING) - { - *info = fileio->already; - release_fileio( &fileio->io ); - } - return status; + + *info = fileio->already; + release_fileio( &fileio->io ); + return TRUE; }
-static NTSTATUS async_write_proc( void *user, ULONG_PTR *info, NTSTATUS status ) +static BOOL async_write_proc( void *user, ULONG_PTR *info, NTSTATUS *status ) { struct async_fileio_write *fileio = user; int result, fd, needs_close; enum server_fd_type type;
- switch (status) + switch (*status) { case STATUS_ALERTED: /* write some data (non-blocking) */ - if ((status = server_get_unix_fd( fileio->io.handle, FILE_WRITE_DATA, &fd, + if ((*status = server_get_unix_fd( fileio->io.handle, FILE_WRITE_DATA, &fd, &needs_close, &type, NULL ))) break;
@@ -4770,27 +4770,26 @@ static NTSTATUS async_write_proc( void *user, ULONG_PTR *info, NTSTATUS status )
if (result < 0) { - if (errno == EAGAIN || errno == EINTR) status = STATUS_PENDING; - else status = errno_to_status( errno ); + if (errno == EAGAIN || errno == EINTR) return FALSE; + *status = errno_to_status( errno ); } else { fileio->already += result; - status = (fileio->already < fileio->count) ? STATUS_PENDING : STATUS_SUCCESS; + if (fileio->already < fileio->count) return FALSE; + *status = STATUS_SUCCESS; } break;
case STATUS_TIMEOUT: case STATUS_IO_TIMEOUT: - if (fileio->already) status = STATUS_SUCCESS; + if (fileio->already) *status = STATUS_SUCCESS; break; } - if (status != STATUS_PENDING) - { - *info = fileio->already; - release_fileio( &fileio->io ); - } - return status; + + *info = fileio->already; + release_fileio( &fileio->io ); + return TRUE; }
/* do a read call through the server */ @@ -6054,23 +6053,23 @@ NTSTATUS WINAPI NtUnlockFile( HANDLE handle, IO_STATUS_BLOCK *io_status, LARGE_I }
-static NTSTATUS read_changes_apc( void *user, ULONG_PTR *info, NTSTATUS status ) +static BOOL read_changes_apc( void *user, ULONG_PTR *info, NTSTATUS *status ) { struct async_fileio_read_changes *fileio = user; int size = 0;
- if (status == STATUS_ALERTED) + if (*status == STATUS_ALERTED) { SERVER_START_REQ( read_change ) { req->handle = wine_server_obj_handle( fileio->io.handle ); wine_server_set_reply( req, fileio->data, fileio->data_size ); - status = wine_server_call( req ); + *status = wine_server_call( req ); size = wine_server_reply_size( reply ); } SERVER_END_REQ;
- if (status == STATUS_SUCCESS && fileio->buffer) + if (*status == STATUS_SUCCESS && fileio->buffer) { FILE_NOTIFY_INFORMATION *pfni = fileio->buffer; int i, left = fileio->buffer_size; @@ -6105,7 +6104,7 @@ static NTSTATUS read_changes_apc( void *user, ULONG_PTR *info, NTSTATUS status )
if (size) { - status = STATUS_NOTIFY_ENUM_DIR; + *status = STATUS_NOTIFY_ENUM_DIR; size = 0; } else @@ -6116,17 +6115,14 @@ static NTSTATUS read_changes_apc( void *user, ULONG_PTR *info, NTSTATUS status ) } else { - status = STATUS_NOTIFY_ENUM_DIR; + *status = STATUS_NOTIFY_ENUM_DIR; size = 0; } }
- if (status != STATUS_PENDING) - { - *info = size; - release_fileio( &fileio->io ); - } - return status; + *info = size; + release_fileio( &fileio->io ); + return TRUE; }
#define FILE_NOTIFY_ALL ( \ diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 08733fba710..050824a1440 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -379,11 +379,13 @@ static void invoke_system_apc( const apc_call_t *call, apc_result_t *result, BOO { struct async_fileio *user = wine_server_get_ptr( call->async_io.user ); ULONG_PTR info = call->async_io.result; + NTSTATUS status;
result->type = call->type; - result->async_io.status = user->callback( user, &info, call->async_io.status ); - if (result->async_io.status != STATUS_PENDING) + status = call->async_io.status; + if (user->callback( user, &info, &status )) { + result->async_io.status = status; result->async_io.total = info; /* the server will pass us NULL if a call failed synchronously */ set_async_iosb( call->async_io.sb, result->async_io.status, info ); diff --git a/dlls/ntdll/unix/socket.c b/dlls/ntdll/unix/socket.c index db58d2e5b12..73d61c0d4e6 100644 --- a/dlls/ntdll/unix/socket.c +++ b/dlls/ntdll/unix/socket.c @@ -562,28 +562,27 @@ static NTSTATUS try_recv( int fd, struct async_recv_ioctl *async, ULONG_PTR *siz return status; }
-static NTSTATUS async_recv_proc( void *user, ULONG_PTR *info, NTSTATUS status ) +static BOOL async_recv_proc( void *user, ULONG_PTR *info, NTSTATUS *status ) { struct async_recv_ioctl *async = user; int fd, needs_close;
- TRACE( "%#x\n", status ); + TRACE( "%#x\n", *status );
- if (status == STATUS_ALERTED) + if (*status == STATUS_ALERTED) { - if ((status = server_get_unix_fd( async->io.handle, 0, &fd, &needs_close, NULL, NULL ))) - return status; - - status = try_recv( fd, async, info ); - TRACE( "got status %#x, %#lx bytes read\n", status, *info ); - - if (status == STATUS_DEVICE_NOT_READY) - status = STATUS_PENDING; + if ((*status = server_get_unix_fd( async->io.handle, 0, &fd, &needs_close, NULL, NULL ))) + return TRUE;
+ *status = try_recv( fd, async, info ); + TRACE( "got status %#x, %#lx bytes read\n", *status, *info ); if (needs_close) close( fd ); + + if (*status == STATUS_DEVICE_NOT_READY) + return FALSE; } - if (status != STATUS_PENDING) release_fileio( &async->io ); - return status; + release_fileio( &async->io ); + return TRUE; }
static NTSTATUS sock_recv( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, IO_STATUS_BLOCK *io, @@ -696,29 +695,26 @@ static ULONG_PTR fill_poll_output( struct async_poll_ioctl *async, NTSTATUS stat return offsetof( struct afd_poll_params, sockets[count] ); }
-static NTSTATUS async_poll_proc( void *user, ULONG_PTR *info, NTSTATUS status ) +static BOOL async_poll_proc( void *user, ULONG_PTR *info, NTSTATUS *status ) { struct async_poll_ioctl *async = user;
- if (status == STATUS_ALERTED) + if (*status == STATUS_ALERTED) { SERVER_START_REQ( get_async_result ) { req->user_arg = wine_server_client_ptr( async ); wine_server_set_reply( req, async->sockets, async->count * sizeof(async->sockets[0]) ); - status = wine_server_call( req ); + *status = wine_server_call( req ); } SERVER_END_REQ;
- *info = fill_poll_output( async, status ); + *info = fill_poll_output( async, *status ); }
- if (status != STATUS_PENDING) - { - free( async->input ); - release_fileio( &async->io ); - } - return status; + free( async->input ); + release_fileio( &async->io ); + return TRUE; }
@@ -877,32 +873,29 @@ static NTSTATUS try_send( int fd, struct async_send_ioctl *async ) return STATUS_SUCCESS; }
-static NTSTATUS async_send_proc( void *user, ULONG_PTR *info, NTSTATUS status ) +static BOOL async_send_proc( void *user, ULONG_PTR *info, NTSTATUS *status ) { struct async_send_ioctl *async = user; int fd, needs_close;
- TRACE( "%#x\n", status ); + TRACE( "%#x\n", *status );
- if (status == STATUS_ALERTED) + if (*status == STATUS_ALERTED) { - if ((status = server_get_unix_fd( async->io.handle, 0, &fd, &needs_close, NULL, NULL ))) - return status; + if ((*status = server_get_unix_fd( async->io.handle, 0, &fd, &needs_close, NULL, NULL ))) + return TRUE;
- status = try_send( fd, async ); - TRACE( "got status %#x\n", status ); - - if (status == STATUS_DEVICE_NOT_READY) - status = STATUS_PENDING; + *status = try_send( fd, async ); + TRACE( "got status %#x\n", *status );
if (needs_close) close( fd ); + + if (*status == STATUS_DEVICE_NOT_READY) + return FALSE; } - if (status != STATUS_PENDING) - { - *info = async->sent_len; - release_fileio( &async->io ); - } - return status; + *info = async->sent_len; + release_fileio( &async->io ); + return TRUE; }
static NTSTATUS sock_send( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, @@ -1040,39 +1033,36 @@ static NTSTATUS try_transmit( int sock_fd, int file_fd, struct async_transmit_io return STATUS_SUCCESS; }
-static NTSTATUS async_transmit_proc( void *user, ULONG_PTR *info, NTSTATUS status ) +static BOOL async_transmit_proc( void *user, ULONG_PTR *info, NTSTATUS *status ) { int sock_fd, file_fd = -1, sock_needs_close = FALSE, file_needs_close = FALSE; struct async_transmit_ioctl *async = user;
- TRACE( "%#x\n", status ); + TRACE( "%#x\n", *status );
- if (status == STATUS_ALERTED) + if (*status == STATUS_ALERTED) { - if ((status = server_get_unix_fd( async->io.handle, 0, &sock_fd, &sock_needs_close, NULL, NULL ))) - return status; + if ((*status = server_get_unix_fd( async->io.handle, 0, &sock_fd, &sock_needs_close, NULL, NULL ))) + return TRUE;
- if (async->file && (status = server_get_unix_fd( async->file, 0, &file_fd, &file_needs_close, NULL, NULL ))) + if (async->file && (*status = server_get_unix_fd( async->file, 0, &file_fd, &file_needs_close, NULL, NULL ))) { if (sock_needs_close) close( sock_fd ); - return status; + return TRUE; }
- status = try_transmit( sock_fd, file_fd, async ); - TRACE( "got status %#x\n", status ); - - if (status == STATUS_DEVICE_NOT_READY) - status = STATUS_PENDING; + *status = try_transmit( sock_fd, file_fd, async ); + TRACE( "got status %#x\n", *status );
if (sock_needs_close) close( sock_fd ); if (file_needs_close) close( file_fd ); + + if (*status == STATUS_DEVICE_NOT_READY) + return FALSE; } - if (status != STATUS_PENDING) - { - *info = async->head_cursor + async->file_cursor + async->tail_cursor; - release_fileio( &async->io ); - } - return status; + *info = async->head_cursor + async->file_cursor + async->tail_cursor; + release_fileio( &async->io ); + return TRUE; }
static NTSTATUS sock_transmit( HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, void *apc_user, diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index fb1a4a397e9..6b8835bcba0 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -70,7 +70,8 @@ static inline struct ntdll_thread_data *ntdll_get_thread_data(void) return (struct ntdll_thread_data *)&NtCurrentTeb()->GdiTebBatch; }
-typedef NTSTATUS async_callback_t( void *user, ULONG_PTR *info, NTSTATUS status ); +/* returns TRUE if the async is complete; FALSE if it should be restarted */ +typedef BOOL async_callback_t( void *user, ULONG_PTR *info, NTSTATUS *status );
struct async_fileio { diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 2484479efc3..00daccb8487 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -677,7 +677,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) if (NT_ERROR(expect_status)) ok(size == 0xdeadf00d, "got size %u\n", size); else if (!NT_ERROR(params->iosb_status)) - todo_wine_if (params->iosb_status == STATUS_PENDING) ok(size == 3, "got size %u\n", size); + ok(size == 3, "got size %u\n", size); /* size is garbage if !NT_ERROR(expect_status) && NT_ERROR(iosb_status) */ ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer);
@@ -694,11 +694,8 @@ 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.Status == params->iosb_status, "got %#x\n", io.Status); + ok(io.Information == 3, "got size %Iu\n", io.Information); } ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer);
@@ -731,11 +728,8 @@ 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.Status == params->iosb_status, "got %#x\n", io.Status); + ok(io.Information == 3, "got size %Iu\n", io.Information); ret = WaitForSingleObject(event, 0); ok(!ret, "got %d\n", ret); } @@ -758,8 +752,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) 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.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 @@ -782,11 +775,8 @@ 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.Status == params->iosb_status, "got %#x\n", io.Status); + ok(io.Information == 3, "got size %Iu\n", io.Information); ret = WaitForSingleObject(event, 0); ok(!ret, "got %d\n", ret); } @@ -813,11 +803,8 @@ 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.Status == params->iosb_status, "got %#x\n", io.Status); + ok(io.Information == 3, "got size %Iu\n", io.Information); ret = WaitForSingleObject(file, 0); ok(!ret, "got %d\n", ret); } @@ -848,11 +835,8 @@ 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.Status == params->iosb_status, "got %#x\n", io.Status); + ok(io.Information == 3, "got size %Iu\n", io.Information); ret = WaitForSingleObject(event, 0); ok(!ret, "got %d\n", ret); } @@ -883,8 +867,7 @@ static void do_return_status(ULONG ioctl, struct return_status_params *params) 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.Information == 3, "got information %Iu\n", io.Information); + ok(io.Information == 3, "got information %Iu\n", io.Information); } }
@@ -914,11 +897,8 @@ 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.Status == params->iosb_status, "got %#x\n", io.Status); + ok(io.Information == 3, "got size %Iu\n", io.Information); } ok(!strcmp(buffer, expect_buffer), "got buffer %s\n", buffer);