Commit 0a02b6a8 authored by Daniel Lehman's avatar Daniel Lehman Committed by Alexandre Julliard

ntdll: Implement NtCancelSynchronousIoFile.

parent 05d00d5e
......@@ -648,7 +648,6 @@ static void test_cancelsynchronousio(void)
struct synchronousio_thread_args ctx;
/* bogus values */
todo_wine {
res = pNtCancelSynchronousIoFile((HANDLE)0xdeadbeef, NULL, &iosb);
ok(res == STATUS_INVALID_HANDLE, "NtCancelSynchronousIoFile returned %lx\n", res);
res = pNtCancelSynchronousIoFile(GetCurrentThread(), NULL, NULL);
......@@ -664,7 +663,6 @@ static void test_cancelsynchronousio(void)
ok(U(iosb).Status == STATUS_NOT_FOUND, "iosb.Status got changed to %lx\n", U(iosb).Status);
ok(U(iosb).Information == 0, "iosb.Information got changed to %Iu\n", U(iosb).Information);
}
}
/* synchronous i/o */
res = create_pipe(&ctx.pipe, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT);
......@@ -679,13 +677,9 @@ static void test_cancelsynchronousio(void)
ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %lu (error %lu)\n", ret, GetLastError());
memset(&iosb, 0x55, sizeof(iosb));
res = pNtCancelSynchronousIoFile(thread, NULL, &iosb);
todo_wine {
ok(res == STATUS_SUCCESS, "Failed to cancel I/O\n");
ok(U(iosb).Status == STATUS_SUCCESS, "iosb.Status got changed to %lx\n", U(iosb).Status);
ok(U(iosb).Information == 0, "iosb.Information got changed to %Iu\n", U(iosb).Information);
}
if (res == STATUS_NOT_IMPLEMENTED)
pNtCancelIoFileEx(ctx.pipe, NULL, &iosb);
ret = WaitForSingleObject(thread, 1000);
ok(ret == WAIT_OBJECT_0, "wait returned %lx\n", ret);
CloseHandle(thread);
......@@ -705,7 +699,6 @@ static void test_cancelsynchronousio(void)
ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %lu (error %lu)\n", ret, GetLastError());
memset(&iosb, 0x55, sizeof(iosb));
res = pNtCancelSynchronousIoFile(thread, &iosb, &iosb);
todo_wine {
ok(res == STATUS_NOT_FOUND, "NtCancelSynchronousIoFile returned %lx\n", res);
res = pNtCancelSynchronousIoFile(NULL, &ctx.iosb, &iosb);
ok(res == STATUS_INVALID_HANDLE, "NtCancelSynchronousIoFile returned %lx\n", res);
......@@ -715,15 +708,12 @@ static void test_cancelsynchronousio(void)
ok(U(iosb).Status == STATUS_SUCCESS || broken(is_wow64 && U(iosb).Status == STATUS_NOT_FOUND),
"iosb.Status got changed to %lx\n", U(iosb).Status);
ok(U(iosb).Information == 0, "iosb.Information got changed to %Iu\n", U(iosb).Information);
}
if (res == STATUS_NOT_FOUND)
{
res = pNtCancelSynchronousIoFile(thread, NULL, &iosb);
ok(res == STATUS_SUCCESS, "Failed to cancel I/O\n");
ok(U(iosb).Status == STATUS_SUCCESS, "iosb.Status got changed to %lx\n", U(iosb).Status);
}
if (res == STATUS_NOT_IMPLEMENTED)
pNtCancelIoFileEx(ctx.pipe, NULL, &iosb);
ret = WaitForSingleObject(thread, 1000);
ok(ret == WAIT_OBJECT_0, "wait returned %lx\n", ret);
CloseHandle(thread);
......@@ -742,7 +732,6 @@ static void test_cancelsynchronousio(void)
ok(res == STATUS_PENDING, "NtFsControlFile returned %lx\n", res);
memset(&iosb, 0x55, sizeof(iosb));
res = pNtCancelSynchronousIoFile(GetCurrentThread(), NULL, &iosb);
todo_wine {
ok(res == STATUS_NOT_FOUND, "NtCancelSynchronousIoFile returned %lx\n", res);
ok(U(iosb).Status == STATUS_NOT_FOUND, "iosb.Status got changed to %lx\n", U(iosb).Status);
ok(U(iosb).Information == 0, "iosb.Information got changed to %Iu\n", U(iosb).Information);
......@@ -751,7 +740,6 @@ static void test_cancelsynchronousio(void)
ok(res == STATUS_NOT_FOUND, "NtCancelSynchronousIoFile returned %lx\n", res);
ok(U(iosb).Status == STATUS_NOT_FOUND, "iosb.Status got changed to %lx\n", U(iosb).Status);
ok(U(iosb).Information == 0, "iosb.Information got changed to %Iu\n", U(iosb).Information);
}
ret = WaitForSingleObject(event, 0);
ok(ret == WAIT_TIMEOUT, "wait returned %lx\n", ret);
client = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,
......
......@@ -6180,8 +6180,21 @@ NTSTATUS WINAPI NtCancelIoFileEx( HANDLE handle, IO_STATUS_BLOCK *io, IO_STATUS_
*/
NTSTATUS WINAPI NtCancelSynchronousIoFile( HANDLE handle, IO_STATUS_BLOCK *io, IO_STATUS_BLOCK *io_status )
{
FIXME( "(%p,%p,%p) stub\n", handle, io, io_status );
return STATUS_NOT_IMPLEMENTED;
NTSTATUS status;
TRACE( "(%p %p %p)\n", handle, io, io_status );
SERVER_START_REQ( cancel_sync )
{
req->handle = wine_server_obj_handle( handle );
req->iosb = wine_server_client_ptr( io );
status = wine_server_call( req );
}
SERVER_END_REQ;
io_status->u.Status = status;
io_status->Information = 0;
return status;
}
/******************************************************************
......
......@@ -2905,6 +2905,17 @@ struct set_serial_info_reply
#define SERIALINFO_PENDING_WAIT 0x08
struct cancel_sync_request
{
struct request_header __header;
obj_handle_t handle;
client_ptr_t iosb;
};
struct cancel_sync_reply
{
struct reply_header __header;
};
struct register_async_request
{
......@@ -5600,6 +5611,7 @@ enum request
REQ_is_window_hung,
REQ_get_serial_info,
REQ_set_serial_info,
REQ_cancel_sync,
REQ_register_async,
REQ_cancel_async,
REQ_get_async_result,
......@@ -5884,6 +5896,7 @@ union generic_request
struct is_window_hung_request is_window_hung_request;
struct get_serial_info_request get_serial_info_request;
struct set_serial_info_request set_serial_info_request;
struct cancel_sync_request cancel_sync_request;
struct register_async_request register_async_request;
struct cancel_async_request cancel_async_request;
struct get_async_result_request get_async_result_request;
......@@ -6166,6 +6179,7 @@ union generic_reply
struct is_window_hung_reply is_window_hung_reply;
struct get_serial_info_reply get_serial_info_reply;
struct set_serial_info_reply set_serial_info_reply;
struct cancel_sync_reply cancel_sync_reply;
struct register_async_reply register_async_reply;
struct cancel_async_reply cancel_async_reply;
struct get_async_result_reply get_async_result_reply;
......@@ -6324,7 +6338,7 @@ union generic_reply
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 755
#define SERVER_PROTOCOL_VERSION 756
/* ### protocol_version end ### */
......
......@@ -588,6 +588,27 @@ restart:
return woken;
}
static int cancel_blocking( struct process *process, struct thread *thread, client_ptr_t iosb )
{
struct async *async;
int woken = 0;
restart:
LIST_FOR_EACH_ENTRY( async, &process->asyncs, struct async, process_entry )
{
if (async->terminated || async->canceled) continue;
if (async->blocking && async->thread == thread &&
(!iosb || async->data.iosb == iosb))
{
async->canceled = 1;
fd_cancel_async( async->fd, async );
woken++;
goto restart;
}
}
return woken;
}
void cancel_process_asyncs( struct process *process )
{
cancel_async( process, NULL, NULL, 0 );
......@@ -731,6 +752,19 @@ struct async *find_pending_async( struct async_queue *queue )
return NULL;
}
/* cancels sync I/O on a thread */
DECL_HANDLER(cancel_sync)
{
struct thread *thread = get_thread_from_handle( req->handle, THREAD_TERMINATE );
if (thread)
{
if (!cancel_blocking( current->process, thread, req->iosb ))
set_error( STATUS_NOT_FOUND );
release_object( thread );
}
}
/* cancels all async I/O */
DECL_HANDLER(cancel_async)
{
......
......@@ -2159,6 +2159,11 @@ enum message_type
#define SERIALINFO_PENDING_WRITE 0x04
#define SERIALINFO_PENDING_WAIT 0x08
/* Cancel all sync io on a thread */
@REQ(cancel_sync)
obj_handle_t handle; /* thread handle on which to cancel io */
client_ptr_t iosb; /* I/O status block (NULL=all) */
@END
/* Create an async I/O */
@REQ(register_async)
......
......@@ -242,6 +242,7 @@ DECL_HANDLER(kill_win_timer);
DECL_HANDLER(is_window_hung);
DECL_HANDLER(get_serial_info);
DECL_HANDLER(set_serial_info);
DECL_HANDLER(cancel_sync);
DECL_HANDLER(register_async);
DECL_HANDLER(cancel_async);
DECL_HANDLER(get_async_result);
......@@ -525,6 +526,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_is_window_hung,
(req_handler)req_get_serial_info,
(req_handler)req_set_serial_info,
(req_handler)req_cancel_sync,
(req_handler)req_register_async,
(req_handler)req_cancel_async,
(req_handler)req_get_async_result,
......@@ -1402,6 +1404,9 @@ C_ASSERT( sizeof(struct get_serial_info_reply) == 24 );
C_ASSERT( FIELD_OFFSET(struct set_serial_info_request, handle) == 12 );
C_ASSERT( FIELD_OFFSET(struct set_serial_info_request, flags) == 16 );
C_ASSERT( sizeof(struct set_serial_info_request) == 24 );
C_ASSERT( FIELD_OFFSET(struct cancel_sync_request, handle) == 12 );
C_ASSERT( FIELD_OFFSET(struct cancel_sync_request, iosb) == 16 );
C_ASSERT( sizeof(struct cancel_sync_request) == 24 );
C_ASSERT( FIELD_OFFSET(struct register_async_request, type) == 12 );
C_ASSERT( FIELD_OFFSET(struct register_async_request, async) == 16 );
C_ASSERT( FIELD_OFFSET(struct register_async_request, count) == 56 );
......
......@@ -2757,6 +2757,12 @@ static void dump_set_serial_info_request( const struct set_serial_info_request *
fprintf( stderr, ", flags=%d", req->flags );
}
static void dump_cancel_sync_request( const struct cancel_sync_request *req )
{
fprintf( stderr, " handle=%04x", req->handle );
dump_uint64( ", iosb=", &req->iosb );
}
static void dump_register_async_request( const struct register_async_request *req )
{
fprintf( stderr, " type=%d", req->type );
......@@ -4623,6 +4629,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_is_window_hung_request,
(dump_func)dump_get_serial_info_request,
(dump_func)dump_set_serial_info_request,
(dump_func)dump_cancel_sync_request,
(dump_func)dump_register_async_request,
(dump_func)dump_cancel_async_request,
(dump_func)dump_get_async_result_request,
......@@ -4905,6 +4912,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
NULL,
NULL,
NULL,
NULL,
(dump_func)dump_get_async_result_reply,
(dump_func)dump_set_async_direct_result_reply,
(dump_func)dump_read_reply,
......@@ -5183,6 +5191,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"is_window_hung",
"get_serial_info",
"set_serial_info",
"cancel_sync",
"register_async",
"cancel_async",
"get_async_result",
......
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