diff --git a/reactos/drivers/filesystems/npfs_new/CMakeLists.txt b/reactos/drivers/filesystems/npfs_new/CMakeLists.txt index 7b2a5675c62..3f02743df67 100644 --- a/reactos/drivers/filesystems/npfs_new/CMakeLists.txt +++ b/reactos/drivers/filesystems/npfs_new/CMakeLists.txt @@ -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 index 00000000000..1be907c5536 --- /dev/null +++ b/reactos/drivers/filesystems/npfs_new/cleanup.c @@ -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 index 00000000000..2d0f26cde56 --- /dev/null +++ b/reactos/drivers/filesystems/npfs_new/close.c @@ -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 index 00000000000..6e3a0635b22 --- /dev/null +++ b/reactos/drivers/filesystems/npfs_new/fileinfo.c @@ -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 index 00000000000..8bffd8852de --- /dev/null +++ b/reactos/drivers/filesystems/npfs_new/flushbuf.c @@ -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 index 00000000000..27ac9f1bb65 --- /dev/null +++ b/reactos/drivers/filesystems/npfs_new/fsctrl.c @@ -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; +} + + diff --git a/reactos/drivers/filesystems/npfs_new/main.c b/reactos/drivers/filesystems/npfs_new/main.c index 1a8b46975a4..0ae3eb00d88 100644 --- a/reactos/drivers/filesystems/npfs_new/main.c +++ b/reactos/drivers/filesystems/npfs_new/main.c @@ -4,8 +4,8 @@ PDEVICE_OBJECT NpfsDeviceObject; NTSTATUS NTAPI -NpFsdClose(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) +NpFsdSetSecurity(IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) { UNIMPLEMENTED; @@ -18,36 +18,8 @@ NpFsdClose(IN PDEVICE_OBJECT DeviceObject, 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) -{ - UNIMPLEMENTED; - - Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; - Irp->IoStatus.Information = 0; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_NOT_IMPLEMENTED; -} - -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, diff --git a/reactos/drivers/filesystems/npfs_new/npfs.h b/reactos/drivers/filesystems/npfs_new/npfs.h index a93b786e460..20fb513924f 100644 --- a/reactos/drivers/filesystems/npfs_new/npfs.h +++ b/reactos/drivers/filesystems/npfs_new/npfs.h @@ -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); + diff --git a/reactos/drivers/filesystems/npfs_new/read.c b/reactos/drivers/filesystems/npfs_new/read.c index 88c6aaf2de0..03bb9d48c37 100644 --- a/reactos/drivers/filesystems/npfs_new/read.c +++ b/reactos/drivers/filesystems/npfs_new/read.c @@ -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; diff --git a/reactos/drivers/filesystems/npfs_new/statesup.c b/reactos/drivers/filesystems/npfs_new/statesup.c index 7e45b33dfbb..dd01a06aed1 100644 --- a/reactos/drivers/filesystems/npfs_new/statesup.c +++ b/reactos/drivers/filesystems/npfs_new/statesup.c @@ -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; +} + diff --git a/reactos/drivers/filesystems/npfs_new/strucsup.c b/reactos/drivers/filesystems/npfs_new/strucsup.c index 5faf02215cc..869ff6f8053 100644 --- a/reactos/drivers/filesystems/npfs_new/strucsup.c +++ b/reactos/drivers/filesystems/npfs_new/strucsup.c @@ -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 diff --git a/reactos/drivers/filesystems/npfs_new/waitsup.c b/reactos/drivers/filesystems/npfs_new/waitsup.c index fbbd3907db1..7fcabbda3e0 100644 --- a/reactos/drivers/filesystems/npfs_new/waitsup.c +++ b/reactos/drivers/filesystems/npfs_new/waitsup.c @@ -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 index 00000000000..96fe2d85b9f --- /dev/null +++ b/reactos/drivers/filesystems/npfs_new/write.c @@ -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 index 00000000000..860f0401bb8 --- /dev/null +++ b/reactos/drivers/filesystems/npfs_new/writesup.c @@ -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; +} +