Revert r20089, thanks SVN for not a nice conflict resolution!
[reactos.git] / reactos / lib / kernel32 / file / npipe.c
index 846a155..a9fcd27 100644 (file)
@@ -1,11 +1,10 @@
-/* $Id$
- *
+/*
  * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS system libraries
+ * PROJECT:         ReactOS Win32 Kernel Library
  * FILE:            lib/kernel32/file/npipe.c
- * PURPOSE:         Directory functions
- * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
- * UPDATE HISTORY:
+ * PURPOSE:         Named Pipe Functions
+ * PROGRAMMER:      Alex Ionescu (alex@relsoft.net)
+ *                  Ariadne ( ariadne@xs4all.nl)
  */
 
 /* INCLUDES *****************************************************************/
 /*
  * @implemented
  */
-HANDLE STDCALL
+HANDLE
+WINAPI
 CreateNamedPipeA(LPCSTR lpName,
-                DWORD dwOpenMode,
-                DWORD dwPipeMode,
-                DWORD nMaxInstances,
-                DWORD nOutBufferSize,
-                DWORD nInBufferSize,
-                DWORD nDefaultTimeOut,
-                LPSECURITY_ATTRIBUTES lpSecurityAttributes)
+                 DWORD dwOpenMode,
+                 DWORD dwPipeMode,
+                 DWORD nMaxInstances,
+                 DWORD nOutBufferSize,
+                 DWORD nInBufferSize,
+                 DWORD nDefaultTimeOut,
+                 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
 {
-   HANDLE NamedPipeHandle;
-   UNICODE_STRING NameU;
-   ANSI_STRING NameA;
-
-   RtlInitAnsiString(&NameA, (LPSTR)lpName);
-   RtlAnsiStringToUnicodeString(&NameU, &NameA, TRUE);
-
-   NamedPipeHandle = CreateNamedPipeW(NameU.Buffer,
-                                     dwOpenMode,
-                                     dwPipeMode,
-                                     nMaxInstances,
-                                     nOutBufferSize,
-                                     nInBufferSize,
-                                     nDefaultTimeOut,
-                                     lpSecurityAttributes);
-
-   RtlFreeUnicodeString(&NameU);
-
-   return(NamedPipeHandle);
+    PUNICODE_STRING NameU = &NtCurrentTeb()->StaticUnicodeString;
+    ANSI_STRING NameA;
+
+    /* Initialize the string as ANSI_STRING and convert to Unicode */
+    RtlInitAnsiString(&NameA, (LPSTR)lpName);
+    RtlAnsiStringToUnicodeString(NameU, &NameA, FALSE);
+
+    /* Call the Unicode API */
+    return CreateNamedPipeW(NameU->Buffer,
+                            dwOpenMode,
+                            dwPipeMode,
+                            nMaxInstances,
+                            nOutBufferSize,
+                            nInBufferSize,
+                            nDefaultTimeOut,
+                            lpSecurityAttributes);
 }
 
 /*
@@ -104,8 +101,8 @@ CreateNamedPipeW(LPCWSTR lpName,
         return(INVALID_HANDLE_VALUE);
     }
 
-    DPRINT1("Pipe name: %wZ\n", &NamedPipeName);
-    DPRINT1("Pipe name: %S\n", NamedPipeName.Buffer);
+    DPRINT("Pipe name: %wZ\n", &NamedPipeName);
+    DPRINT("Pipe name: %S\n", NamedPipeName.Buffer);
 
     /* Always case insensitive, check if we got extra attributes */
     Attributes = OBJ_CASE_INSENSITIVE;
@@ -210,6 +207,13 @@ CreateNamedPipeW(LPCWSTR lpName,
                                    nOutBufferSize,
                                    &DefaultTimeOut);
 
+    /* Normalize special error codes */
+    if ((Status == STATUS_INVALID_DEVICE_REQUEST) ||
+        (Status == STATUS_NOT_SUPPORTED))
+    {
+        Status = STATUS_OBJECT_NAME_INVALID;
+    }
+
     /* Free the name */
     RtlFreeUnicodeString(&NamedPipeName);
 
@@ -226,26 +230,28 @@ CreateNamedPipeW(LPCWSTR lpName,
     return PipeHandle;
 }
 
-
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL
+WINAPI
 WaitNamedPipeA(LPCSTR lpNamedPipeName,
-              DWORD nTimeOut)
+               DWORD nTimeOut)
 {
-   BOOL r;
-   UNICODE_STRING NameU;
-   ANSI_STRING NameA;
+    BOOL r;
+    UNICODE_STRING NameU;
 
-   RtlInitAnsiString(&NameA, (LPSTR)lpNamedPipeName);
-   RtlAnsiStringToUnicodeString(&NameU, &NameA, TRUE);
+    /* Convert the name to Unicode */
+    Basep8BitStringToLiveUnicodeString(&NameU, lpNamedPipeName);
 
-   r = WaitNamedPipeW(NameU.Buffer, nTimeOut);
+    /* Call the Unicode API */
+    r = WaitNamedPipeW(NameU.Buffer, nTimeOut);
 
-   RtlFreeUnicodeString(&NameU);
+    /* Free the Unicode string */
+    RtlFreeUnicodeString(&NameU);
 
-   return(r);
+    /* Return result */
+    return r;
 }
 
 /*
@@ -347,6 +353,16 @@ WaitNamedPipeW(LPCWSTR lpNamedPipeName,
         return FALSE;
     }
 
+    /* Now calculate the total length of the structure and allocate it */
+    WaitPipeInfoSize = FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name[0]) +
+                       NewName.Length;
+    WaitPipeInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, WaitPipeInfoSize);
+    if (WaitPipeInfo == NULL)
+    {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
+    }
+
     /* Initialize the object attributes */
     DPRINT("Opening: %wZ\n", &DevicePath);
     InitializeObjectAttributes(&ObjectAttributes,
@@ -368,14 +384,10 @@ WaitNamedPipeW(LPCWSTR lpNamedPipeName,
         DPRINT1("Status: %lx\n", Status);
         SetLastErrorByStatus(Status);
         RtlFreeUnicodeString(&NamedPipeName);
+        RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo);
         return(FALSE);
     }
 
-    /* Now calculate the total length of the structure and allocate it */
-    WaitPipeInfoSize = FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name[0]) +
-                       NewName.Length;
-    WaitPipeInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, WaitPipeInfoSize);
-
     /* Check what timeout we got */
     if (nTimeOut == NMPWAIT_USE_DEFAULT_WAIT)
     {
@@ -665,137 +677,138 @@ SetNamedPipeHandleState(HANDLE hNamedPipe,
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL
+WINAPI
 CallNamedPipeA(LPCSTR lpNamedPipeName,
-              LPVOID lpInBuffer,
-              DWORD nInBufferSize,
-              LPVOID lpOutBuffer,
-              DWORD nOutBufferSize,
-              LPDWORD lpBytesRead,
-              DWORD nTimeOut)
+               LPVOID lpInBuffer,
+               DWORD nInBufferSize,
+               LPVOID lpOutBuffer,
+               DWORD nOutBufferSize,
+               LPDWORD lpBytesRead,
+               DWORD nTimeOut)
 {
-  UNICODE_STRING PipeName;
-  BOOL Result;
-
-  RtlCreateUnicodeStringFromAsciiz(&PipeName,
-                                  (LPSTR)lpNamedPipeName);
-
-  Result = CallNamedPipeW(PipeName.Buffer,
-                         lpInBuffer,
-                         nInBufferSize,
-                         lpOutBuffer,
-                         nOutBufferSize,
-                         lpBytesRead,
-                         nTimeOut);
-
-  RtlFreeUnicodeString(&PipeName);
-
-  return(Result);
+    PUNICODE_STRING PipeName = &NtCurrentTeb()->StaticUnicodeString;
+    ANSI_STRING AnsiPipe;
+
+    /* Initialize the string as ANSI_STRING and convert to Unicode */
+    RtlInitAnsiString(&AnsiPipe, (LPSTR)lpNamedPipeName);
+    RtlAnsiStringToUnicodeString(PipeName, &AnsiPipe, FALSE);
+
+    /* Call the Unicode function */
+    return CallNamedPipeW(PipeName->Buffer,
+                          lpInBuffer,
+                          nInBufferSize,
+                          lpOutBuffer,
+                          nOutBufferSize,
+                          lpBytesRead,
+                          nTimeOut);
 }
 
-
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL
+WINAPI
 CallNamedPipeW(LPCWSTR lpNamedPipeName,
-              LPVOID lpInBuffer,
-              DWORD nInBufferSize,
-              LPVOID lpOutBuffer,
-              DWORD nOutBufferSize,
-              LPDWORD lpBytesRead,
-              DWORD nTimeOut)
+               LPVOID lpInBuffer,
+               DWORD nInBufferSize,
+               LPVOID lpOutBuffer,
+               DWORD nOutBufferSize,
+               LPDWORD lpBytesRead,
+               DWORD nTimeOut)
 {
-  HANDLE hPipe = INVALID_HANDLE_VALUE;
-  BOOL bRetry = TRUE;
-  BOOL bError = FALSE;
-  DWORD dwPipeMode;
+    HANDLE hPipe;
+    BOOL bRetry = TRUE;
+    BOOL bError;
+    DWORD dwPipeMode;
 
-  while (TRUE)
+    while (TRUE)
     {
-      hPipe = CreateFileW(lpNamedPipeName,
-                         GENERIC_READ | GENERIC_WRITE,
-                         FILE_SHARE_READ | FILE_SHARE_WRITE,
-                         NULL,
-                         OPEN_EXISTING,
-                         FILE_ATTRIBUTE_NORMAL,
-                         NULL);
-      if (hPipe != INVALID_HANDLE_VALUE)
-       break;
-
-      if (bRetry == FALSE)
-       return(FALSE);
-
-      WaitNamedPipeW(lpNamedPipeName,
-                    nTimeOut);
-
-      bRetry = FALSE;
+        /* Try creating it */
+        hPipe = CreateFileW(lpNamedPipeName,
+                            GENERIC_READ | GENERIC_WRITE,
+                            FILE_SHARE_READ | FILE_SHARE_WRITE,
+                            NULL,
+                            OPEN_EXISTING,
+                            FILE_ATTRIBUTE_NORMAL,
+                            NULL);
+
+        /* Success, break out */
+        if (hPipe != INVALID_HANDLE_VALUE) break;
+
+        /* Already tried twice, give up */
+        if (bRetry == FALSE) return FALSE;
+
+        /* Wait on it */
+        WaitNamedPipeW(lpNamedPipeName, nTimeOut);
+
+        /* Get ready to try again */
+        bRetry = FALSE;
     }
 
-  dwPipeMode = PIPE_READMODE_MESSAGE;
-  bError = SetNamedPipeHandleState(hPipe,
-                                  &dwPipeMode,
-                                  NULL,
-                                  NULL);
-  if (!bError)
+    /* Set the pipe mode */
+    dwPipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
+    bError = SetNamedPipeHandleState(hPipe, &dwPipeMode, NULL, NULL);
+    if (!bError)
     {
-      CloseHandle(hPipe);
-      return(FALSE);
+        /* Couldn't change state, fail */
+        CloseHandle(hPipe);
+        return FALSE;
     }
 
-  bError = TransactNamedPipe(hPipe,
-                            lpInBuffer,
-                            nInBufferSize,
-                            lpOutBuffer,
-                            nOutBufferSize,
-                            lpBytesRead,
-                            NULL);
-  CloseHandle(hPipe);
-
-  return(bError);
+    /* Do the transact */
+    bError = TransactNamedPipe(hPipe,
+                               lpInBuffer,
+                               nInBufferSize,
+                               lpOutBuffer,
+                               nOutBufferSize,
+                               lpBytesRead,
+                               NULL);
+    
+    /* Close the handle and return */
+    CloseHandle(hPipe);
+    return bError;
 }
 
-
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL 
+WINAPI
 DisconnectNamedPipe(HANDLE hNamedPipe)
 {
-  IO_STATUS_BLOCK Iosb;
-  NTSTATUS Status;
+    IO_STATUS_BLOCK Iosb;
+    NTSTATUS Status;
 
-  Status = NtFsControlFile(hNamedPipe,
-                          NULL,
-                          NULL,
-                          NULL,
-                          &Iosb,
-                          FSCTL_PIPE_DISCONNECT,
-                          NULL,
-                          0,
-                          NULL,
-                          0);
-  if (Status == STATUS_PENDING)
+    /* Send the FSCTL to the driver */
+    Status = NtFsControlFile(hNamedPipe,
+                             NULL,
+                             NULL,
+                             NULL,
+                             &Iosb,
+                             FSCTL_PIPE_DISCONNECT,
+                             NULL,
+                             0,
+                             NULL,
+                             0);
+    if (Status == STATUS_PENDING)
     {
-      Status = NtWaitForSingleObject(hNamedPipe,
-                                    FALSE,
-                                    NULL);
-      if (!NT_SUCCESS(Status))
-       {
-         SetLastErrorByStatus(Status);
-         return(FALSE);
-       }
+        /* Wait on NPFS to finish and get updated status */
+        Status = NtWaitForSingleObject(hNamedPipe, FALSE, NULL);
+        if (NT_SUCCESS(Status)) Status = Iosb.Status;
     }
 
-  if (!NT_SUCCESS(Status))
+    /* Check for error */
+    if (!NT_SUCCESS(Status))
     {
-      SetLastErrorByStatus(Status);
-      return(FALSE);
-    }
-  return(TRUE);
+        /* Fail */
+        SetLastErrorByStatus(Status);
+        return FALSE;
+       }
+    
+    return TRUE;
 }
 
-
 /*
  * @unimplemented
  */
@@ -898,15 +911,19 @@ GetNamedPipeHandleStateA(HANDLE hNamedPipe,
                         LPSTR lpUserName,
                         DWORD nMaxUserNameSize)
 {
-  UNICODE_STRING UserNameW;
+  UNICODE_STRING UserNameW = {0};
   ANSI_STRING UserNameA;
   BOOL Ret;
 
   if(lpUserName != NULL)
   {
-    UserNameW.Length = 0;
     UserNameW.MaximumLength = nMaxUserNameSize * sizeof(WCHAR);
-    UserNameW.Buffer = HeapAlloc(GetCurrentProcess(), 0, UserNameW.MaximumLength);
+    UserNameW.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, UserNameW.MaximumLength);
+    if (UserNameW.Buffer == NULL)
+    {
+      SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+      return FALSE;
+    }
 
     UserNameA.Buffer = lpUserName;
     UserNameA.Length = 0;
@@ -923,7 +940,10 @@ GetNamedPipeHandleStateA(HANDLE hNamedPipe,
 
   if(Ret && lpUserName != NULL)
   {
-    NTSTATUS Status = RtlUnicodeStringToAnsiString(&UserNameA, &UserNameW, FALSE);
+    NTSTATUS Status;
+
+    RtlInitUnicodeString(&UserNameW, UserNameW.Buffer);
+    Status = RtlUnicodeStringToAnsiString(&UserNameA, &UserNameW, FALSE);
     if(!NT_SUCCESS(Status))
     {
       SetLastErrorByStatus(Status);
@@ -933,7 +953,7 @@ GetNamedPipeHandleStateA(HANDLE hNamedPipe,
 
   if(UserNameW.Buffer != NULL)
   {
-    HeapFree(GetCurrentProcess(), 0, UserNameW.Buffer);
+    RtlFreeHeap(RtlGetProcessHeap(), 0, UserNameW.Buffer);
   }
 
   return Ret;
@@ -988,91 +1008,97 @@ GetNamedPipeInfo(HANDLE hNamedPipe,
   return(TRUE);
 }
 
-
 /*
  * @implemented
  */
-BOOL STDCALL
+BOOL
+WINAPI
 PeekNamedPipe(HANDLE hNamedPipe,
-             LPVOID lpBuffer,
-             DWORD nBufferSize,
-             LPDWORD lpBytesRead,
-             LPDWORD lpTotalBytesAvail,
-             LPDWORD lpBytesLeftThisMessage)
+              LPVOID lpBuffer,
+              DWORD nBufferSize,
+              LPDWORD lpBytesRead,
+              LPDWORD lpTotalBytesAvail,
+              LPDWORD lpBytesLeftThisMessage)
 {
-  PFILE_PIPE_PEEK_BUFFER Buffer;
-  IO_STATUS_BLOCK Iosb;
-  ULONG BufferSize;
-  NTSTATUS Status;
+    PFILE_PIPE_PEEK_BUFFER Buffer;
+    IO_STATUS_BLOCK Iosb;
+    ULONG BufferSize;
+    NTSTATUS Status;
 
-  BufferSize = nBufferSize + sizeof(FILE_PIPE_PEEK_BUFFER);
-  Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
-                          0,
-                          BufferSize);
-
-  Status = NtFsControlFile(hNamedPipe,
-                          NULL,
-                          NULL,
-                          NULL,
-                          &Iosb,
-                          FSCTL_PIPE_PEEK,
-                          NULL,
-                          0,
-                          Buffer,
-                          BufferSize);
-  if (Status == STATUS_PENDING)
+    /* Calculate the buffer space that we'll need and allocate it */
+    BufferSize = nBufferSize + FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]);
+    Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferSize);
+    if (Buffer == NULL)
     {
-      Status = NtWaitForSingleObject(hNamedPipe,
-                                    FALSE,
-                                    NULL);
-      if (NT_SUCCESS(Status))
-       Status = Iosb.Status;
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return FALSE;
     }
 
-  if (Status == STATUS_BUFFER_OVERFLOW)
+    /* Tell the driver to seek */
+    Status = NtFsControlFile(hNamedPipe,
+                             NULL,
+                             NULL,
+                             NULL,
+                             &Iosb,
+                             FSCTL_PIPE_PEEK,
+                             NULL,
+                             0,
+                             Buffer,
+                             BufferSize);
+    if (Status == STATUS_PENDING)
     {
-      Status = STATUS_SUCCESS;
+        /* Wait for npfs to be done, and update the status */
+        Status = NtWaitForSingleObject(hNamedPipe, FALSE, NULL);
+        if (NT_SUCCESS(Status)) Status = Iosb.Status;
     }
 
-  if (!NT_SUCCESS(Status))
-    {
-      RtlFreeHeap(RtlGetProcessHeap(),
-                 0,
-                 Buffer);
-      SetLastErrorByStatus(Status);
-      return(FALSE);
-    }
+    /* Overflow is success for us */
+    if (Status == STATUS_BUFFER_OVERFLOW) Status = STATUS_SUCCESS;
 
-  if (lpTotalBytesAvail != NULL)
+    /* If we failed */
+    if (!NT_SUCCESS(Status))
     {
-      *lpTotalBytesAvail = Buffer->ReadDataAvailable;
+        /* Free the buffer and return failure */
+        RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
+        SetLastErrorByStatus(Status);
+        return FALSE;
     }
 
-  if (lpBytesRead != NULL)
+    /* Check if caller requested bytes available */
+    if (lpTotalBytesAvail) *lpTotalBytesAvail = Buffer->ReadDataAvailable;
+
+    /* Check if caller requested bytes read */
+    if (lpBytesRead)
     {
-      *lpBytesRead = Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER);
+        /* Calculate the bytes returned, minus our structure overhead */
+        *lpBytesRead = (ULONG)(Iosb.Information -
+                               FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));
     }
 
-  if (lpBytesLeftThisMessage != NULL)
+    /* Check if caller requested bytes left */
+    if (lpBytesLeftThisMessage)
     {
-      *lpBytesLeftThisMessage = Buffer->MessageLength -
-       (Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER));
+        /* Calculate total minus what we returned and our structure overhead */
+        *lpBytesLeftThisMessage = Buffer->MessageLength -
+                                  (ULONG)(Iosb.Information -
+                                          FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));
     }
 
-  if (lpBuffer != NULL)
+    /* Check if the caller wanted to see the actual data */
+    if (lpBuffer)
     {
-      memcpy(lpBuffer, Buffer->Data,
-            min(nBufferSize, Iosb.Information - sizeof(FILE_PIPE_PEEK_BUFFER)));
+        /* Give him what he wants */
+        RtlCopyMemory(lpBuffer,
+                      Buffer->Data,
+                         Iosb.Information -
+                      FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data[0]));
     }
 
-  RtlFreeHeap(RtlGetProcessHeap(),
-             0,
-             Buffer);
-
-  return(TRUE);
+    /* Free the buffer and return success */
+    RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
+    return TRUE;
 }
 
-
 /*
  * @implemented
  */