From b5edd2ce20d9f11413a31a1d4e541e13088d2a3c Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Mon, 9 Sep 2013 01:16:06 +0000 Subject: [PATCH] [NPFS-NEW]: Add data queue management routines, and add read support. Implement NpFsdRead & NpfsCommonRead (Peek is inherently implemented too, just didn't write the FSCTL handlers yet). Next up will be Write/Peek/Close/Cleanup. Code is WIP. svn path=/trunk/; revision=59998 --- .../filesystems/npfs_new/CMakeLists.txt | 21 +- .../drivers/filesystems/npfs_new/datasup.c | 431 +++++++++++++++++- reactos/drivers/filesystems/npfs_new/main.c | 14 - reactos/drivers/filesystems/npfs_new/npfs.h | 102 ++++- reactos/drivers/filesystems/npfs_new/read.c | 189 ++++++++ .../drivers/filesystems/npfs_new/readsup.c | 138 ++++++ .../drivers/filesystems/npfs_new/secursup.c | 81 +++- 7 files changed, 934 insertions(+), 42 deletions(-) create mode 100644 reactos/drivers/filesystems/npfs_new/read.c create mode 100644 reactos/drivers/filesystems/npfs_new/readsup.c diff --git a/reactos/drivers/filesystems/npfs_new/CMakeLists.txt b/reactos/drivers/filesystems/npfs_new/CMakeLists.txt index 03ba64409fd..7b2a5675c62 100644 --- a/reactos/drivers/filesystems/npfs_new/CMakeLists.txt +++ b/reactos/drivers/filesystems/npfs_new/CMakeLists.txt @@ -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) diff --git a/reactos/drivers/filesystems/npfs_new/datasup.c b/reactos/drivers/filesystems/npfs_new/datasup.c index 3c7794d8a87..41f4edb5c24 100644 --- a/reactos/drivers/filesystems/npfs_new/datasup.c +++ b/reactos/drivers/filesystems/npfs_new/datasup.c @@ -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; +} diff --git a/reactos/drivers/filesystems/npfs_new/main.c b/reactos/drivers/filesystems/npfs_new/main.c index a69c91b053e..1a8b46975a4 100644 --- a/reactos/drivers/filesystems/npfs_new/main.c +++ b/reactos/drivers/filesystems/npfs_new/main.c @@ -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, diff --git a/reactos/drivers/filesystems/npfs_new/npfs.h b/reactos/drivers/filesystems/npfs_new/npfs.h index 10ab7336870..a93b786e460 100644 --- a/reactos/drivers/filesystems/npfs_new/npfs.h +++ b/reactos/drivers/filesystems/npfs_new/npfs.h @@ -3,6 +3,7 @@ // #include #include +#include #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 index 00000000000..88c6aaf2de0 --- /dev/null +++ b/reactos/drivers/filesystems/npfs_new/read.c @@ -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 index 00000000000..44d04b63e8b --- /dev/null +++ b/reactos/drivers/filesystems/npfs_new/readsup.c @@ -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; +} + diff --git a/reactos/drivers/filesystems/npfs_new/secursup.c b/reactos/drivers/filesystems/npfs_new/secursup.c index 5b0c47e522e..36051c38f68 100644 --- a/reactos/drivers/filesystems/npfs_new/secursup.c +++ b/reactos/drivers/filesystems/npfs_new/secursup.c @@ -1,25 +1,45 @@ #include "npfs.h" +VOID +NTAPI +NpFreeClientSecurityContext(IN PSECURITY_CLIENT_CONTEXT ClientContext) +{ + TOKEN_TYPE TokenType; + PVOID ClientToken; + + if (!ClientContext) return; + + TokenType = SeTokenType(ClientContext->ClientToken); + ClientToken = ClientContext->ClientToken; + if ((TokenType == TokenPrimary) || (ClientToken)) + { + ObfDereferenceObject(ClientToken); + } + 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) { - PACCESS_TOKEN ClientToken; - PSECURITY_CLIENT_CONTEXT ClientContext; - TOKEN_TYPE TokenType; PAGED_CODE(); - ClientContext = Ccb->ClientContext; - if (!ClientContext) return; - - TokenType = SeTokenType(ClientContext->ClientToken); - ClientToken = Ccb->ClientContext->ClientToken; - if ((TokenType == TokenPrimary) || (ClientToken)) - { - ObfDereferenceObject(ClientToken); - } - ExFreePool(Ccb->ClientContext); - Ccb->ClientContext = 0; + 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; +}