server: Store I/O completion information in async structure.
This is to allow completions to be sent on handle close. Also this can be helpful for AcceptEx/TransmitFile implementation.
This commit is contained in:
parent
01380b0554
commit
3afbee5218
|
@ -566,9 +566,21 @@ static void test_iocp_fileio(HANDLE h)
|
|||
ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
|
||||
ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
|
||||
}
|
||||
|
||||
ReadFile( hPipeSrv, buf, sizeof(buf), &read, &o);
|
||||
CloseHandle( hPipeSrv );
|
||||
count = get_pending_msgs(h);
|
||||
ok( count == 1, "Unexpected msg count: %ld\n", count );
|
||||
if (get_msg(h))
|
||||
{
|
||||
ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey );
|
||||
ok( ioSb.Information == 0, "Invalid ioSb.Information: %ld\n", ioSb.Information );
|
||||
/* wine sends wrong status here */
|
||||
todo_wine ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status);
|
||||
ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue );
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle( hPipeSrv );
|
||||
CloseHandle( hPipeClt );
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@ struct async
|
|||
struct timeout_user *timeout;
|
||||
unsigned int timeout_status; /* status to report upon timeout */
|
||||
struct event *event;
|
||||
struct completion *completion;
|
||||
unsigned long comp_key;
|
||||
async_data_t data; /* data for async I/O call */
|
||||
};
|
||||
|
||||
|
@ -121,6 +123,7 @@ static void async_destroy( struct object *obj )
|
|||
|
||||
if (async->timeout) remove_timeout_user( async->timeout );
|
||||
if (async->event) release_object( async->event );
|
||||
if (async->completion) release_object( async->completion );
|
||||
release_object( async->queue );
|
||||
release_object( async->thread );
|
||||
}
|
||||
|
@ -146,10 +149,6 @@ void async_terminate( struct async *async, unsigned int status )
|
|||
return;
|
||||
}
|
||||
|
||||
/* send error completion event */
|
||||
if (status != STATUS_ALERTED && async->data.cvalue && async->queue->fd)
|
||||
fd_add_completion( async->queue->fd, async->data.cvalue, status, 0 );
|
||||
|
||||
memset( &data, 0, sizeof(data) );
|
||||
data.type = APC_ASYNC_IO;
|
||||
data.async_io.func = async->data.callback;
|
||||
|
@ -214,6 +213,7 @@ struct async *create_async( struct thread *thread, struct async_queue *queue, co
|
|||
async->data = *data;
|
||||
async->timeout = NULL;
|
||||
async->queue = (struct async_queue *)grab_object( queue );
|
||||
fd_assign_completion( queue->fd, &async->completion, &async->comp_key );
|
||||
|
||||
list_add_tail( &queue->queue, &async->queue_entry );
|
||||
grab_object( async );
|
||||
|
@ -257,8 +257,8 @@ void async_set_result( struct object *obj, unsigned int status, unsigned long to
|
|||
if (async->timeout) remove_timeout_user( async->timeout );
|
||||
async->timeout = NULL;
|
||||
async->status = status;
|
||||
if (async->data.cvalue && async->queue->fd)
|
||||
fd_add_completion( async->queue->fd, async->data.cvalue, status, total );
|
||||
if (async->completion && async->data.cvalue)
|
||||
add_completion( async->completion, async->comp_key, async->data.cvalue, status, total );
|
||||
if (async->data.apc)
|
||||
{
|
||||
apc_call_t data;
|
||||
|
|
10
server/fd.c
10
server/fd.c
|
@ -1922,11 +1922,10 @@ static struct fd *get_handle_fd_obj( struct process *process, obj_handle_t handl
|
|||
return fd;
|
||||
}
|
||||
|
||||
/* add a completion result to a completion queue attached to the fd */
|
||||
void fd_add_completion( struct fd *fd, unsigned long cvalue, unsigned int status, unsigned long information )
|
||||
void fd_assign_completion( struct fd *fd, struct completion **p_port, unsigned long *p_key )
|
||||
{
|
||||
if (fd->completion)
|
||||
add_completion( fd->completion, fd->comp_key, cvalue, status, information );
|
||||
*p_key = fd->comp_key;
|
||||
*p_port = fd->completion ? (struct completion *)grab_object( fd->completion ) : NULL;
|
||||
}
|
||||
|
||||
/* flush a file buffers */
|
||||
|
@ -2066,7 +2065,8 @@ DECL_HANDLER(add_fd_completion)
|
|||
struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
|
||||
if (fd)
|
||||
{
|
||||
fd_add_completion( fd, req->cvalue, req->status, req->information );
|
||||
if (fd->completion)
|
||||
add_completion( fd->completion, fd->comp_key, req->cvalue, req->status, req->information );
|
||||
release_object( fd );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,7 +139,7 @@ extern void async_set_result( struct object *obj, unsigned int status, unsigned
|
|||
extern int async_waiting( struct async_queue *queue );
|
||||
extern void async_terminate( struct async *async, unsigned int status );
|
||||
extern void async_wake_up( struct async_queue *queue, unsigned int status );
|
||||
extern void fd_add_completion( struct fd *fd, unsigned long cvalue, unsigned int status, unsigned long information );
|
||||
extern void fd_assign_completion( struct fd *fd, struct completion **p_port, unsigned long *p_key );
|
||||
|
||||
/* access rights that require Unix read permission */
|
||||
#define FILE_UNIX_READ_ACCESS (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
|
||||
|
|
Loading…
Reference in New Issue