Commit 05d00d5e authored by Daniel Lehman's avatar Daniel Lehman Committed by Alexandre Julliard

ntdll: Add NtCancelSynchronousIoFile stub.

parent 3a4674f2
......@@ -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)
......@@ -1186,6 +1187,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
......
......@@ -75,6 +75,9 @@ typedef struct _FILE_PIPE_WAIT_FOR_BUFFER {
#endif
#endif
static BOOL is_wow64;
static BOOL (WINAPI *pIsWow64Process)(HANDLE, BOOL *);
static NTSTATUS (WINAPI *pNtFsControlFile) (HANDLE handle, HANDLE event, PIO_APC_ROUTINE apc, PVOID apc_context, PIO_STATUS_BLOCK io, ULONG code, PVOID in_buffer, ULONG in_size, PVOID out_buffer, ULONG out_size);
static NTSTATUS (WINAPI *pNtCreateDirectoryObject)(HANDLE *, ACCESS_MASK, OBJECT_ATTRIBUTES *);
static NTSTATUS (WINAPI *pNtCreateNamedPipeFile) (PHANDLE handle, ULONG access,
......@@ -90,6 +93,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);
......@@ -114,6 +118,7 @@ static BOOL init_func_ptrs(void)
loadfunc(NtQueryVolumeInformationFile)
loadfunc(NtSetInformationFile)
loadfunc(NtCancelIoFile)
loadfunc(NtCancelSynchronousIoFile)
loadfunc(RtlInitUnicodeString)
loadfunc(NtRemoveIoCompletion)
......@@ -122,6 +127,7 @@ static BOOL init_func_ptrs(void)
module = GetModuleHandleA("kernel32.dll");
pOpenThread = (void *)GetProcAddress(module, "OpenThread");
pQueueUserAPC = (void *)GetProcAddress(module, "QueueUserAPC");
pIsWow64Process = (void *)GetProcAddress(module, "IsWow64Process");
return TRUE;
}
......@@ -615,6 +621,149 @@ 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);
ok(res == STATUS_CANCELLED, "NtFsControlFile returned %lx\n", res);
return 0;
}
static void test_cancelsynchronousio(void)
{
DWORD ret;
NTSTATUS res;
HANDLE event;
HANDLE thread;
HANDLE client;
IO_STATUS_BLOCK iosb;
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);
ok(res == STATUS_ACCESS_VIOLATION, "NtCancelSynchronousIoFile returned %lx\n", res);
res = pNtCancelSynchronousIoFile(GetCurrentThread(), NULL, (IO_STATUS_BLOCK*)0xdeadbeef);
ok(res == STATUS_ACCESS_VIOLATION, "NtCancelSynchronousIoFile returned %lx\n", res);
memset(&iosb, 0x55, sizeof(iosb));
res = pNtCancelSynchronousIoFile(GetCurrentThread(), (IO_STATUS_BLOCK*)0xdeadbeef, &iosb);
ok(res == STATUS_NOT_FOUND || broken(is_wow64 && res == STATUS_ACCESS_VIOLATION),
"NtCancelSynchronousIoFile returned %lx\n", res);
if (res != STATUS_ACCESS_VIOLATION)
{
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);
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 I/O to start, which transitions the pipe handle from signaled to nonsignaled state. */
while ((ret = WaitForSingleObject(ctx.pipe, 0)) == WAIT_OBJECT_0) Sleep(1);
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);
CloseHandle(ctx.pipe);
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 I/O to start, which transitions the pipe handle from signaled to nonsignaled state. */
while ((ret = WaitForSingleObject(ctx.pipe, 0)) == WAIT_OBJECT_0) Sleep(1);
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);
res = pNtCancelSynchronousIoFile(thread, &ctx.iosb, &iosb);
ok(res == STATUS_SUCCESS || broken(is_wow64 && res == STATUS_NOT_FOUND),
"Failed to cancel I/O\n");
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);
CloseHandle(ctx.pipe);
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;
......@@ -2663,6 +2812,8 @@ START_TEST(pipe)
if (!init_func_ptrs())
return;
if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 )) is_wow64 = FALSE;
trace("starting invalid create tests\n");
test_create_invalid();
......@@ -2694,6 +2845,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");
......
......@@ -6175,6 +6175,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.@)
*/
......
......@@ -139,6 +139,7 @@ static void * const syscalls[] =
NtCallbackReturn,
NtCancelIoFile,
NtCancelIoFileEx,
NtCancelSynchronousIoFile,
NtCancelTimer,
NtClearEvent,
NtClose,
......
......@@ -228,6 +228,24 @@ NTSTATUS WINAPI wow64_NtCancelIoFileEx( UINT *args )
/**********************************************************************
* wow64_NtCancelSynchronousIoFile
*/
NTSTATUS WINAPI wow64_NtCancelSynchronousIoFile( UINT *args )
{
HANDLE handle = get_handle( &args );
IO_STATUS_BLOCK32 *io_ptr = get_ptr( &args );
IO_STATUS_BLOCK32 *io32 = get_ptr( &args );
IO_STATUS_BLOCK io;
NTSTATUS status;
status = NtCancelSynchronousIoFile( handle, (IO_STATUS_BLOCK *)io_ptr, iosb_32to64( &io, io32 ));
put_iosb( io32, &io );
return status;
}
/**********************************************************************
* wow64_NtCreateFile
*/
NTSTATUS WINAPI wow64_NtCreateFile( UINT *args )
......
......@@ -40,6 +40,7 @@
SYSCALL_ENTRY( NtCallbackReturn ) \
SYSCALL_ENTRY( NtCancelIoFile ) \
SYSCALL_ENTRY( NtCancelIoFileEx ) \
SYSCALL_ENTRY( NtCancelSynchronousIoFile ) \
SYSCALL_ENTRY( NtCancelTimer ) \
SYSCALL_ENTRY( NtClearEvent ) \
SYSCALL_ENTRY( NtClose ) \
......
......@@ -3948,6 +3948,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);
......
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