ConnectNamedPipe must return TRUE if lpOverlapped is not NULL and NtFsIoControl retur...
[reactos.git] / reactos / lib / kernel32 / file / npipe.c
index b16f14d..687888b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: npipe.c,v 1.12 2002/09/07 15:12:26 chorns Exp $
+/* $Id$
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
 
 /* INCLUDES *****************************************************************/
 
-#include <windows.h>
-#define NTOS_USER_MODE
-#include <ntos.h>
-#include <kernel32/error.h>
-#include <limits.h>
+#include <k32.h>
 
 #define NDEBUG
-#include <kernel32/kernel32.h>
+#include "../include/debug.h"
 
 /* FUNCTIONS ****************************************************************/
 
+/*
+ * @implemented
+ */
 HANDLE STDCALL
 CreateNamedPipeA(LPCSTR lpName,
                 DWORD dwOpenMode,
@@ -53,6 +52,9 @@ CreateNamedPipeA(LPCSTR lpName,
 }
 
 
+/*
+ * @implemented
+ */
 HANDLE STDCALL
 CreateNamedPipeW(LPCWSTR lpName,
                 DWORD dwOpenMode,
@@ -71,13 +73,14 @@ CreateNamedPipeW(LPCWSTR lpName,
    ACCESS_MASK DesiredAccess;
    ULONG CreateOptions;
    ULONG CreateDisposition;
-   BOOLEAN WriteModeMessage;
-   BOOLEAN ReadModeMessage;
-   BOOLEAN NonBlocking;
+   ULONG WriteModeMessage;
+   ULONG ReadModeMessage;
+   ULONG NonBlocking;
    IO_STATUS_BLOCK Iosb;
-   ULONG ShareAccess;
+   ULONG ShareAccess, Attributes;
    LARGE_INTEGER DefaultTimeOut;
-   
+   PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
+
    Result = RtlDosPathNameToNtPathName_U((LPWSTR)lpName,
                                         &NamedPipeName,
                                         NULL,
@@ -87,90 +90,98 @@ CreateNamedPipeW(LPCWSTR lpName,
        SetLastError(ERROR_PATH_NOT_FOUND);
        return(INVALID_HANDLE_VALUE);
      }
-   
+
    DPRINT("Pipe name: %wZ\n", &NamedPipeName);
    DPRINT("Pipe name: %S\n", NamedPipeName.Buffer);
-   
+
+   Attributes = OBJ_CASE_INSENSITIVE;
+   if(lpSecurityAttributes)
+     {
+       SecurityDescriptor = lpSecurityAttributes->lpSecurityDescriptor;
+       if(lpSecurityAttributes->bInheritHandle)
+          Attributes |= OBJ_INHERIT;
+     }
+
    InitializeObjectAttributes(&ObjectAttributes,
                              &NamedPipeName,
-                             OBJ_CASE_INSENSITIVE,
+                             Attributes,
                              NULL,
-                             NULL);
-   
+                             SecurityDescriptor);
+
    DesiredAccess = 0;
-   
    ShareAccess = 0;
-   
    CreateDisposition = FILE_OPEN_IF;
-   
    CreateOptions = 0;
    if (dwOpenMode & FILE_FLAG_WRITE_THROUGH)
      {
        CreateOptions = CreateOptions | FILE_WRITE_THROUGH;
      }
-   if (dwOpenMode & FILE_FLAG_OVERLAPPED)
+   if (!(dwOpenMode & FILE_FLAG_OVERLAPPED))
      {
-       CreateOptions = CreateOptions | FILE_SYNCHRONOUS_IO_ALERT;
+       CreateOptions = CreateOptions | FILE_SYNCHRONOUS_IO_NONALERT;
      }
    if (dwOpenMode & PIPE_ACCESS_DUPLEX)
      {
        CreateOptions = CreateOptions | FILE_PIPE_FULL_DUPLEX;
+       DesiredAccess |= (FILE_GENERIC_READ | FILE_GENERIC_WRITE);
      }
    else if (dwOpenMode & PIPE_ACCESS_INBOUND)
      {
        CreateOptions = CreateOptions | FILE_PIPE_INBOUND;
+       DesiredAccess |= FILE_GENERIC_READ;
      }
    else if (dwOpenMode & PIPE_ACCESS_OUTBOUND)
      {
        CreateOptions = CreateOptions | FILE_PIPE_OUTBOUND;
+       DesiredAccess |= FILE_GENERIC_WRITE;
      }
-   
+
    if (dwPipeMode & PIPE_TYPE_BYTE)
      {
-       WriteModeMessage = FALSE;
+       WriteModeMessage = FILE_PIPE_BYTE_STREAM_MODE;
      }
    else if (dwPipeMode & PIPE_TYPE_MESSAGE)
      {
-       WriteModeMessage = TRUE;
+       WriteModeMessage = FILE_PIPE_MESSAGE_MODE;
      }
    else
      {
-       WriteModeMessage = FALSE;
+       WriteModeMessage = FILE_PIPE_BYTE_STREAM_MODE;
      }
-   
+
    if (dwPipeMode & PIPE_READMODE_BYTE)
      {
-       ReadModeMessage = FALSE;
+       ReadModeMessage = FILE_PIPE_BYTE_STREAM_MODE;
      }
    else if (dwPipeMode & PIPE_READMODE_MESSAGE)
      {
-       ReadModeMessage = TRUE;
+       ReadModeMessage = FILE_PIPE_MESSAGE_MODE;
      }
    else
      {
-       ReadModeMessage = FALSE;
+       ReadModeMessage = FILE_PIPE_BYTE_STREAM_MODE;
      }
-   
+
    if (dwPipeMode & PIPE_WAIT)
      {
-       NonBlocking = FALSE;
+       NonBlocking = FILE_PIPE_QUEUE_OPERATION;
      }
    else if (dwPipeMode & PIPE_NOWAIT)
      {
-       NonBlocking = TRUE;
+       NonBlocking = FILE_PIPE_COMPLETE_OPERATION;
      }
    else
      {
-       NonBlocking = FALSE;
+       NonBlocking = FILE_PIPE_QUEUE_OPERATION;
      }
-   
+
    if (nMaxInstances >= PIPE_UNLIMITED_INSTANCES)
      {
        nMaxInstances = ULONG_MAX;
      }
-   
+
    DefaultTimeOut.QuadPart = nDefaultTimeOut * -10000;
-   
+
    Status = NtCreateNamedPipeFile(&PipeHandle,
                                  DesiredAccess,
                                  &ObjectAttributes,
@@ -185,20 +196,23 @@ CreateNamedPipeW(LPCWSTR lpName,
                                  nInBufferSize,
                                  nOutBufferSize,
                                  &DefaultTimeOut);
-   
+
    RtlFreeUnicodeString(&NamedPipeName);
-   
+
    if (!NT_SUCCESS(Status))
      {
        DPRINT("NtCreateNamedPipe failed (Status %x)!\n", Status);
        SetLastErrorByStatus (Status);
-       return(INVALID_HANDLE_VALUE);
+       return INVALID_HANDLE_VALUE;
      }
-   
-   return(PipeHandle);
+
+   return PipeHandle;
 }
 
 
+/*
+ * @implemented
+ */
 BOOL STDCALL
 WaitNamedPipeA(LPCSTR lpNamedPipeName,
               DWORD nTimeOut)
@@ -218,6 +232,9 @@ WaitNamedPipeA(LPCSTR lpNamedPipeName,
 }
 
 
+/*
+ * @implemented
+ */
 BOOL STDCALL
 WaitNamedPipeW(LPCWSTR lpNamedPipeName,
               DWORD nTimeOut)
@@ -234,7 +251,6 @@ WaitNamedPipeW(LPCWSTR lpNamedPipeName,
                                    &NamedPipeName,
                                    NULL,
                                    NULL);
-   
    if (!r)
      {
        return(FALSE);
@@ -249,8 +265,8 @@ WaitNamedPipeW(LPCWSTR lpNamedPipeName,
                       FILE_GENERIC_READ,
                       &ObjectAttributes,
                       &Iosb,
-                      0,
-                      FILE_SYNCHRONOUS_IO_ALERT);
+                      FILE_SHARE_READ | FILE_SHARE_WRITE,
+                      FILE_SYNCHRONOUS_IO_NONALERT);
    if (!NT_SUCCESS(Status))
      {
        SetLastErrorByStatus (Status);
@@ -280,6 +296,9 @@ WaitNamedPipeW(LPCWSTR lpNamedPipeName,
 }
 
 
+/*
+ * @implemented
+ */
 BOOL STDCALL
 ConnectNamedPipe(HANDLE hNamedPipe,
                 LPOVERLAPPED lpOverlapped)
@@ -311,6 +330,9 @@ ConnectNamedPipe(HANDLE hNamedPipe,
                           0,
                           NULL,
                           0);
+  if ((lpOverlapped != NULL) && (Status == STATUS_PENDING))
+    return TRUE;
+
   if ((lpOverlapped == NULL) && (Status == STATUS_PENDING))
     {
       Status = NtWaitForSingleObject(hNamedPipe,
@@ -319,20 +341,25 @@ ConnectNamedPipe(HANDLE hNamedPipe,
       if (!NT_SUCCESS(Status))
        {
          SetLastErrorByStatus(Status);
-         return(FALSE);
+         return FALSE;
        }
       Status = Iosb.Status;
     }
+
   if ((!NT_SUCCESS(Status) && Status != STATUS_PIPE_CONNECTED) ||
       (Status == STATUS_PENDING))
     {
       SetLastErrorByStatus(Status);
-      return(FALSE);
+      return FALSE;
     }
-  return(TRUE);
+
+  return TRUE;
 }
 
 
+/*
+ * @implemented
+ */
 BOOL STDCALL
 SetNamedPipeHandleState(HANDLE hNamedPipe,
                        LPDWORD lpMode,
@@ -439,6 +466,9 @@ SetNamedPipeHandleState(HANDLE hNamedPipe,
 }
 
 
+/*
+ * @implemented
+ */
 BOOL STDCALL
 CallNamedPipeA(LPCSTR lpNamedPipeName,
               LPVOID lpInBuffer,
@@ -468,6 +498,9 @@ CallNamedPipeA(LPCSTR lpNamedPipeName,
 }
 
 
+/*
+ * @implemented
+ */
 BOOL STDCALL
 CallNamedPipeW(LPCWSTR lpNamedPipeName,
               LPVOID lpInBuffer,
@@ -527,6 +560,9 @@ CallNamedPipeW(LPCWSTR lpNamedPipeName,
 }
 
 
+/*
+ * @implemented
+ */
 BOOL STDCALL
 DisconnectNamedPipe(HANDLE hNamedPipe)
 {
@@ -564,7 +600,10 @@ DisconnectNamedPipe(HANDLE hNamedPipe)
 }
 
 
-WINBOOL STDCALL
+/*
+ * @unimplemented
+ */
+BOOL STDCALL
 GetNamedPipeHandleStateW(HANDLE hNamedPipe,
                         LPDWORD lpState,
                         LPDWORD lpCurInstances,
@@ -573,50 +612,88 @@ GetNamedPipeHandleStateW(HANDLE hNamedPipe,
                         LPWSTR lpUserName,
                         DWORD nMaxUserNameSize)
 {
-  FILE_PIPE_LOCAL_INFORMATION LocalInfo;
-  FILE_PIPE_INFORMATION PipeInfo;
   IO_STATUS_BLOCK StatusBlock;
   NTSTATUS Status;
 
   if (lpState != NULL)
+  {
+    FILE_PIPE_INFORMATION PipeInfo;
+    
+    Status = NtQueryInformationFile(hNamedPipe,
+                                    &StatusBlock,
+                                    &PipeInfo,
+                                    sizeof(FILE_PIPE_INFORMATION),
+                                    FilePipeInformation);
+    if (!NT_SUCCESS(Status))
     {
-      Status = NtQueryInformationFile(hNamedPipe,
-                                     &StatusBlock,
-                                     &PipeInfo,
-                                     sizeof(FILE_PIPE_INFORMATION),
-                                     FilePipeInformation);
-      if (!NT_SUCCESS(Status))
-       {
-         SetLastErrorByStatus(Status);
-         return(FALSE);
-       }
-      *lpState = 0; /* FIXME */
+      SetLastErrorByStatus(Status);
+      return FALSE;
     }
 
-  if (lpCurInstances != NULL)
+    *lpState = ((PipeInfo.CompletionMode != FILE_PIPE_QUEUE_OPERATION) ? PIPE_NOWAIT : PIPE_WAIT);
+    *lpState |= ((PipeInfo.ReadMode != FILE_PIPE_BYTE_STREAM_MODE) ? PIPE_READMODE_MESSAGE : PIPE_READMODE_BYTE);
+  }
+
+  if(lpCurInstances != NULL)
+  {
+    FILE_PIPE_LOCAL_INFORMATION LocalInfo;
+    
+    Status = NtQueryInformationFile(hNamedPipe,
+                                    &StatusBlock,
+                                    &LocalInfo,
+                                    sizeof(FILE_PIPE_LOCAL_INFORMATION),
+                                    FilePipeLocalInformation);
+    if(!NT_SUCCESS(Status))
     {
-      Status = NtQueryInformationFile(hNamedPipe,
-                                     &StatusBlock,
-                                     &LocalInfo,
-                                     sizeof(FILE_PIPE_LOCAL_INFORMATION),
-                                     FilePipeLocalInformation);
-      if (!NT_SUCCESS(Status))
-       {
-         SetLastErrorByStatus(Status);
-         return(FALSE);
-       }
-      *lpCurInstances = min(LocalInfo.CurrentInstances, 255);
+      SetLastErrorByStatus(Status);
+      return FALSE;
     }
 
+    *lpCurInstances = min(LocalInfo.CurrentInstances, PIPE_UNLIMITED_INSTANCES);
+  }
+
+  if(lpMaxCollectionCount != NULL || lpCollectDataTimeout != NULL)
+  {
+    FILE_PIPE_REMOTE_INFORMATION RemoteInfo;
+    
+    Status = NtQueryInformationFile(hNamedPipe,
+                                    &StatusBlock,
+                                    &RemoteInfo,
+                                    sizeof(FILE_PIPE_REMOTE_INFORMATION),
+                                    FilePipeRemoteInformation);
+    if(!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return FALSE;
+    }
 
-  /* FIXME: retrieve remaining information */
-
-
-  return(TRUE);
+    if(lpMaxCollectionCount != NULL)
+    {
+      *lpMaxCollectionCount = RemoteInfo.MaximumCollectionCount;
+    }
+    
+    if(lpCollectDataTimeout != NULL)
+    {
+      /* FIXME */
+      *lpCollectDataTimeout = 0;
+    }
+  }
+  
+  if(lpUserName != NULL)
+  {
+    /* FIXME - open the thread token, call ImpersonateNamedPipeClient() and
+               retreive the user name with GetUserName(), revert the impersonation
+               and finally restore the thread token */
+  }
+
+  return TRUE;
 }
 
 
-WINBOOL STDCALL
+/*
+ * @implemented
+ */
+BOOL STDCALL
 GetNamedPipeHandleStateA(HANDLE hNamedPipe,
                         LPDWORD lpState,
                         LPDWORD lpCurInstances,
@@ -625,12 +702,52 @@ GetNamedPipeHandleStateA(HANDLE hNamedPipe,
                         LPSTR lpUserName,
                         DWORD nMaxUserNameSize)
 {
-       SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-       return FALSE;
+  UNICODE_STRING UserNameW;
+  ANSI_STRING UserNameA;
+  BOOL Ret;
+  
+  if(lpUserName != NULL)
+  {
+    UserNameW.Length = 0;
+    UserNameW.MaximumLength = nMaxUserNameSize * sizeof(WCHAR);
+    UserNameW.Buffer = HeapAlloc(GetCurrentProcess(), 0, UserNameW.MaximumLength);
+    
+    UserNameA.Buffer = lpUserName;
+    UserNameA.Length = 0;
+    UserNameA.MaximumLength = nMaxUserNameSize;
+  }
+  
+  Ret = GetNamedPipeHandleStateW(hNamedPipe,
+                                 lpState,
+                                 lpCurInstances,
+                                 lpMaxCollectionCount,
+                                 lpCollectDataTimeout,
+                                 UserNameW.Buffer,
+                                 nMaxUserNameSize);
+
+  if(Ret && lpUserName != NULL)
+  {
+    NTSTATUS Status = RtlUnicodeStringToAnsiString(&UserNameA, &UserNameW, FALSE);
+    if(!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      Ret = FALSE;
+    }
+  }
+  
+  if(UserNameW.Buffer != NULL)
+  {
+    HeapFree(GetCurrentProcess(), 0, UserNameW.Buffer);
+  }
+  
+  return Ret;
 }
 
 
-WINBOOL STDCALL
+/*
+ * @implemented
+ */
+BOOL STDCALL
 GetNamedPipeInfo(HANDLE hNamedPipe,
                 LPDWORD lpFlags,
                 LPDWORD lpOutBufferSize,
@@ -676,6 +793,9 @@ GetNamedPipeInfo(HANDLE hNamedPipe,
 }
 
 
+/*
+ * @implemented
+ */
 BOOL STDCALL
 PeekNamedPipe(HANDLE hNamedPipe,
              LPVOID lpBuffer,
@@ -757,6 +877,9 @@ PeekNamedPipe(HANDLE hNamedPipe,
 }
 
 
+/*
+ * @implemented
+ */
 BOOL STDCALL
 TransactNamedPipe(HANDLE hNamedPipe,
                  LPVOID lpInBuffer,