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:
parent
2f17e0112d
commit
4be482bc82
|
@ -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++)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
Loading…
Reference in New Issue