ntdll: Add setting FileIoCompletionNotificationInformation implementation.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=38960 Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
b81c0c3e47
commit
2f17e0112d
|
@ -2656,6 +2656,25 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
|
|||
io->u.Status = STATUS_INVALID_PARAMETER_3;
|
||||
break;
|
||||
|
||||
case FileIoCompletionNotificationInformation:
|
||||
if (len >= sizeof(FILE_IO_COMPLETION_NOTIFICATION_INFORMATION))
|
||||
{
|
||||
FILE_IO_COMPLETION_NOTIFICATION_INFORMATION *info = ptr;
|
||||
|
||||
if (info->Flags & ~FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)
|
||||
FIXME( "Unsupported completion flags %x\n", info->Flags );
|
||||
|
||||
SERVER_START_REQ( set_fd_completion_mode )
|
||||
{
|
||||
req->handle = wine_server_obj_handle( handle );
|
||||
req->flags = info->Flags;
|
||||
io->u.Status = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
} else
|
||||
io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
|
||||
break;
|
||||
|
||||
case FileAllInformation:
|
||||
io->u.Status = STATUS_INVALID_INFO_CLASS;
|
||||
break;
|
||||
|
|
|
@ -3331,12 +3331,11 @@ static void test_file_completion_information(void)
|
|||
if (!(h = create_temp_file(0))) return;
|
||||
|
||||
status = pNtSetInformationFile(h, &io, &info, sizeof(info) - 1, FileIoCompletionNotificationInformation);
|
||||
todo_wine
|
||||
ok(status == STATUS_INFO_LENGTH_MISMATCH || status == STATUS_INVALID_INFO_CLASS /* XP */,
|
||||
ok(status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INVALID_INFO_CLASS /* XP */),
|
||||
"expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
|
||||
if (status == STATUS_INVALID_INFO_CLASS || status == STATUS_NOT_IMPLEMENTED)
|
||||
if (status != STATUS_INFO_LENGTH_MISMATCH)
|
||||
{
|
||||
skip("FileIoCompletionNotificationInformation class not supported\n");
|
||||
win_skip("FileIoCompletionNotificationInformation class not supported\n");
|
||||
CloseHandle(h);
|
||||
return;
|
||||
}
|
||||
|
@ -3408,7 +3407,9 @@ static void test_file_completion_information(void)
|
|||
|
||||
pov = (void *)0xdeadbeef;
|
||||
ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 500);
|
||||
todo_wine
|
||||
ok(!ret, "GetQueuedCompletionStatus succeeded\n");
|
||||
todo_wine
|
||||
ok(pov == NULL, "expected NULL, got %p\n", pov);
|
||||
}
|
||||
else
|
||||
|
@ -3435,7 +3436,9 @@ static void test_file_completion_information(void)
|
|||
|
||||
pov = (void *)0xdeadbeef;
|
||||
ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
|
||||
todo_wine
|
||||
ok(!ret, "GetQueuedCompletionStatus succeeded\n");
|
||||
todo_wine
|
||||
ok(pov == NULL, "expected NULL, got %p\n", pov);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -5382,6 +5382,20 @@ struct add_fd_completion_reply
|
|||
|
||||
|
||||
|
||||
struct set_fd_completion_mode_request
|
||||
{
|
||||
struct request_header __header;
|
||||
obj_handle_t handle;
|
||||
unsigned int flags;
|
||||
char __pad_20[4];
|
||||
};
|
||||
struct set_fd_completion_mode_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct set_fd_disp_info_request
|
||||
{
|
||||
struct request_header __header;
|
||||
|
@ -5918,6 +5932,7 @@ enum request
|
|||
REQ_query_completion,
|
||||
REQ_set_completion_info,
|
||||
REQ_add_fd_completion,
|
||||
REQ_set_fd_completion_mode,
|
||||
REQ_set_fd_disp_info,
|
||||
REQ_set_fd_name_info,
|
||||
REQ_get_window_layered_info,
|
||||
|
@ -6215,6 +6230,7 @@ union generic_request
|
|||
struct query_completion_request query_completion_request;
|
||||
struct set_completion_info_request set_completion_info_request;
|
||||
struct add_fd_completion_request add_fd_completion_request;
|
||||
struct set_fd_completion_mode_request set_fd_completion_mode_request;
|
||||
struct set_fd_disp_info_request set_fd_disp_info_request;
|
||||
struct set_fd_name_info_request set_fd_name_info_request;
|
||||
struct get_window_layered_info_request get_window_layered_info_request;
|
||||
|
@ -6510,6 +6526,7 @@ union generic_reply
|
|||
struct query_completion_reply query_completion_reply;
|
||||
struct set_completion_info_reply set_completion_info_reply;
|
||||
struct add_fd_completion_reply add_fd_completion_reply;
|
||||
struct set_fd_completion_mode_reply set_fd_completion_mode_reply;
|
||||
struct set_fd_disp_info_reply set_fd_disp_info_reply;
|
||||
struct set_fd_name_info_reply set_fd_name_info_reply;
|
||||
struct get_window_layered_info_reply get_window_layered_info_reply;
|
||||
|
@ -6529,6 +6546,6 @@ union generic_reply
|
|||
struct terminate_job_reply terminate_job_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 568
|
||||
#define SERVER_PROTOCOL_VERSION 569
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
25
server/fd.c
25
server/fd.c
|
@ -194,6 +194,7 @@ struct fd
|
|||
struct async_queue wait_q; /* other async waiters of this fd */
|
||||
struct completion *completion; /* completion object attached to this fd */
|
||||
apc_param_t comp_key; /* completion key to set in completion events */
|
||||
unsigned int comp_flags; /* completion flags */
|
||||
};
|
||||
|
||||
static void fd_dump( struct object *obj, int verbose );
|
||||
|
@ -1604,6 +1605,7 @@ static struct fd *alloc_fd_object(void)
|
|||
fd->fs_locks = 1;
|
||||
fd->poll_index = -1;
|
||||
fd->completion = NULL;
|
||||
fd->comp_flags = 0;
|
||||
init_async_queue( &fd->read_q );
|
||||
init_async_queue( &fd->write_q );
|
||||
init_async_queue( &fd->wait_q );
|
||||
|
@ -1639,6 +1641,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
|
|||
fd->fs_locks = 0;
|
||||
fd->poll_index = -1;
|
||||
fd->completion = NULL;
|
||||
fd->comp_flags = 0;
|
||||
fd->no_fd_status = STATUS_BAD_DEVICE_TYPE;
|
||||
init_async_queue( &fd->read_q );
|
||||
init_async_queue( &fd->write_q );
|
||||
|
@ -2200,7 +2203,7 @@ void default_fd_get_file_info( struct fd *fd, obj_handle_t handle, unsigned int
|
|||
set_error( STATUS_INFO_LENGTH_MISMATCH );
|
||||
return;
|
||||
}
|
||||
info.Flags = 0; /* FIXME */
|
||||
info.Flags = fd->comp_flags;
|
||||
set_reply_data( &info, sizeof(info) );
|
||||
break;
|
||||
}
|
||||
|
@ -2400,6 +2403,7 @@ void fd_copy_completion( struct fd *src, struct fd *dst )
|
|||
{
|
||||
assert( !dst->completion );
|
||||
dst->completion = fd_get_completion( src, &dst->comp_key );
|
||||
dst->comp_flags = src->comp_flags;
|
||||
}
|
||||
|
||||
/* flush a file buffers */
|
||||
|
@ -2613,6 +2617,25 @@ DECL_HANDLER(add_fd_completion)
|
|||
}
|
||||
}
|
||||
|
||||
/* set fd completion information */
|
||||
DECL_HANDLER(set_fd_completion_mode)
|
||||
{
|
||||
struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 );
|
||||
if (fd)
|
||||
{
|
||||
if (!(fd->options & (FILE_SYNCHRONOUS_IO_ALERT | FILE_SYNCHRONOUS_IO_NONALERT)))
|
||||
{
|
||||
/* removing COMPLETION_SKIP_ON_SUCCESS is not allowed */
|
||||
fd->comp_flags |= req->flags & ( FILE_SKIP_COMPLETION_PORT_ON_SUCCESS
|
||||
| FILE_SKIP_SET_EVENT_ON_HANDLE
|
||||
| FILE_SKIP_SET_USER_EVENT_ON_FAST_IO );
|
||||
}
|
||||
else
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
release_object( fd );
|
||||
}
|
||||
}
|
||||
|
||||
/* set fd disposition information */
|
||||
DECL_HANDLER(set_fd_disp_info)
|
||||
{
|
||||
|
|
|
@ -3700,6 +3700,13 @@ struct handle_info
|
|||
@END
|
||||
|
||||
|
||||
/* set fd completion information */
|
||||
@REQ(set_fd_completion_mode)
|
||||
obj_handle_t handle; /* handle to a file or directory */
|
||||
unsigned int flags; /* completion notification flags */
|
||||
@END
|
||||
|
||||
|
||||
/* set fd disposition information */
|
||||
@REQ(set_fd_disp_info)
|
||||
obj_handle_t handle; /* handle to a file or directory */
|
||||
|
|
|
@ -385,6 +385,7 @@ DECL_HANDLER(remove_completion);
|
|||
DECL_HANDLER(query_completion);
|
||||
DECL_HANDLER(set_completion_info);
|
||||
DECL_HANDLER(add_fd_completion);
|
||||
DECL_HANDLER(set_fd_completion_mode);
|
||||
DECL_HANDLER(set_fd_disp_info);
|
||||
DECL_HANDLER(set_fd_name_info);
|
||||
DECL_HANDLER(get_window_layered_info);
|
||||
|
@ -681,6 +682,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_query_completion,
|
||||
(req_handler)req_set_completion_info,
|
||||
(req_handler)req_add_fd_completion,
|
||||
(req_handler)req_set_fd_completion_mode,
|
||||
(req_handler)req_set_fd_disp_info,
|
||||
(req_handler)req_set_fd_name_info,
|
||||
(req_handler)req_get_window_layered_info,
|
||||
|
@ -2330,6 +2332,9 @@ C_ASSERT( FIELD_OFFSET(struct add_fd_completion_request, cvalue) == 16 );
|
|||
C_ASSERT( FIELD_OFFSET(struct add_fd_completion_request, information) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct add_fd_completion_request, status) == 32 );
|
||||
C_ASSERT( sizeof(struct add_fd_completion_request) == 40 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_fd_completion_mode_request, handle) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_fd_completion_mode_request, flags) == 16 );
|
||||
C_ASSERT( sizeof(struct set_fd_completion_mode_request) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_fd_disp_info_request, handle) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_fd_disp_info_request, unlink) == 16 );
|
||||
C_ASSERT( sizeof(struct set_fd_disp_info_request) == 24 );
|
||||
|
|
|
@ -4389,6 +4389,12 @@ static void dump_add_fd_completion_request( const struct add_fd_completion_reque
|
|||
fprintf( stderr, ", status=%08x", req->status );
|
||||
}
|
||||
|
||||
static void dump_set_fd_completion_mode_request( const struct set_fd_completion_mode_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%04x", req->handle );
|
||||
fprintf( stderr, ", flags=%08x", req->flags );
|
||||
}
|
||||
|
||||
static void dump_set_fd_disp_info_request( const struct set_fd_disp_info_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%04x", req->handle );
|
||||
|
@ -4808,6 +4814,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_query_completion_request,
|
||||
(dump_func)dump_set_completion_info_request,
|
||||
(dump_func)dump_add_fd_completion_request,
|
||||
(dump_func)dump_set_fd_completion_mode_request,
|
||||
(dump_func)dump_set_fd_disp_info_request,
|
||||
(dump_func)dump_set_fd_name_info_request,
|
||||
(dump_func)dump_get_window_layered_info_request,
|
||||
|
@ -5103,6 +5110,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
(dump_func)dump_get_window_layered_info_reply,
|
||||
NULL,
|
||||
(dump_func)dump_alloc_user_handle_reply,
|
||||
|
@ -5394,6 +5402,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"query_completion",
|
||||
"set_completion_info",
|
||||
"add_fd_completion",
|
||||
"set_fd_completion_mode",
|
||||
"set_fd_disp_info",
|
||||
"set_fd_name_info",
|
||||
"get_window_layered_info",
|
||||
|
|
Loading…
Reference in New Issue