ntdll/tests: Added more FILE_SKIP_COMPLETION_PORT_ON_SUCCESS tests.

Based on a patch by Sebastian Lackner.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2018-10-25 14:55:57 +02:00 committed by Alexandre Julliard
parent 2f17e0112d
commit 4be482bc82
2 changed files with 198 additions and 9 deletions

View file

@ -3315,6 +3315,24 @@ static void test_file_all_name_information(void)
HeapFree( GetProcessHeap(), 0, file_name );
}
#define test_completion_flags(a,b) _test_completion_flags(__LINE__,a,b)
static void _test_completion_flags(unsigned line, HANDLE handle, DWORD expected_flags)
{
FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info;
IO_STATUS_BLOCK io;
NTSTATUS status;
info.Flags = 0xdeadbeef;
status = pNtQueryInformationFile(handle, &io, &info, sizeof(info),
FileIoCompletionNotificationInformation);
ok_(__FILE__,line)(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
ok_(__FILE__,line)(io.Status == STATUS_SUCCESS, "Status = %x\n", io.Status);
ok_(__FILE__,line)(io.Information == sizeof(info), "Information = %lu\n", io.Information);
/* FILE_SKIP_SET_USER_EVENT_ON_FAST_IO is not supported on win2k3 */
ok_(__FILE__,line)((info.Flags & ~FILE_SKIP_SET_USER_EVENT_ON_FAST_IO) == expected_flags,
"got %08x\n", info.Flags);
}
static void test_file_completion_information(void)
{
static const char buf[] = "testdata";
@ -3350,13 +3368,31 @@ static void test_file_completion_information(void)
info.Flags = FILE_SKIP_SET_EVENT_ON_HANDLE;
status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
test_completion_flags(h, FILE_SKIP_SET_EVENT_ON_HANDLE);
info.Flags = FILE_SKIP_SET_USER_EVENT_ON_FAST_IO;
status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
test_completion_flags(h, FILE_SKIP_SET_EVENT_ON_HANDLE);
info.Flags = 0;
status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
test_completion_flags(h, FILE_SKIP_SET_EVENT_ON_HANDLE);
info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
test_completion_flags(h, FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
info.Flags = 0xdeadbeef;
status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
test_completion_flags(h, FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
CloseHandle(h);
if (!(h = create_temp_file(FILE_FLAG_OVERLAPPED))) return;
test_completion_flags(h, 0);
memset(&ov, 0, sizeof(ov));
ov.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
@ -3391,6 +3427,7 @@ static void test_file_completion_information(void)
info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
test_completion_flags(h, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
for (i = 0; i < 10; i++)
{
@ -3418,6 +3455,7 @@ static void test_file_completion_information(void)
info.Flags = 0;
status = pNtSetInformationFile(h, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
test_completion_flags(h, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
for (i = 0; i < 10; i++)
{

View file

@ -77,6 +77,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 *pNtRemoveIoCompletion)(HANDLE, PULONG_PTR, PULONG_PTR, PIO_STATUS_BLOCK, PLARGE_INTEGER);
static void (WINAPI *pRtlInitUnicodeString) (PUNICODE_STRING target, PCWSTR source);
static HANDLE (WINAPI *pOpenThread)(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId);
@ -99,6 +100,7 @@ static BOOL init_func_ptrs(void)
loadfunc(NtSetInformationFile)
loadfunc(NtCancelIoFile)
loadfunc(RtlInitUnicodeString)
loadfunc(NtRemoveIoCompletion)
/* not fatal */
pNtCancelIoFileEx = (void *)GetProcAddress(module, "NtCancelIoFileEx");
@ -807,30 +809,31 @@ static void test_peek(HANDLE pipe)
static BOOL create_pipe_pair( HANDLE *read, HANDLE *write, ULONG flags, ULONG type, ULONG size )
{
const BOOL server_reader = flags & PIPE_ACCESS_INBOUND;
HANDLE client, server;
server = CreateNamedPipeA(PIPENAME, flags, PIPE_WAIT | type,
1, size, size, NMPWAIT_USE_DEFAULT_WAIT, NULL);
ok(server != INVALID_HANDLE_VALUE, "CreateNamedPipe failed\n");
client = CreateFileA(PIPENAME, server_reader ? GENERIC_WRITE : GENERIC_READ | FILE_WRITE_ATTRIBUTES, 0,
client = CreateFileA(PIPENAME, (flags & PIPE_ACCESS_INBOUND ? GENERIC_WRITE : 0)
| (flags & PIPE_ACCESS_OUTBOUND ? GENERIC_READ : 0)
| FILE_WRITE_ATTRIBUTES, 0,
NULL, OPEN_EXISTING, flags & FILE_FLAG_OVERLAPPED, 0);
ok(client != INVALID_HANDLE_VALUE, "CreateFile failed (%d)\n", GetLastError());
if(server_reader)
if ((type & PIPE_READMODE_MESSAGE) && (flags & PIPE_ACCESS_OUTBOUND))
{
DWORD read_mode = PIPE_READMODE_MESSAGE;
ok(SetNamedPipeHandleState(client, &read_mode, NULL, NULL), "Change mode\n");
}
if (flags & PIPE_ACCESS_INBOUND)
{
*read = server;
*write = client;
}
else
{
if(type & PIPE_READMODE_MESSAGE)
{
DWORD read_mode = PIPE_READMODE_MESSAGE;
ok(SetNamedPipeHandleState(client, &read_mode, NULL, NULL), "Change mode\n");
}
*read = client;
*write = server;
}
@ -1200,6 +1203,151 @@ static void test_transceive(void)
CloseHandle( callee );
}
#define test_no_queued_completion(a) _test_no_queued_completion(__LINE__,a)
static void _test_no_queued_completion(unsigned line, HANDLE port)
{
OVERLAPPED *pov;
DWORD num_bytes;
ULONG_PTR key;
BOOL ret;
pov = (void *)0xdeadbeef;
ret = GetQueuedCompletionStatus(port, &num_bytes, &key, &pov, 10);
ok_(__FILE__,line)(!ret && GetLastError() == WAIT_TIMEOUT,
"GetQueuedCompletionStatus returned %x(%u)\n", ret, GetLastError());
}
#define test_queued_completion(a,b,c,d) _test_queued_completion(__LINE__,a,b,c,d)
static void _test_queued_completion(unsigned line, HANDLE port, IO_STATUS_BLOCK *io,
NTSTATUS expected_status, ULONG expected_information)
{
LARGE_INTEGER timeout = {{0}};
ULONG_PTR value = 0xdeadbeef;
IO_STATUS_BLOCK iosb;
ULONG_PTR key;
NTSTATUS status;
status = pNtRemoveIoCompletion(port, &key, &value, &iosb, &timeout);
ok_(__FILE__,line)(status == STATUS_SUCCESS, "NtRemoveIoCompletion returned %x\n", status);
ok_(__FILE__,line)(value == (ULONG_PTR)io, "value = %lx\n", value);
ok_(__FILE__,line)(io->Status == expected_status, "Status = %x\n", io->Status);
ok_(__FILE__,line)(io->Information == expected_information,
"Information = %lu\n", io->Information);
}
static void test_completion(void)
{
static const char buf[] = "testdata";
FILE_IO_COMPLETION_NOTIFICATION_INFORMATION info;
FILE_PIPE_PEEK_BUFFER peek_buf;
char read_buf[16];
HANDLE port, pipe, client;
OVERLAPPED ov;
IO_STATUS_BLOCK io;
NTSTATUS status;
DWORD num_bytes;
BOOL ret;
create_pipe_pair( &pipe, &client, FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 4096 );
status = pNtQueryInformationFile(pipe, &io, &info, sizeof(info),
FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS || broken(status == STATUS_INVALID_INFO_CLASS),
"status = %x\n", status);
if (status)
{
win_skip("FileIoCompletionNotificationInformation not supported\n");
CloseHandle(pipe);
CloseHandle(client);
return;
}
memset(&ov, 0, sizeof(ov));
ov.hEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
ok(ov.hEvent != INVALID_HANDLE_VALUE, "CreateEvent failed, error %u\n", GetLastError());
port = CreateIoCompletionPort(client, NULL, 0xdeadbeef, 0);
ok(port != NULL, "CreateIoCompletionPort failed, error %u\n", GetLastError());
ret = WriteFile(client, buf, sizeof(buf), &num_bytes, &ov);
ok(ret, "WriteFile failed, error %u\n", GetLastError());
ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
test_queued_completion(port, (IO_STATUS_BLOCK*)&ov, STATUS_SUCCESS, num_bytes);
status = NtFsControlFile(client, NULL, NULL, &io, &io, FSCTL_PIPE_PEEK,
NULL, 0, &peek_buf, sizeof(peek_buf));
ok(status == STATUS_PENDING || status == STATUS_SUCCESS, "FSCTL_PIPE_PEEK returned %x\n", status);
test_queued_completion(port, &io, STATUS_SUCCESS, FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data));
info.Flags = FILE_SKIP_COMPLETION_PORT_ON_SUCCESS;
status = pNtSetInformationFile(client, &io, &info, sizeof(info), FileIoCompletionNotificationInformation);
ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %08x\n", status);
ret = WriteFile(client, buf, sizeof(buf), &num_bytes, &ov);
ok(ret, "WriteFile failed, error %u\n", GetLastError());
ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
todo_wine
test_no_queued_completion(port);
ret = WriteFile(pipe, buf, sizeof(buf), &num_bytes, &ov);
ok(ret, "WriteFile failed, error %u\n", GetLastError());
ok(num_bytes == sizeof(buf), "expected sizeof(buf), got %u\n", num_bytes);
status = NtReadFile(client, NULL, NULL, &io, &io, read_buf, 1, NULL, NULL);
ok(status == STATUS_BUFFER_OVERFLOW || status == STATUS_PENDING, "status = %x\n", status);
ok(io.Status == STATUS_BUFFER_OVERFLOW, "Status = %x\n", io.Status);
ok(io.Information == 1, "Information = %lu\n", io.Information);
if(status == STATUS_PENDING) /* win8+ */
test_queued_completion(port, &io, STATUS_BUFFER_OVERFLOW, 1);
else
todo_wine
test_no_queued_completion(port);
status = NtReadFile(client, NULL, NULL, &io, &io, read_buf, sizeof(read_buf), NULL, NULL);
ok(status == STATUS_SUCCESS, "status = %x\n", status);
ok(io.Status == STATUS_SUCCESS, "Status = %x\n", io.Status);
ok(io.Information == sizeof(buf)-1, "Information = %lu\n", io.Information);
todo_wine
test_no_queued_completion(port);
status = NtFsControlFile(client, NULL, NULL, &io, &io, FSCTL_PIPE_PEEK,
NULL, 0, &peek_buf, sizeof(peek_buf));
ok(status == STATUS_PENDING || status == STATUS_SUCCESS, "FSCTL_PIPE_PEEK returned %x\n", status);
if(status == STATUS_PENDING) /* win8+ */
test_queued_completion(port, &io, STATUS_SUCCESS, FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data));
else
todo_wine
test_no_queued_completion(port);
memset(&io, 0xcc, sizeof(io));
status = NtReadFile(client, ov.hEvent, NULL, &io, &io, read_buf, sizeof(read_buf), NULL, NULL);
ok(status == STATUS_PENDING, "status = %x\n", status);
ok(!is_signaled(ov.hEvent), "event is signtaled\n");
test_no_queued_completion(port);
ret = WriteFile(pipe, buf, sizeof(buf), &num_bytes, NULL);
ok(ret, "WriteFile failed, error %u\n", GetLastError());
test_queued_completion(port, &io, STATUS_SUCCESS, sizeof(buf));
ret = WriteFile(pipe, buf, sizeof(buf), &num_bytes, NULL);
ok(ret, "WriteFile failed, error %u\n", GetLastError());
status = NtFsControlFile(client, NULL, NULL, &io, &io, FSCTL_PIPE_PEEK,
NULL, 0, &peek_buf, sizeof(peek_buf));
ok(status == STATUS_PENDING || status == STATUS_BUFFER_OVERFLOW,
"FSCTL_PIPE_PEEK returned %x\n", status);
if(status == STATUS_PENDING) /* win8+ */
test_queued_completion(port, &io, STATUS_BUFFER_OVERFLOW, sizeof(peek_buf));
else
todo_wine
test_no_queued_completion(port);
CloseHandle(ov.hEvent);
CloseHandle(client);
CloseHandle(pipe);
CloseHandle(port);
}
static void test_volume_info(void)
{
FILE_FS_DEVICE_INFORMATION *device_info;
@ -1946,6 +2094,9 @@ START_TEST(pipe)
trace("starting overlapped tests\n");
test_overlapped();
trace("starting completion tests\n");
test_completion();
trace("starting FILE_PIPE_INFORMATION tests\n");
test_filepipeinfo();