[PATCH 3/4] ntdll: Partially implement NtCancelSynchronousIoFile.

Jin-oh Kang jinoh.kang.kr at gmail.com
Tue Apr 19 06:13:30 CDT 2022


On Tue, Apr 19, 2022, 2:49 PM Daniel Lehman <dlehman25 at gmail.com> wrote:

> Signed-off-by: Daniel Lehman <dlehman25 at gmail.com>
> ---
>  dlls/ntdll/tests/pipe.c | 11 +----------
>  dlls/ntdll/unix/file.c  | 18 ++++++++++++++++--
>  server/async.c          | 33 +++++++++++++++++++++++++++++++++
>  server/protocol.def     |  4 ++++
>  4 files changed, 54 insertions(+), 12 deletions(-)
>
> diff --git a/dlls/ntdll/tests/pipe.c b/dlls/ntdll/tests/pipe.c
> index 1298e7a37ae..cfad711a09d 100644
> --- a/dlls/ntdll/tests/pipe.c
> +++ b/dlls/ntdll/tests/pipe.c
> @@ -574,11 +574,9 @@ static DWORD WINAPI synchronousio_thread(void *arg)
>      U(iosb).Status = 0xdeadbabe;
>      iosb.Information = 0xdeadbeef;
>      res = listen_pipe(pipe, NULL, &iosb, FALSE);
> -    todo_wine {
>      ok(res == STATUS_CANCELLED, "NtFsControlFile returned %lx\n", res);
>      ok(U(iosb).Status == 0xdeadbabe, "wrong status %lx\n",
> U(iosb).Status);
>      ok(iosb.Information == 0xdeadbeef, "wrong info %Iu\n",
> iosb.Information);
> -    }
>      return 0;
>  }
>
> @@ -594,13 +592,10 @@ static void test_cancelsynchronousio(void)
>
>      /* bogus values */
>      res = pNtCancelSynchronousIoFile((HANDLE)0xdeadbeef, NULL, &iosb);
> -    todo_wine
>      ok(res == STATUS_INVALID_HANDLE, "NtCancelSynchronousIoFile returned
> %lx\n", res);
>      res = pNtCancelSynchronousIoFile(GetCurrentThread(), NULL, NULL);
> -    todo_wine
>      ok(res == STATUS_ACCESS_VIOLATION, "NtCancelSynchronousIoFile
> returned %lx\n", res);
>      res = pNtCancelSynchronousIoFile(GetCurrentThread(), NULL,
> (IO_STATUS_BLOCK*)0xdeadbeef);
> -    todo_wine
>      ok(res == STATUS_ACCESS_VIOLATION, "NtCancelSynchronousIoFile
> returned %lx\n", res);
>      memset(&iosb, 0x55, sizeof(iosb));
>      res = pNtCancelSynchronousIoFile(GetCurrentThread(),
> (HANDLE)0xdeadbeef, &iosb);
> @@ -616,14 +611,12 @@ static void test_cancelsynchronousio(void)
>      Sleep(100);
>      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);
> -    }
> -    CloseHandle(pipe);
>      WaitForSingleObject(thread, INFINITE);
>      CloseHandle(thread);
> +    CloseHandle(pipe);
>
>      /* asynchronous i/o */
>      res = create_pipe(&pipe, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0 /*
> OVERLAPPED */);
> @@ -635,11 +628,9 @@ 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);
> -    }
>      ret = WaitForSingleObject(event, 0);
>      ok(ret == WAIT_TIMEOUT, "wait returned %lx\n", ret);
>      client = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0,
> OPEN_EXISTING,
> diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
> index 6990f9b4719..d833a136357 100644
> --- a/dlls/ntdll/unix/file.c
> +++ b/dlls/ntdll/unix/file.c
> @@ -5975,8 +5975,22 @@ 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;
> +
> +    FIXME( "(%p %p %p),partial stub\n", handle, io, io_status );
> +
> +    if (io) FIXME( "stub: unused IO_STATUS_BLOCK\n" );
>

If io is specified, it should never cancel any I/O operations other than
the one specified by the parameter.

Better keep returning STATUS_NOT_IMPLEMENTED in this case?

+
> +    SERVER_START_REQ( cancel_sync )
> +    {
> +        req->handle = wine_server_obj_handle( handle );
> +        status = wine_server_call( req );
> +    }
> +    SERVER_END_REQ;
> +
> +    io_status->u.Status = status;
> +    io_status->Information = 0;
> +    return status;
>  }
>
>  /******************************************************************
> diff --git a/server/async.c b/server/async.c
> index a4fbeab555e..b78d3a0532a 100644
> --- a/server/async.c
> +++ b/server/async.c
> @@ -588,6 +588,26 @@ restart:
>      return woken;
>  }
>
> +static int cancel_blocking( struct process *process, struct thread
> *thread )
> +{
> +    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->thread == thread) && async->blocking)
> +        {
> +            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 );
> @@ -715,6 +735,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 ))
> +            set_error( STATUS_NOT_FOUND );
> +        release_object( thread );
> +    }
> +}
> +
>  /* cancels all async I/O */
>  DECL_HANDLER(cancel_async)
>  {
> diff --git a/server/protocol.def b/server/protocol.def
> index 9b7b99ae86a..52a1b7767ce 100644
> --- a/server/protocol.def
> +++ b/server/protocol.def
> @@ -2135,6 +2135,10 @@ enum message_type
>  #define SERIALINFO_PENDING_WRITE 0x04
>  #define SERIALINFO_PENDING_WAIT  0x08
>
> +/* Cancel all sync io on a thread */
> + at REQ(cancel_sync)
> +    obj_handle_t handle;        /* thread handle on which to cancel io */
> + at END
>
>  /* Create an async I/O */
>  @REQ(register_async)
> --
> 2.25.1
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20220419/b6737719/attachment.htm>


More information about the wine-devel mailing list