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, ...@@ -2656,6 +2656,25 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
io->u.Status = STATUS_INVALID_PARAMETER_3; io->u.Status = STATUS_INVALID_PARAMETER_3;
break; 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: case FileAllInformation:
io->u.Status = STATUS_INVALID_INFO_CLASS; io->u.Status = STATUS_INVALID_INFO_CLASS;
break; break;
......
...@@ -3331,12 +3331,11 @@ static void test_file_completion_information(void) ...@@ -3331,12 +3331,11 @@ static void test_file_completion_information(void)
if (!(h = create_temp_file(0))) return; if (!(h = create_temp_file(0))) return;
status = pNtSetInformationFile(h, &io, &info, sizeof(info) - 1, FileIoCompletionNotificationInformation); status = pNtSetInformationFile(h, &io, &info, sizeof(info) - 1, FileIoCompletionNotificationInformation);
todo_wine ok(status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INVALID_INFO_CLASS /* XP */),
ok(status == STATUS_INFO_LENGTH_MISMATCH || status == STATUS_INVALID_INFO_CLASS /* XP */,
"expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status); "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); CloseHandle(h);
return; return;
} }
...@@ -3408,7 +3407,9 @@ static void test_file_completion_information(void) ...@@ -3408,7 +3407,9 @@ static void test_file_completion_information(void)
pov = (void *)0xdeadbeef; pov = (void *)0xdeadbeef;
ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 500); ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 500);
todo_wine
ok(!ret, "GetQueuedCompletionStatus succeeded\n"); ok(!ret, "GetQueuedCompletionStatus succeeded\n");
todo_wine
ok(pov == NULL, "expected NULL, got %p\n", pov); ok(pov == NULL, "expected NULL, got %p\n", pov);
} }
else else
...@@ -3435,7 +3436,9 @@ static void test_file_completion_information(void) ...@@ -3435,7 +3436,9 @@ static void test_file_completion_information(void)
pov = (void *)0xdeadbeef; pov = (void *)0xdeadbeef;
ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000); ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 1000);
todo_wine
ok(!ret, "GetQueuedCompletionStatus succeeded\n"); ok(!ret, "GetQueuedCompletionStatus succeeded\n");
todo_wine
ok(pov == NULL, "expected NULL, got %p\n", pov); ok(pov == NULL, "expected NULL, got %p\n", pov);
} }
else else
......
...@@ -5382,6 +5382,20 @@ struct add_fd_completion_reply ...@@ -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 set_fd_disp_info_request
{ {
struct request_header __header; struct request_header __header;
...@@ -5918,6 +5932,7 @@ enum request ...@@ -5918,6 +5932,7 @@ enum request
REQ_query_completion, REQ_query_completion,
REQ_set_completion_info, REQ_set_completion_info,
REQ_add_fd_completion, REQ_add_fd_completion,
REQ_set_fd_completion_mode,
REQ_set_fd_disp_info, REQ_set_fd_disp_info,
REQ_set_fd_name_info, REQ_set_fd_name_info,
REQ_get_window_layered_info, REQ_get_window_layered_info,
...@@ -6215,6 +6230,7 @@ union generic_request ...@@ -6215,6 +6230,7 @@ union generic_request
struct query_completion_request query_completion_request; struct query_completion_request query_completion_request;
struct set_completion_info_request set_completion_info_request; struct set_completion_info_request set_completion_info_request;
struct add_fd_completion_request add_fd_completion_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_disp_info_request set_fd_disp_info_request;
struct set_fd_name_info_request set_fd_name_info_request; struct set_fd_name_info_request set_fd_name_info_request;
struct get_window_layered_info_request get_window_layered_info_request; struct get_window_layered_info_request get_window_layered_info_request;
...@@ -6510,6 +6526,7 @@ union generic_reply ...@@ -6510,6 +6526,7 @@ union generic_reply
struct query_completion_reply query_completion_reply; struct query_completion_reply query_completion_reply;
struct set_completion_info_reply set_completion_info_reply; struct set_completion_info_reply set_completion_info_reply;
struct add_fd_completion_reply add_fd_completion_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_disp_info_reply set_fd_disp_info_reply;
struct set_fd_name_info_reply set_fd_name_info_reply; struct set_fd_name_info_reply set_fd_name_info_reply;
struct get_window_layered_info_reply get_window_layered_info_reply; struct get_window_layered_info_reply get_window_layered_info_reply;
...@@ -6529,6 +6546,6 @@ union generic_reply ...@@ -6529,6 +6546,6 @@ union generic_reply
struct terminate_job_reply terminate_job_reply; struct terminate_job_reply terminate_job_reply;
}; };
#define SERVER_PROTOCOL_VERSION 568 #define SERVER_PROTOCOL_VERSION 569
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
...@@ -194,6 +194,7 @@ struct fd ...@@ -194,6 +194,7 @@ struct fd
struct async_queue wait_q; /* other async waiters of this fd */ struct async_queue wait_q; /* other async waiters of this fd */
struct completion *completion; /* completion object attached to this fd */ struct completion *completion; /* completion object attached to this fd */
apc_param_t comp_key; /* completion key to set in completion events */ 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 ); static void fd_dump( struct object *obj, int verbose );
...@@ -1604,6 +1605,7 @@ static struct fd *alloc_fd_object(void) ...@@ -1604,6 +1605,7 @@ static struct fd *alloc_fd_object(void)
fd->fs_locks = 1; fd->fs_locks = 1;
fd->poll_index = -1; fd->poll_index = -1;
fd->completion = NULL; fd->completion = NULL;
fd->comp_flags = 0;
init_async_queue( &fd->read_q ); init_async_queue( &fd->read_q );
init_async_queue( &fd->write_q ); init_async_queue( &fd->write_q );
init_async_queue( &fd->wait_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 ...@@ -1639,6 +1641,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use
fd->fs_locks = 0; fd->fs_locks = 0;
fd->poll_index = -1; fd->poll_index = -1;
fd->completion = NULL; fd->completion = NULL;
fd->comp_flags = 0;
fd->no_fd_status = STATUS_BAD_DEVICE_TYPE; fd->no_fd_status = STATUS_BAD_DEVICE_TYPE;
init_async_queue( &fd->read_q ); init_async_queue( &fd->read_q );
init_async_queue( &fd->write_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 ...@@ -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 ); set_error( STATUS_INFO_LENGTH_MISMATCH );
return; return;
} }
info.Flags = 0; /* FIXME */ info.Flags = fd->comp_flags;
set_reply_data( &info, sizeof(info) ); set_reply_data( &info, sizeof(info) );
break; break;
} }
...@@ -2400,6 +2403,7 @@ void fd_copy_completion( struct fd *src, struct fd *dst ) ...@@ -2400,6 +2403,7 @@ void fd_copy_completion( struct fd *src, struct fd *dst )
{ {
assert( !dst->completion ); assert( !dst->completion );
dst->completion = fd_get_completion( src, &dst->comp_key ); dst->completion = fd_get_completion( src, &dst->comp_key );
dst->comp_flags = src->comp_flags;
} }
/* flush a file buffers */ /* flush a file buffers */
...@@ -2613,6 +2617,25 @@ DECL_HANDLER(add_fd_completion) ...@@ -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 */ /* set fd disposition information */
DECL_HANDLER(set_fd_disp_info) DECL_HANDLER(set_fd_disp_info)
{ {
......
...@@ -3700,6 +3700,13 @@ struct handle_info ...@@ -3700,6 +3700,13 @@ struct handle_info
@END @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 */ /* set fd disposition information */
@REQ(set_fd_disp_info) @REQ(set_fd_disp_info)
obj_handle_t handle; /* handle to a file or directory */ obj_handle_t handle; /* handle to a file or directory */
......
...@@ -385,6 +385,7 @@ DECL_HANDLER(remove_completion); ...@@ -385,6 +385,7 @@ DECL_HANDLER(remove_completion);
DECL_HANDLER(query_completion); DECL_HANDLER(query_completion);
DECL_HANDLER(set_completion_info); DECL_HANDLER(set_completion_info);
DECL_HANDLER(add_fd_completion); DECL_HANDLER(add_fd_completion);
DECL_HANDLER(set_fd_completion_mode);
DECL_HANDLER(set_fd_disp_info); DECL_HANDLER(set_fd_disp_info);
DECL_HANDLER(set_fd_name_info); DECL_HANDLER(set_fd_name_info);
DECL_HANDLER(get_window_layered_info); DECL_HANDLER(get_window_layered_info);
...@@ -681,6 +682,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = ...@@ -681,6 +682,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_query_completion, (req_handler)req_query_completion,
(req_handler)req_set_completion_info, (req_handler)req_set_completion_info,
(req_handler)req_add_fd_completion, (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_disp_info,
(req_handler)req_set_fd_name_info, (req_handler)req_set_fd_name_info,
(req_handler)req_get_window_layered_info, (req_handler)req_get_window_layered_info,
...@@ -2330,6 +2332,9 @@ C_ASSERT( FIELD_OFFSET(struct add_fd_completion_request, cvalue) == 16 ); ...@@ -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, information) == 24 );
C_ASSERT( FIELD_OFFSET(struct add_fd_completion_request, status) == 32 ); C_ASSERT( FIELD_OFFSET(struct add_fd_completion_request, status) == 32 );
C_ASSERT( sizeof(struct add_fd_completion_request) == 40 ); 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, handle) == 12 );
C_ASSERT( FIELD_OFFSET(struct set_fd_disp_info_request, unlink) == 16 ); C_ASSERT( FIELD_OFFSET(struct set_fd_disp_info_request, unlink) == 16 );
C_ASSERT( sizeof(struct set_fd_disp_info_request) == 24 ); 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 ...@@ -4389,6 +4389,12 @@ static void dump_add_fd_completion_request( const struct add_fd_completion_reque
fprintf( stderr, ", status=%08x", req->status ); 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 ) static void dump_set_fd_disp_info_request( const struct set_fd_disp_info_request *req )
{ {
fprintf( stderr, " handle=%04x", req->handle ); fprintf( stderr, " handle=%04x", req->handle );
...@@ -4808,6 +4814,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { ...@@ -4808,6 +4814,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_query_completion_request, (dump_func)dump_query_completion_request,
(dump_func)dump_set_completion_info_request, (dump_func)dump_set_completion_info_request,
(dump_func)dump_add_fd_completion_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_disp_info_request,
(dump_func)dump_set_fd_name_info_request, (dump_func)dump_set_fd_name_info_request,
(dump_func)dump_get_window_layered_info_request, (dump_func)dump_get_window_layered_info_request,
...@@ -5103,6 +5110,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { ...@@ -5103,6 +5110,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL,
(dump_func)dump_get_window_layered_info_reply, (dump_func)dump_get_window_layered_info_reply,
NULL, NULL,
(dump_func)dump_alloc_user_handle_reply, (dump_func)dump_alloc_user_handle_reply,
...@@ -5394,6 +5402,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { ...@@ -5394,6 +5402,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"query_completion", "query_completion",
"set_completion_info", "set_completion_info",
"add_fd_completion", "add_fd_completion",
"set_fd_completion_mode",
"set_fd_disp_info", "set_fd_disp_info",
"set_fd_name_info", "set_fd_name_info",
"get_window_layered_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