>From 6fea1c8cec0affa035df7d5bb01bdf53655f113d Mon Sep 17 00:00:00 2001
From: Adam Martinson <adam.r.martinson@gmail.com>
Date: Tue, 18 Dec 2012 19:42:53 -0600
Subject: [PATCH 8/9] kernel32: Add support for {Get|Set}NamedPipeHandleState().

RPC & InstallShield don't seem to use the args we still don't support.
---
 dlls/kernel32/sync.c       |  122 +++++++++++++++++++++++++++++++++++++-------
 dlls/kernel32/tests/pipe.c |   12 +----
 2 files changed, 104 insertions(+), 30 deletions(-)

diff --git a/dlls/kernel32/sync.c b/dlls/kernel32/sync.c
index 3264884..ad7a7b3 100644
--- a/dlls/kernel32/sync.c
+++ b/dlls/kernel32/sync.c
@@ -1696,12 +1696,24 @@ BOOL WINAPI GetNamedPipeHandleStateA(
     LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
     LPSTR lpUsername, DWORD nUsernameMaxSize)
 {
-    FIXME("%p %p %p %p %p %p %d\n",
-          hNamedPipe, lpState, lpCurInstances,
-          lpMaxCollectionCount, lpCollectDataTimeout,
-          lpUsername, nUsernameMaxSize);
+    if (lpUsername)
+    {
+        FIXME("(%p, %p, %p, %p, %p, %p, %d) partial stub!\n",
+            hNamedPipe, lpState, lpCurInstances,
+            lpMaxCollectionCount, lpCollectDataTimeout,
+            lpUsername, nUsernameMaxSize);
+        *lpUsername = 0;
+    }
+    else
+    {
+        TRACE("(%p, %p, %p, %p, %p, %p, %d)\n",
+            hNamedPipe, lpState, lpCurInstances,
+            lpMaxCollectionCount, lpCollectDataTimeout,
+            lpUsername, nUsernameMaxSize);
+    }
 
-    return FALSE;
+    return GetNamedPipeHandleStateW(hNamedPipe, lpState, lpCurInstances,
+            lpMaxCollectionCount, lpCollectDataTimeout, NULL, 0);
 }
 
 /***********************************************************************
@@ -1712,12 +1724,55 @@ BOOL WINAPI GetNamedPipeHandleStateW(
     LPDWORD lpMaxCollectionCount, LPDWORD lpCollectDataTimeout,
     LPWSTR lpUsername, DWORD nUsernameMaxSize)
 {
-    FIXME("%p %p %p %p %p %p %d\n",
-          hNamedPipe, lpState, lpCurInstances,
-          lpMaxCollectionCount, lpCollectDataTimeout,
-          lpUsername, nUsernameMaxSize);
+    IO_STATUS_BLOCK iosb;
+    NTSTATUS status;
 
-    return FALSE;
+    if (lpMaxCollectionCount || lpCollectDataTimeout || lpUsername)
+    {
+        FIXME("(%p, %p, %p, %p, %p, %p, %d) partial stub!\n",
+            hNamedPipe, lpState, lpCurInstances,
+            lpMaxCollectionCount, lpCollectDataTimeout,
+            lpUsername, nUsernameMaxSize);
+        if (lpUsername) *lpUsername = 0;
+    }
+    else
+    {
+        TRACE("(%p, %p, %p, %p, %p, %p, %d)\n",
+            hNamedPipe, lpState, lpCurInstances,
+            lpMaxCollectionCount, lpCollectDataTimeout,
+            lpUsername, nUsernameMaxSize);
+    }
+
+    if (lpState)
+    {
+        FILE_PIPE_INFORMATION fpi;
+        status = NtQueryInformationFile(hNamedPipe, &iosb, &fpi, sizeof(fpi),
+                                        FilePipeInformation);
+        if (status)
+        {
+            SetLastError( RtlNtStatusToDosError(status) );
+            return FALSE;
+        }
+
+        *lpState = (fpi.ReadMode? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE) |
+                   (fpi.CompletionMode? PIPE_NOWAIT : PIPE_WAIT);
+    }
+
+    if (lpCurInstances)
+    {
+        FILE_PIPE_LOCAL_INFORMATION fpli;
+        status = NtQueryInformationFile(hNamedPipe, &iosb, &fpli, sizeof(fpli),
+                                        FilePipeLocalInformation);
+        if (status)
+        {
+            SetLastError( RtlNtStatusToDosError(status) );
+            return FALSE;
+        }
+
+        *lpCurInstances = fpli.CurrentInstances;
+    }
+
+    return TRUE;
 }
 
 /***********************************************************************
@@ -1727,11 +1782,43 @@ BOOL WINAPI SetNamedPipeHandleState(
     HANDLE hNamedPipe, LPDWORD lpMode, LPDWORD lpMaxCollectionCount,
     LPDWORD lpCollectDataTimeout)
 {
-    /* should be a fixme, but this function is called a lot by the RPC
-     * runtime, and it slows down InstallShield a fair bit. */
-    WARN("stub: %p %p/%d %p %p\n",
-          hNamedPipe, lpMode, lpMode ? *lpMode : 0, lpMaxCollectionCount, lpCollectDataTimeout);
-    return FALSE;
+    BOOL ret = FALSE;
+    if (lpMaxCollectionCount || lpCollectDataTimeout)
+    {
+        FIXME("(%p, %p/%d, %p, %p) partial stub!\n",
+              hNamedPipe, lpMode, lpMode ? *lpMode : 0,
+              lpMaxCollectionCount, lpCollectDataTimeout);
+    }
+    else
+    {
+        TRACE("(%p, %p/%d, %p, %p)\n",
+              hNamedPipe, lpMode, lpMode ? *lpMode : 0,
+              lpMaxCollectionCount, lpCollectDataTimeout);
+    }
+
+    if (lpMode)
+    {
+        FILE_PIPE_INFORMATION fpi;
+        IO_STATUS_BLOCK iosb;
+        NTSTATUS status;
+
+        if (*lpMode & (~(PIPE_NOWAIT|PIPE_READMODE_MESSAGE)))
+        {
+            SetLastError(ERROR_INVALID_PARAMETER);
+        }
+        else
+        {
+            fpi.CompletionMode = (*lpMode & PIPE_NOWAIT)? FILE_PIPE_COMPLETE_OPERATION : FILE_PIPE_QUEUE_OPERATION;
+            fpi.ReadMode = (*lpMode & PIPE_READMODE_MESSAGE)? FILE_PIPE_MESSAGE_MODE : FILE_PIPE_BYTE_STREAM_MODE;
+
+            if ((status = NtSetInformationFile(hNamedPipe, &iosb, &fpi, sizeof(fpi), FilePipeInformation)))
+                SetLastError( RtlNtStatusToDosError(status) );
+            else
+                ret = TRUE;
+        }
+    }
+
+    return ret;
 }
 
 /***********************************************************************
@@ -1794,14 +1881,11 @@ BOOL WINAPI CallNamedPipeW(
     mode = PIPE_READMODE_MESSAGE;
     ret = SetNamedPipeHandleState(pipe, &mode, NULL, NULL);
 
-    /* Currently SetNamedPipeHandleState() is a stub returning FALSE */
-    if (ret) FIXME("Now that SetNamedPipeHandleState() is more than a stub, please update CallNamedPipeW\n");
-    /*
     if (!ret)
     {
         CloseHandle(pipe);
         return FALSE;
-    }*/
+    }
 
     ret = TransactNamedPipe(pipe, lpInput, lpInputSize, lpOutput, lpOutputSize, lpBytesRead, NULL);
     CloseHandle(pipe);
diff --git a/dlls/kernel32/tests/pipe.c b/dlls/kernel32/tests/pipe.c
index 74274f1..81772d6 100644
--- a/dlls/kernel32/tests/pipe.c
+++ b/dlls/kernel32/tests/pipe.c
@@ -228,9 +228,7 @@ static void test_CreateNamedPipe(int pipemode)
             ok(!SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
         }
         else {
-            todo_wine {
-                ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
-            }
+            ok(SetNamedPipeHandleState(hFile, &lpmode, NULL, NULL), "Change mode\n");
         
             memset(ibuf, 0, sizeof(ibuf));
             ok(WriteFile(hnp, obuf, sizeof(obuf), &written, NULL), "WriteFile5a\n");
@@ -1743,7 +1741,6 @@ static void test_NamedPipeHandleState(void)
         /* lpSecurityAttrib */ NULL);
     ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
     ret = GetNamedPipeHandleState(server, NULL, NULL, NULL, NULL, NULL, 0);
-    todo_wine
     ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
     ret = GetNamedPipeHandleState(server, &state, &instances, NULL, NULL, NULL,
         0);
@@ -1768,7 +1765,6 @@ static void test_NamedPipeHandleState(void)
     state = PIPE_READMODE_MESSAGE;
     SetLastError(0xdeadbeef);
     ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
-    todo_wine
     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
        "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
 
@@ -1778,13 +1774,11 @@ static void test_NamedPipeHandleState(void)
 
     state = PIPE_READMODE_BYTE;
     ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
-    todo_wine
     ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
     /* A byte-mode pipe client can't be changed to message mode, either. */
     state = PIPE_READMODE_MESSAGE;
     SetLastError(0xdeadbeef);
     ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
-    todo_wine
     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
        "expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
 
@@ -1800,7 +1794,6 @@ static void test_NamedPipeHandleState(void)
         /* lpSecurityAttrib */ NULL);
     ok(server != INVALID_HANDLE_VALUE, "cf failed\n");
     ret = GetNamedPipeHandleState(server, NULL, NULL, NULL, NULL, NULL, 0);
-    todo_wine
     ok(ret, "GetNamedPipeHandleState failed: %d\n", GetLastError());
     ret = GetNamedPipeHandleState(server, &state, &instances, NULL, NULL, NULL,
         0);
@@ -1816,7 +1809,6 @@ static void test_NamedPipeHandleState(void)
      */
     state = PIPE_READMODE_BYTE;
     ret = SetNamedPipeHandleState(server, &state, NULL, NULL);
-    todo_wine
     ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
 
     client = CreateFileA(PIPENAME, GENERIC_READ|GENERIC_WRITE, 0, NULL,
@@ -1825,13 +1817,11 @@ static void test_NamedPipeHandleState(void)
 
     state = PIPE_READMODE_MESSAGE;
     ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
-    todo_wine
     ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
     /* A message-mode pipe client can also be changed to byte mode.
      */
     state = PIPE_READMODE_BYTE;
     ret = SetNamedPipeHandleState(client, &state, NULL, NULL);
-    todo_wine
     ok(ret, "SetNamedPipeHandleState failed: %d\n", GetLastError());
 
     CloseHandle(client);
-- 
1.7.1

