>From b09133f0d2844cf7011ff7658a2f2440d0417fd5 Mon Sep 17 00:00:00 2001
From: Adam Martinson <adam.r.martinson@gmail.com>
Date: Tue, 18 Dec 2012 17:06:49 -0600
Subject: [PATCH 5/7] ntdll: Tests for FILE_PIPE_INFORMATION.

---
 dlls/ntdll/tests/pipe.c |  123 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 123 insertions(+), 0 deletions(-)

diff --git a/dlls/ntdll/tests/pipe.c b/dlls/ntdll/tests/pipe.c
index 3ab4d07..7fb033e 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,119 @@ static void test_cancelio(void)
     CloseHandle(hPipe);
 }
 
+#define check_pipe_handle_state(handle, r, c) \
+    memset(&fpi, 0x55, sizeof(fpi)); \
+    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)
+
+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;
+
+    /* 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);
+
+    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);
+    /* CreateFile() always creates a byte-mode blocking client */
+    check_pipe_handle_state(hClient, 0, 0);
+
+    fpi.ReadMode = 0;
+    fpi.CompletionMode = 0;
+    res = pNtSetInformationFile(hServer, &iosb, &fpi, sizeof(fpi), (FILE_INFORMATION_CLASS)23);
+    /* can't set server state */
+    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);
+    /* can't set server state */
+    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(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);
+    /* CompletionMode is unchanged because the call failed */
+    check_pipe_handle_state(hClient, 0, 0);
+
+    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);
+
+    CloseHandle(hClient);
+    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);
+
+    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);
+    /* CreateFile() always creates a byte-mode blocking client */
+    check_pipe_handle_state(hClient, 0, 0);
+
+    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);
+    /* this time we can set the server state */
+    ok(!res, "NtSetInformationFile returned %x\n", res);
+
+    check_pipe_handle_state(hServer, 0, 1);
+    check_pipe_handle_state(hClient, 1, 1);
+
+    CloseHandle(hClient);
+    CloseHandle(hServer);
+}
+
 START_TEST(pipe)
 {
     if (!init_func_ptrs())
@@ -493,6 +613,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.1

