From: Sebastian Lackner Subject: [4/4] ntdll/tests: Add tests for FILE_PIPE_INFORMATION. Message-Id: <53EA6B74.10101@fds-team.de> Date: Tue, 12 Aug 2014 21:31:00 +0200 Based on patch by Adam Martinson. I've added more tests, and have marked failing tests as broken(...). On Windows 8 we still get some failures, but as there is a lot more going wrong there, we probably shouldn't worry about that. ;) --- dlls/ntdll/tests/pipe.c | 188 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) From 4ff5ec73bba69bec53fe967bcbf59f5a6156f4fa Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Tue, 12 Aug 2014 21:13:50 +0200 Subject: ntdll/tests: Add tests for FILE_PIPE_INFORMATION. Based on patch by Adam Martinson. --- dlls/ntdll/tests/pipe.c | 188 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) diff --git a/dlls/ntdll/tests/pipe.c b/dlls/ntdll/tests/pipe.c index c275e3d..75faf76 100644 --- a/dlls/ntdll/tests/pipe.c +++ b/dlls/ntdll/tests/pipe.c @@ -34,6 +34,11 @@ #ifndef __WINE_WINTERNL_H typedef struct { + ULONG ReadMode; + ULONG CompletionMode; +} FILE_PIPE_INFORMATION; + +typedef struct { ULONG NamedPipeType; ULONG NamedPipeConfiguration; ULONG MaximumInstances; @@ -68,6 +73,7 @@ static NTSTATUS (WINAPI *pNtCreateNamedPipeFile) (PHANDLE handle, ULONG access, ULONG inbound_quota, ULONG outbound_quota, PLARGE_INTEGER timeout); static NTSTATUS (WINAPI *pNtQueryInformationFile) (IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformation, IN ULONG Length, IN FILE_INFORMATION_CLASS FileInformationClass); +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 void (WINAPI *pRtlInitUnicodeString) (PUNICODE_STRING target, PCWSTR source); @@ -87,6 +93,7 @@ static BOOL init_func_ptrs(void) loadfunc(NtFsControlFile) loadfunc(NtCreateNamedPipeFile) loadfunc(NtQueryInformationFile) + loadfunc(NtSetInformationFile) loadfunc(NtCancelIoFile) loadfunc(RtlInitUnicodeString) @@ -479,6 +486,184 @@ static void test_cancelio(void) CloseHandle(hPipe); } +#define check_pipe_handle_state(handle, r, c) \ + do \ + { \ + memset(&fpi, 0x55, sizeof(fpi)); \ + if (handle == INVALID_HANDLE_VALUE) break; \ + res = pNtQueryInformationFile(handle, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); \ + ok(!res, "NtQueryInformationFile returned %x\n", res); \ + ok(fpi.ReadMode == r, "ReadMode == %x\n", fpi.ReadMode); \ + ok(fpi.CompletionMode == c, "CompletionMode == %x\n", fpi.CompletionMode); \ + } \ + while (0) + +static void test_filepipeinfo(void) +{ + IO_STATUS_BLOCK iosb; + OBJECT_ATTRIBUTES attr; + UNICODE_STRING name; + LARGE_INTEGER timeout; + HANDLE hServer, hClient; + FILE_PIPE_INFORMATION fpi; + NTSTATUS res; + + pRtlInitUnicodeString(&name, testpipe_nt); + + attr.Length = sizeof(attr); + attr.RootDirectory = 0; + attr.ObjectName = &name; + attr.Attributes = 0x40; /* case insensitive */ + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + + timeout.QuadPart = -100000000000ll; + + /* test with INVALID_HANDLE_VALUE */ + res = pNtQueryInformationFile(INVALID_HANDLE_VALUE, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); + ok(res == STATUS_OBJECT_TYPE_MISMATCH, "NtQueryInformationFile returned %x\n", res); + + fpi.ReadMode = 0; + fpi.CompletionMode = 0; + res = pNtSetInformationFile(INVALID_HANDLE_VALUE, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); + ok(res == STATUS_OBJECT_TYPE_MISMATCH, "NtSetInformationFile returned %x\n", res); + + /* server end with read-only attributes */ + res = pNtCreateNamedPipeFile(&hServer, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb, + FILE_SHARE_READ | FILE_SHARE_WRITE, 2 /* FILE_CREATE */, + 0, 0, 0, 1, 0xFFFFFFFF, 500, 500, &timeout); + ok(!res, "NtCreateNamedPipeFile returned %x\n", res); + + check_pipe_handle_state(hServer, 0, 1); + + hClient = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); + ok(hClient != INVALID_HANDLE_VALUE, "can't open pipe, GetLastError: %x\n", GetLastError()); + + check_pipe_handle_state(hServer, 0, 1); + check_pipe_handle_state(hClient, 0, 0); + + fpi.ReadMode = 0; + fpi.CompletionMode = 0; + res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); + ok(res == STATUS_ACCESS_DENIED, "NtSetInformationFile returned %x\n", res); + + check_pipe_handle_state(hServer, 0, 1); + check_pipe_handle_state(hClient, 0, 0); + + fpi.ReadMode = 1; /* invalid on a byte stream pipe */ + fpi.CompletionMode = 1; + res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); + ok(res == STATUS_ACCESS_DENIED, "NtSetInformationFile returned %x\n", res); + + check_pipe_handle_state(hServer, 0, 1); + check_pipe_handle_state(hClient, 0, 0); + + if (hClient != INVALID_HANDLE_VALUE) + { + fpi.ReadMode = 1; /* invalid on a byte stream pipe */ + fpi.CompletionMode = 1; + res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); + ok(res == STATUS_INVALID_PARAMETER, "NtSetInformationFile returned %x\n", res); + } + + check_pipe_handle_state(hServer, 0, 1); + check_pipe_handle_state(hClient, 0, 0); + + if (hClient != INVALID_HANDLE_VALUE) + { + fpi.ReadMode = 0; + fpi.CompletionMode = 1; + res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); + ok(!res, "NtSetInformationFile returned %x\n", res); + } + + check_pipe_handle_state(hServer, 0, 1); + check_pipe_handle_state(hClient, 0, 1); + + if (hClient != INVALID_HANDLE_VALUE) + { + fpi.ReadMode = 0; + fpi.CompletionMode = 2; /* not in range 0-1 */ + res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); + ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */, "NtSetInformationFile returned %x\n", res); + + fpi.ReadMode = 2; /* not in range 0-1 */ + fpi.CompletionMode = 0; + res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); + ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */, "NtSetInformationFile returned %x\n", res); + } + + CloseHandle(hClient); + + check_pipe_handle_state(hServer, 0, 1); + + fpi.ReadMode = 0; + fpi.CompletionMode = 0; + res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); + ok(res == STATUS_ACCESS_DENIED, "NtSetInformationFile returned %x\n", res); + + CloseHandle(hServer); + + /* message mode server with read/write attributes */ + res = pNtCreateNamedPipeFile(&hServer, FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE, &attr, &iosb, + FILE_SHARE_READ | FILE_SHARE_WRITE, 2 /* FILE_CREATE */, + 0, 1, 1, 0, 0xFFFFFFFF, 500, 500, &timeout); + ok(!res, "NtCreateNamedPipeFile returned %x\n", res); + + check_pipe_handle_state(hServer, 1, 0); + + hClient = CreateFileW(testpipe, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); + ok(hClient != INVALID_HANDLE_VALUE, "can't open pipe, GetLastError: %x\n", GetLastError()); + + check_pipe_handle_state(hServer, 1, 0); + check_pipe_handle_state(hClient, 0, 0); + + if (hClient != INVALID_HANDLE_VALUE) + { + fpi.ReadMode = 1; + fpi.CompletionMode = 1; + res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); + ok(!res, "NtSetInformationFile returned %x\n", res); + } + + check_pipe_handle_state(hServer, 1, 0); + check_pipe_handle_state(hClient, 1, 1); + + fpi.ReadMode = 0; + fpi.CompletionMode = 1; + res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); + ok(!res, "NtSetInformationFile returned %x\n", res); + + check_pipe_handle_state(hServer, 0, 1); + check_pipe_handle_state(hClient, 1, 1); + + if (hClient != INVALID_HANDLE_VALUE) + { + fpi.ReadMode = 0; + fpi.CompletionMode = 2; /* not in range 0-1 */ + res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); + ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */, "NtSetInformationFile returned %x\n", res); + + fpi.ReadMode = 2; /* not in range 0-1 */ + fpi.CompletionMode = 0; + res = pNtSetInformationFile(hClient, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); + ok(res == STATUS_INVALID_PARAMETER || broken(!res) /* < Vista */, "NtSetInformationFile returned %x\n", res); + } + + CloseHandle(hClient); + + check_pipe_handle_state(hServer, 0, 1); + + fpi.ReadMode = 1; + fpi.CompletionMode = 0; + res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23); + ok(!res, "NtSetInformationFile returned %x\n", res); + + check_pipe_handle_state(hServer, 1, 0); + + CloseHandle(hServer); +} + START_TEST(pipe) { if (!init_func_ptrs()) @@ -493,6 +678,9 @@ START_TEST(pipe) trace("starting overlapped tests\n"); test_overlapped(); + trace("starting FILE_PIPE_INFORMATION tests\n"); + test_filepipeinfo(); + if (!pOpenThread || !pQueueUserAPC) return; -- 1.7.9.5