- Data is now written to the readers data buffer and the reader reads from his own...
[reactos.git] / reactos / drivers / fs / np / rw.c
index a693b54..f7ff3a5 100644 (file)
@@ -1,8 +1,8 @@
-/* $Id: rw.c,v 1.14 2004/05/07 12:13:13 navaraf Exp $
+/* $Id$
  *
  * COPYRIGHT:  See COPYING in the top level directory
  * PROJECT:    ReactOS kernel
- * FILE:       services/fs/np/rw.c
+ * FILE:       drivers/fs/np/rw.c
  * PURPOSE:    Named pipe filesystem
  * PROGRAMMER: David Welch <welch@cwcom.net>
  */
 #include <rosrtl/minmax.h>
 #include "npfs.h"
 
-//#define NDEBUG
+#define NDEBUG
 #include <debug.h>
 
 /* FUNCTIONS *****************************************************************/
 
+#ifndef NDEBUG
+VOID HexDump(PUCHAR Buffer, ULONG Length)
+{
+  CHAR Line[65];
+  UCHAR ch;
+  const char Hex[] = "0123456789ABCDEF";
+  int i, j;
+
+  DbgPrint("---------------\n");
+
+  for (i = 0; i < ROUND_UP(Length, 16); i+= 16)
+    {
+      memset(Line, ' ', 64);
+      Line[64] = 0;
+
+      for (j = 0; j < 16 && j + i < Length; j++)
+        {
+          ch = Buffer[i + j];
+          Line[3*j + 0] = Hex[ch >> 4];
+         Line[3*j + 1] = Hex[ch & 0x0f];
+         Line[48 + j] = isprint(ch) ? ch : '.';
+        }
+      DbgPrint("%s\n", Line);
+    }
+  DbgPrint("---------------\n");
+}
+#endif
+
+
 NTSTATUS STDCALL
-NpfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+NpfsRead(PDEVICE_OBJECT DeviceObject,
+        PIRP Irp)
 {
   PIO_STACK_LOCATION IoStack;
   PFILE_OBJECT FileObject;
@@ -28,7 +58,7 @@ NpfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
   KIRQL OldIrql;
   ULONG Information;
   PNPFS_FCB Fcb;
-  PNPFS_FCB ReadFcb;
+  PNPFS_FCB WriterFcb;
   PNPFS_PIPE Pipe;
   ULONG Length;
   PVOID Buffer;
@@ -36,26 +66,13 @@ NpfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
   ULONG TempLength;
 
   DPRINT("NpfsRead(DeviceObject %p  Irp %p)\n", DeviceObject, Irp);
-  
+
   DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
   IoStack = IoGetCurrentIrpStackLocation(Irp);
   FileObject = IoStack->FileObject;
   Fcb = FileObject->FsContext;
   Pipe = Fcb->Pipe;
-  ReadFcb = Fcb->OtherSide;
-
-  if (ReadFcb == NULL)
-    {
-      DPRINT("Pipe is NOT connected!\n");
-      if (Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
-        Status = STATUS_PIPE_LISTENING;
-      else if (Fcb->PipeState == FILE_PIPE_DISCONNECTED_STATE)
-        Status = STATUS_PIPE_DISCONNECTED;
-      else
-        Status = STATUS_UNSUCCESSFUL;
-      Information = 0;
-      goto done;
-    }
+  WriterFcb = Fcb->OtherSide;
 
   if (Irp->MdlAddress == NULL)
     {
@@ -64,8 +81,8 @@ NpfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
       Information = 0;
       goto done;
     }
-  
-  if (ReadFcb->Data == NULL)
+
+  if (Fcb->Data == NULL)
     {
       DPRINT("Pipe is NOT readable!\n");
       Status = STATUS_UNSUCCESSFUL;
@@ -73,126 +90,113 @@ NpfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
       goto done;
     }
 
-
   Status = STATUS_SUCCESS;
   Length = IoStack->Parameters.Read.Length;
   Information = 0;
 
   Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
-  KeAcquireSpinLock(&ReadFcb->DataListLock, &OldIrql);
+  KeAcquireSpinLock(&Fcb->DataListLock, &OldIrql);
   while (1)
     {
       /* FIXME: check if in blocking mode */
-      if (ReadFcb->ReadDataAvailable == 0)
-        {
-          KeResetEvent(&Fcb->Event);
-         KeSetEvent(&ReadFcb->Event, IO_NO_INCREMENT, FALSE);
-          KeReleaseSpinLock(&ReadFcb->DataListLock, OldIrql);
+      if (Fcb->ReadDataAvailable == 0)
+       {
+         KeResetEvent(&Fcb->Event);
+         KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE);
+         KeReleaseSpinLock(&Fcb->DataListLock, OldIrql);
          if (Information > 0)
            {
              Status = STATUS_SUCCESS;
              goto done;
            }
-          if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE)
+
+         if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE)
            {
              DPRINT("PipeState: %x\n", Fcb->PipeState);
              Status = STATUS_PIPE_BROKEN;
              goto done;
            }
-          /* Wait for ReadEvent to become signaled */
-          DPRINT("Waiting for readable data (%S)\n", Pipe->PipeName.Buffer);
-          Status = KeWaitForSingleObject(&Fcb->Event,
+
+         /* Wait for ReadEvent to become signaled */
+         DPRINT("Waiting for readable data (%S)\n", Pipe->PipeName.Buffer);
+         Status = KeWaitForSingleObject(&Fcb->Event,
                                         UserRequest,
                                         KernelMode,
                                         FALSE,
                                         NULL);
-          DPRINT("Finished waiting (%S)! Status: %x\n", Pipe->PipeName.Buffer, Status);
-          /*
-           * It's possible that the event was signaled because the
-           * other side of pipe was closed.
-           */
-          if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE)
+         DPRINT("Finished waiting (%S)! Status: %x\n", Pipe->PipeName.Buffer, Status);
+
+         KeAcquireSpinLock(&Fcb->DataListLock, &OldIrql);
+       }
+
+      if (Pipe->ReadMode == FILE_PIPE_BYTE_STREAM_MODE)
+       {
+         DPRINT("Byte stream mode\n");
+         /* Byte stream mode */
+         while (Length > 0 && Fcb->ReadDataAvailable > 0)
            {
-             DPRINT("PipeState: %x\n", Fcb->PipeState);
-             Status = STATUS_PIPE_BROKEN;
-             goto done;
+             CopyLength = RtlRosMin(Fcb->ReadDataAvailable, Length);
+             if (Fcb->ReadPtr + CopyLength <= Fcb->Data + Fcb->MaxDataLength)
+               {
+                 memcpy(Buffer, Fcb->ReadPtr, CopyLength);
+                 Fcb->ReadPtr += CopyLength;
+                 if (Fcb->ReadPtr == Fcb->Data + Fcb->MaxDataLength)
+                   {
+                     Fcb->ReadPtr = Fcb->Data;
+                   }
+               }
+             else
+               {
+                 TempLength = Fcb->Data + Fcb->MaxDataLength - Fcb->ReadPtr;
+                 memcpy(Buffer, Fcb->ReadPtr, TempLength);
+                 memcpy(Buffer + TempLength, Fcb->Data, CopyLength - TempLength);
+                 Fcb->ReadPtr = Fcb->Data + CopyLength - TempLength;
+               }
+
+             Buffer += CopyLength;
+             Length -= CopyLength;
+             Information += CopyLength;
+
+             Fcb->ReadDataAvailable -= CopyLength;
+             Fcb->WriteQuotaAvailable += CopyLength;
+           }
+
+         if (Length == 0)
+           {
+             KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE);
+             break;
            }
-          KeAcquireSpinLock(&ReadFcb->DataListLock, &OldIrql);
        }
+      else
+       {
+         DPRINT("Message mode\n");
 
-     if (Pipe->PipeReadMode == FILE_PIPE_BYTE_STREAM_MODE)
-       {
-         DPRINT("Byte stream mode\n");
-         /* Byte stream mode */
-        while (Length > 0 && ReadFcb->ReadDataAvailable > 0)
-          {
-            CopyLength = RtlRosMin(ReadFcb->ReadDataAvailable, Length);
-            if (ReadFcb->ReadPtr + CopyLength <= ReadFcb->Data + ReadFcb->MaxDataLength)
-              {
-                 memcpy(Buffer, ReadFcb->ReadPtr, CopyLength);
-                ReadFcb->ReadPtr += CopyLength;
-                if (ReadFcb->ReadPtr == ReadFcb->Data + ReadFcb->MaxDataLength)
-                  {
-                    ReadFcb->ReadPtr = ReadFcb->Data;
-                  }
-              }
-            else
-              {
-                TempLength = ReadFcb->Data + ReadFcb->MaxDataLength - ReadFcb->ReadPtr;
-                memcpy(Buffer, ReadFcb->ReadPtr, TempLength);
-                memcpy(Buffer + TempLength, ReadFcb->Data, CopyLength - TempLength);
-                ReadFcb->ReadPtr = ReadFcb->Data + CopyLength - TempLength;
-              }
-
-            Buffer += CopyLength;
-            Length -= CopyLength;
-            Information += CopyLength;
-
-            ReadFcb->ReadDataAvailable -= CopyLength;
-            ReadFcb->WriteQuotaAvailable += CopyLength;
-          }
-
-       if (Length == 0)
-         {
-           KeSetEvent(&ReadFcb->Event, IO_NO_INCREMENT, FALSE);
-           break;
-         }
-       }
-     else
-       {
-         DPRINT("Message mode\n");
-
-         /* Message mode */
-        if (ReadFcb->ReadDataAvailable)
-          {
-            /* Truncate the message if the receive buffer is too small */
-            CopyLength = RtlRosMin(ReadFcb->ReadDataAvailable, Length);
-            memcpy(Buffer, ReadFcb->Data, CopyLength);
+         /* Message mode */
+         if (Fcb->ReadDataAvailable)
+           {
+             /* Truncate the message if the receive buffer is too small */
+             CopyLength = RtlRosMin(Fcb->ReadDataAvailable, Length);
+             memcpy(Buffer, Fcb->Data, CopyLength);
 
 #ifndef NDEBUG
-             DPRINT("Length %d Buffer %x\n",CopyLength,Buffer);
-             {
-                DbgPrint("------\n");
-                ULONG X;
-                for (X = 0; X < CopyLength; X++)
-                   DbgPrint("%02x ", ((PUCHAR)Buffer)[X]);
-                DbgPrint("\n");
-                DbgPrint("------\n");
-             }
+             DPRINT("Length %d Buffer %x\n",CopyLength,Buffer);
+             HexDump((PUCHAR)Buffer, CopyLength);
 #endif
 
-            Information = CopyLength;
-            ReadFcb->ReadDataAvailable = 0;
-            ReadFcb->WriteQuotaAvailable = ReadFcb->MaxDataLength;
-          }
-        if (Information > 0)
-          {
-            KeSetEvent(&ReadFcb->Event, IO_NO_INCREMENT, FALSE);
-            break;
-          }
-       }
+             Information = CopyLength;
+             Fcb->ReadDataAvailable = 0;
+             Fcb->WriteQuotaAvailable = Fcb->MaxDataLength;
+           }
+
+         if (Information > 0)
+           {
+             KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE);
+             break;
+           }
+       }
     }
-  KeReleaseSpinLock(&ReadFcb->DataListLock, OldIrql);
+
+  KeReleaseSpinLock(&Fcb->DataListLock, OldIrql);
 
 done:
   Irp->IoStatus.Status = Status;
@@ -200,7 +204,9 @@ done:
 
   IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
-  return(Status);
+  DPRINT("NpfsRead done (Status %lx)\n", Status);
+
+  return Status;
 }
 
 
@@ -211,6 +217,7 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject,
   PIO_STACK_LOCATION IoStack;
   PFILE_OBJECT FileObject;
   PNPFS_FCB Fcb = NULL;
+  PNPFS_FCB ReaderFcb;
   PNPFS_PIPE Pipe = NULL;
   PUCHAR Buffer;
   NTSTATUS Status = STATUS_SUCCESS;
@@ -229,6 +236,7 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject,
   DPRINT("Pipe name %wZ\n", &FileObject->FileName);
 
   Fcb = FileObject->FsContext;
+  ReaderFcb = Fcb->OtherSide;
   Pipe = Fcb->Pipe;
 
   Length = IoStack->Parameters.Write.Length;
@@ -243,7 +251,7 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject,
       goto done;
     }
 
-  if (Fcb->OtherSide == NULL)
+  if (ReaderFcb == NULL)
     {
       DPRINT("Pipe is NOT connected!\n");
       if (Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
@@ -255,8 +263,8 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject,
       Length = 0;
       goto done;
     }
-  
-  if (Fcb->Data == NULL)
+
+  if (ReaderFcb->Data == NULL)
     {
       DPRINT("Pipe is NOT writable!\n");
       Status = STATUS_UNSUCCESSFUL;
@@ -266,114 +274,116 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject,
 
   Status = STATUS_SUCCESS;
   Buffer = MmGetSystemAddressForMdl (Irp->MdlAddress);
+
+  KeAcquireSpinLock(&ReaderFcb->DataListLock, &OldIrql);
 #ifndef NDEBUG
   DPRINT("Length %d Buffer %x Offset %x\n",Length,Buffer,Offset);
-  {
-     DbgPrint("------\n");
-     ULONG X;
-     for (X = 0; X < Length; X++)
-        DbgPrint("%02x ", Buffer[X]);
-     DbgPrint("\n");
-     DbgPrint("------\n");
-  }
+  HexDump(Buffer, Length);
 #endif
 
-  KeAcquireSpinLock(&Fcb->DataListLock, &OldIrql);
   while(1)
     {
-      if (Fcb->WriteQuotaAvailable == 0)
-        {
-          KeResetEvent(&Fcb->Event);
-         KeSetEvent(&Fcb->OtherSide->Event, IO_NO_INCREMENT, FALSE);
-          KeReleaseSpinLock(&Fcb->DataListLock, OldIrql);
-          if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE)
+      if (ReaderFcb->WriteQuotaAvailable == 0)
+       {
+         KeResetEvent(&Fcb->Event);
+         KeSetEvent(&ReaderFcb->Event, IO_NO_INCREMENT, FALSE);
+         KeReleaseSpinLock(&ReaderFcb->DataListLock, OldIrql);
+         if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE)
            {
              Status = STATUS_PIPE_BROKEN;
              goto done;
            }
-          DPRINT("Waiting for buffer space (%S)\n", Pipe->PipeName.Buffer);
-          Status = KeWaitForSingleObject(&Fcb->Event,
+
+         DPRINT("Waiting for buffer space (%S)\n", Pipe->PipeName.Buffer);
+         Status = KeWaitForSingleObject(&Fcb->Event,
                                         UserRequest,
                                         KernelMode,
                                         FALSE,
                                         NULL);
-          DPRINT("Finished waiting (%S)! Status: %x\n", Pipe->PipeName.Buffer, Status);
-          /*
-           * It's possible that the event was signaled because the
-           * other side of pipe was closed.
-           */
-          if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE)
+         DPRINT("Finished waiting (%S)! Status: %x\n", Pipe->PipeName.Buffer, Status);
+
+         /*
+          * It's possible that the event was signaled because the
+          * other side of pipe was closed.
+          */
+         if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE)
            {
              DPRINT("PipeState: %x\n", Fcb->PipeState);
              Status = STATUS_PIPE_BROKEN;
              goto done;
            }
-          KeAcquireSpinLock(&Fcb->DataListLock, &OldIrql);
-        }
-      if (Pipe->PipeWriteMode == FILE_PIPE_BYTE_STREAM_MODE)
-        {
-          DPRINT("Byte stream mode\n");
-         while (Length > 0 && Fcb->WriteQuotaAvailable > 0)
+         KeAcquireSpinLock(&ReaderFcb->DataListLock, &OldIrql);
+       }
+
+      if (Pipe->WriteMode == FILE_PIPE_BYTE_STREAM_MODE)
+       {
+         DPRINT("Byte stream mode\n");
+         while (Length > 0 && ReaderFcb->WriteQuotaAvailable > 0)
            {
-              CopyLength = RtlRosMin(Length, Fcb->WriteQuotaAvailable);
-              if (Fcb->WritePtr + CopyLength <= Fcb->Data + Fcb->MaxDataLength)
-               {
-                  memcpy(Fcb->WritePtr, Buffer, CopyLength);
-                 Fcb->WritePtr += CopyLength;
-                 if (Fcb->WritePtr == Fcb->Data + Fcb->MaxDataLength)
+             CopyLength = RtlRosMin(Length, ReaderFcb->WriteQuotaAvailable);
+             if (ReaderFcb->WritePtr + CopyLength <= ReaderFcb->Data + ReaderFcb->MaxDataLength)
+               {
+                 memcpy(ReaderFcb->WritePtr, Buffer, CopyLength);
+                 ReaderFcb->WritePtr += CopyLength;
+                 if (ReaderFcb->WritePtr == ReaderFcb->Data + ReaderFcb->MaxDataLength)
                    {
-                     Fcb->WritePtr = Fcb->Data;
+                     ReaderFcb->WritePtr = ReaderFcb->Data;
                    }
                }
              else
-               {
-                 TempLength = Fcb->Data + Fcb->MaxDataLength - Fcb->WritePtr;
-                 memcpy(Fcb->WritePtr, Buffer, TempLength);
-                 memcpy(Fcb->Data, Buffer + TempLength, CopyLength - TempLength);
-                 Fcb->WritePtr = Fcb->Data + CopyLength - TempLength;
+               {
+                 TempLength = ReaderFcb->Data + ReaderFcb->MaxDataLength - ReaderFcb->WritePtr;
+                 memcpy(ReaderFcb->WritePtr, Buffer, TempLength);
+                 memcpy(ReaderFcb->Data, Buffer + TempLength, CopyLength - TempLength);
+                 ReaderFcb->WritePtr = ReaderFcb->Data + CopyLength - TempLength;
                }
-                 
+
              Buffer += CopyLength;
              Length -= CopyLength;
-              Information += CopyLength;
+             Information += CopyLength;
 
-             Fcb->ReadDataAvailable += CopyLength;
-             Fcb->WriteQuotaAvailable -= CopyLength;
+             ReaderFcb->ReadDataAvailable += CopyLength;
+             ReaderFcb->WriteQuotaAvailable -= CopyLength;
            }
 
          if (Length == 0)
            {
-             KeSetEvent(&Fcb->OtherSide->Event, IO_NO_INCREMENT, FALSE);
+             KeSetEvent(&ReaderFcb->Event, IO_NO_INCREMENT, FALSE);
              break;
            }
        }
       else
-        {
-          if (Length > 0)
+       {
+         DPRINT("Message mode\n");
+         if (Length > 0)
            {
-              CopyLength = RtlRosMin(Length, Fcb->WriteQuotaAvailable);
-             memcpy(Fcb->Data, Buffer, CopyLength);
+             CopyLength = RtlRosMin(Length, ReaderFcb->WriteQuotaAvailable);
+             memcpy(ReaderFcb->Data, Buffer, CopyLength);
 
              Information = CopyLength;
-             Fcb->ReadDataAvailable = CopyLength;
-             Fcb->WriteQuotaAvailable = 0;
+             ReaderFcb->ReadDataAvailable = CopyLength;
+             ReaderFcb->WriteQuotaAvailable = 0;
            }
+
          if (Information > 0)
            {
-             KeSetEvent(&Fcb->OtherSide->Event, IO_NO_INCREMENT, FALSE);
+             KeSetEvent(&ReaderFcb->Event, IO_NO_INCREMENT, FALSE);
              break;
            }
        }
     }
-  KeReleaseSpinLock(&Fcb->DataListLock, OldIrql);
+
+  KeReleaseSpinLock(&ReaderFcb->DataListLock, OldIrql);
 
 done:
   Irp->IoStatus.Status = Status;
   Irp->IoStatus.Information = Information;
-  
+
   IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
-  return(Status);
+  DPRINT("NpfsWrite done (Status %lx)\n", Status);
+
+  return Status;
 }
 
 /* EOF */