Commit 2f17e011 authored by Sebastian Lackner's avatar Sebastian Lackner Committed by Alexandre Julliard

ntdll: Add setting FileIoCompletionNotificationInformation implementation.

parent b81c0c3e
......@@ -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 */
......@@ -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",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment