Ejemplo n.º 1
0
PLIST_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();

    for (NextEntry = DataQueue->Queue.Flink;
         NextEntry != &DataQueue->Queue;
         NextEntry = DataQueue->Queue.Flink)
    {
        DataEntry = CONTAINING_RECORD(NextEntry,
                                      NP_DATA_QUEUE_ENTRY,
                                      QueueEntry);

        Type = DataEntry->DataEntryType;
        if (Type == Buffered || Type == Unbuffered) break;

        Irp = NpRemoveDataQueueEntry(DataQueue, FALSE, List);
        if (Irp)
        {
            Irp->IoStatus.Status = STATUS_SUCCESS;
            InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
        }
    }

    return NextEntry;
}
Ejemplo n.º 2
0
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->EventBuffer[FILE_PIPE_CLIENT_END];

            while (Ccb->DataQueue[FILE_PIPE_INBOUND].QueueState != Empty)
            {
                Irp = NpRemoveDataQueueEntry(&Ccb->DataQueue[FILE_PIPE_INBOUND], FALSE, List);
                if (Irp)
                {
                    Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED;
                    InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
                }
            }

            while (Ccb->DataQueue[FILE_PIPE_OUTBOUND].QueueState != Empty)
            {
                Irp = NpRemoveDataQueueEntry(&Ccb->DataQueue[FILE_PIPE_OUTBOUND], FALSE, List);
                if (Irp)
                {
                    Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED;
                    InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
                }
            }

            if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);

            // drop down on purpose... queue will be empty so flush code is nop
            ASSERT(Ccb->DataQueue[FILE_PIPE_OUTBOUND].QueueState == Empty);

        case FILE_PIPE_CLOSING_STATE:

            EventBuffer = NonPagedCcb->EventBuffer[FILE_PIPE_CLIENT_END];

            while (Ccb->DataQueue[FILE_PIPE_INBOUND].QueueState != Empty)
            {
                Irp = NpRemoveDataQueueEntry(&Ccb->DataQueue[FILE_PIPE_INBOUND], FALSE, List);
                if (Irp)
                {
                    Irp->IoStatus.Status = STATUS_PIPE_DISCONNECTED;
                    InsertTailList(List, &Irp->Tail.Overlay.ListEntry);
                }
            }

            ASSERT(Ccb->DataQueue[FILE_PIPE_OUTBOUND].QueueState == Empty);

            NpDeleteEventTableEntry(&NpVcb->EventTable, EventBuffer);
            NonPagedCcb->EventBuffer[FILE_PIPE_CLIENT_END] = NULL;

            NpSetFileObject(Ccb->FileObject[FILE_PIPE_CLIENT_END], NULL, NULL, FALSE);
            Ccb->FileObject[FILE_PIPE_CLIENT_END] = NULL;

            NpUninitializeSecurity(Ccb);

            if (Ccb->ClientSession)
            {
                ExFreePool(Ccb->ClientSession);
                Ccb->ClientSession = NULL;
            }

            Status = STATUS_SUCCESS;
            break;

        default:
            NpBugCheck(Ccb->NamedPipeState, 0, 0);
            break;
    }

    Ccb->NamedPipeState = FILE_PIPE_DISCONNECTED_STATE;
    return Status;
}
Ejemplo n.º 3
0
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;
    PIRP ListIrp;

    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);

                ListIrp = CONTAINING_RECORD(NextEntry, IRP, Tail.Overlay.ListEntry);

                if (IoSetCancelRoutine(ListIrp, NULL))
                {
                    ListIrp->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->FileObject[FILE_PIPE_SERVER_END], NULL, NULL, TRUE);
            Ccb->FileObject[FILE_PIPE_SERVER_END] = NULL;

            NpSetFileObject(Ccb->FileObject[FILE_PIPE_CLIENT_END], NULL, NULL, FALSE);
            Ccb->FileObject[FILE_PIPE_CLIENT_END] = NULL;

            NpDeleteCcb(Ccb, List);
            if (!Fcb->CurrentInstances) NpDeleteFcb(Fcb, List);
            break;

        case FILE_PIPE_CLOSING_STATE:

            if (NamedPipeEnd == FILE_PIPE_SERVER_END)
            {
                DataQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
            }
            else
            {
                DataQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
            }

            NpSetFileObject(Ccb->FileObject[FILE_PIPE_SERVER_END], NULL, NULL, TRUE);
            Ccb->FileObject[FILE_PIPE_SERVER_END] = NULL;

            NpSetFileObject(Ccb->FileObject[FILE_PIPE_CLIENT_END], NULL, NULL, FALSE);
            Ccb->FileObject[FILE_PIPE_CLIENT_END] = NULL;

            while (DataQueue->QueueState != Empty)
            {
                ListIrp = NpRemoveDataQueueEntry(DataQueue, FALSE, List);
                if (ListIrp)
                {
                    ListIrp->IoStatus.Status = STATUS_PIPE_BROKEN;
                    InsertTailList(List, &ListIrp->Tail.Overlay.ListEntry);
                }
            }

            NpUninitializeSecurity(Ccb);

            if (Ccb->ClientSession)
            {
                ExFreePool(Ccb->ClientSession);
                Ccb->ClientSession = NULL;
            }

            NpDeleteCcb(Ccb, List);
            if (!Fcb->CurrentInstances) NpDeleteFcb(Fcb, List);
            break;

        case FILE_PIPE_CONNECTED_STATE:

            if (NamedPipeEnd == FILE_PIPE_SERVER_END)
            {
                ReadQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
                WriteQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];

                NpSetFileObject(Ccb->FileObject[FILE_PIPE_SERVER_END], NULL, NULL, TRUE);
                Ccb->FileObject[FILE_PIPE_SERVER_END] = NULL;
            }
            else
            {
                ReadQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
                WriteQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];

                NpSetFileObject(Ccb->FileObject[FILE_PIPE_CLIENT_END], NULL, NULL, FALSE);
                Ccb->FileObject[FILE_PIPE_CLIENT_END] = NULL;
            }

            EventBuffer = NonPagedCcb->EventBuffer[NamedPipeEnd];

            Ccb->NamedPipeState = FILE_PIPE_CLOSING_STATE;

            while (ReadQueue->QueueState != Empty)
            {
                ListIrp = NpRemoveDataQueueEntry(ReadQueue, FALSE, List);
                if (ListIrp)
                {
                    ListIrp->IoStatus.Status = STATUS_PIPE_BROKEN;
                    InsertTailList(List, &ListIrp->Tail.Overlay.ListEntry);
                }
            }

            while (WriteQueue->QueueState == ReadEntries)
            {
                ListIrp = NpRemoveDataQueueEntry(WriteQueue, FALSE, List);
                if (ListIrp)
                {
                    ListIrp->IoStatus.Status = STATUS_PIPE_BROKEN;
                    InsertTailList(List, &ListIrp->Tail.Overlay.ListEntry);
                }
            }

            if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE);
            break;

        default:
            NpBugCheck(Ccb->NamedPipeState, 0, 0);
            break;
    }
    return STATUS_SUCCESS;
}
Ejemplo n.º 4
0
NTSTATUS
NTAPI
NpWriteDataQueue(IN PNP_DATA_QUEUE WriteQueue,
                 IN ULONG Mode,
                 IN PVOID OutBuffer,
                 IN ULONG OutBufferSize,
                 IN ULONG PipeType,
                 OUT PULONG BytesNotWritten,
                 IN PNP_CCB Ccb,
                 IN ULONG NamedPipeEnd,
                 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();

    *BytesNotWritten = OutBufferSize;

    MoreProcessing = TRUE;
    if ((PipeType != FILE_PIPE_MESSAGE_MODE) || (OutBufferSize))
    {
        MoreProcessing = FALSE;
    }

    for (DataEntry = CONTAINING_RECORD(NpGetNextRealDataQueueEntry(WriteQueue, List),
                                       NP_DATA_QUEUE_ENTRY,
                                       QueueEntry);
         ((WriteQueue->QueueState == ReadEntries) &&
         ((*BytesNotWritten > 0) || (MoreProcessing)));
         DataEntry = CONTAINING_RECORD(NpGetNextRealDataQueueEntry(WriteQueue, List),
                                       NP_DATA_QUEUE_ENTRY,
                                       QueueEntry))
    {
        DataSize = DataEntry->DataSize;

        IoStack = IoGetCurrentIrpStackLocation(DataEntry->Irp);

        if (IoStack->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL &&
            IoStack->Parameters.FileSystemControl.FsControlCode == FSCTL_PIPE_INTERNAL_READ_OVFLOW &&
            (DataSize < OutBufferSize || MoreProcessing))
        {
            WriteIrp = NpRemoveDataQueueEntry(WriteQueue, TRUE, 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 = *BytesNotWritten;
        if (BufferSize >= DataSize) BufferSize = DataSize;

        if (DataEntry->DataEntryType != Unbuffered && BufferSize)
        {
            Buffer = ExAllocatePoolWithTag(NonPagedPool, BufferSize, NPFS_DATA_ENTRY_TAG);
            if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
            AllocatedBuffer = TRUE;
        }
        else
        {
            Buffer = DataEntry->Irp->AssociatedIrp.SystemBuffer;
            AllocatedBuffer = FALSE;
        }

        _SEH2_TRY
        {
            RtlCopyMemory(Buffer,
                          (PVOID)((ULONG_PTR)OutBuffer + OutBufferSize - *BytesNotWritten),
                          BufferSize);
        }
        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
        {
            if (AllocatedBuffer) ExFreePool(Buffer);
            _SEH2_YIELD(return _SEH2_GetExceptionCode());
        }
        _SEH2_END;

        if (!HaveContext)
        {
            HaveContext = TRUE;
            Status = NpGetClientSecurityContext(NamedPipeEnd, Ccb, Thread, &ClientContext);
            if (!NT_SUCCESS(Status))
            {
                if (AllocatedBuffer) ExFreePool(Buffer);
                return Status;
            }

            if (ClientContext)
            {
                NpFreeClientSecurityContext(Ccb->ClientContext);
                Ccb->ClientContext = ClientContext;
            }
        }

        WriteIrp = NpRemoveDataQueueEntry(WriteQueue, TRUE, List);
        if (WriteIrp)
        {
            *BytesNotWritten -= BufferSize;
            WriteIrp->IoStatus.Information = BufferSize;

            if (AllocatedBuffer)
            {
                WriteIrp->AssociatedIrp.SystemBuffer = Buffer;
                WriteIrp->Flags |= IRP_DEALLOCATE_BUFFER  | IRP_BUFFERED_IO | IRP_INPUT_OPERATION;
            }

            if (!*BytesNotWritten)
            {
                MoreProcessing = FALSE;
                WriteIrp->IoStatus.Status = STATUS_SUCCESS;
                InsertTailList(List, &WriteIrp->Tail.Overlay.ListEntry);
                continue;
            }

            if (Mode == FILE_PIPE_MESSAGE_MODE)
            {
                WriteIrp->IoStatus.Status = STATUS_BUFFER_OVERFLOW;
            }
            else
            {
                WriteIrp->IoStatus.Status = STATUS_SUCCESS;
            }

            InsertTailList(List, &WriteIrp->Tail.Overlay.ListEntry);
        }
        else if (AllocatedBuffer)
        {
            ExFreePool(Buffer);
        }
    }

    if (*BytesNotWritten > 0 || MoreProcessing)
    {
        ASSERT(WriteQueue->QueueState != ReadEntries);
        Status = STATUS_MORE_PROCESSING_REQUIRED;
    }
    else
    {
        Status = STATUS_SUCCESS;
    }

    return Status;
}