- Fix error spotted by winetest: some status codes need to be normalized in CreateNam...
[reactos.git] / reactos / lib / kernel32 / file / npipe.c
index 7695bbe..a3e47c5 100644 (file)
@@ -12,7 +12,7 @@
 #include <k32.h>
 
 #define NDEBUG
-#define USING_PROPER_NPFS_WAIT_SEMANTICS
+//#define USING_PROPER_NPFS_WAIT_SEMANTICS
 #include "../include/debug.h"
 
 /* FUNCTIONS ****************************************************************/
@@ -207,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);
 
@@ -664,137 +671,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);
+    PUNICODE_STRING PipeName = &NtCurrentTeb()->StaticUnicodeString;
+    ANSI_STRING AnsiPipe;
 
-  RtlFreeUnicodeString(&PipeName);
-
-  return(Result);
+    /* 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
  */
@@ -987,91 +995,92 @@ 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)
-    {
-      Status = NtWaitForSingleObject(hNamedPipe,
-                                    FALSE,
-                                    NULL);
-      if (NT_SUCCESS(Status))
-       Status = Iosb.Status;
-    }
+    /* 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 (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
  */