[PATCH 2/4] ntdll: Add NtCancelSynchronousIoFile stub.

Daniel Lehman wine at gitlab.winehq.org
Sat May 7 14:48:33 CDT 2022


From: Daniel Lehman <dlehman25 at gmail.com>

Signed-off-by: Daniel Lehman <dlehman25 at gmail.com>
---
 dlls/ntdll/ntdll.spec    |   2 +
 dlls/ntdll/tests/pipe.c  | 138 +++++++++++++++++++++++++++++++++++++++
 dlls/ntdll/unix/file.c   |   9 +++
 dlls/ntdll/unix/loader.c |   1 +
 include/winternl.h       |   1 +
 5 files changed, 151 insertions(+)

diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index b1650ab4306..591fc690a24 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -153,6 +153,7 @@
 # @ stub NtCancelDeviceWakeupRequest
 @ stdcall -syscall NtCancelIoFile(long ptr)
 @ stdcall -syscall NtCancelIoFileEx(long ptr ptr)
+@ stdcall -syscall NtCancelSynchronousIoFile(long ptr ptr)
 @ stdcall -syscall NtCancelTimer(long ptr)
 @ stdcall -syscall NtClearEvent(long)
 @ stdcall -syscall NtClose(long)
@@ -1183,6 +1184,7 @@
 # @ stub ZwCancelDeviceWakeupRequest
 @ stdcall -private -syscall ZwCancelIoFile(long ptr) NtCancelIoFile
 @ stdcall -private -syscall ZwCancelIoFileEx(long ptr ptr) NtCancelIoFileEx
+@ stdcall -private -syscall ZwCancelSynchronousIoFile(long ptr ptr) NtCancelSynchronousIoFile
 @ stdcall -private -syscall ZwCancelTimer(long ptr) NtCancelTimer
 @ stdcall -private -syscall ZwClearEvent(long) NtClearEvent
 @ stdcall -private -syscall ZwClose(long) NtClose
diff --git a/dlls/ntdll/tests/pipe.c b/dlls/ntdll/tests/pipe.c
index dc9737e73d8..6ef32caab5d 100644
--- a/dlls/ntdll/tests/pipe.c
+++ b/dlls/ntdll/tests/pipe.c
@@ -79,6 +79,7 @@ static NTSTATUS (WINAPI *pNtQueryVolumeInformationFile)(HANDLE handle, PIO_STATU
 static NTSTATUS (WINAPI *pNtSetInformationFile) (HANDLE handle, PIO_STATUS_BLOCK io, PVOID ptr, ULONG len, FILE_INFORMATION_CLASS class);
 static NTSTATUS (WINAPI *pNtCancelIoFile) (HANDLE hFile, PIO_STATUS_BLOCK io_status);
 static NTSTATUS (WINAPI *pNtCancelIoFileEx) (HANDLE hFile, IO_STATUS_BLOCK *iosb, IO_STATUS_BLOCK *io_status);
+static NTSTATUS (WINAPI *pNtCancelSynchronousIoFile) (HANDLE hFile, IO_STATUS_BLOCK *iosb, IO_STATUS_BLOCK *io_status);
 static NTSTATUS (WINAPI *pNtRemoveIoCompletion)(HANDLE, PULONG_PTR, PULONG_PTR, PIO_STATUS_BLOCK, PLARGE_INTEGER);
 static void (WINAPI *pRtlInitUnicodeString) (PUNICODE_STRING target, PCWSTR source);
 
@@ -103,6 +104,7 @@ static BOOL init_func_ptrs(void)
     loadfunc(NtQueryVolumeInformationFile)
     loadfunc(NtSetInformationFile)
     loadfunc(NtCancelIoFile)
+    loadfunc(NtCancelSynchronousIoFile)
     loadfunc(RtlInitUnicodeString)
     loadfunc(NtRemoveIoCompletion)
 
@@ -562,6 +564,139 @@ static void test_cancelio(void)
     CloseHandle(hEvent);
 }
 
+struct synchronousio_thread_args
+{
+    HANDLE pipe;
+    IO_STATUS_BLOCK iosb;
+};
+
+static DWORD WINAPI synchronousio_thread(void *arg)
+{
+    struct synchronousio_thread_args *ctx = arg;
+    NTSTATUS res;
+
+    res = listen_pipe(ctx->pipe, NULL, &ctx->iosb, FALSE);
+    todo_wine
+    ok(res == STATUS_CANCELLED, "NtFsControlFile returned %lx\n", res);
+    return 0;
+}
+
+static void test_cancelsynchronousio(void)
+{
+    DWORD ret;
+    HANDLE event;
+    HANDLE thread;
+    HANDLE client;
+    NTSTATUS res;
+    IO_STATUS_BLOCK iosb;
+    struct synchronousio_thread_args ctx;
+
+    /* 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);
+    todo_wine
+    ok(res == STATUS_ACCESS_VIOLATION || broken(res == STATUS_NOT_FOUND), /* Win<10 */
+        "NtCancelSynchronousIoFile returned %lx\n", res);
+
+    /* synchronous i/o */
+    res = create_pipe(&ctx.pipe, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT);
+    ok(!res, "NtCreateNamedPipeFile returned %lx\n", res);
+
+    /* NULL io */
+    U(ctx.iosb).Status = 0xdeadbabe;
+    ctx.iosb.Information = 0xdeadbeef;
+    thread = CreateThread(NULL, 0, synchronousio_thread, &ctx, 0, 0);
+    /* wait for thread to start listening */
+    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(ctx.pipe);
+    WaitForSingleObject(thread, INFINITE);
+    CloseHandle(thread);
+    ok(U(ctx.iosb).Status == 0xdeadbabe, "wrong status %lx\n", U(ctx.iosb).Status);
+    ok(ctx.iosb.Information == 0xdeadbeef, "wrong info %Iu\n", ctx.iosb.Information);
+    }
+
+    /* specified io */
+    res = create_pipe(&ctx.pipe, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT);
+    ok(!res, "NtCreateNamedPipeFile returned %lx\n", res);
+
+    U(ctx.iosb).Status = 0xdeadbabe;
+    ctx.iosb.Information = 0xdeadbeef;
+    thread = CreateThread(NULL, 0, synchronousio_thread, &ctx, 0, 0);
+    /* wait for thread to start listening */
+    Sleep(100);
+    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);
+    res = pNtCancelSynchronousIoFile(thread, &ctx.iosb, &iosb);
+    ok(res == STATUS_SUCCESS || broken(res == STATUS_NOT_FOUND) /* 32-bit */,
+        "Failed to cancel I/O\n");
+    ok(U(iosb).Status == STATUS_SUCCESS || broken(U(iosb).Status == STATUS_NOT_FOUND) /* 32-bit */,
+        "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);
+    }
+    CloseHandle(ctx.pipe);
+    WaitForSingleObject(thread, INFINITE);
+    CloseHandle(thread);
+    ok(U(ctx.iosb).Status == 0xdeadbabe, "wrong status %lx\n", U(ctx.iosb).Status);
+    ok(ctx.iosb.Information == 0xdeadbeef, "wrong info %Iu\n", ctx.iosb.Information);
+    }
+
+    /* asynchronous i/o */
+    U(ctx.iosb).Status = 0xdeadbabe;
+    ctx.iosb.Information = 0xdeadbeef;
+    res = create_pipe(&ctx.pipe, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0 /* OVERLAPPED */);
+    ok(!res, "NtCreateNamedPipeFile returned %lx\n", res);
+    event = CreateEventW(NULL, TRUE, FALSE, NULL);
+    ok(event != INVALID_HANDLE_VALUE, "Can't create event, GetLastError: %lx\n", GetLastError());
+    res = listen_pipe(ctx.pipe, event, &ctx.iosb, FALSE);
+    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);
+    memset(&iosb, 0x55, sizeof(iosb));
+    res = pNtCancelSynchronousIoFile(GetCurrentThread(), &ctx.iosb, &iosb);
+    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,
+                         FILE_FLAG_OVERLAPPED, 0);
+    ok(client != INVALID_HANDLE_VALUE, "can't open pipe: %lu\n", GetLastError());
+    ret = WaitForSingleObject(event, 0);
+    ok(ret == WAIT_OBJECT_0, "wait returned %lx\n", ret);
+    CloseHandle(ctx.pipe);
+    CloseHandle(event);
+    CloseHandle(client);
+}
+
 static void _check_pipe_handle_state(int line, HANDLE handle, ULONG read, ULONG completion)
 {
     IO_STATUS_BLOCK iosb;
@@ -2606,6 +2741,9 @@ START_TEST(pipe)
     trace("starting cancelio tests\n");
     test_cancelio();
 
+    trace("starting cancelsynchronousio tests\n");
+    test_cancelsynchronousio();
+
     trace("starting byte read in byte mode client -> server\n");
     read_pipe_test(PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE);
     trace("starting byte read in message mode client -> server\n");
diff --git a/dlls/ntdll/unix/file.c b/dlls/ntdll/unix/file.c
index cc8bf0c6e82..6990f9b4719 100644
--- a/dlls/ntdll/unix/file.c
+++ b/dlls/ntdll/unix/file.c
@@ -5970,6 +5970,15 @@ NTSTATUS WINAPI NtCancelIoFileEx( HANDLE handle, IO_STATUS_BLOCK *io, IO_STATUS_
 }
 
 
+/**************************************************************************
+ *           NtCancelSynchronousIoFile (NTDLL.@)
+ */
+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;
+}
+
 /******************************************************************
  *           NtLockFile   (NTDLL.@)
  */
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
index 7f85582adf3..8fa3739957b 100644
--- a/dlls/ntdll/unix/loader.c
+++ b/dlls/ntdll/unix/loader.c
@@ -139,6 +139,7 @@ static void * const syscalls[] =
     NtCallbackReturn,
     NtCancelIoFile,
     NtCancelIoFileEx,
+    NtCancelSynchronousIoFile,
     NtCancelTimer,
     NtClearEvent,
     NtClose,
diff --git a/include/winternl.h b/include/winternl.h
index 84babcbb0e9..fbd23a58257 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -3927,6 +3927,7 @@ NTSYSAPI NTSTATUS  WINAPI NtAssignProcessToJobObject(HANDLE,HANDLE);
 NTSYSAPI NTSTATUS  WINAPI NtCallbackReturn(PVOID,ULONG,NTSTATUS);
 NTSYSAPI NTSTATUS  WINAPI NtCancelIoFile(HANDLE,PIO_STATUS_BLOCK);
 NTSYSAPI NTSTATUS  WINAPI NtCancelIoFileEx(HANDLE,PIO_STATUS_BLOCK,PIO_STATUS_BLOCK);
+NTSYSAPI NTSTATUS  WINAPI NtCancelSynchronousIoFile(HANDLE,PIO_STATUS_BLOCK,PIO_STATUS_BLOCK);
 NTSYSAPI NTSTATUS  WINAPI NtCancelTimer(HANDLE, BOOLEAN*);
 NTSYSAPI NTSTATUS  WINAPI NtClearEvent(HANDLE);
 NTSYSAPI NTSTATUS  WINAPI NtClose(HANDLE);
-- 
GitLab


https://gitlab.winehq.org/wine/wine/-/merge_requests/47



More information about the wine-devel mailing list