- Fix pipe connection to non-waiting pipes.
- More corrections to the cancellation logic.
- Minor correction to read/write event setting (still I'm getting infinite loops there in some cases).
Modified: trunk/reactos/drivers/fs/np/create.c
Modified: trunk/reactos/drivers/fs/np/fsctrl.c
Modified: trunk/reactos/drivers/fs/np/rw.c
Modified: trunk/reactos/drivers/fs/np/volume.c

Modified: trunk/reactos/drivers/fs/np/create.c
--- trunk/reactos/drivers/fs/np/create.c	2005-03-06 14:03:37 UTC (rev 13855)
+++ trunk/reactos/drivers/fs/np/create.c	2005-03-06 16:42:36 UTC (rev 13856)
@@ -148,39 +148,13 @@
   KeUnlockMutex(&DeviceExt->PipeListLock);
 
   /*
-   * Step 2. Search for listening server FCB.
-   */
-
-  /*
    * Acquire the lock for FCB lists. From now on no modifications to the
    * FCB lists are allowed, because it can cause various misconsistencies.
    */
   KeLockMutex(&Pipe->FcbListLock);
 
-  if (!SpecialAccess)
-    {
-      ServerFcb = NpfsFindListeningServerInstance(Pipe);
-      if (ServerFcb == NULL)
-        {
-          /* Not found, bail out with error for FILE_OPEN requests. */
-          DPRINT("No listening server fcb found!\n");
-          KeUnlockMutex(&Pipe->FcbListLock);
-          Irp->IoStatus.Status = STATUS_PIPE_BUSY;
-          IoCompleteRequest(Irp, IO_NO_INCREMENT);
-          return STATUS_PIPE_BUSY;
-        }
-    }
-  else if (IsListEmpty(&Pipe->ServerFcbListHead))
-    {
-      DPRINT("No server fcb found!\n");
-      KeUnlockMutex(&Pipe->FcbListLock);
-      Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-      IoCompleteRequest(Irp, IO_NO_INCREMENT);
-      return STATUS_UNSUCCESSFUL;
-    }
-
   /*
-   * Step 3. Create the client FCB.
+   * Step 2. Create the client FCB.
    */
   ClientFcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_FCB));
   if (ClientFcb == NULL)
@@ -227,6 +201,73 @@
   KeInitializeEvent(&ClientFcb->Event, SynchronizationEvent, FALSE);
 
   /*
+   * Step 3. Search for listening server FCB.
+   */
+
+  if (!SpecialAccess)
+    {
+      /*
+       * WARNING: Point of no return! Once we get the server FCB it's
+       * possible that we completed a wait request and so we have to
+       * complete even this request.
+       */
+
+      ServerFcb = NpfsFindListeningServerInstance(Pipe);
+      if (ServerFcb == NULL)
+        {
+          PLIST_ENTRY CurrentEntry;
+          PNPFS_FCB Fcb;
+
+          /*
+           * If no waiting server FCB was found then try to pick
+           * one of the listing server FCB on the pipe.
+           */
+
+          CurrentEntry = Pipe->ServerFcbListHead.Flink;
+          while (CurrentEntry != &Pipe->ServerFcbListHead)
+            {
+              Fcb = CONTAINING_RECORD(CurrentEntry, NPFS_FCB, FcbListEntry);
+              if (Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
+                {
+                  ServerFcb = Fcb;
+                  break;
+                }
+              CurrentEntry = CurrentEntry->Flink;
+            }
+
+          /*
+           * No one is listening to me?! I'm so lonely... :(
+           */
+
+          if (ServerFcb == NULL)
+            {
+              /* Not found, bail out with error for FILE_OPEN requests. */
+              DPRINT("No listening server fcb found!\n");
+              if (ClientFcb->Data)
+                ExFreePool(ClientFcb->Data);
+              KeUnlockMutex(&Pipe->FcbListLock);
+              Irp->IoStatus.Status = STATUS_PIPE_BUSY;
+              IoCompleteRequest(Irp, IO_NO_INCREMENT);
+              return STATUS_PIPE_BUSY;
+            }
+        }
+      else
+        {
+          /* Signal the server thread and remove it from the waiter list */
+          /* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
+          NpfsSignalAndRemoveListeningServerInstance(Pipe, ServerFcb);
+        }
+    }
+  else if (IsListEmpty(&Pipe->ServerFcbListHead))
+    {
+      DPRINT("No server fcb found!\n");
+      KeUnlockMutex(&Pipe->FcbListLock);
+      Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+      IoCompleteRequest(Irp, IO_NO_INCREMENT);
+      return STATUS_UNSUCCESSFUL;
+    }
+
+  /*
    * Step 4. Add the client FCB to a list and connect it if possible.
    */
 
@@ -240,9 +281,6 @@
       ServerFcb->OtherSide = ClientFcb;
       ClientFcb->PipeState = FILE_PIPE_CONNECTED_STATE;
       ServerFcb->PipeState = FILE_PIPE_CONNECTED_STATE;
-
-      /* Signal the server thread and remove it from the waiter list */
-      NpfsSignalAndRemoveListeningServerInstance(Pipe, ServerFcb);
     }
 
   KeUnlockMutex(&Pipe->FcbListLock);

Modified: trunk/reactos/drivers/fs/np/fsctrl.c
--- trunk/reactos/drivers/fs/np/fsctrl.c	2005-03-06 14:03:37 UTC (rev 13855)
+++ trunk/reactos/drivers/fs/np/fsctrl.c	2005-03-06 16:42:36 UTC (rev 13856)
@@ -26,19 +26,12 @@
 
   DPRINT1("NpfsListeningCancelRoutine() called\n");
 
-  /* FIXME: Not tested. */
-
   IoReleaseCancelSpinLock(Irp->CancelIrql);
 
   Waiter = Irp->Tail.Overlay.DriverContext[0];
 
   KeLockMutex(&Waiter->Pipe->FcbListLock);
   RemoveEntryList(&Waiter->Entry);
-  if (IoSetCancelRoutine(Waiter->Irp, NULL) == NULL)
-    {
-      KeUnlockMutex(&Waiter->Pipe->FcbListLock);
-      return;
-    }
   KeUnlockMutex(&Waiter->Pipe->FcbListLock);
 
   Irp->IoStatus.Status = STATUS_CANCELLED;
@@ -53,7 +46,6 @@
 			       PNPFS_FCB Fcb)
 {
   PNPFS_WAITER_ENTRY Entry;
-  KIRQL OldIrql;
 
   Entry = ExAllocatePool(NonPagedPool, sizeof(NPFS_WAITER_ENTRY));
   if (Entry == NULL)
@@ -63,21 +55,26 @@
   Entry->Fcb = Fcb;
   Entry->Pipe = Fcb->Pipe;
 
-  IoAcquireCancelSpinLock(&OldIrql);
+  KeLockMutex(&Fcb->Pipe->FcbListLock);
+
+  IoMarkIrpPending(Irp);
+  Irp->Tail.Overlay.DriverContext[0] = Entry;
+  InsertTailList(&Fcb->Pipe->WaiterListHead, &Entry->Entry);
+
+  IoSetCancelRoutine(Irp, NpfsListeningCancelRoutine);
+  
   if (!Irp->Cancel)
     {
-      Irp->Tail.Overlay.DriverContext[0] = Entry;
-      IoMarkIrpPending(Irp);
-      IoSetCancelRoutine(Irp, NpfsListeningCancelRoutine);
-      KeLockMutex(&Fcb->Pipe->FcbListLock);
-      InsertTailList(&Fcb->Pipe->WaiterListHead, &Entry->Entry);
       KeUnlockMutex(&Fcb->Pipe->FcbListLock);
-      IoReleaseCancelSpinLock(OldIrql);
       return STATUS_PENDING;
     }
-  /* IRP has already been cancelled */
-  IoReleaseCancelSpinLock(OldIrql);
-
+  
+  RemoveEntryList(&Entry->Entry);
+  
+  Irp->IoStatus.Status = STATUS_CANCELLED;
+  Irp->IoStatus.Information = 0;
+  IoCompleteRequest(Irp, IO_NO_INCREMENT);
+  KeUnlockMutex(&Fcb->Pipe->FcbListLock);
   ExFreePool(Entry);
 
   return STATUS_CANCELLED;

Modified: trunk/reactos/drivers/fs/np/rw.c
--- trunk/reactos/drivers/fs/np/rw.c	2005-03-06 14:03:37 UTC (rev 13855)
+++ trunk/reactos/drivers/fs/np/rw.c	2005-03-06 16:42:36 UTC (rev 13856)
@@ -165,7 +165,10 @@
 
 	  if (Length == 0)
 	    {
-	      KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE);
+	      if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
+	        {
+	          KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE);
+	        }
 	      KeResetEvent(&Fcb->Event);
 	      break;
 	    }
@@ -197,6 +200,11 @@
 	        }
 	      else
 	        {
+                  KeResetEvent(&Fcb->Event);
+                  if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
+                    {
+                      KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE);
+                    }
 	          Fcb->ReadDataAvailable = 0;
 	          Fcb->WriteQuotaAvailable = Fcb->MaxDataLength;
 	        }
@@ -204,11 +212,6 @@
 
 	  if (Information > 0)
 	    {
-	      if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
-	        {
-	          KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE);
-	        }
-	      KeResetEvent(&Fcb->Event);
 	      break;
 	    }
 	}
@@ -383,12 +386,12 @@
 	      ReaderFcb->WriteQuotaAvailable = 0;
 	    }
 
-	  if (Information > 0)
-	    {
-	      KeSetEvent(&ReaderFcb->Event, IO_NO_INCREMENT, FALSE);
-	      KeResetEvent(&Fcb->Event);
-	      break;
-	    }
+   	  if (Information > 0)
+   	    {
+   	      KeSetEvent(&ReaderFcb->Event, IO_NO_INCREMENT, FALSE);
+   	      KeResetEvent(&Fcb->Event);
+   	      break;
+   	    }
 	}
     }
 

Modified: trunk/reactos/drivers/fs/np/volume.c
--- trunk/reactos/drivers/fs/np/volume.c	2005-03-06 14:03:37 UTC (rev 13855)
+++ trunk/reactos/drivers/fs/np/volume.c	2005-03-06 16:42:36 UTC (rev 13856)
@@ -36,7 +36,7 @@
 
   DPRINT("NpfsQueryFsDeviceInformation() finished.\n");
 
-   return STATUS_SUCCESS;
+  return STATUS_SUCCESS;
 }