[NPFS-NEW]: Implement Close, Cleanup, Disconnect, Flush, Listen, Peek, SetInfo, Trans...
authorAlex Ionescu <aionescu@gmail.com>
Tue, 10 Sep 2013 02:23:32 +0000 (02:23 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Tue, 10 Sep 2013 02:23:32 +0000 (02:23 +0000)
svn path=/trunk/; revision=59999

14 files changed:
reactos/drivers/filesystems/npfs_new/CMakeLists.txt
reactos/drivers/filesystems/npfs_new/cleanup.c [new file with mode: 0644]
reactos/drivers/filesystems/npfs_new/close.c [new file with mode: 0644]
reactos/drivers/filesystems/npfs_new/fileinfo.c [new file with mode: 0644]
reactos/drivers/filesystems/npfs_new/flushbuf.c [new file with mode: 0644]
reactos/drivers/filesystems/npfs_new/fsctrl.c [new file with mode: 0644]
reactos/drivers/filesystems/npfs_new/main.c
reactos/drivers/filesystems/npfs_new/npfs.h
reactos/drivers/filesystems/npfs_new/read.c
reactos/drivers/filesystems/npfs_new/statesup.c
reactos/drivers/filesystems/npfs_new/strucsup.c
reactos/drivers/filesystems/npfs_new/waitsup.c
reactos/drivers/filesystems/npfs_new/write.c [new file with mode: 0644]
reactos/drivers/filesystems/npfs_new/writesup.c [new file with mode: 0644]

index 7b2a567..3f02743 100644 (file)
@@ -1,8 +1,13 @@
 
 list(APPEND SOURCE
+     cleanup.c
+     close.c
      create.c
      datasup.c
+     fileinfo.c
      fileobsup.c
+     flushbuf.c
+     fsctrl.c
      main.c
      prefxsup.c
      read.c
@@ -10,7 +15,9 @@ list(APPEND SOURCE
      secursup.c
      statesup.c
      strucsup.c
-     waitsup.c)
+     waitsup.c
+     write.c
+     writesup.c)
 
 add_library(npfs_new SHARED ${SOURCE})
 set_module_type(npfs_new kernelmodedriver)
diff --git a/reactos/drivers/filesystems/npfs_new/cleanup.c b/reactos/drivers/filesystems/npfs_new/cleanup.c
new file mode 100644 (file)
index 0000000..1be907c
--- /dev/null
@@ -0,0 +1,73 @@
+#include "npfs.h"
+
+NTSTATUS
+NTAPI
+NpCommonCleanup(IN PDEVICE_OBJECT DeviceObject,
+                IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    NODE_TYPE_CODE NodeTypeCode;
+    LIST_ENTRY List;
+    PNP_FCB Fcb;
+    PNP_CCB Ccb;
+    BOOLEAN ServerSide;
+    PLIST_ENTRY ThisEntry, NextEntry;
+    PAGED_CODE();
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    InitializeListHead(&List);
+
+    ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE);
+    NodeTypeCode = NpDecodeFileObject(IoStack->FileObject,
+                                      (PVOID*)&Fcb,
+                                      &Ccb,
+                                      &ServerSide);
+    if (NodeTypeCode == NPFS_NTC_CCB )
+    {
+        if ( ServerSide == 1 )
+        {
+            ASSERT(Ccb->Fcb->ServerOpenCount != 0);
+            --Ccb->Fcb->ServerOpenCount;
+        }
+
+        NpSetClosingPipeState(Ccb, Irp, ServerSide, &List);
+    }
+
+    ExReleaseResourceLite(&NpVcb->Lock);
+
+    NextEntry = List.Flink;
+    while (NextEntry != &List)
+    {
+        ThisEntry = NextEntry;
+        NextEntry = NextEntry->Flink;
+
+        Irp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry);
+        IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+    }
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+NpFsdCleanup(IN PDEVICE_OBJECT DeviceObject,
+             IN PIRP Irp)
+{
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    FsRtlEnterFileSystem();
+
+    Status = NpCommonCleanup(DeviceObject, Irp);
+
+    FsRtlExitFileSystem();
+
+    if ( Status != STATUS_PENDING )
+    {
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+    }
+
+    return Status;
+}
+
diff --git a/reactos/drivers/filesystems/npfs_new/close.c b/reactos/drivers/filesystems/npfs_new/close.c
new file mode 100644 (file)
index 0000000..2d0f26c
--- /dev/null
@@ -0,0 +1,68 @@
+#include "npfs.h"
+
+NTSTATUS
+NTAPI
+NpCommonClose(IN PDEVICE_OBJECT DeviceObject,
+              IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    NODE_TYPE_CODE NodeTypeCode;
+    LIST_ENTRY List;
+    PNP_FCB Fcb;
+    PNP_CCB Ccb;
+    BOOLEAN ServerSide;
+    PLIST_ENTRY ThisEntry, NextEntry;
+    PAGED_CODE();
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    InitializeListHead(&List);
+
+    ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE);
+    NodeTypeCode = NpDecodeFileObject(IoStack->FileObject,
+                                      (PVOID*)&Fcb,
+                                      &Ccb,
+                                      &ServerSide);
+    if (NodeTypeCode == NPFS_NTC_ROOT_DCB)
+    {
+        --Fcb->CurrentInstances;
+        NpDeleteCcb(Ccb, &List);
+    }
+    else if (NodeTypeCode == NPFS_NTC_VCB)
+    {
+        --NpVcb->ReferenceCount;
+    }
+
+    ExReleaseResourceLite(&NpVcb->Lock);
+
+    NextEntry = List.Flink;
+    while (NextEntry != &List)
+    {
+        ThisEntry = NextEntry;
+        NextEntry = NextEntry->Flink;
+
+        Irp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry);
+        IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+    }
+
+    Irp->IoStatus.Status = STATUS_SUCCESS;
+    IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+NpFsdClose(IN PDEVICE_OBJECT DeviceObject,
+           IN PIRP Irp)
+{
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    FsRtlEnterFileSystem();
+
+    Status = NpCommonClose(DeviceObject, Irp);
+
+    FsRtlExitFileSystem();
+
+    return Status;
+}
+
diff --git a/reactos/drivers/filesystems/npfs_new/fileinfo.c b/reactos/drivers/filesystems/npfs_new/fileinfo.c
new file mode 100644 (file)
index 0000000..6e3a063
--- /dev/null
@@ -0,0 +1,178 @@
+#include "npfs.h"
+
+NTSTATUS
+NTAPI
+NpSetBasicInfo(IN PNP_CCB Ccb,
+               IN PFILE_BASIC_INFORMATION Buffer)
+{
+    PAGED_CODE();
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+NpSetPipeInfo(IN PNP_FCB Fcb,
+              IN PNP_CCB Ccb, 
+              IN PFILE_PIPE_INFORMATION Buffer,
+              IN ULONG ServerSide, 
+              IN PLIST_ENTRY List)
+{
+    NTSTATUS Status;
+    PNP_DATA_QUEUE ReadQueue, WriteQueue; 
+    ULONG CompletionMode;
+    PAGED_CODE();
+
+    if ( Buffer->ReadMode == FILE_PIPE_MESSAGE_MODE && Fcb->NamedPipeType == FILE_PIPE_BYTE_STREAM_TYPE )
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    if ( ServerSide )
+    {
+        if ( ServerSide != 1 ) KeBugCheckEx(NPFS_FILE_SYSTEM, 0xA04EFu, ServerSide, 0, 0);
+        ReadQueue = &Ccb->InQueue;
+        WriteQueue = &Ccb->OutQueue;
+        CompletionMode = Ccb->ServerCompletionMode;
+    }
+    else
+    {
+        ReadQueue = &Ccb->OutQueue;
+        WriteQueue = &Ccb->InQueue;
+        CompletionMode = Ccb->ClientCompletionMode;
+    }
+
+    if ( Buffer->CompletionMode != FILE_PIPE_COMPLETE_OPERATION ||
+        CompletionMode == FILE_PIPE_COMPLETE_OPERATION || 
+        (ReadQueue->QueueState == ReadEntries &&
+        WriteQueue->QueueState != WriteEntries ))
+    {
+        if (ServerSide)
+        {
+            Ccb->ServerReadMode = Buffer->ReadMode & 0xFF;
+            Ccb->ServerCompletionMode = Buffer->CompletionMode & 0xFF;
+        }
+        else
+        {
+            Ccb->ClientReadMode = Buffer->ReadMode & 0xFF;
+            Ccb->ClientCompletionMode = Buffer->CompletionMode & 0xFF;
+        }
+
+        NpCheckForNotify(Fcb->ParentDcb, 0, List);
+        Status = 0;
+    }
+    else
+    {
+        Status = STATUS_PIPE_BUSY;
+    }
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+NpCommonSetInformation(IN PDEVICE_OBJECT DeviceObject,
+                       IN PIRP Irp,
+                       IN PLIST_ENTRY List)
+{
+    NODE_TYPE_CODE NodeTypeCode;
+    PIO_STACK_LOCATION IoStack;
+    ULONG InfoClass;
+    PVOID Buffer;
+    PNP_FCB Fcb;
+    PNP_CCB Ccb;
+    BOOLEAN ServerSide;
+    PAGED_CODE();
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    NodeTypeCode = NpDecodeFileObject(IoStack->FileObject,
+                                      (PVOID*)&Fcb,
+                                      &Ccb,
+                                      &ServerSide);
+    if ( !NodeTypeCode ) return STATUS_PIPE_DISCONNECTED;
+    if ( NodeTypeCode != NPFS_NTC_CCB ) return STATUS_INVALID_PARAMETER;
+
+    InfoClass = IoStack->Parameters.QueryFile.FileInformationClass;
+    Buffer = Irp->AssociatedIrp.SystemBuffer;
+
+    if ( InfoClass == FileBasicInformation ) return NpSetBasicInfo(Ccb, Buffer);
+    
+    if ( InfoClass != FilePipeInformation ) return STATUS_INVALID_PARAMETER;
+
+    return NpSetPipeInfo(Fcb, Ccb, Buffer, ServerSide, List);
+}
+
+NTSTATUS
+NTAPI
+NpFsdSetInformation(IN PDEVICE_OBJECT DeviceObject,
+                    IN PIRP Irp)
+{
+    NTSTATUS Status;
+    LIST_ENTRY List;
+    PLIST_ENTRY NextEntry, ThisEntry;
+    PAGED_CODE();
+
+    InitializeListHead(&List);
+
+    FsRtlEnterFileSystem();
+    ExAcquireResourceSharedLite(&NpVcb->Lock, TRUE);
+
+    Status = NpCommonSetInformation(DeviceObject, Irp, &List);
+
+    ExReleaseResourceLite(&NpVcb->Lock);
+
+    NextEntry = List.Flink;
+    while (NextEntry != &List)
+    {
+        ThisEntry = NextEntry;
+        NextEntry = NextEntry->Flink;
+
+        Irp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry);
+        IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+    }
+
+    FsRtlExitFileSystem();
+
+    if ( Status != STATUS_PENDING )
+    {
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+    }
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+NpCommonQueryInformation(IN PDEVICE_OBJECT DeviceObject,
+                         IN PIRP Irp)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NpFsdQueryInformation(IN PDEVICE_OBJECT DeviceObject,
+                      IN PIRP Irp)
+{
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    FsRtlEnterFileSystem();
+    ExAcquireResourceSharedLite(&NpVcb->Lock, TRUE);
+
+    Status = NpCommonQueryInformation(DeviceObject, Irp);
+
+    ExReleaseResourceLite(&NpVcb->Lock);
+    FsRtlExitFileSystem();
+
+    if ( Status != STATUS_PENDING )
+    {
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+    }
+
+    return Status;
+}
+
diff --git a/reactos/drivers/filesystems/npfs_new/flushbuf.c b/reactos/drivers/filesystems/npfs_new/flushbuf.c
new file mode 100644 (file)
index 0000000..8bffd88
--- /dev/null
@@ -0,0 +1,68 @@
+#include "npfs.h"
+
+NTSTATUS
+NTAPI
+NpCommonFlushBuffers(IN PDEVICE_OBJECT DeviceObject,
+                     IN PIRP Irp)
+{
+    NODE_TYPE_CODE NodeTypeCode;
+    PNP_CCB Ccb;
+    BOOLEAN ServerSide;
+    NTSTATUS Status;
+    PNP_DATA_QUEUE FlushQueue;
+    PAGED_CODE();
+
+    NodeTypeCode = NpDecodeFileObject(IoGetCurrentIrpStackLocation(Irp)->FileObject,
+                                      NULL,
+                                      &Ccb,
+                                      &ServerSide);
+    if (NodeTypeCode != NPFS_NTC_CCB ) return STATUS_PIPE_DISCONNECTED;
+
+    ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE);
+    //ms_exc.registration.TryLevel = 0;
+
+    FlushQueue = &Ccb->OutQueue;
+    if ( ServerSide != 1 ) FlushQueue = &Ccb->InQueue;
+
+    if ( FlushQueue->QueueState == WriteEntries)
+    {
+        Status = NpAddDataQueueEntry(ServerSide,
+                                     Ccb,
+                                     FlushQueue,
+                                     1,
+                                     2u,
+                                     0,
+                                     Irp,
+                                     NULL,
+                                     0);
+    }
+    else
+    {
+        Status = STATUS_SUCCESS;
+    }
+
+   // ms_exc.registration.TryLevel = -1;
+    ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+NpFsdFlushBuffers(IN PDEVICE_OBJECT DeviceObject,
+                  IN PIRP Irp)
+{
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    FsRtlEnterFileSystem();
+    ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE);
+
+    Status = NpCommonFlushBuffers(DeviceObject, Irp);
+
+    ExReleaseResourceLite(&NpVcb->Lock);
+    FsRtlExitFileSystem();
+
+    return Status;
+}
+
diff --git a/reactos/drivers/filesystems/npfs_new/fsctrl.c b/reactos/drivers/filesystems/npfs_new/fsctrl.c
new file mode 100644 (file)
index 0000000..27ac9f1
--- /dev/null
@@ -0,0 +1,692 @@
+#include "npfs.h"
+
+IO_STATUS_BLOCK NpUserIoStatusBlock;
+
+NTSTATUS
+NTAPI
+NpInternalTransceive(IN PDEVICE_OBJECT DeviceObject,
+                     IN PIRP Irp,
+                     IN PLIST_ENTRY List)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NpInternalRead(IN PDEVICE_OBJECT DeviceObject,
+               IN PIRP Irp,
+               IN BOOLEAN Overflow,
+               IN PLIST_ENTRY List)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NpInternalWrite(IN PDEVICE_OBJECT DeviceObject,
+                IN PIRP Irp,
+                IN PLIST_ENTRY List)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NpQueryClientProcess(IN PDEVICE_OBJECT DeviceObject,
+                     IN PIRP Irp)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NpSetClientProcess(IN PDEVICE_OBJECT DeviceObject,
+                   IN PIRP Irp)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NpAssignEvent(IN PDEVICE_OBJECT DeviceObject,
+              IN PIRP Irp)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NpQueryEvent(IN PDEVICE_OBJECT DeviceObject,
+             IN PIRP Irp)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NpImpersonate(IN PDEVICE_OBJECT DeviceObject,
+              IN PIRP Irp)
+{
+    UNIMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NpDisconnect(IN PDEVICE_OBJECT DeviceObject,
+             IN PIRP Irp,
+             IN PLIST_ENTRY List)
+{
+    BOOLEAN ServerSide;
+    PNP_CCB Ccb;
+    NTSTATUS Status;
+    NODE_TYPE_CODE NodeTypeCode;
+    PIO_STACK_LOCATION IoStack;
+    PAGED_CODE();
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &ServerSide);
+    if (NodeTypeCode == NPFS_NTC_CCB)
+    {
+        if ( ServerSide == 1 )
+        {
+            ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE);
+
+            Status = NpSetDisconnectedPipeState(Ccb, List);
+
+            NpUninitializeSecurity(Ccb);
+
+            ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
+        }
+        else
+        {
+            Status = STATUS_ILLEGAL_FUNCTION;
+        }
+    }
+    else
+    {
+        Status = STATUS_PIPE_DISCONNECTED;
+    }
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+NpListen(IN PDEVICE_OBJECT DeviceObject,
+         IN PIRP Irp,
+         IN PLIST_ENTRY List)
+{
+    BOOLEAN ServerSide;
+    PNP_CCB Ccb;
+    NTSTATUS Status;
+    NODE_TYPE_CODE NodeTypeCode;
+    PIO_STACK_LOCATION IoStack;
+    PAGED_CODE();
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &ServerSide);
+    if (NodeTypeCode == NPFS_NTC_CCB)
+    {
+        if ( ServerSide == 1 )
+        {
+            ExAcquireResourceExclusiveLite(&Ccb->NonPagedCcb->Lock, TRUE);
+
+            Status = NpSetListeningPipeState(Ccb, Irp, List);
+
+            NpUninitializeSecurity(Ccb);
+
+            ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
+        }
+        else
+        {
+            Status = STATUS_ILLEGAL_FUNCTION;
+        }
+    }
+    else
+    {
+        Status = STATUS_ILLEGAL_FUNCTION;
+    }
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+NpPeek(IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp, 
+       IN PLIST_ENTRY List)
+{
+    PIO_STACK_LOCATION IoStack;
+    NODE_TYPE_CODE Type;
+    ULONG InputLength;
+    BOOLEAN ServerSide;
+    PNP_CCB Ccb;
+    PFILE_PIPE_PEEK_BUFFER PeekBuffer;
+    PNP_DATA_QUEUE DataQueue;
+    ULONG BytesPeeked;
+    IO_STATUS_BLOCK IoStatus;
+    NTSTATUS Status;
+    PNP_DATA_QUEUE_ENTRY DataEntry;
+    PAGED_CODE();
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    InputLength = IoStack->Parameters.FileSystemControl.OutputBufferLength;
+    Type = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &ServerSide);
+    if (!Type) return STATUS_PIPE_DISCONNECTED;
+
+    if ((Type != NPFS_NTC_CCB) && (InputLength < sizeof(*PeekBuffer)))
+    {
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    PeekBuffer = (PFILE_PIPE_PEEK_BUFFER)Irp->AssociatedIrp.SystemBuffer;
+    if ( ServerSide )
+    {
+        if ( ServerSide != 1 )
+        {
+            KeBugCheckEx(NPFS_FILE_SYSTEM, 0xD02E5, ServerSide, 0, 0);
+        }
+        DataQueue = &Ccb->InQueue;
+    }
+    else
+    {
+        DataQueue = &Ccb->OutQueue;
+    }
+
+    if ( Ccb->NamedPipeState != FILE_PIPE_CONNECTED_STATE )
+    {
+        if ( Ccb->NamedPipeState != FILE_PIPE_CLOSING_STATE )
+        {
+            return STATUS_INVALID_PIPE_STATE;
+        }
+        if ( DataQueue->QueueState != WriteEntries)
+        {
+            return STATUS_PIPE_BROKEN;
+        }
+    }
+
+    PeekBuffer->NamedPipeState = 0;
+    PeekBuffer->ReadDataAvailable = 0;
+    PeekBuffer->NumberOfMessages = 0;
+    PeekBuffer->MessageLength = 0;
+    PeekBuffer->NamedPipeState = Ccb->NamedPipeState;
+    BytesPeeked = sizeof(*PeekBuffer);
+
+    if ( DataQueue->QueueState == WriteEntries)
+    {
+        DataEntry = CONTAINING_RECORD(DataQueue->Queue.Flink,
+                                      NP_DATA_QUEUE_ENTRY,
+                                      QueueEntry);
+        ASSERT((DataEntry->DataEntryType == Buffered) || (DataEntry->DataEntryType == Unbuffered));
+
+        PeekBuffer->ReadDataAvailable = DataQueue->BytesInQueue - DataQueue->ByteOffset;
+        if ( Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE)
+        {
+            PeekBuffer->NumberOfMessages = DataQueue->EntriesInQueue;
+            PeekBuffer->MessageLength = DataEntry->DataSize - DataQueue->ByteOffset;
+        }
+        if ( InputLength == sizeof(*PeekBuffer) )
+        {
+            Status = PeekBuffer->ReadDataAvailable != 0 ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS;
+        }
+        else
+        {
+            IoStatus = NpReadDataQueue(DataQueue,
+                                       TRUE,
+                                       FALSE,
+                                       PeekBuffer->Data,
+                                       InputLength - sizeof(*PeekBuffer),
+                                       Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE,
+                                       Ccb,
+                                       List);
+            Status = IoStatus.Status;
+            BytesPeeked = IoStatus.Information + sizeof(*PeekBuffer);
+        }
+    }
+    else
+    {
+        Status = STATUS_SUCCESS;
+    }
+
+    Irp->IoStatus.Information = BytesPeeked;
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+NpCompleteTransceiveIrp(IN PDEVICE_OBJECT DeviceObject,
+                        IN PIRP Irp,
+                        IN PVOID Context)
+{
+    PAGED_CODE();
+
+    if ( Irp->AssociatedIrp.SystemBuffer )
+    {
+        ExFreePool(Irp->AssociatedIrp.SystemBuffer);
+    }
+
+    IoFreeIrp(Irp);
+    return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS
+NTAPI
+NpTransceive(IN PDEVICE_OBJECT DeviceObject,
+             IN PIRP Irp,
+             IN PLIST_ENTRY List)
+{
+    PIO_STACK_LOCATION IoStack;
+    PVOID InBuffer, OutBuffer;
+    ULONG InLength, OutLength, ReadMode, BytesWritten;
+    NODE_TYPE_CODE NodeTypeCode;
+    PNP_CCB Ccb;
+    BOOLEAN ServerSide;
+    PNP_NONPAGED_CCB NonPagedCcb;
+    PNP_DATA_QUEUE ReadQueue, WriteQueue;
+    PNP_EVENT_BUFFER EventBuffer;
+    NTSTATUS Status;
+    PIRP NewIrp;
+    PAGED_CODE();
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    InLength = IoStack->Parameters.FileSystemControl.InputBufferLength;
+    InBuffer = IoStack->Parameters.FileSystemControl.Type3InputBuffer;
+    OutLength = IoStack->Parameters.FileSystemControl.OutputBufferLength;
+    OutBuffer = Irp->UserBuffer;
+
+    if ( Irp->RequestorMode  == UserMode)
+    {
+        _SEH2_TRY
+        {
+            ProbeForRead(InBuffer, InLength, sizeof(CHAR));
+            ProbeForWrite(OutBuffer, OutLength, sizeof(CHAR));
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            ASSERT(FALSE);
+        }
+        _SEH2_END;
+    }
+
+    NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &ServerSide);
+    if (NodeTypeCode != NPFS_NTC_CCB )
+    {
+        return STATUS_PIPE_DISCONNECTED;
+    }
+
+    NonPagedCcb = Ccb->NonPagedCcb;
+    ExAcquireResourceExclusiveLite(&NonPagedCcb->Lock, TRUE);
+
+    //ms_exc.registration.TryLevel = 1;
+    if ( Ccb->NamedPipeState != FILE_PIPE_CONNECTED_STATE )
+    {
+        Status = STATUS_INVALID_PIPE_STATE;
+        goto Quickie;
+    }
+
+    if ( ServerSide )
+    {
+        if ( ServerSide != 1 ) KeBugCheckEx(NPFS_FILE_SYSTEM, 0xD0538, ServerSide, 0, 0);
+        ReadQueue = &Ccb->InQueue;
+        WriteQueue = &Ccb->OutQueue;
+        WriteQueue = &Ccb->OutQueue;
+        EventBuffer = NonPagedCcb->EventBufferServer;
+        ReadMode = Ccb->ServerReadMode;
+    }
+    else
+    {
+        ReadQueue = &Ccb->OutQueue;
+        WriteQueue = &Ccb->InQueue;
+        EventBuffer = NonPagedCcb->EventBufferClient;
+        ReadMode = Ccb->ClientReadMode;
+        WriteQueue = &Ccb->InQueue;
+    }
+
+    if (Ccb->Fcb->NamedPipeConfiguration != FILE_PIPE_FULL_DUPLEX ||
+        ReadMode != FILE_PIPE_MESSAGE_MODE )
+    {
+        Status = STATUS_INVALID_PIPE_STATE;
+        goto Quickie;
+    }
+
+    if ( ReadQueue->QueueState != Empty)
+    {
+        Status = STATUS_PIPE_BUSY;
+        goto Quickie;
+    }
+
+    Status = NpWriteDataQueue(WriteQueue,
+                              1,
+                              InBuffer,
+                              InLength,
+                              Ccb->Fcb->NamedPipeType,
+                              &BytesWritten,
+                              Ccb,
+                              ServerSide,
+                              Irp->Tail.Overlay.Thread,
+                              List);
+    if ( Status == STATUS_MORE_PROCESSING_REQUIRED )
+    {
+        ASSERT(WriteQueue->QueueState != ReadEntries);
+        NewIrp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
+        if ( !NewIrp )
+        {
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            goto Quickie;
+        }
+
+        IoSetCompletionRoutine(Irp, NpCompleteTransceiveIrp, NULL, TRUE, TRUE, TRUE);
+
+        if ( BytesWritten )
+        {
+            NewIrp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithQuotaTag(PagedPool, BytesWritten, 'wFpN');
+            if ( !NewIrp->AssociatedIrp.SystemBuffer )
+            {
+                IoFreeIrp(NewIrp);
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+                goto Quickie;
+            }
+
+            RtlCopyMemory(NewIrp->AssociatedIrp.SystemBuffer,
+                          (PVOID)((ULONG_PTR)InBuffer + InLength - BytesWritten),
+                          BytesWritten);
+            //ms_exc.registration.TryLevel = 1;
+        }
+        else
+        {
+            NewIrp->AssociatedIrp.SystemBuffer = NULL;
+        }
+
+        IoStack = IoGetNextIrpStackLocation(NewIrp);
+        IoSetNextIrpStackLocation(NewIrp);
+
+        NewIrp->Tail.Overlay.Thread = Irp->Tail.Overlay.Thread;
+        NewIrp->IoStatus.Information = BytesWritten;
+
+        IoStack->Parameters.Read.Length = BytesWritten;
+        IoStack->MajorFunction = IRP_MJ_WRITE;
+
+        if ( BytesWritten > 0 ) NewIrp->Flags = IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO;
+        NewIrp->UserIosb = &NpUserIoStatusBlock;
+
+        Status = NpAddDataQueueEntry(ServerSide,
+                                     Ccb,
+                                     WriteQueue,
+                                     WriteEntries,
+                                     1,
+                                     BytesWritten,
+                                     NewIrp,
+                                     NULL,
+                                     0);
+        if ( Status != STATUS_PENDING )
+        {
+            NewIrp->IoStatus.Status = Status;
+            InsertTailList(List, &NewIrp->Tail.Overlay.ListEntry);
+        }
+    }
+
+    if (!NT_SUCCESS(Status)) goto Quickie;
+    if ( EventBuffer ) KeSetEvent(EventBuffer->Event, 0, 0);
+    ASSERT(ReadQueue->QueueState == Empty);
+    Status = NpAddDataQueueEntry(ServerSide,
+                                 Ccb,
+                                 ReadQueue,
+                                 ReadEntries,
+                                 0,
+                                 OutLength,
+                                 Irp,
+                                 NULL,
+                                 0);
+    if (NT_SUCCESS(Status))
+    {
+        if ( EventBuffer ) KeSetEvent(EventBuffer->Event, 0, 0);
+    }
+
+Quickie:
+    //ms_exc.registration.TryLevel = -1;
+    ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+NpWaitForNamedPipe(IN PDEVICE_OBJECT DeviceObject,
+                   IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    ULONG InLength, NameLength;
+    UNICODE_STRING SourceString, Prefix;
+    BOOLEAN ServerSide;
+    PNP_CCB Ccb;
+    PFILE_PIPE_WAIT_FOR_BUFFER Buffer;
+    NTSTATUS Status;
+    NODE_TYPE_CODE NodeTypeCode;
+    PLIST_ENTRY NextEntry;
+    PNP_FCB Fcb;
+    PAGED_CODE();
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+    InLength = IoStack->Parameters.DeviceIoControl.InputBufferLength;
+
+    SourceString.Buffer = NULL;
+
+    //ms_exc.registration.TryLevel = 0;
+
+    if (NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &ServerSide) != NPFS_NTC_ROOT_DCB )
+    {
+        Status = STATUS_ILLEGAL_FUNCTION;
+        goto Quickie;
+    }
+
+    Buffer = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer;
+    if (InLength < sizeof(*Buffer))
+    {
+        Status = STATUS_INVALID_PARAMETER;
+        goto Quickie;
+    }
+
+    NameLength = Buffer->NameLength;
+    if ((NameLength > 0xFFFD) || ((NameLength + sizeof(*Buffer)) > InLength ))
+    {
+        Status = STATUS_INVALID_PARAMETER;
+        goto Quickie;
+    }
+
+    SourceString.Length = (USHORT)NameLength + sizeof(OBJ_NAME_PATH_SEPARATOR);
+    SourceString.Buffer = ExAllocatePoolWithTag(PagedPool, SourceString.Length, 'WFpN');
+    if (!SourceString.Buffer )
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+        goto Quickie;
+    }
+
+    SourceString.Buffer[0] = OBJ_NAME_PATH_SEPARATOR;
+    RtlCopyMemory(&SourceString.Buffer[1], Buffer->Name, Buffer->NameLength);
+
+    Status = STATUS_SUCCESS;
+    //Status = NpTranslateAlias(&SourceString);
+    if (!NT_SUCCESS(Status)) goto Quickie;
+
+    Fcb = NpFindPrefix(&SourceString, TRUE, &Prefix);
+    Fcb = (PNP_FCB)((ULONG_PTR)Fcb & ~1);
+
+    NodeTypeCode = Fcb ? Fcb->NodeType : 0;
+    if ( NodeTypeCode != NPFS_NTC_FCB )
+    {
+        Status = STATUS_OBJECT_NAME_NOT_FOUND;
+        goto Quickie;
+    }
+
+    for (NextEntry = Fcb->CcbList.Flink;
+         NextEntry != &Fcb->CcbList;
+         NextEntry = NextEntry->Flink)
+    {
+        Ccb = CONTAINING_RECORD(NextEntry, NP_CCB, CcbEntry);
+        if ( Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE ) break;
+    }
+
+    if ( NextEntry == &Fcb->CcbList )
+    {
+        Status = STATUS_SUCCESS;
+    }
+    else
+    {
+        Status = NpAddWaiter(&NpVcb->WaitQueue,
+                             Fcb->Timeout,
+                             Irp,
+                             &SourceString);
+    }
+
+Quickie:
+    //ms_exc.registration.TryLevel = -1;
+    if ( SourceString.Buffer ) ExFreePool(SourceString.Buffer);
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+NpCommonFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
+                          IN PIRP Irp)
+{
+    ULONG Fsctl;
+    BOOLEAN Overflow = FALSE;
+    LIST_ENTRY List;
+    PLIST_ENTRY NextEntry, ThisEntry;
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    InitializeListHead(&List);
+    Fsctl = IoGetCurrentIrpStackLocation(Irp)->Parameters.FileSystemControl.FsControlCode;
+
+    switch (Fsctl)
+    {
+        case FSCTL_PIPE_PEEK:
+            ExAcquireResourceExclusiveLite(&NpVcb->Lock, 1u);
+            Status = NpPeek(DeviceObject, Irp, &List);
+            break;
+
+        case FSCTL_PIPE_INTERNAL_WRITE:
+            ExAcquireResourceSharedLite(&NpVcb->Lock, 1u);
+            Status = NpInternalWrite(DeviceObject, Irp, &List);
+            break;
+
+        case FSCTL_PIPE_TRANSCEIVE:
+            ExAcquireResourceSharedLite(&NpVcb->Lock, 1u);
+            Status = NpTransceive(DeviceObject, Irp, &List);
+            break;
+
+        case FSCTL_PIPE_INTERNAL_TRANSCEIVE:
+            ExAcquireResourceSharedLite(&NpVcb->Lock, 1u);
+            Status = NpInternalTransceive(DeviceObject, Irp, &List);
+            break;
+        case FSCTL_PIPE_INTERNAL_READ_OVFLOW:
+            Overflow = TRUE;
+            // on purpose
+
+        case FSCTL_PIPE_INTERNAL_READ:
+            ExAcquireResourceSharedLite(&NpVcb->Lock, 1u);
+            Status = NpInternalRead(DeviceObject, Irp, Overflow, &List);
+            break;
+
+        case FSCTL_PIPE_QUERY_CLIENT_PROCESS:
+
+            ExAcquireResourceSharedLite(&NpVcb->Lock, 1u);
+            Status = NpQueryClientProcess(DeviceObject, Irp);
+            break;
+
+        case FSCTL_PIPE_ASSIGN_EVENT:
+
+            ExAcquireResourceExclusiveLite(&NpVcb->Lock, 1u);
+            Status = NpAssignEvent(DeviceObject, Irp);
+            break;
+
+        case FSCTL_PIPE_DISCONNECT:
+
+            ExAcquireResourceExclusiveLite(&NpVcb->Lock, 1u);
+            Status = NpDisconnect(DeviceObject, Irp, &List);
+            break;
+
+        case FSCTL_PIPE_LISTEN:
+
+            ExAcquireResourceSharedLite(&NpVcb->Lock, 1u);
+            Status = NpListen(DeviceObject, Irp, &List);
+            break;
+
+        case FSCTL_PIPE_QUERY_EVENT:
+
+            ExAcquireResourceExclusiveLite(&NpVcb->Lock, 1u);
+            Status = NpQueryEvent(DeviceObject, Irp);
+            break;
+
+        case FSCTL_PIPE_WAIT:
+
+            ExAcquireResourceExclusiveLite(&NpVcb->Lock, 1u);
+            Status = NpWaitForNamedPipe(DeviceObject, Irp);
+            break;
+
+        case FSCTL_PIPE_IMPERSONATE:
+
+            ExAcquireResourceExclusiveLite(&NpVcb->Lock, 1u);
+            Status = NpImpersonate(DeviceObject, Irp);
+            break;
+
+        case FSCTL_PIPE_SET_CLIENT_PROCESS:
+            ExAcquireResourceExclusiveLite(&NpVcb->Lock, 1u);
+            Status = NpSetClientProcess(DeviceObject, Irp);
+            break;
+
+        default:
+            return STATUS_NOT_SUPPORTED;
+    }
+
+    ExReleaseResourceLite(&NpVcb->Lock);
+
+    NextEntry = List.Flink;
+    while (NextEntry != &List)
+    {
+        ThisEntry = NextEntry;
+        NextEntry = NextEntry->Flink;
+
+        Irp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry);
+        IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+    }
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+NpFsdFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
+                       IN PIRP Irp)
+{
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    FsRtlEnterFileSystem();
+
+    Status = NpCommonFileSystemControl(DeviceObject, Irp);
+
+    FsRtlExitFileSystem();
+
+    if ( Status != STATUS_PENDING )
+    {
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+    }
+
+    return Status;
+}
+
+
index 1a8b469..0ae3eb0 100644 (file)
@@ -4,36 +4,8 @@ PDEVICE_OBJECT NpfsDeviceObject;
 
 NTSTATUS
 NTAPI
-NpFsdClose(IN PDEVICE_OBJECT DeviceObject,
-                     IN PIRP Irp)
-{
-    UNIMPLEMENTED;
-
-    Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
-    Irp->IoStatus.Information = 0;
-
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-    return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS
-NTAPI
-NpFsdWrite(IN PDEVICE_OBJECT DeviceObject,
-                     IN PIRP Irp)
-{
-    UNIMPLEMENTED;
-
-    Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
-    Irp->IoStatus.Information = 0;
-
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-    return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS
-NTAPI
-NpFsdQueryInformation(IN PDEVICE_OBJECT DeviceObject,
-                     IN PIRP Irp)
+NpFsdSetSecurity(IN PDEVICE_OBJECT DeviceObject,
+                 IN PIRP Irp)
 {
     UNIMPLEMENTED;
 
@@ -46,8 +18,8 @@ NpFsdQueryInformation(IN PDEVICE_OBJECT DeviceObject,
 
 NTSTATUS
 NTAPI
-NpFsdSetInformation(IN PDEVICE_OBJECT DeviceObject,
-                     IN PIRP Irp)
+NpFsdQuerySecurity(IN PDEVICE_OBJECT DeviceObject,
+                   IN PIRP Irp)
 {
     UNIMPLEMENTED;
 
@@ -72,34 +44,6 @@ NpFsdQueryVolumeInformation(IN PDEVICE_OBJECT DeviceObject,
     return STATUS_NOT_IMPLEMENTED;
 }
 
-NTSTATUS
-NTAPI
-NpFsdCleanup(IN PDEVICE_OBJECT DeviceObject,
-                     IN PIRP Irp)
-{
-    UNIMPLEMENTED;
-
-    Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
-    Irp->IoStatus.Information = 0;
-
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-    return STATUS_NOT_IMPLEMENTED;
-}
-
-NTSTATUS
-NTAPI
-NpFsdFlushBuffers(IN PDEVICE_OBJECT DeviceObject,
-                     IN PIRP Irp)
-{
-    UNIMPLEMENTED;
-
-    Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
-    Irp->IoStatus.Information = 0;
-
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-    return STATUS_NOT_IMPLEMENTED;
-}
-
 NTSTATUS
 NTAPI
 NpFsdDirectoryControl(IN PDEVICE_OBJECT DeviceObject,
@@ -114,20 +58,6 @@ NpFsdDirectoryControl(IN PDEVICE_OBJECT DeviceObject,
     return STATUS_NOT_IMPLEMENTED;
 }
 
-NTSTATUS
-NTAPI
-NpFsdFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
-                     IN PIRP Irp)
-{
-    UNIMPLEMENTED;
-
-    Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
-    Irp->IoStatus.Information = 0;
-
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-    return STATUS_NOT_IMPLEMENTED;
-}
-
 NTSTATUS
 NTAPI
 DriverEntry(IN PDRIVER_OBJECT DriverObject,
@@ -152,14 +82,12 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
     DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = NpFsdFlushBuffers;
     DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = NpFsdDirectoryControl;
     DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = NpFsdFileSystemControl;
-    //   DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] =
-    //     NpfsQuerySecurity;
-    //   DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] =
-    //     NpfsSetSecurity;
+    DriverObject->MajorFunction[IRP_MJ_QUERY_SECURITY] = NpFsdQuerySecurity;
+    DriverObject->MajorFunction[IRP_MJ_SET_SECURITY] = NpFsdSetSecurity;
 
     DriverObject->DriverUnload = NULL;
 
-    RtlInitUnicodeString(&DeviceName, L"\\Device\\NamedPipe");
+    RtlInitUnicodeString(&DeviceName, L"\\Device\\NamedPipe2");
     Status = IoCreateDevice(DriverObject,
                             sizeof(NP_VCB),
                             &DeviceName,
index a93b786..20fb513 100644 (file)
@@ -82,6 +82,19 @@ typedef struct _NP_WAIT_QUEUE
     KSPIN_LOCK WaitLock;
 } NP_WAIT_QUEUE, *PNP_WAIT_QUEUE;
 
+//
+// The Entries in the Queue above, one for each Waiter.
+//
+typedef struct _NP_WAIT_QUEUE_ENTRY
+{
+    PIRP Irp;
+    KDPC Dpc;
+    KTIMER Timer;
+    PNP_WAIT_QUEUE WaitQueue;
+    UNICODE_STRING String;
+    PFILE_OBJECT FileObject;
+} NP_WAIT_QUEUE_ENTRY, *PNP_WAIT_QUEUE_ENTRY;
+
 //
 // The event buffer in the NonPaged CCB
 //
@@ -225,6 +238,11 @@ typedef struct _NP_VCB
 
 extern PNP_VCB NpVcb;
 
+BOOLEAN
+NTAPI
+NpDeleteEventTableEntry(IN PRTL_GENERIC_TABLE Table,
+                        IN PVOID Buffer);
+
 VOID
 NTAPI
 NpInitializeWaitQueue(IN PNP_WAIT_QUEUE WaitQueue);
@@ -320,12 +338,47 @@ NTAPI
 NpFsdCreate(IN PDEVICE_OBJECT DeviceObject,
             IN PIRP Irp);
 
+NTSTATUS
+NTAPI
+NpFsdClose(IN PDEVICE_OBJECT DeviceObject,
+                     IN PIRP Irp);
+
+
+NTSTATUS
+NTAPI
+NpFsdCleanup(IN PDEVICE_OBJECT DeviceObject,
+                    IN PIRP Irp);
+
+NTSTATUS
+NTAPI
+NpFsdFileSystemControl(IN PDEVICE_OBJECT DeviceObject,
+                     IN PIRP Irp);
+
 NTSTATUS
 NTAPI
 NpSetConnectedPipeState(IN PNP_CCB Ccb,
                         IN PFILE_OBJECT FileObject,
                         IN PLIST_ENTRY List);
 
+NTSTATUS
+NTAPI
+NpSetListeningPipeState(IN PNP_CCB Ccb,
+                        IN PIRP Irp, 
+                        IN PLIST_ENTRY List);
+
+
+NTSTATUS
+NTAPI
+NpSetDisconnectedPipeState(IN PNP_CCB Ccb, 
+                           IN PLIST_ENTRY List);
+
+NTSTATUS
+NTAPI
+NpSetClosingPipeState(IN PNP_CCB Ccb,
+                      IN PIRP Irp, 
+                      IN ULONG NamedPipeEnd, 
+                      IN PLIST_ENTRY List);
+
 VOID
 NTAPI
 NpFreeClientSecurityContext(IN PSECURITY_CLIENT_CONTEXT ClientContext);
@@ -386,6 +439,13 @@ NpCheckForNotify(IN PNP_DCB Dcb,
                  IN BOOLEAN SecondList,
                  IN PLIST_ENTRY List);
 
+NTSTATUS
+NTAPI
+NpAddWaiter(IN PNP_WAIT_QUEUE WaitQueue,
+            IN LARGE_INTEGER WaitTime,
+            IN PIRP Irp, 
+            IN PUNICODE_STRING Name);
+
 NTSTATUS
 NTAPI
 NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue,
@@ -405,8 +465,43 @@ NpReadDataQueue(IN PNP_DATA_QUEUE DataQueue,
                 IN PNP_CCB Ccb,
                 IN PLIST_ENTRY List);
 
+
+NTSTATUS 
+NTAPI
+NpWriteDataQueue(IN PNP_DATA_QUEUE WriteQueue,
+                 IN ULONG Mode, 
+                 IN PVOID OutBuffer, 
+                 IN ULONG OutBufferSize, 
+                 IN ULONG PipeType, 
+                 OUT PULONG BytesWritten, 
+                 IN PNP_CCB Ccb, 
+                 IN BOOLEAN ServerSide, 
+                 IN PETHREAD Thread, 
+                 IN PLIST_ENTRY List);
+
 NTSTATUS
 NTAPI
 NpFsdRead(IN PDEVICE_OBJECT DeviceObject,
           IN PIRP Irp);
 
+
+NTSTATUS
+NTAPI
+NpFsdWrite(IN PDEVICE_OBJECT DeviceObject,
+           IN PIRP Irp);
+
+NTSTATUS
+NTAPI
+NpFsdFlushBuffers(IN PDEVICE_OBJECT DeviceObject,
+                  IN PIRP Irp);
+
+NTSTATUS
+NTAPI
+NpFsdSetInformation(IN PDEVICE_OBJECT DeviceObject,
+                    IN PIRP Irp);
+
+NTSTATUS
+NTAPI
+NpFsdQueryInformation(IN PDEVICE_OBJECT DeviceObject,
+                     IN PIRP Irp);
+
index 88c6aaf..03bb9d4 100644 (file)
@@ -12,7 +12,6 @@ NpCommonRead(IN PFILE_OBJECT FileObject,
              IN PLIST_ENTRY List)
 {
     NODE_TYPE_CODE NodeType;
-    ULONG NamedPipeConfiguation;
     PNP_DATA_QUEUE Queue;
     PNP_EVENT_BUFFER EventBuffer;
     NTSTATUS Status;
@@ -51,10 +50,8 @@ NpCommonRead(IN PFILE_OBJECT FileObject,
 
     ASSERT((Ccb->NamedPipeState == FILE_PIPE_CONNECTED_STATE) || (Ccb->NamedPipeState == FILE_PIPE_CLOSING_STATE));
 
-    NamedPipeConfiguation = Ccb->Fcb->NamedPipeConfiguration;
-
-    if ((ServerSide == 1 && NamedPipeConfiguation == FILE_PIPE_OUTBOUND) ||
-        (ServerSide == 0 && NamedPipeConfiguation == FILE_PIPE_INBOUND) )
+    if ((ServerSide == 1 && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_OUTBOUND) ||
+        (ServerSide == 0 && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_INBOUND ))
     {
         IoStatus->Status = STATUS_INVALID_PARAMETER;
         ReadOk = TRUE;
@@ -109,30 +106,32 @@ NpCommonRead(IN PFILE_OBJECT FileObject,
         goto Quickie;
     }
 
-    if ( Irp )
+    if ( !Irp )
     {
-        Status = NpAddDataQueueEntry(ServerSide,
-                                     Ccb,
-                                     Queue,
-                                     0,
-                                     0,
-                                     BufferSize,
-                                     Irp,
-                                     0,
-                                     0);
-        IoStatus->Status = Status;
-        if (!NT_SUCCESS(Status))
-        {
-            ReadOk = FALSE;
-            goto Quickie;
-        }
+        ReadOk = FALSE;
+        goto Quickie;
 
+    }
+    Status = NpAddDataQueueEntry(ServerSide,
+                                    Ccb,
+                                    Queue,
+                                    0,
+                                    0,
+                                    BufferSize,
+                                    Irp,
+                                    0,
+                                    0);
+    IoStatus->Status = Status;
+    if (!NT_SUCCESS(Status))
+    {
+        ReadOk = FALSE;
+    }
+    else
+    {
         ReadOk = TRUE;
         if ( EventBuffer ) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
-        goto Quickie;
     }
 
-    ReadOk = FALSE;
 Quickie:
     //ms_exc.registration.TryLevel = -1;
     ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
@@ -182,7 +181,7 @@ NpFsdRead(IN PDEVICE_OBJECT DeviceObject,
     {
         Irp->IoStatus.Information = IoStatus.Information;
         Irp->IoStatus.Status = IoStatus.Status;
-        IofCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+        IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
     }
 
     return IoStatus.Status;
index 7e45b33..dd01a06 100644 (file)
@@ -1,5 +1,22 @@
 #include "npfs.h"
 
+VOID
+NTAPI
+NpCancelListeningQueueIrp(IN PDEVICE_OBJECT DeviceObject,
+                          IN PIRP Irp)
+{
+    FsRtlEnterFileSystem();
+    ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE);
+
+    RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+
+    FsRtlExitFileSystem();
+    ExReleaseResourceLite(&NpVcb->Lock);
+
+    Irp->IoStatus.Status = STATUS_CANCELLED;
+    IofCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+}
+
 NTSTATUS
 NTAPI
 NpSetConnectedPipeState(IN PNP_CCB Ccb,
@@ -37,3 +54,316 @@ NpSetConnectedPipeState(IN PNP_CCB Ccb,
 
     return STATUS_SUCCESS;
 }
+
+NTSTATUS
+NTAPI
+NpSetDisconnectedPipeState(IN PNP_CCB Ccb, 
+                           IN PLIST_ENTRY List)
+{
+    PIRP Irp;
+    PNP_NONPAGED_CCB NonPagedCcb;
+    NTSTATUS Status;
+    PLIST_ENTRY NextEntry;
+    PNP_EVENT_BUFFER EventBuffer;
+
+    NonPagedCcb = Ccb->NonPagedCcb;
+
+    switch (Ccb->NamedPipeState)
+    {
+        case FILE_PIPE_DISCONNECTED_STATE:
+            Status = STATUS_PIPE_DISCONNECTED;
+            break;
+
+        case FILE_PIPE_LISTENING_STATE:
+            while (!IsListEmpty(&Ccb->IrpList))
+            {
+                NextEntry = RemoveHeadList(&Ccb->IrpList);
+
+                Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
+
+                if (IoSetCancelRoutine(Irp, NULL))
+                {
+                    Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED;
+                    InsertTailList(List, NextEntry);
+                }
+                else
+                {
+                    InitializeListHead(NextEntry);
+                }
+            }
+
+            Status = STATUS_SUCCESS;
+            break;
+        case FILE_PIPE_CONNECTED_STATE:
+
+            EventBuffer = NonPagedCcb->EventBufferClient;
+            while (Ccb->InQueue.QueueState != Empty)
+            {
+                Irp = NpRemoveDataQueueEntry(&Ccb->InQueue, FALSE, List);
+                if ( Irp )
+                {
+                    Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED;
+                    InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
+                }
+            }
+
+            while ( Ccb->OutQueue.QueueState != Empty)
+            {
+                Irp = NpRemoveDataQueueEntry(&Ccb->OutQueue, FALSE, List);
+                if ( Irp )
+                {
+                    Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED;
+                    InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
+                }
+            }
+
+            if ( EventBuffer ) KeSetEvent(EventBuffer->Event, 0, 0);
+
+            Status = STATUS_SUCCESS;
+            break;
+
+        case FILE_PIPE_CLOSING_STATE:
+
+            EventBuffer = NonPagedCcb->EventBufferClient;
+            while (Ccb->InQueue.QueueState != Empty)
+            {
+                Irp = NpRemoveDataQueueEntry(&Ccb->InQueue, FALSE, List);
+                if ( Irp )
+                {
+                    Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED;
+                    InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
+                }
+            }
+
+            ASSERT(Ccb->OutQueue.QueueState == Empty);
+
+            NpDeleteEventTableEntry(&NpVcb->EventTable, EventBuffer);
+            NonPagedCcb->EventBufferClient = NULL;
+
+            NpSetFileObject(Ccb->ClientFileObject, NULL, NULL, FALSE);
+            Ccb->ClientFileObject = NULL;
+
+            NpUninitializeSecurity(Ccb);
+
+            if ( Ccb->ClientSession )
+            {
+                ExFreePool(Ccb->ClientSession);
+                Ccb->ClientSession = NULL;
+            }
+
+            Status = STATUS_SUCCESS;
+            break;
+
+        default:
+            KeBugCheckEx(NPFS_FILE_SYSTEM, 0x1603DD, Ccb->NamedPipeState, 0, 0);
+            break;
+    }
+
+    Ccb->NamedPipeState = FILE_PIPE_DISCONNECTED_STATE;
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+NpSetListeningPipeState(IN PNP_CCB Ccb,
+                        IN PIRP Irp, 
+                        IN PLIST_ENTRY List)
+{
+    NTSTATUS Status;
+
+    switch (Ccb->NamedPipeState)
+    {
+        case FILE_PIPE_DISCONNECTED_STATE:
+
+        Status = NpCancelWaiter(&NpVcb->WaitQueue,
+                                &Ccb->Fcb->FullName,
+                                STATUS_SUCCESS,
+                                List);
+        if (!NT_SUCCESS(Status)) return Status;
+
+        //
+        // Drop down on purpose
+        //
+
+        case FILE_PIPE_LISTENING_STATE:
+
+            if ( Ccb->ServerCompletionMode == FILE_PIPE_COMPLETE_OPERATION)
+            {
+                Ccb->NamedPipeState = FILE_PIPE_LISTENING_STATE;
+                return STATUS_PIPE_LISTENING;
+            }
+
+            IoSetCancelRoutine(Irp, NpCancelListeningQueueIrp);
+            if ( Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
+            {
+                return STATUS_CANCELLED;
+            }
+
+            Ccb->NamedPipeState = FILE_PIPE_LISTENING_STATE;
+            IoMarkIrpPending(Irp);
+            InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
+            return STATUS_PENDING;
+
+        case FILE_PIPE_CONNECTED_STATE:
+            Status = STATUS_PIPE_CONNECTED;
+            break;
+
+        case FILE_PIPE_CLOSING_STATE:
+            Status = STATUS_PIPE_CLOSING;
+            break;
+
+        default:
+            KeBugCheckEx(NPFS_FILE_SYSTEM, 0x160133, Ccb->NamedPipeState, 0, 0);
+            break;
+    }
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+NpSetClosingPipeState(IN PNP_CCB Ccb,
+                      IN PIRP Irp, 
+                      IN ULONG NamedPipeEnd, 
+                      IN PLIST_ENTRY List)
+{
+    PNP_NONPAGED_CCB NonPagedCcb;
+    PNP_FCB Fcb;
+    PLIST_ENTRY NextEntry;
+    PNP_DATA_QUEUE ReadQueue, WriteQueue, DataQueue;
+    PNP_EVENT_BUFFER EventBuffer;
+
+    NonPagedCcb = Ccb->NonPagedCcb;
+    Fcb = Ccb->Fcb;
+
+    switch (Ccb->NamedPipeState)
+    {
+        case FILE_PIPE_LISTENING_STATE:
+
+            ASSERT(NamedPipeEnd == FILE_PIPE_SERVER_END);
+
+            while (!IsListEmpty(&Ccb->IrpList))
+            {
+                NextEntry = RemoveHeadList(&Ccb->IrpList);
+
+                Irp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);
+
+                if (IoSetCancelRoutine(Irp, NULL))
+                {
+                    Irp->IoStatus.Status = STATUS_PIPE_BROKEN;
+                    InsertTailList(List, NextEntry);
+                }
+                else
+                {
+                    InitializeListHead(NextEntry);
+                }
+            }
+
+            // Drop on purpose
+
+        case FILE_PIPE_DISCONNECTED_STATE:
+
+            ASSERT(NamedPipeEnd == FILE_PIPE_SERVER_END);
+
+            NpSetFileObject(Ccb->ServerFileObject, NULL, NULL, TRUE);
+            Ccb->ServerFileObject = NULL;
+
+            NpSetFileObject(Ccb->ClientFileObject, NULL, NULL, FALSE);
+            Ccb->ClientFileObject = NULL;
+
+            NpDeleteCcb(Ccb, List);
+            if ( !Fcb->CurrentInstances ) NpDeleteFcb(Fcb, List);
+            break;
+
+        case FILE_PIPE_CLOSING_STATE:
+
+            if ( NamedPipeEnd == FILE_PIPE_SERVER_END)
+            {
+                DataQueue = &Ccb->InQueue;
+            }
+            else
+            {
+                DataQueue = &Ccb->OutQueue;
+            }
+
+            NpSetFileObject(Ccb->ServerFileObject, NULL, NULL, TRUE);
+            Ccb->ServerFileObject = NULL;
+
+            NpSetFileObject(Ccb->ClientFileObject, NULL, NULL, FALSE);
+            Ccb->ClientFileObject = NULL;
+
+            while (Ccb->InQueue.QueueState != Empty)
+            {
+                Irp = NpRemoveDataQueueEntry(&Ccb->InQueue, FALSE, List);
+                if ( Irp )
+                {
+                    Irp->IoStatus.Status = STATUS_PIPE_BROKEN;
+                    InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
+                }
+            }
+
+            NpUninitializeSecurity(Ccb);
+
+            if ( Ccb->ClientSession )
+            {
+                ExFreePool(Ccb->ClientSession);
+                Ccb->ClientSession = 0;
+            }
+
+            NpDeleteCcb(Ccb, List);
+            if ( !Fcb->CurrentInstances ) NpDeleteFcb(Fcb, List);
+            break;
+
+        case FILE_PIPE_CONNECTED_STATE:
+            if ( NamedPipeEnd == FILE_PIPE_SERVER_END)
+            {
+                ReadQueue = &Ccb->InQueue;
+                WriteQueue = &Ccb->OutQueue;
+                EventBuffer = NonPagedCcb->EventBufferServer;
+
+                NpSetFileObject(Ccb->ServerFileObject, NULL, NULL, TRUE);
+                Ccb->ServerFileObject = 0;
+            }
+            else
+            {
+                ReadQueue = &Ccb->OutQueue;
+                WriteQueue = &Ccb->InQueue;
+                EventBuffer = NonPagedCcb->EventBufferClient;
+
+                NpSetFileObject(Ccb->ClientFileObject, NULL, NULL, FALSE);
+                Ccb->ClientFileObject = 0;
+            }
+
+            Ccb->NamedPipeState = FILE_PIPE_CLOSING_STATE;
+
+            while (Ccb->InQueue.QueueState != Empty)
+            {
+                Irp = NpRemoveDataQueueEntry(&Ccb->InQueue, FALSE, List);
+                if ( Irp )
+                {
+                    Irp->IoStatus.Status = STATUS_PIPE_BROKEN;
+                    InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
+                }
+            }
+
+            while (WriteQueue->QueueState == WriteEntries)
+            {
+                Irp = NpRemoveDataQueueEntry(WriteQueue, FALSE, List);
+                if ( Irp )
+                {
+                    Irp->IoStatus.Status = STATUS_PIPE_BROKEN;
+                    InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
+                }
+            }
+
+            if ( EventBuffer ) KeSetEvent(EventBuffer->Event, 0, 0);
+            break;
+
+        default:
+            KeBugCheckEx(0x25u, 0x1602F9, Ccb->NamedPipeState, 0, 0);
+            break;
+    }
+    return STATUS_SUCCESS;
+}
+
index 5faf022..869ff6f 100644 (file)
@@ -37,8 +37,10 @@ NTAPI
 NpDeleteEventTableEntry(IN PRTL_GENERIC_TABLE Table,
                         IN PVOID Buffer)
 {
-    UNIMPLEMENTED;
-    return FALSE;
+    if (!Buffer) return FALSE;
+
+    ObfDereferenceObject(((PNP_EVENT_BUFFER)Buffer)->Event);
+    return RtlDeleteElementGenericTable(Table, Buffer);
 }
 
 VOID
index fbbd390..7fcabbd 100644 (file)
@@ -1,5 +1,76 @@
 #include "npfs.h"
 
+VOID
+NTAPI
+NpCancelWaitQueueIrp(IN PDEVICE_OBJECT DeviceObject, 
+                     IN PIRP Irp)
+{
+    KIRQL OldIrql;
+    PNP_WAIT_QUEUE_ENTRY WaitEntry;
+    PNP_WAIT_QUEUE WaitQueue;
+
+    IoReleaseCancelSpinLock(Irp->CancelIrql);
+
+    WaitQueue = (PNP_WAIT_QUEUE)Irp->Tail.Overlay.DriverContext[0];
+
+    OldIrql = KfAcquireSpinLock(&WaitQueue->WaitLock);
+
+    WaitEntry = (PNP_WAIT_QUEUE_ENTRY)Irp->Tail.Overlay.DriverContext[1];
+    if ( WaitEntry )
+    {
+        RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+        if ( !KeCancelTimer(&WaitEntry->Timer) )
+        {
+            WaitEntry->Irp = NULL;
+            WaitEntry = NULL;
+        }
+    }
+
+    KfReleaseSpinLock(&WaitQueue->WaitLock, OldIrql);
+
+    if ( WaitEntry )
+    {
+        ObfDereferenceObject(WaitEntry->FileObject);
+        ExFreePool(WaitEntry);
+    }
+
+    Irp->IoStatus.Information = 0;
+    Irp->IoStatus.Status = STATUS_CANCELLED;
+    IofCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+}
+VOID
+NTAPI
+NpTimerDispatch(IN PKDPC Dpc,
+                IN PVOID Context,
+                IN PVOID Argument1,
+                IN PVOID Argument2)
+{
+    PIRP Irp;
+    KIRQL OldIrql;
+    PNP_WAIT_QUEUE_ENTRY WaitEntry = Context;
+
+    OldIrql = KfAcquireSpinLock(&WaitEntry->WaitQueue->WaitLock);
+    Irp = WaitEntry->Irp;
+    if ( Irp);
+    {
+        RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+        if ( !IoSetCancelRoutine(Irp, NULL))
+        {
+            Irp->Tail.Overlay.DriverContext[1] = NULL;
+            Irp = NULL;
+        }
+    }
+    KfReleaseSpinLock(&WaitEntry->WaitQueue->WaitLock, OldIrql);
+    if ( Irp )
+    {
+        Irp->IoStatus.Status = STATUS_IO_TIMEOUT;
+        IofCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+    }
+    ObfDereferenceObject(WaitEntry->FileObject);
+    ExFreePoolWithTag(WaitEntry, 0);
+}
+
 VOID
 NTAPI
 NpInitializeWaitQueue(IN PNP_WAIT_QUEUE WaitQueue)
@@ -33,3 +104,88 @@ NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue,
     ExFreePool(DestinationString.Buffer);
     return STATUS_SUCCESS;
 }
+
+NTSTATUS
+NTAPI
+NpAddWaiter(IN PNP_WAIT_QUEUE WaitQueue,
+            IN LARGE_INTEGER WaitTime,
+            IN PIRP Irp, 
+            IN PUNICODE_STRING Name)
+{
+    PIO_STACK_LOCATION IoStack;
+    KIRQL OldIrql;
+    NTSTATUS Status;
+    PNP_WAIT_QUEUE_ENTRY WaitEntry;
+    PFILE_PIPE_WAIT_FOR_BUFFER WaitBuffer;
+    LARGE_INTEGER DueTime;
+    ULONG i;
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    WaitEntry = ExAllocatePoolWithQuotaTag(NonPagedPool, sizeof(*WaitEntry), 'wFpN');
+    if ( WaitEntry )
+    {
+        KeInitializeDpc(&WaitEntry->Dpc, NpTimerDispatch, WaitEntry);
+        KeInitializeTimer(&WaitEntry->Timer);
+
+        if ( Name )
+        {
+            WaitEntry->String = *Name;
+        }
+        else
+        {
+            WaitEntry->String.Length = 0;
+            WaitEntry->String.Buffer = 0;
+        }
+
+        WaitEntry->WaitQueue = WaitQueue;
+        WaitEntry->Irp = Irp;
+
+        WaitBuffer = (PFILE_PIPE_WAIT_FOR_BUFFER)Irp->AssociatedIrp.SystemBuffer;
+        if ( WaitBuffer->TimeoutSpecified )
+        {
+            DueTime = WaitBuffer->Timeout;
+        }
+        else
+        {
+            DueTime = WaitTime;
+        }
+
+        for (i = 0; i < WaitBuffer->NameLength / sizeof(WCHAR); i++)
+        {
+            WaitBuffer->Name[i] = RtlUpcaseUnicodeChar(WaitBuffer->Name[i]);
+        }
+
+        Irp->Tail.Overlay.DriverContext[0] = WaitQueue;
+        Irp->Tail.Overlay.DriverContext[1] = WaitEntry;
+        OldIrql = KfAcquireSpinLock(&WaitQueue->WaitLock);
+
+        IoSetCancelRoutine(Irp, NpCancelWaitQueueIrp);
+
+        if ( Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
+        {
+            Status = STATUS_CANCELLED;
+        }
+        else
+        {
+            InsertTailList(&WaitQueue->WaitList, &Irp->Tail.Overlay.ListEntry);
+
+            IoMarkIrpPending(Irp);
+            Status = STATUS_PENDING;
+
+            WaitEntry->FileObject = IoStack->FileObject;
+            ObfReferenceObject(WaitEntry->FileObject);
+
+            KeSetTimer(&WaitEntry->Timer, DueTime, &WaitEntry->Dpc);
+            WaitEntry = NULL;
+
+        }
+        KfReleaseSpinLock(&WaitQueue->WaitLock, OldIrql);
+        if ( WaitEntry ) ExFreePool(WaitEntry);
+    }
+    else
+    {
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+    }
+    return Status;
+}
diff --git a/reactos/drivers/filesystems/npfs_new/write.c b/reactos/drivers/filesystems/npfs_new/write.c
new file mode 100644 (file)
index 0000000..96fe2d8
--- /dev/null
@@ -0,0 +1,204 @@
+#include "npfs.h"
+
+LONG NpSlowWriteCalls;
+
+BOOLEAN
+NTAPI
+NpCommonWrite(IN PFILE_OBJECT FileObject,
+              IN PVOID Buffer,
+              IN ULONG DataSize, 
+              IN PETHREAD Thread, 
+              IN PIO_STATUS_BLOCK IoStatus, 
+              IN PIRP Irp, 
+              IN PLIST_ENTRY List)
+{
+    NODE_TYPE_CODE NodeType;
+    BOOLEAN WriteOk, ServerSide;
+    PNP_CCB Ccb;
+    PNP_NONPAGED_CCB NonPagedCcb;
+    PNP_DATA_QUEUE WriteQueue;
+    NTSTATUS Status;
+    PNP_EVENT_BUFFER EventBuffer;
+    ULONG BytesWritten;
+    PAGED_CODE();
+
+    IoStatus->Information = 0;
+    NodeType = NpDecodeFileObject(FileObject, NULL, &Ccb, &ServerSide);
+
+    if (!NodeType)
+    {
+        IoStatus->Status = STATUS_PIPE_DISCONNECTED;
+        return TRUE;
+    }
+
+    if ( NodeType != NPFS_NTC_CCB )
+    {
+        IoStatus->Status = STATUS_INVALID_PARAMETER;
+        return TRUE;
+    }
+
+    NonPagedCcb = Ccb->NonPagedCcb;
+    ExAcquireResourceExclusiveLite(&NonPagedCcb->Lock, TRUE);
+
+   // ms_exc.registration.TryLevel = 0;
+
+    if ( Ccb->NamedPipeState == FILE_PIPE_DISCONNECTED_STATE )
+    {
+        IoStatus->Status = STATUS_PIPE_DISCONNECTED;
+        WriteOk = TRUE;
+        goto Quickie;
+    }
+
+    if ( Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE || Ccb->NamedPipeState == FILE_PIPE_CLOSING_STATE )
+    {
+        IoStatus->Status = Ccb->NamedPipeState != FILE_PIPE_LISTENING_STATE ? STATUS_PIPE_LISTENING : STATUS_PIPE_CLOSING;
+        WriteOk = TRUE;
+        goto Quickie;
+    }
+
+    ASSERT(Ccb->NamedPipeState == FILE_PIPE_CONNECTED_STATE);
+
+    if ((ServerSide == 1 && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_INBOUND) ||
+        (ServerSide == 0 && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_OUTBOUND))
+    {
+        IoStatus->Status = STATUS_INVALID_PARAMETER;
+        WriteOk = TRUE;
+        goto Quickie;
+    }
+
+    IoStatus->Status = 0;
+    IoStatus->Information = DataSize;
+
+    if ( ServerSide == 1 )
+    {
+        WriteQueue = &Ccb->OutQueue;
+        EventBuffer = NonPagedCcb->EventBufferClient;
+    }
+    else
+    {
+        WriteQueue = &Ccb->InQueue;
+        EventBuffer = NonPagedCcb->EventBufferServer;
+    }
+
+    if (WriteQueue->QueueState != ReadEntries ||
+        WriteQueue->BytesInQueue >= DataSize ||
+        WriteQueue->Quota >= DataSize - WriteQueue->BytesInQueue )
+    {
+        if (WriteQueue->QueueState != ReadEntries ||
+            WriteQueue->Quota - WriteQueue->QuotaUsed >= DataSize )
+        {
+            goto DoWrite;
+        }
+    }
+
+    if (Ccb->Fcb->NamedPipeType == FILE_PIPE_BYTE_STREAM_TYPE &&
+        Ccb->ServerCompletionMode & FILE_PIPE_COMPLETE_OPERATION)
+    {
+        IoStatus->Information = 0;
+        IoStatus->Status = 0;
+        WriteOk = TRUE;
+        goto Quickie;
+    }
+
+    if (!Irp )
+    {
+        WriteOk = 0;
+        goto Quickie;
+    }
+
+DoWrite:
+    Status = NpWriteDataQueue(WriteQueue,
+                              ServerSide ? Ccb->ClientReadMode : Ccb->ServerReadMode,
+                              Buffer,
+                              DataSize,
+                              Ccb->Fcb->NamedPipeType,
+                              &BytesWritten,
+                              Ccb,
+                              ServerSide,
+                              Thread,
+                              List);
+    IoStatus->Status = Status;
+    if ( Status == STATUS_MORE_PROCESSING_REQUIRED )
+    {
+        ASSERT(WriteQueue->QueueState != ReadEntries);
+        if ( (Ccb->ServerCompletionMode & FILE_PIPE_COMPLETE_OPERATION || !Irp)
+            && WriteQueue->Quota - WriteQueue->QuotaUsed < BytesWritten )
+        {
+            IoStatus->Information = DataSize - BytesWritten;
+            IoStatus->Status = 0;
+        }
+        else
+        {
+            ASSERT(WriteQueue->QueueState != ReadEntries);
+
+            IoStatus->Status = NpAddDataQueueEntry(ServerSide,
+                                                    Ccb,
+                                                    WriteQueue,
+                                                    WriteEntries,
+                                                    0,
+                                                    DataSize,
+                                                    Irp,
+                                                    Buffer,
+                                                    DataSize - BytesWritten);
+        }
+    }
+
+    if ( EventBuffer ) KeSetEvent(EventBuffer->Event, 0, 0);
+    WriteOk = 1;
+
+Quickie:
+    //ms_exc.registration.TryLevel = -1;
+    ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
+    return WriteOk;
+}
+
+NTSTATUS
+NTAPI
+NpFsdWrite(IN PDEVICE_OBJECT DeviceObject,
+           IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    IO_STATUS_BLOCK IoStatus;
+    LIST_ENTRY List;
+    PLIST_ENTRY NextEntry, ThisEntry;
+    PAGED_CODE();
+    NpSlowWriteCalls++;
+
+    InitializeListHead(&List);
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    FsRtlEnterFileSystem();
+    ExAcquireResourceSharedLite(&NpVcb->Lock, TRUE);
+
+    NpCommonWrite(IoStack->FileObject,
+                  Irp->UserBuffer,
+                  IoStack->Parameters.Write.Length,
+                  Irp->Tail.Overlay.Thread,
+                  &IoStatus,
+                  Irp,
+                  &List);
+
+    ExReleaseResourceLite(&NpVcb->Lock);
+
+    NextEntry = List.Flink;
+    while (NextEntry != &List)
+    {
+        ThisEntry = NextEntry;
+        NextEntry = NextEntry->Flink;
+
+        Irp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry);
+        IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+    }
+
+    FsRtlExitFileSystem();
+
+    if ( IoStatus.Status != STATUS_PENDING )
+    {
+        Irp->IoStatus.Information = IoStatus.Information;
+        Irp->IoStatus.Status = IoStatus.Status;
+        IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+    }
+
+    return IoStatus.Status;
+}
+
diff --git a/reactos/drivers/filesystems/npfs_new/writesup.c b/reactos/drivers/filesystems/npfs_new/writesup.c
new file mode 100644 (file)
index 0000000..860f040
--- /dev/null
@@ -0,0 +1,151 @@
+#include "npfs.h"
+
+NTSTATUS 
+NTAPI
+NpWriteDataQueue(IN PNP_DATA_QUEUE WriteQueue,
+                 IN ULONG Mode, 
+                 IN PVOID OutBuffer, 
+                 IN ULONG OutBufferSize, 
+                 IN ULONG PipeType, 
+                 OUT PULONG BytesWritten, 
+                 IN PNP_CCB Ccb, 
+                 IN BOOLEAN ServerSide, 
+                 IN PETHREAD Thread, 
+                 IN PLIST_ENTRY List)
+{
+    BOOLEAN HaveContext = FALSE, MoreProcessing, AllocatedBuffer;
+    PNP_DATA_QUEUE_ENTRY DataEntry;
+    ULONG DataSize, BufferSize;
+    PIRP WriteIrp;
+    PIO_STACK_LOCATION IoStack;
+    PVOID Buffer;
+    NTSTATUS Status;
+    PSECURITY_CLIENT_CONTEXT ClientContext;
+    PAGED_CODE();
+
+    *BytesWritten = OutBufferSize;
+
+    MoreProcessing = 1;
+    if ( PipeType != FILE_PIPE_OUTBOUND || (OutBufferSize) ) MoreProcessing = 0;
+
+    for (DataEntry = NpGetNextRealDataQueueEntry(WriteQueue, List);
+         ((WriteQueue->QueueState == ReadEntries) &&
+          ((*BytesWritten > 0) || (MoreProcessing)));
+         DataEntry = NpGetNextRealDataQueueEntry(WriteQueue, List))
+    {
+        DataSize = DataEntry->DataSize;
+
+        IoStack = IoGetCurrentIrpStackLocation( DataEntry->Irp);
+
+        if ( IoStack->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL && 
+             IoStack->Parameters.FileSystemControl.FsControlCode == FSCTL_PIPE_INTERNAL_WRITE &&
+             (DataSize < OutBufferSize || MoreProcessing) )
+        {
+            WriteIrp = NpRemoveDataQueueEntry(WriteQueue, 1, List);
+            if (WriteIrp )
+            {
+                WriteIrp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
+                InsertTailList(List, &WriteIrp->Tail.Overlay.ListEntry);
+            }
+            continue;
+        }
+
+        if ( DataEntry->DataEntryType == Unbuffered )
+        {
+             DataEntry->Irp->Overlay.AllocationSize.QuadPart = 0;
+        }
+        
+        BufferSize = *BytesWritten;
+        if ( BufferSize >= DataSize ) BufferSize = DataSize;
+
+        if ( DataEntry->DataEntryType != Unbuffered && BufferSize )
+        {
+            Buffer = ExAllocatePoolWithTag(NonPagedPool, BufferSize, 'RFpN');
+            if ( !Buffer ) return STATUS_INSUFFICIENT_RESOURCES;
+            AllocatedBuffer = 1;
+        }
+        else
+        {
+            Buffer = DataEntry->Irp->AssociatedIrp.SystemBuffer;
+            AllocatedBuffer = 0;
+        }
+
+        _SEH2_TRY
+        {
+             RtlCopyMemory(Buffer,
+                           (PVOID)((ULONG_PTR)OutBuffer + OutBufferSize - *BytesWritten),
+                           BufferSize);
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            ASSERT(FALSE);
+        }
+        _SEH2_END;
+
+        if ( !HaveContext )
+        {
+            HaveContext = 1;
+            Status = NpGetClientSecurityContext(ServerSide, Ccb, Thread, &ClientContext);
+            if (!NT_SUCCESS(Status))
+            {
+                if ( AllocatedBuffer ) ExFreePool(Buffer);
+                return Status;
+            }
+
+            if ( ClientContext )
+            {
+                NpFreeClientSecurityContext(Ccb->ClientContext);
+                Ccb->ClientContext = ClientContext;
+            }
+        }
+
+        WriteIrp = NpRemoveDataQueueEntry(WriteQueue, 1, List);
+        if ( WriteIrp )
+        {
+            *BytesWritten -= BufferSize;
+            WriteIrp->IoStatus.Information = BufferSize;
+
+            if ( AllocatedBuffer )
+            {
+                WriteIrp->AssociatedIrp.SystemBuffer = Buffer;
+                WriteIrp->Flags |= IRP_DEALLOCATE_BUFFER  | IRP_BUFFERED_IO | IRP_INPUT_OPERATION;
+            }
+
+            if ( !*BytesWritten )
+            {
+                MoreProcessing = 0;
+                WriteIrp->IoStatus.Status = 0;
+                InsertTailList(List, &WriteIrp->Tail.Overlay.ListEntry);
+                continue;
+            }
+
+            if ( Mode == FILE_PIPE_MESSAGE_MODE )
+            {
+                WriteIrp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
+            }
+            else
+            {
+                WriteIrp->IoStatus.Status = 0;
+            }
+
+            InsertTailList(List, &WriteIrp->Tail.Overlay.ListEntry);
+        }
+        else if ( AllocatedBuffer )
+        {
+            ExFreePool(Buffer);
+        }
+    }
+
+    if ( *BytesWritten > 0 || MoreProcessing )
+    {
+        ASSERT(WriteQueue->QueueState != ReadEntries);
+        Status = STATUS_MORE_PROCESSING_REQUIRED;
+    }
+    else
+    {
+        Status = STATUS_SUCCESS;
+    }
+
+    return Status;
+}
+