Skip to content

Commit 0a02b6a

Browse files
dlehman25julliard
authored andcommitted
ntdll: Implement NtCancelSynchronousIoFile.
Signed-off-by: Daniel Lehman <dlehman25@gmail.com>
1 parent 05d00d5 commit 0a02b6a

File tree

7 files changed

+83
-15
lines changed

7 files changed

+83
-15
lines changed

dlls/ntdll/tests/pipe.c

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,6 @@ static void test_cancelsynchronousio(void)
648648
struct synchronousio_thread_args ctx;
649649

650650
/* bogus values */
651-
todo_wine {
652651
res = pNtCancelSynchronousIoFile((HANDLE)0xdeadbeef, NULL, &iosb);
653652
ok(res == STATUS_INVALID_HANDLE, "NtCancelSynchronousIoFile returned %lx\n", res);
654653
res = pNtCancelSynchronousIoFile(GetCurrentThread(), NULL, NULL);
@@ -664,7 +663,6 @@ static void test_cancelsynchronousio(void)
664663
ok(U(iosb).Status == STATUS_NOT_FOUND, "iosb.Status got changed to %lx\n", U(iosb).Status);
665664
ok(U(iosb).Information == 0, "iosb.Information got changed to %Iu\n", U(iosb).Information);
666665
}
667-
}
668666

669667
/* synchronous i/o */
670668
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)
679677
ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %lu (error %lu)\n", ret, GetLastError());
680678
memset(&iosb, 0x55, sizeof(iosb));
681679
res = pNtCancelSynchronousIoFile(thread, NULL, &iosb);
682-
todo_wine {
683680
ok(res == STATUS_SUCCESS, "Failed to cancel I/O\n");
684681
ok(U(iosb).Status == STATUS_SUCCESS, "iosb.Status got changed to %lx\n", U(iosb).Status);
685682
ok(U(iosb).Information == 0, "iosb.Information got changed to %Iu\n", U(iosb).Information);
686-
}
687-
if (res == STATUS_NOT_IMPLEMENTED)
688-
pNtCancelIoFileEx(ctx.pipe, NULL, &iosb);
689683
ret = WaitForSingleObject(thread, 1000);
690684
ok(ret == WAIT_OBJECT_0, "wait returned %lx\n", ret);
691685
CloseHandle(thread);
@@ -705,7 +699,6 @@ static void test_cancelsynchronousio(void)
705699
ok(ret == WAIT_TIMEOUT, "WaitForSingleObject returned %lu (error %lu)\n", ret, GetLastError());
706700
memset(&iosb, 0x55, sizeof(iosb));
707701
res = pNtCancelSynchronousIoFile(thread, &iosb, &iosb);
708-
todo_wine {
709702
ok(res == STATUS_NOT_FOUND, "NtCancelSynchronousIoFile returned %lx\n", res);
710703
res = pNtCancelSynchronousIoFile(NULL, &ctx.iosb, &iosb);
711704
ok(res == STATUS_INVALID_HANDLE, "NtCancelSynchronousIoFile returned %lx\n", res);
@@ -715,15 +708,12 @@ static void test_cancelsynchronousio(void)
715708
ok(U(iosb).Status == STATUS_SUCCESS || broken(is_wow64 && U(iosb).Status == STATUS_NOT_FOUND),
716709
"iosb.Status got changed to %lx\n", U(iosb).Status);
717710
ok(U(iosb).Information == 0, "iosb.Information got changed to %Iu\n", U(iosb).Information);
718-
}
719711
if (res == STATUS_NOT_FOUND)
720712
{
721713
res = pNtCancelSynchronousIoFile(thread, NULL, &iosb);
722714
ok(res == STATUS_SUCCESS, "Failed to cancel I/O\n");
723715
ok(U(iosb).Status == STATUS_SUCCESS, "iosb.Status got changed to %lx\n", U(iosb).Status);
724716
}
725-
if (res == STATUS_NOT_IMPLEMENTED)
726-
pNtCancelIoFileEx(ctx.pipe, NULL, &iosb);
727717
ret = WaitForSingleObject(thread, 1000);
728718
ok(ret == WAIT_OBJECT_0, "wait returned %lx\n", ret);
729719
CloseHandle(thread);
@@ -742,7 +732,6 @@ static void test_cancelsynchronousio(void)
742732
ok(res == STATUS_PENDING, "NtFsControlFile returned %lx\n", res);
743733
memset(&iosb, 0x55, sizeof(iosb));
744734
res = pNtCancelSynchronousIoFile(GetCurrentThread(), NULL, &iosb);
745-
todo_wine {
746735
ok(res == STATUS_NOT_FOUND, "NtCancelSynchronousIoFile returned %lx\n", res);
747736
ok(U(iosb).Status == STATUS_NOT_FOUND, "iosb.Status got changed to %lx\n", U(iosb).Status);
748737
ok(U(iosb).Information == 0, "iosb.Information got changed to %Iu\n", U(iosb).Information);
@@ -751,7 +740,6 @@ static void test_cancelsynchronousio(void)
751740
ok(res == STATUS_NOT_FOUND, "NtCancelSynchronousIoFile returned %lx\n", res);
752741
ok(U(iosb).Status == STATUS_NOT_FOUND, "iosb.Status got changed to %lx\n", U(iosb).Status);
753742
ok(U(iosb).Information == 0, "iosb.Information got changed to %Iu\n", U(iosb).Information);
754-
}
755743
ret = WaitForSingleObject(event, 0);
756744
ok(ret == WAIT_TIMEOUT, "wait returned %lx\n", ret);
757745
client = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING,

dlls/ntdll/unix/file.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6180,8 +6180,21 @@ NTSTATUS WINAPI NtCancelIoFileEx( HANDLE handle, IO_STATUS_BLOCK *io, IO_STATUS_
61806180
*/
61816181
NTSTATUS WINAPI NtCancelSynchronousIoFile( HANDLE handle, IO_STATUS_BLOCK *io, IO_STATUS_BLOCK *io_status )
61826182
{
6183-
FIXME( "(%p,%p,%p) stub\n", handle, io, io_status );
6184-
return STATUS_NOT_IMPLEMENTED;
6183+
NTSTATUS status;
6184+
6185+
TRACE( "(%p %p %p)\n", handle, io, io_status );
6186+
6187+
SERVER_START_REQ( cancel_sync )
6188+
{
6189+
req->handle = wine_server_obj_handle( handle );
6190+
req->iosb = wine_server_client_ptr( io );
6191+
status = wine_server_call( req );
6192+
}
6193+
SERVER_END_REQ;
6194+
6195+
io_status->u.Status = status;
6196+
io_status->Information = 0;
6197+
return status;
61856198
}
61866199

61876200
/******************************************************************

include/wine/server_protocol.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2905,6 +2905,17 @@ struct set_serial_info_reply
29052905
#define SERIALINFO_PENDING_WAIT 0x08
29062906

29072907

2908+
struct cancel_sync_request
2909+
{
2910+
struct request_header __header;
2911+
obj_handle_t handle;
2912+
client_ptr_t iosb;
2913+
};
2914+
struct cancel_sync_reply
2915+
{
2916+
struct reply_header __header;
2917+
};
2918+
29082919

29092920
struct register_async_request
29102921
{
@@ -5600,6 +5611,7 @@ enum request
56005611
REQ_is_window_hung,
56015612
REQ_get_serial_info,
56025613
REQ_set_serial_info,
5614+
REQ_cancel_sync,
56035615
REQ_register_async,
56045616
REQ_cancel_async,
56055617
REQ_get_async_result,
@@ -5884,6 +5896,7 @@ union generic_request
58845896
struct is_window_hung_request is_window_hung_request;
58855897
struct get_serial_info_request get_serial_info_request;
58865898
struct set_serial_info_request set_serial_info_request;
5899+
struct cancel_sync_request cancel_sync_request;
58875900
struct register_async_request register_async_request;
58885901
struct cancel_async_request cancel_async_request;
58895902
struct get_async_result_request get_async_result_request;
@@ -6166,6 +6179,7 @@ union generic_reply
61666179
struct is_window_hung_reply is_window_hung_reply;
61676180
struct get_serial_info_reply get_serial_info_reply;
61686181
struct set_serial_info_reply set_serial_info_reply;
6182+
struct cancel_sync_reply cancel_sync_reply;
61696183
struct register_async_reply register_async_reply;
61706184
struct cancel_async_reply cancel_async_reply;
61716185
struct get_async_result_reply get_async_result_reply;
@@ -6324,7 +6338,7 @@ union generic_reply
63246338

63256339
/* ### protocol_version begin ### */
63266340

6327-
#define SERVER_PROTOCOL_VERSION 755
6341+
#define SERVER_PROTOCOL_VERSION 756
63286342

63296343
/* ### protocol_version end ### */
63306344

server/async.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,27 @@ static int cancel_async( struct process *process, struct object *obj, struct thr
588588
return woken;
589589
}
590590

591+
static int cancel_blocking( struct process *process, struct thread *thread, client_ptr_t iosb )
592+
{
593+
struct async *async;
594+
int woken = 0;
595+
596+
restart:
597+
LIST_FOR_EACH_ENTRY( async, &process->asyncs, struct async, process_entry )
598+
{
599+
if (async->terminated || async->canceled) continue;
600+
if (async->blocking && async->thread == thread &&
601+
(!iosb || async->data.iosb == iosb))
602+
{
603+
async->canceled = 1;
604+
fd_cancel_async( async->fd, async );
605+
woken++;
606+
goto restart;
607+
}
608+
}
609+
return woken;
610+
}
611+
591612
void cancel_process_asyncs( struct process *process )
592613
{
593614
cancel_async( process, NULL, NULL, 0 );
@@ -731,6 +752,19 @@ struct async *find_pending_async( struct async_queue *queue )
731752
return NULL;
732753
}
733754

755+
/* cancels sync I/O on a thread */
756+
DECL_HANDLER(cancel_sync)
757+
{
758+
struct thread *thread = get_thread_from_handle( req->handle, THREAD_TERMINATE );
759+
760+
if (thread)
761+
{
762+
if (!cancel_blocking( current->process, thread, req->iosb ))
763+
set_error( STATUS_NOT_FOUND );
764+
release_object( thread );
765+
}
766+
}
767+
734768
/* cancels all async I/O */
735769
DECL_HANDLER(cancel_async)
736770
{

server/protocol.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2159,6 +2159,11 @@ enum message_type
21592159
#define SERIALINFO_PENDING_WRITE 0x04
21602160
#define SERIALINFO_PENDING_WAIT 0x08
21612161

2162+
/* Cancel all sync io on a thread */
2163+
@REQ(cancel_sync)
2164+
obj_handle_t handle; /* thread handle on which to cancel io */
2165+
client_ptr_t iosb; /* I/O status block (NULL=all) */
2166+
@END
21622167

21632168
/* Create an async I/O */
21642169
@REQ(register_async)

server/request.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ DECL_HANDLER(kill_win_timer);
242242
DECL_HANDLER(is_window_hung);
243243
DECL_HANDLER(get_serial_info);
244244
DECL_HANDLER(set_serial_info);
245+
DECL_HANDLER(cancel_sync);
245246
DECL_HANDLER(register_async);
246247
DECL_HANDLER(cancel_async);
247248
DECL_HANDLER(get_async_result);
@@ -525,6 +526,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
525526
(req_handler)req_is_window_hung,
526527
(req_handler)req_get_serial_info,
527528
(req_handler)req_set_serial_info,
529+
(req_handler)req_cancel_sync,
528530
(req_handler)req_register_async,
529531
(req_handler)req_cancel_async,
530532
(req_handler)req_get_async_result,
@@ -1402,6 +1404,9 @@ C_ASSERT( sizeof(struct get_serial_info_reply) == 24 );
14021404
C_ASSERT( FIELD_OFFSET(struct set_serial_info_request, handle) == 12 );
14031405
C_ASSERT( FIELD_OFFSET(struct set_serial_info_request, flags) == 16 );
14041406
C_ASSERT( sizeof(struct set_serial_info_request) == 24 );
1407+
C_ASSERT( FIELD_OFFSET(struct cancel_sync_request, handle) == 12 );
1408+
C_ASSERT( FIELD_OFFSET(struct cancel_sync_request, iosb) == 16 );
1409+
C_ASSERT( sizeof(struct cancel_sync_request) == 24 );
14051410
C_ASSERT( FIELD_OFFSET(struct register_async_request, type) == 12 );
14061411
C_ASSERT( FIELD_OFFSET(struct register_async_request, async) == 16 );
14071412
C_ASSERT( FIELD_OFFSET(struct register_async_request, count) == 56 );

server/trace.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2757,6 +2757,12 @@ static void dump_set_serial_info_request( const struct set_serial_info_request *
27572757
fprintf( stderr, ", flags=%d", req->flags );
27582758
}
27592759

2760+
static void dump_cancel_sync_request( const struct cancel_sync_request *req )
2761+
{
2762+
fprintf( stderr, " handle=%04x", req->handle );
2763+
dump_uint64( ", iosb=", &req->iosb );
2764+
}
2765+
27602766
static void dump_register_async_request( const struct register_async_request *req )
27612767
{
27622768
fprintf( stderr, " type=%d", req->type );
@@ -4623,6 +4629,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
46234629
(dump_func)dump_is_window_hung_request,
46244630
(dump_func)dump_get_serial_info_request,
46254631
(dump_func)dump_set_serial_info_request,
4632+
(dump_func)dump_cancel_sync_request,
46264633
(dump_func)dump_register_async_request,
46274634
(dump_func)dump_cancel_async_request,
46284635
(dump_func)dump_get_async_result_request,
@@ -4905,6 +4912,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
49054912
NULL,
49064913
NULL,
49074914
NULL,
4915+
NULL,
49084916
(dump_func)dump_get_async_result_reply,
49094917
(dump_func)dump_set_async_direct_result_reply,
49104918
(dump_func)dump_read_reply,
@@ -5183,6 +5191,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
51835191
"is_window_hung",
51845192
"get_serial_info",
51855193
"set_serial_info",
5194+
"cancel_sync",
51865195
"register_async",
51875196
"cancel_async",
51885197
"get_async_result",

0 commit comments

Comments
 (0)