ntdll: Explicitly return whether an async is complete in async_callback_t.

Signed-off-by: Zebediah Figura <zfigura@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2021-09-14 01:02:48 -05:00 committed by Alexandre Julliard
parent f5bd946399
commit 1eb56b20ba
5 changed files with 112 additions and 143 deletions

View File

@ -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 ( \

View File

@ -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 );

View File

@ -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,

View File

@ -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
{

View File

@ -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);