[NPFS-NEW]: Add data queue management routines, and add read support. Implement NpFsd...
authorAlex Ionescu <aionescu@gmail.com>
Mon, 9 Sep 2013 01:16:06 +0000 (01:16 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Mon, 9 Sep 2013 01:16:06 +0000 (01:16 +0000)
svn path=/trunk/; revision=59998

reactos/drivers/filesystems/npfs_new/CMakeLists.txt
reactos/drivers/filesystems/npfs_new/datasup.c
reactos/drivers/filesystems/npfs_new/main.c
reactos/drivers/filesystems/npfs_new/npfs.h
reactos/drivers/filesystems/npfs_new/read.c [new file with mode: 0644]
reactos/drivers/filesystems/npfs_new/readsup.c [new file with mode: 0644]
reactos/drivers/filesystems/npfs_new/secursup.c

index 03ba644..7b2a567 100644 (file)
@@ -1,17 +1,20 @@
 
 list(APPEND SOURCE
-    create.c
-    datasup.c
-    fileobsup.c
-    main.c
-    prefxsup.c
-    secursup.c
-    statesup.c
-    strucsup.c
-    waitsup.c)
+     create.c
+     datasup.c
+     fileobsup.c
+     main.c
+     prefxsup.c
+     read.c
+     readsup.c
+     secursup.c
+     statesup.c
+     strucsup.c
+     waitsup.c)
 
 add_library(npfs_new SHARED ${SOURCE})
 set_module_type(npfs_new kernelmodedriver)
+target_link_libraries(npfs_new ${PSEH_LIB})
 add_importlibs(npfs_new ntoskrnl hal)
 add_pch(npfs_new npfs.h)
 add_cd_file(TARGET npfs_new DESTINATION reactos/system32/drivers FOR all)
index 3c7794d..41f4edb 100644 (file)
@@ -25,6 +25,435 @@ NpInitializeDataQueue(IN PNP_DATA_QUEUE DataQueue,
     DataQueue->ByteOffset = 0;
     DataQueue->QueueState = Empty;
     DataQueue->Quota = Quota;
-    InitializeListHead(&DataQueue->List);
+    InitializeListHead(&DataQueue->Queue);
     return STATUS_SUCCESS;
 }
+
+VOID
+NTAPI
+NpCompleteStalledWrites(IN PNP_DATA_QUEUE DataQueue,
+                        IN PLIST_ENTRY List)
+{
+    ULONG QuotaLeft, ByteOffset, DataLeft, NewQuotaLeft;
+    PNP_DATA_QUEUE_ENTRY DataQueueEntry;
+    PIRP Irp;
+    PLIST_ENTRY NextEntry;
+
+    QuotaLeft = DataQueue->Quota - DataQueue->QuotaUsed;
+    ByteOffset = DataQueue->ByteOffset;
+
+    NextEntry = DataQueue->Queue.Flink;
+    while (NextEntry != &DataQueue->Queue)
+    {
+        if ( !QuotaLeft ) break;
+
+        DataQueueEntry = CONTAINING_RECORD(NextEntry, NP_DATA_QUEUE_ENTRY, Irp);
+
+        Irp = DataQueueEntry->Irp;
+
+        if ((DataQueueEntry->DataEntryType == 0) && (Irp))
+        {
+            DataLeft = DataQueueEntry->DataSize - ByteOffset;
+
+            if ( DataQueueEntry->QuotaInEntry < DataLeft )
+            {
+                NewQuotaLeft = DataLeft - DataQueueEntry->QuotaInEntry;
+                if ( NewQuotaLeft > QuotaLeft ) NewQuotaLeft = QuotaLeft;
+
+                QuotaLeft -= NewQuotaLeft;
+                DataQueueEntry->QuotaInEntry += NewQuotaLeft;
+
+                if (DataQueueEntry->QuotaInEntry == DataLeft &&
+                    IoSetCancelRoutine(Irp, NULL))
+                {
+                    DataQueueEntry->Irp = NULL;
+
+                    Irp->IoStatus.Status = 0;
+                    Irp->IoStatus.Information = DataQueueEntry->DataSize;
+
+                    InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
+                }
+            }
+        }
+
+        NextEntry = NextEntry->Flink;
+        ByteOffset = 0;
+    }
+
+    DataQueue->QuotaUsed = DataQueue->Quota - QuotaLeft;
+}
+
+PIRP
+NTAPI
+NpRemoveDataQueueEntry(IN PNP_DATA_QUEUE DataQueue,
+                       IN BOOLEAN Flag,
+                       IN PLIST_ENTRY List)
+{
+    PIRP Irp;
+    PNP_DATA_QUEUE_ENTRY QueueEntry;
+    BOOLEAN HasWrites;
+
+    if ( DataQueue->QueueState == Empty)
+    {
+        Irp = NULL;
+        ASSERT(IsListEmpty(&DataQueue->Queue));
+        ASSERT(DataQueue->EntriesInQueue == 0);
+        ASSERT(DataQueue->BytesInQueue == 0);
+        ASSERT(DataQueue->QuotaUsed == 0);
+    }
+    else
+    {
+        QueueEntry = CONTAINING_RECORD(RemoveHeadList(&DataQueue->Queue),
+                                       NP_DATA_QUEUE_ENTRY,
+                                       QueueEntry);
+
+        DataQueue->BytesInQueue -= QueueEntry->DataSize;
+        --DataQueue->EntriesInQueue;
+
+        HasWrites = 1;
+        if ( !DataQueue->QueueState != WriteEntries || DataQueue->QuotaUsed < DataQueue->Quota || !QueueEntry->QuotaInEntry )
+        {
+            HasWrites = 0;
+        }
+
+        DataQueue->QuotaUsed -= QueueEntry->QuotaInEntry;
+
+        if (DataQueue->Queue.Flink == &DataQueue->Queue)
+        {
+            DataQueue->QueueState = Empty;
+            HasWrites = 0;
+        }
+
+        Irp = QueueEntry->Irp;
+        NpFreeClientSecurityContext(QueueEntry->ClientSecurityContext);
+
+        if (Irp && IoSetCancelRoutine(Irp, NULL))
+        {
+            Irp->Tail.Overlay.DriverContext[3] = 0;
+        }
+
+        ExFreePool(QueueEntry);
+
+        if ( Flag )
+        {
+            NpGetNextRealDataQueueEntry(DataQueue, List);
+        }
+
+        if ( HasWrites )
+        {
+            NpCompleteStalledWrites(DataQueue, List);
+        }
+    }
+
+    DataQueue->ByteOffset = 0;
+    return Irp;
+}
+
+PNP_DATA_QUEUE_ENTRY
+NTAPI
+NpGetNextRealDataQueueEntry(IN PNP_DATA_QUEUE DataQueue,
+                            IN PLIST_ENTRY List)
+{
+    PNP_DATA_QUEUE_ENTRY DataEntry;
+    ULONG Type;
+    PIRP Irp;
+    PLIST_ENTRY NextEntry;
+    PAGED_CODE();
+
+    DataEntry = NULL;
+
+    NextEntry = DataQueue->Queue.Flink;
+    while (NextEntry != &DataQueue->Queue)
+    {
+        DataEntry = CONTAINING_RECORD(NextEntry, NP_DATA_QUEUE_ENTRY, QueueEntry);
+
+        Type = DataEntry->DataEntryType;
+        if ( Type == Buffered || Type == Unbuffered ) break;
+
+        Irp = NpRemoveDataQueueEntry(DataQueue, 0, List);
+        if ( Irp )
+        {
+            Irp->IoStatus.Status = STATUS_SUCCESS;
+            InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
+        }
+    }
+
+    return DataEntry;
+}
+
+VOID
+NTAPI
+NpCancelDataQueueIrp(IN PDEVICE_OBJECT DeviceObject,
+                     IN PIRP Irp)
+{
+    PNP_DATA_QUEUE DataQueue;
+    PNP_DATA_QUEUE_ENTRY DataEntry;
+    LIST_ENTRY List;
+    PSECURITY_CLIENT_CONTEXT ClientSecurityContext;
+    BOOLEAN CompleteWrites, FirstEntry;
+    PLIST_ENTRY NextEntry, ThisEntry;
+
+    if ( DeviceObject ) IoReleaseCancelSpinLock(Irp->CancelIrql);
+
+    InitializeListHead(&List);
+
+    DataQueue = (PNP_DATA_QUEUE)Irp->Tail.Overlay.DriverContext[2];
+    ClientSecurityContext = NULL;
+
+    if ( DeviceObject )
+    {
+        FsRtlEnterFileSystem();
+        ExAcquireResourceExclusiveLite(&NpVcb->Lock, TRUE);
+    }
+
+    DataEntry = (PNP_DATA_QUEUE_ENTRY)Irp->Tail.Overlay.DriverContext[3];
+    if ( DataEntry )
+    {
+        if (DataEntry->QueueEntry.Blink == &DataQueue->Queue )
+        {
+            DataQueue->ByteOffset = 0;
+            FirstEntry = 1;
+        }
+        else
+        {
+            FirstEntry = 0;
+        }
+
+        RemoveEntryList(&DataEntry->QueueEntry);
+
+        ClientSecurityContext = DataEntry->ClientSecurityContext;
+
+        CompleteWrites = 1;
+        if ( !DataQueue->QueueState != WriteEntries || DataQueue->QuotaUsed < DataQueue->Quota || !DataEntry->QuotaInEntry )
+        {
+            CompleteWrites = 0;
+        }
+
+        DataQueue->BytesInQueue -= DataEntry->DataSize;
+        DataQueue->QuotaUsed -= DataEntry->QuotaInEntry;
+        --DataQueue->EntriesInQueue;
+
+        if (DataQueue->Queue.Flink == &DataQueue->Queue )
+        {
+            DataQueue->QueueState = Empty;
+            ASSERT(DataQueue->BytesInQueue == 0);
+            ASSERT(DataQueue->EntriesInQueue == 0);
+            ASSERT(DataQueue->QuotaUsed == 0);
+        }
+        else
+        {
+            if ( FirstEntry )
+            {
+                NpGetNextRealDataQueueEntry(DataQueue, &List);
+            }
+            if ( CompleteWrites )
+            {
+                NpCompleteStalledWrites(DataQueue, &List);
+            }
+        }
+    }
+
+    if ( DeviceObject )
+    {
+        ExReleaseResourceLite(&NpVcb->Lock);
+        FsRtlExitFileSystem();
+    }
+
+    if ( DataEntry ) ExFreePool(DataEntry);
+
+    NpFreeClientSecurityContext(ClientSecurityContext);
+    Irp->IoStatus.Status = STATUS_CANCELLED;
+    IofCompleteRequest(Irp, IO_DISK_INCREMENT);
+
+    NextEntry = List.Flink;
+    while (NextEntry != &List)
+    {
+        ThisEntry = NextEntry;
+        NextEntry = NextEntry->Flink;
+
+        Irp = CONTAINING_RECORD(ThisEntry, IRP, Tail.Overlay.ListEntry);
+        IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+    }
+}
+
+NTSTATUS
+NTAPI
+NpAddDataQueueEntry(IN BOOLEAN ServerSide,
+                    IN PNP_CCB Ccb,
+                    IN PNP_DATA_QUEUE DataQueue,
+                    IN ULONG Who, 
+                    IN ULONG Type,
+                    IN ULONG DataSize,
+                    IN PIRP Irp,
+                    IN PVOID Buffer,
+                    IN ULONG ByteOffset)
+{
+    NTSTATUS Status;
+    PNP_DATA_QUEUE_ENTRY DataEntry;
+    SIZE_T EntrySize;
+    ULONG QuotaInEntry;
+    PSECURITY_CLIENT_CONTEXT ClientContext;
+    BOOLEAN HasSpace;
+
+    ClientContext = NULL;
+    ASSERT((DataQueue->QueueState == Empty) || (DataQueue->QueueState == Who));
+
+    Status = STATUS_SUCCESS;
+
+    if ((Type != 2) && (Who == WriteEntries))
+    {
+        Status = NpGetClientSecurityContext(ServerSide,
+                                            Ccb,
+                                            Irp ? Irp->Tail.Overlay.Thread :
+                                            PsGetCurrentThread(),
+                                            &ClientContext);
+        if (!NT_SUCCESS(Status)) return Status;
+    }
+
+    switch (Type)
+    {
+        case Unbuffered:
+        case 2:
+        case 3:
+
+            ASSERT(Irp != NULL);
+            DataEntry = ExAllocatePoolWithQuotaTag(NonPagedPool, sizeof(*DataEntry), 'rFpN');
+            if ( DataEntry )
+            {
+                DataEntry->DataEntryType = Type;
+                DataEntry->QuotaInEntry = 0;
+                DataEntry->Irp = Irp;
+                DataEntry->DataSize = DataSize;
+                DataEntry->ClientSecurityContext = ClientContext;
+                ASSERT((DataQueue->QueueState == Empty) || (DataQueue->QueueState == Who));
+                Status = STATUS_PENDING;
+                break;
+            }
+
+            NpFreeClientSecurityContext(ClientContext);
+            return STATUS_INSUFFICIENT_RESOURCES;
+    
+        case Buffered:
+
+            EntrySize = sizeof(*DataEntry);
+            if ( Who != Empty)
+            {
+                EntrySize = DataSize + sizeof(*DataEntry);
+                if ((DataSize + sizeof(*DataEntry)) < DataSize )
+                {
+                    NpFreeClientSecurityContext(ClientContext);
+                    return STATUS_INVALID_PARAMETER;
+                }
+            }
+
+            QuotaInEntry = DataSize - ByteOffset;
+            if ( DataQueue->Quota - DataQueue->QuotaUsed < QuotaInEntry )
+            {
+                QuotaInEntry = DataQueue->Quota - DataQueue->QuotaUsed;
+                HasSpace = 1;
+            }
+            else
+            {
+                HasSpace = 0;
+            }
+
+            DataEntry = ExAllocatePoolWithQuotaTag(NonPagedPool, EntrySize, 'rFpN');
+            if ( !DataEntry )
+            {
+                NpFreeClientSecurityContext(ClientContext);
+                return STATUS_INSUFFICIENT_RESOURCES;
+            }
+
+            DataEntry->QuotaInEntry = QuotaInEntry;
+            DataEntry->Irp = Irp;
+            DataEntry->DataEntryType = Buffered;
+            DataEntry->ClientSecurityContext = ClientContext;
+            DataEntry->DataSize = DataSize;
+
+            if ( Who == ReadEntries)
+            {
+                ASSERT(Irp);
+
+                Status = STATUS_PENDING;
+                ASSERT((DataQueue->QueueState == Empty) ||
+                       (DataQueue->QueueState == Who));
+            }
+            else
+            {
+                _SEH2_TRY
+                {
+                RtlCopyMemory(DataEntry + 1,
+                              Irp ? Irp->UserBuffer: Buffer,
+                              DataSize);
+                }
+                _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                {
+                    NpFreeClientSecurityContext(ClientContext);
+                    return _SEH2_GetExceptionCode();
+                }
+                _SEH2_END;
+
+                if ( HasSpace && Irp )
+                {
+                    Status = STATUS_PENDING;
+                }
+                else
+                {
+                    DataEntry->Irp = 0;
+                    Status = STATUS_SUCCESS;
+                }
+                
+                ASSERT((DataQueue->QueueState == Empty) || (DataQueue->QueueState == Who));
+            }
+
+        default:
+            ASSERT(FALSE);
+            NpFreeClientSecurityContext(ClientContext);
+            return STATUS_INVALID_PARAMETER;
+    }
+
+    ASSERT((DataQueue->QueueState == Empty) || (DataQueue->QueueState == Who));
+    if ( DataQueue->QueueState == Empty )
+    {
+        ASSERT(DataQueue->BytesInQueue == 0);
+        ASSERT(DataQueue->EntriesInQueue == 0);
+        ASSERT(IsListEmpty (&DataQueue->Queue));
+    }
+    else
+    {
+        ASSERT(DataQueue->QueueState == Who);
+        ASSERT(DataQueue->QueueState != Empty);
+        ASSERT(DataQueue->EntriesInQueue != 0);
+    }
+
+    DataQueue->QuotaUsed += DataEntry->QuotaInEntry;
+    DataQueue->QueueState = Who;
+    DataQueue->BytesInQueue += DataEntry->DataSize;
+    ++DataQueue->EntriesInQueue;
+    if ( ByteOffset )
+    {
+        DataQueue->ByteOffset = ByteOffset;
+        ASSERT(Who == WriteEntries);
+        ASSERT(ByteOffset < DataEntry->DataSize);
+        ASSERT(DataQueue->EntriesInQueue == 1);
+    }
+                    
+    InsertTailList(&DataQueue->Queue, &DataEntry->QueueEntry);
+
+    if ( Status == STATUS_PENDING )
+    {
+        IoMarkIrpPending(Irp);
+        Irp->Tail.Overlay.DriverContext[2] = DataQueue;
+        Irp->Tail.Overlay.DriverContext[3] = DataEntry;
+
+        IoSetCancelRoutine(Irp, NpCancelDataQueueIrp);
+
+        if ( Irp->Cancel )
+        {
+            IoSetCancelRoutine(Irp, NULL);
+            NpCancelDataQueueIrp(0, Irp);
+        }
+    }
+
+    return Status;
+}
index a69c91b..1a8b469 100644 (file)
@@ -16,20 +16,6 @@ NpFsdClose(IN PDEVICE_OBJECT DeviceObject,
     return STATUS_NOT_IMPLEMENTED;
 }
 
-NTSTATUS
-NTAPI
-NpFsdRead(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,
index 10ab733..a93b786 100644 (file)
@@ -3,6 +3,7 @@
 //
 #include <ntifs.h>
 #include <ntndk.h>
+#include <pseh/pseh2.h>
 #define UNIMPLEMENTED
 #define DPRINT1 DbgPrint
 
@@ -31,15 +32,26 @@ typedef USHORT NODE_TYPE_CODE, *PNODE_TYPE_CODE;
 //
 typedef enum _NP_DATA_QUEUE_STATE
 {
+    ReadEntries = 0,
+    WriteEntries = 1,
     Empty = 2
 } NP_DATA_QUEUE_STATE;
 
+//
+// Data Queue Entry Types
+//
+typedef enum _NP_DATA_QUEUE_ENTRY_TYPE
+{
+    Buffered = 0,
+    Unbuffered
+} NP_DATA_QUEUE_ENTRY_TYPE;
+
 //
 // An Input or Output Data Queue. Each CCB has two of these.
 //
 typedef struct _NP_DATA_QUEUE
 {
-    LIST_ENTRY List;
+    LIST_ENTRY Queue;
     ULONG QueueState;
     ULONG BytesInQueue;
     ULONG EntriesInQueue;
@@ -48,6 +60,19 @@ typedef struct _NP_DATA_QUEUE
     ULONG Quota;
 } NP_DATA_QUEUE, *PNP_DATA_QUEUE;
 
+//
+// The Entries that go into the Queue
+//
+typedef struct _NP_DATA_QUEUE_ENTRY
+{
+    LIST_ENTRY QueueEntry;
+    ULONG DataEntryType;
+    PIRP Irp;
+    ULONG QuotaInEntry;
+    PSECURITY_CLIENT_CONTEXT ClientSecurityContext;
+    ULONG DataSize;
+} NP_DATA_QUEUE_ENTRY, *PNP_DATA_QUEUE_ENTRY;
+
 //
 // A Wait Queue. Only the VCB has one of these.
 //
@@ -57,6 +82,14 @@ typedef struct _NP_WAIT_QUEUE
     KSPIN_LOCK WaitLock;
 } NP_WAIT_QUEUE, *PNP_WAIT_QUEUE;
 
+//
+// The event buffer in the NonPaged CCB
+//
+typedef struct _NP_EVENT_BUFFER
+{
+    PKEVENT Event;
+} NP_EVENT_BUFFER, *PNP_EVENT_BUFFER;
+
 //
 // The CCB for the Root DCB
 //
@@ -76,7 +109,7 @@ typedef struct _NP_CB_HEADER
     LIST_ENTRY DcbEntry;
     PVOID ParentDcb;
     ULONG CurrentInstances;
-    ULONG OtherCount;
+    ULONG ServerOpenCount;
     PSECURITY_DESCRIPTOR SecurityDescriptor;
 } NP_CB_HEADER, *PNP_CB_HEADER;
 
@@ -144,8 +177,8 @@ typedef struct _NP_FCB
 typedef struct _NP_NONPAGED_CCB
 {
     NODE_TYPE_CODE NodeType;
-    PVOID EventBufferClient;
-    PVOID EventBufferServer;
+    PNP_EVENT_BUFFER EventBufferClient;
+    PNP_EVENT_BUFFER EventBufferServer;
     ERESOURCE Lock;
 } NP_NONPAGED_CCB, *PNP_NONPAGED_CCB;
 
@@ -201,6 +234,34 @@ NTSTATUS
 NTAPI
 NpUninitializeDataQueue(IN PNP_DATA_QUEUE DataQueue);
 
+PNP_DATA_QUEUE_ENTRY
+NTAPI
+NpGetNextRealDataQueueEntry(IN PNP_DATA_QUEUE DataQueue,
+                            IN PLIST_ENTRY List);
+
+PIRP
+NTAPI
+NpRemoveDataQueueEntry(IN PNP_DATA_QUEUE DataQueue,
+                       IN BOOLEAN Flag,
+                       IN PLIST_ENTRY List);
+
+NTSTATUS
+NTAPI
+NpAddDataQueueEntry(IN BOOLEAN ServerSide,
+                    IN PNP_CCB Ccb,
+                    IN PNP_DATA_QUEUE DataQueue,
+                    IN ULONG Who, 
+                    IN ULONG Type,
+                    IN ULONG DataSize,
+                    IN PIRP Irp,
+                    IN PVOID Buffer,
+                    IN ULONG ByteOffset);
+
+VOID
+NTAPI
+NpCompleteStalledWrites(IN PNP_DATA_QUEUE DataQueue,
+                        IN PLIST_ENTRY List);
+
 NTSTATUS
 NTAPI
 NpInitializeDataQueue(IN PNP_DATA_QUEUE DataQueue,
@@ -265,6 +326,15 @@ NpSetConnectedPipeState(IN PNP_CCB Ccb,
                         IN PFILE_OBJECT FileObject,
                         IN PLIST_ENTRY List);
 
+VOID
+NTAPI
+NpFreeClientSecurityContext(IN PSECURITY_CLIENT_CONTEXT ClientContext);
+
+VOID
+NTAPI
+NpCopyClientContext(IN PNP_CCB Ccb,
+                    IN PNP_DATA_QUEUE_ENTRY DataQueueEntry);
+
 VOID
 NTAPI
 NpUninitializeSecurity(IN PNP_CCB Ccb);
@@ -275,6 +345,13 @@ NpInitializeSecurity(IN PNP_CCB Ccb,
                      IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
                      IN PETHREAD Thread);
 
+NTSTATUS
+NTAPI
+NpGetClientSecurityContext(IN BOOLEAN ServerSide,
+                           IN PNP_CCB Ccb,
+                           IN PETHREAD Thread,
+                           IN PSECURITY_CLIENT_CONTEXT *Context);
+
 VOID
 NTAPI
 NpSetFileObject(IN PFILE_OBJECT FileObject,
@@ -316,3 +393,20 @@ NpCancelWaiter(IN PNP_WAIT_QUEUE WaitQueue,
                IN NTSTATUS Status,
                IN PLIST_ENTRY ListEntry);
 
+
+IO_STATUS_BLOCK
+NTAPI
+NpReadDataQueue(IN PNP_DATA_QUEUE DataQueue, 
+                IN BOOLEAN Peek,
+                IN BOOLEAN ReadOverflowOperation,
+                IN PVOID Buffer,
+                IN ULONG BufferSize, 
+                IN ULONG Mode, 
+                IN PNP_CCB Ccb,
+                IN PLIST_ENTRY List);
+
+NTSTATUS
+NTAPI
+NpFsdRead(IN PDEVICE_OBJECT DeviceObject,
+          IN PIRP Irp);
+
diff --git a/reactos/drivers/filesystems/npfs_new/read.c b/reactos/drivers/filesystems/npfs_new/read.c
new file mode 100644 (file)
index 0000000..88c6aaf
--- /dev/null
@@ -0,0 +1,189 @@
+#include "npfs.h"
+
+LONG NpSlowReadCalls;
+
+BOOLEAN
+NTAPI
+NpCommonRead(IN PFILE_OBJECT FileObject,
+             IN PVOID Buffer,
+             IN ULONG BufferSize, 
+             OUT PIO_STATUS_BLOCK IoStatus, 
+             IN PIRP Irp,
+             IN PLIST_ENTRY List)
+{
+    NODE_TYPE_CODE NodeType;
+    ULONG NamedPipeConfiguation;
+    PNP_DATA_QUEUE Queue;
+    PNP_EVENT_BUFFER EventBuffer;
+    NTSTATUS Status;
+    BOOLEAN ServerSide;
+    PNP_CCB Ccb;
+    PNP_NONPAGED_CCB NonPagedCcb;
+    BOOLEAN ReadOk;
+    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 || Ccb->NamedPipeState == FILE_PIPE_LISTENING_STATE )
+    {
+        IoStatus->Status = Ccb->NamedPipeState != FILE_PIPE_DISCONNECTED_STATE ? STATUS_PIPE_LISTENING : STATUS_PIPE_DISCONNECTED;
+        ReadOk = TRUE;
+        goto Quickie;
+    }
+
+    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) )
+    {
+        IoStatus->Status = STATUS_INVALID_PARAMETER;
+        ReadOk = TRUE;
+        goto Quickie;
+    }
+
+    if ( ServerSide == 1 )
+    {
+        Queue = &Ccb->InQueue;
+        EventBuffer = NonPagedCcb->EventBufferClient;
+    }
+    else
+    {
+        Queue = &Ccb->OutQueue;
+        EventBuffer = NonPagedCcb->EventBufferServer;
+    }
+
+    if ( Queue->QueueState == WriteEntries )
+    {
+        *IoStatus = NpReadDataQueue(Queue,
+                                    FALSE,
+                                    FALSE,
+                                    Buffer,
+                                    BufferSize,
+                                    ServerSide ? Ccb->ServerReadMode : Ccb->ClientReadMode,
+                                    Ccb,
+                                    List);
+        if (!NT_SUCCESS(IoStatus->Status))
+        {
+            ReadOk = TRUE;
+            goto Quickie;
+        }
+
+        ReadOk = TRUE;
+        if ( EventBuffer ) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
+        goto Quickie;
+    }
+
+    if ( Ccb->NamedPipeState == FILE_PIPE_CLOSING_STATE )
+    {
+        IoStatus->Status = STATUS_PIPE_BROKEN;
+        ReadOk = TRUE;
+        if ( EventBuffer ) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
+        goto Quickie;
+    }
+
+    if ((ServerSide ? Ccb->ServerCompletionMode : Ccb->ServerCompletionMode) == FILE_PIPE_COMPLETE_OPERATION)
+    {
+        IoStatus->Status = STATUS_PIPE_EMPTY;
+        ReadOk = TRUE;
+        if ( EventBuffer ) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
+        goto Quickie;
+    }
+
+    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 = TRUE;
+        if ( EventBuffer ) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
+        goto Quickie;
+    }
+
+    ReadOk = FALSE;
+Quickie:
+    //ms_exc.registration.TryLevel = -1;
+    ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock);
+    return ReadOk;
+}
+
+NTSTATUS
+NTAPI
+NpFsdRead(IN PDEVICE_OBJECT DeviceObject,
+          IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    IO_STATUS_BLOCK IoStatus;
+    LIST_ENTRY List;
+    PLIST_ENTRY NextEntry, ThisEntry;
+    PAGED_CODE();
+    NpSlowReadCalls++;
+
+    InitializeListHead(&List);
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    FsRtlEnterFileSystem();
+    ExAcquireResourceSharedLite(&NpVcb->Lock, TRUE);
+
+    NpCommonRead(IoStack->FileObject,
+                 Irp->UserBuffer,
+                 IoStack->Parameters.Read.Length,
+                 &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;
+        IofCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+    }
+
+    return IoStatus.Status;
+}
diff --git a/reactos/drivers/filesystems/npfs_new/readsup.c b/reactos/drivers/filesystems/npfs_new/readsup.c
new file mode 100644 (file)
index 0000000..44d04b6
--- /dev/null
@@ -0,0 +1,138 @@
+#include "npfs.h"
+
+IO_STATUS_BLOCK
+NTAPI
+NpReadDataQueue(IN PNP_DATA_QUEUE DataQueue, 
+                IN BOOLEAN Peek,
+                IN BOOLEAN ReadOverflowOperation,
+                IN PVOID Buffer,
+                IN ULONG BufferSize, 
+                IN ULONG Mode, 
+                IN PNP_CCB Ccb,
+                IN PLIST_ENTRY List)
+{
+    PNP_DATA_QUEUE_ENTRY DataEntry, TempDataEntry;
+    PVOID DataBuffer;
+    ULONG DataSize, DataLength, TotalBytesCopied, RemainingSize, Offset;
+    PIRP Irp;
+    IO_STATUS_BLOCK Status;
+    BOOLEAN CompleteWrites = FALSE;
+    PAGED_CODE();
+
+    if ( ReadOverflowOperation ) Peek = TRUE;
+
+    RemainingSize = BufferSize;
+    Status.Status = 0;
+    TotalBytesCopied = 0;
+
+    if ( Peek )
+    {
+        DataEntry = CONTAINING_RECORD(DataQueue->Queue.Flink,
+                                      NP_DATA_QUEUE_ENTRY,
+                                      QueueEntry);
+    }
+    else
+    {
+        DataEntry = NpGetNextRealDataQueueEntry(DataQueue, List);
+    }
+
+    while (&DataEntry->QueueEntry != &DataQueue->Queue && RemainingSize )
+    {
+        if ( !Peek || (DataEntry->DataEntryType == Buffered || DataEntry->DataEntryType == Unbuffered ))
+        {
+            if ( DataEntry->DataEntryType == Unbuffered )
+            {
+                DataBuffer = DataEntry->Irp->AssociatedIrp.SystemBuffer;
+            }
+            else
+            {
+                DataBuffer = &DataEntry[1];
+            }
+            DataSize = DataEntry->DataSize;
+            Offset = DataSize;
+
+            if (&DataEntry->QueueEntry == DataQueue->Queue.Flink)
+            {
+                Offset = DataSize - DataQueue->ByteOffset;
+            }
+
+            DataLength = Offset;
+            if ( Offset >= RemainingSize ) DataLength = RemainingSize;
+
+            _SEH2_TRY
+            {
+                RtlCopyMemory((PVOID)((ULONG_PTR)Buffer + BufferSize - RemainingSize),
+                              (PVOID)((ULONG_PTR)DataBuffer + DataSize - Offset),
+                              DataLength);
+            }
+            _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+            {
+                ASSERT(FALSE);
+            }
+            _SEH2_END;
+
+
+            RemainingSize -= DataLength;
+            Offset -= DataLength;
+            TotalBytesCopied += DataLength;
+            if ( !Peek )
+            {
+                DataEntry->QuotaInEntry -= DataLength;
+                DataQueue->QuotaUsed -= DataLength;
+                DataQueue->ByteOffset += DataLength;
+                CompleteWrites = TRUE;;
+            }
+
+            NpCopyClientContext(Ccb, DataEntry);
+
+            if ( Offset || (ReadOverflowOperation && !TotalBytesCopied ))
+            {
+                if ( Mode == FILE_PIPE_MESSAGE_MODE )
+                {
+                    Status.Status = STATUS_BUFFER_OVERFLOW;
+                    break;
+                }
+            }
+            else
+            {
+                if ( !Peek || ReadOverflowOperation )
+                {
+                    if ( ReadOverflowOperation)
+                    {
+                        TempDataEntry = NpGetNextRealDataQueueEntry(DataQueue, List);
+                        ASSERT(TempDataEntry == DataEntry);
+                    }
+
+                    Irp = NpRemoveDataQueueEntry(DataQueue, TRUE, List);
+                    if ( Irp )
+                    {
+                        Irp->IoStatus.Information = DataSize;
+                        Irp->IoStatus.Status = STATUS_SUCCESS;
+                        InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
+                    }
+                }
+                if ( Mode == FILE_PIPE_MESSAGE_MODE )
+                {
+                    Status.Status = STATUS_SUCCESS;
+                    break;
+                }
+                ASSERT(!ReadOverflowOperation);
+            }
+        }
+        if ( Peek )
+        {
+            DataEntry = CONTAINING_RECORD(DataEntry->QueueEntry.Flink,
+                                          NP_DATA_QUEUE_ENTRY,
+                                          QueueEntry);
+        }
+        else
+        {
+            DataEntry = NpGetNextRealDataQueueEntry(DataQueue, List);
+        }
+    }
+
+    Status.Information = TotalBytesCopied;
+    if ( CompleteWrites ) NpCompleteStalledWrites(DataQueue, List);
+    return Status;
+}
+
index 5b0c47e..36051c3 100644 (file)
@@ -2,24 +2,44 @@
 
 VOID
 NTAPI
-NpUninitializeSecurity(IN PNP_CCB Ccb)
+NpFreeClientSecurityContext(IN PSECURITY_CLIENT_CONTEXT ClientContext)
 {
-    PACCESS_TOKEN ClientToken;
-    PSECURITY_CLIENT_CONTEXT ClientContext;
     TOKEN_TYPE TokenType;
-    PAGED_CODE();
+    PVOID ClientToken;
 
-    ClientContext = Ccb->ClientContext;
     if (!ClientContext) return;
 
     TokenType = SeTokenType(ClientContext->ClientToken);
-    ClientToken = Ccb->ClientContext->ClientToken;
+    ClientToken = ClientContext->ClientToken;
     if ((TokenType == TokenPrimary) || (ClientToken))
     {
         ObfDereferenceObject(ClientToken);
     }
-    ExFreePool(Ccb->ClientContext);
-    Ccb->ClientContext = 0;
+    ExFreePool(ClientContext);
+}
+
+VOID
+NTAPI
+NpCopyClientContext(IN PNP_CCB Ccb,
+                    IN PNP_DATA_QUEUE_ENTRY DataQueueEntry)
+{
+    PAGED_CODE();
+
+    if (!DataQueueEntry->ClientSecurityContext) return;
+
+    NpFreeClientSecurityContext(Ccb->ClientContext);
+    Ccb->ClientContext = DataQueueEntry->ClientSecurityContext;
+    DataQueueEntry->ClientSecurityContext = NULL;
+}
+
+VOID
+NTAPI
+NpUninitializeSecurity(IN PNP_CCB Ccb)
+{
+    PAGED_CODE();
+
+    NpFreeClientSecurityContext(Ccb->ClientContext);
+    Ccb->ClientContext = NULL;
 }
 
 NTSTATUS
@@ -63,3 +83,36 @@ NpInitializeSecurity(IN PNP_CCB Ccb,
     Ccb->ClientContext = 0;
     return Status;
 }
+
+NTSTATUS
+NTAPI
+NpGetClientSecurityContext(IN BOOLEAN ServerSide,
+                           IN PNP_CCB Ccb,
+                           IN PETHREAD Thread,
+                           IN PSECURITY_CLIENT_CONTEXT *Context)
+{
+   
+    PSECURITY_CLIENT_CONTEXT NewContext;
+    NTSTATUS Status;
+    PAGED_CODE();
+
+    if ( ServerSide || Ccb->ClientQos.ContextTrackingMode != 1 )
+    {
+        NewContext = NULL;
+        Status = STATUS_SUCCESS;
+    }
+    else
+    {
+        NewContext = ExAllocatePoolWithQuotaTag(PagedPool, sizeof(*NewContext), 'sFpN');
+        if ( !NewContext ) return STATUS_INSUFFICIENT_RESOURCES;
+
+        Status = SeCreateClientSecurity(Thread, &Ccb->ClientQos, 0, NewContext);
+        if (!NT_SUCCESS(Status))
+        {
+            ExFreePool(NewContext);
+            NewContext = NULL;
+        }
+    }
+    *Context = NewContext;
+    return Status;
+}