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; PNP_DATA_QUEUE ReadQueue; PNP_EVENT_BUFFER EventBuffer; NTSTATUS Status; ULONG NamedPipeEnd; PNP_CCB Ccb; PNP_NONPAGED_CCB NonPagedCcb; BOOLEAN ReadOk; PAGED_CODE(); IoStatus->Information = 0; NodeType = NpDecodeFileObject(FileObject, NULL, &Ccb, &NamedPipeEnd); 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); 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)); if ((NamedPipeEnd == FILE_PIPE_SERVER_END && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_OUTBOUND) || (NamedPipeEnd == FILE_PIPE_CLIENT_END && Ccb->Fcb->NamedPipeConfiguration == FILE_PIPE_INBOUND)) { IoStatus->Status = STATUS_INVALID_PARAMETER; ReadOk = TRUE; goto Quickie; } if (NamedPipeEnd == FILE_PIPE_SERVER_END) { ReadQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND]; } else { ReadQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND]; } EventBuffer = NonPagedCcb->EventBuffer[NamedPipeEnd]; if (ReadQueue->QueueState == WriteEntries) { *IoStatus = NpReadDataQueue(ReadQueue, FALSE, FALSE, Buffer, BufferSize, Ccb->ReadMode[NamedPipeEnd], 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 (Ccb->CompletionMode[NamedPipeEnd] == FILE_PIPE_COMPLETE_OPERATION) { IoStatus->Status = STATUS_PIPE_EMPTY; ReadOk = TRUE; if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE); goto Quickie; } if (!Irp) { ReadOk = FALSE; goto Quickie; } Status = NpAddDataQueueEntry(NamedPipeEnd, Ccb, ReadQueue, ReadEntries, Buffered, BufferSize, Irp, NULL, 0); IoStatus->Status = Status; if (!NT_SUCCESS(Status)) { ReadOk = FALSE; } else { ReadOk = TRUE; if (EventBuffer) KeSetEvent(EventBuffer->Event, IO_NO_INCREMENT, FALSE); } Quickie: ExReleaseResourceLite(&Ccb->NonPagedCcb->Lock); return ReadOk; }
NTSTATUS NTAPI NpPeek(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PLIST_ENTRY List) { PIO_STACK_LOCATION IoStack; NODE_TYPE_CODE Type; ULONG OutputLength; ULONG NamedPipeEnd; PNP_CCB Ccb; PFILE_PIPE_PEEK_BUFFER PeekBuffer; PNP_DATA_QUEUE DataQueue; ULONG_PTR BytesPeeked; IO_STATUS_BLOCK IoStatus; NTSTATUS Status; PNP_DATA_QUEUE_ENTRY DataEntry; PAGED_CODE(); IoStack = IoGetCurrentIrpStackLocation(Irp); OutputLength = IoStack->Parameters.FileSystemControl.OutputBufferLength; Type = NpDecodeFileObject(IoStack->FileObject, NULL, &Ccb, &NamedPipeEnd); if (!Type) { return STATUS_PIPE_DISCONNECTED; } if ((Type != NPFS_NTC_CCB) && (OutputLength < FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data))) { return STATUS_INVALID_PARAMETER; } PeekBuffer = (PFILE_PIPE_PEEK_BUFFER)Irp->AssociatedIrp.SystemBuffer; if (NamedPipeEnd != FILE_PIPE_CLIENT_END) { if (NamedPipeEnd != FILE_PIPE_SERVER_END) { NpBugCheck(NamedPipeEnd, 0, 0); } DataQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND]; } else { DataQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND]; } 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 = FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data); 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 (OutputLength == FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data)) { Status = PeekBuffer->ReadDataAvailable ? STATUS_BUFFER_OVERFLOW : STATUS_SUCCESS; } else { IoStatus = NpReadDataQueue(DataQueue, TRUE, FALSE, PeekBuffer->Data, OutputLength - FIELD_OFFSET(FILE_PIPE_PEEK_BUFFER, Data), Ccb->Fcb->NamedPipeType == FILE_PIPE_MESSAGE_TYPE, Ccb, List); Status = IoStatus.Status; BytesPeeked += IoStatus.Information; } } else { Status = STATUS_SUCCESS; } Irp->IoStatus.Information = BytesPeeked; return Status; }