--- /dev/null
+/*
+ * PROJECT: ReactOS Named Pipe FileSystem
+ * LICENSE: BSD - See COPYING.ARM in the top level directory
+ * FILE: drivers/filesystems/npfs/fileinfo.c
+ * PURPOSE: Pipes Information
+ * PROGRAMMERS: ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include "npfs.h"
+
+// File ID number for NPFS bugchecking support
+#define NPFS_BUGCHECK_FILE_ID (NPFS_BUGCHECK_FILEINFO)
+
+/* FUNCTIONS ******************************************************************/
+
+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 NamedPipeEnd,
+ IN PLIST_ENTRY List)
+{
+ NTSTATUS Status;
+ PNP_DATA_QUEUE ReadQueue, WriteQueue;
+ PAGED_CODE();
+
+ if (Buffer->ReadMode == FILE_PIPE_MESSAGE_MODE && Fcb->NamedPipeType == FILE_PIPE_BYTE_STREAM_TYPE)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if (NamedPipeEnd != FILE_PIPE_CLIENT_END)
+ {
+ if (NamedPipeEnd != FILE_PIPE_SERVER_END)
+ {
+ NpBugCheck(NamedPipeEnd, 0, 0);
+ }
+ ReadQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
+ WriteQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
+ }
+ else
+ {
+ ReadQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
+ WriteQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
+ }
+
+ if (Buffer->CompletionMode != FILE_PIPE_COMPLETE_OPERATION ||
+ Ccb->CompletionMode[NamedPipeEnd] == FILE_PIPE_COMPLETE_OPERATION ||
+ (ReadQueue->QueueState != ReadEntries &&
+ WriteQueue->QueueState != WriteEntries))
+ {
+ Ccb->ReadMode[NamedPipeEnd] = Buffer->ReadMode & 0xFF;
+ Ccb->CompletionMode[NamedPipeEnd] = Buffer->CompletionMode & 0xFF;
+
+ NpCheckForNotify(Fcb->ParentDcb, FALSE, List);
+ Status = STATUS_SUCCESS;
+ }
+ 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;
+ ULONG NamedPipeEnd;
+ PAGED_CODE();
+
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+ NodeTypeCode = NpDecodeFileObject(IoStack->FileObject,
+ (PVOID*)&Fcb,
+ &Ccb,
+ &NamedPipeEnd);
+ 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, NamedPipeEnd, List);
+}
+
+NTSTATUS
+NTAPI
+NpFsdSetInformation(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ NTSTATUS Status;
+ LIST_ENTRY DeferredList;
+ PAGED_CODE();
+
+ InitializeListHead(&DeferredList);
+
+ FsRtlEnterFileSystem();
+ NpAcquireExclusiveVcb();
+
+ Status = NpCommonSetInformation(DeviceObject, Irp, &DeferredList);
+
+ NpReleaseVcb();
+ NpCompleteDeferredIrps(&DeferredList);
+ FsRtlExitFileSystem();
+
+ if (Status != STATUS_PENDING)
+ {
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+NpQueryBasicInfo(IN PNP_CCB Ccb,
+ IN PVOID Buffer,
+ IN OUT PULONG Length)
+{
+ PFILE_BASIC_INFORMATION InfoBuffer = Buffer;
+
+ *Length -= sizeof(*InfoBuffer);
+
+ RtlZeroMemory(InfoBuffer, sizeof(*InfoBuffer));
+ InfoBuffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+NpQueryStandardInfo(IN PNP_CCB Ccb,
+ IN PVOID Buffer,
+ IN OUT PULONG Length,
+ IN ULONG NamedPipeEnd)
+{
+ PNP_DATA_QUEUE DataQueue;
+ PFILE_STANDARD_INFORMATION InfoBuffer = Buffer;
+
+ *Length -= sizeof(*InfoBuffer);
+
+ RtlZeroMemory(InfoBuffer, sizeof(*InfoBuffer));
+
+ if (NamedPipeEnd == FILE_PIPE_SERVER_END)
+ {
+ DataQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
+ }
+ else
+ {
+ DataQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
+ }
+
+ InfoBuffer->AllocationSize.LowPart = Ccb->DataQueue[FILE_PIPE_INBOUND].Quota +
+ Ccb->DataQueue[FILE_PIPE_OUTBOUND].Quota;
+ InfoBuffer->AllocationSize.HighPart = 0;
+
+ if (DataQueue->QueueState == WriteEntries)
+ {
+ InfoBuffer->EndOfFile.HighPart = 0;
+ InfoBuffer->EndOfFile.LowPart = DataQueue->BytesInQueue -
+ DataQueue->ByteOffset;
+ }
+
+ InfoBuffer->Directory = FALSE;
+ InfoBuffer->NumberOfLinks = 1;
+ InfoBuffer->DeletePending = TRUE;
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+NpQueryEaInfo(IN PNP_CCB Ccb,
+ IN PVOID Buffer,
+ IN OUT PULONG Length)
+{
+ PFILE_EA_INFORMATION InfoBuffer = Buffer;
+
+ *Length -= sizeof(*InfoBuffer);
+
+ RtlZeroMemory(InfoBuffer, sizeof(*InfoBuffer));
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+NpQueryNameInfo(IN PNP_CCB Ccb,
+ IN PVOID Buffer,
+ IN OUT PULONG Length)
+{
+ PFILE_NAME_INFORMATION InfoBuffer = Buffer;
+ USHORT NameLength;
+ NTSTATUS Status;
+ PWCHAR Name;
+
+ *Length -= sizeof(*InfoBuffer);
+
+ if (Ccb->NodeType == NPFS_NTC_ROOT_DCB_CCB)
+ {
+ NameLength = NpVcb->RootDcb->FullName.Length;
+ Name = NpVcb->RootDcb->FullName.Buffer;
+ }
+ else
+ {
+ NameLength = Ccb->Fcb->FullName.Length;
+ Name = Ccb->Fcb->FullName.Buffer;
+ }
+
+ if (*Length < NameLength)
+ {
+ Status = STATUS_BUFFER_OVERFLOW;
+ NameLength = (USHORT)*Length;
+ }
+ else
+ {
+ Status = STATUS_SUCCESS;
+ }
+
+ RtlCopyMemory(InfoBuffer->FileName, Name, NameLength);
+ InfoBuffer->FileNameLength = NameLength;
+
+ *Length -= NameLength;
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+NpQueryInternalInfo(IN PNP_CCB Ccb,
+ IN PVOID Buffer,
+ IN OUT PULONG Length)
+{
+ PFILE_INTERNAL_INFORMATION InfoBuffer = Buffer;
+
+ *Length -= sizeof(*InfoBuffer);
+
+ RtlZeroMemory(InfoBuffer, sizeof(*InfoBuffer));
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+NpQueryPositionInfo(IN PNP_CCB Ccb,
+ IN PVOID Buffer,
+ IN OUT PULONG Length,
+ IN ULONG NamedPipeEnd)
+{
+ PNP_DATA_QUEUE DataQueue;
+ PFILE_POSITION_INFORMATION InfoBuffer = Buffer;
+
+ *Length -= sizeof(*InfoBuffer);
+
+ RtlZeroMemory(InfoBuffer, sizeof(*InfoBuffer));
+
+ if (NamedPipeEnd == FILE_PIPE_SERVER_END)
+ {
+ DataQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
+ }
+ else
+ {
+ DataQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
+ }
+
+ if (DataQueue->QueueState == WriteEntries)
+ {
+ InfoBuffer->CurrentByteOffset.QuadPart = DataQueue->BytesInQueue -
+ DataQueue->ByteOffset;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+NpQueryPipeLocalInfo(IN PNP_FCB Fcb,
+ IN PNP_CCB Ccb,
+ IN PVOID Buffer,
+ IN OUT PULONG Length,
+ IN ULONG NamedPipeEnd)
+{
+ PFILE_PIPE_LOCAL_INFORMATION InfoBuffer = Buffer;
+ PNP_DATA_QUEUE InQueue, OutQueue;
+
+ *Length -= sizeof(*InfoBuffer);
+
+ RtlZeroMemory(InfoBuffer, sizeof(*InfoBuffer));
+
+ InQueue = &Ccb->DataQueue[FILE_PIPE_INBOUND];
+ OutQueue = &Ccb->DataQueue[FILE_PIPE_OUTBOUND];
+
+ InfoBuffer->NamedPipeType = Fcb->NamedPipeType;
+ InfoBuffer->NamedPipeConfiguration = Fcb->NamedPipeConfiguration;
+ InfoBuffer->MaximumInstances = Fcb->MaximumInstances;
+ InfoBuffer->CurrentInstances = Fcb->CurrentInstances;
+ InfoBuffer->InboundQuota = InQueue->Quota;
+ InfoBuffer->OutboundQuota = OutQueue->Quota;
+ InfoBuffer->NamedPipeState = Ccb->NamedPipeState;
+ InfoBuffer->NamedPipeEnd = NamedPipeEnd;
+
+ if (NamedPipeEnd == FILE_PIPE_SERVER_END)
+ {
+ if (InQueue->QueueState == WriteEntries)
+ {
+ InfoBuffer->ReadDataAvailable = InQueue->BytesInQueue - InQueue->ByteOffset;
+ }
+ InfoBuffer->WriteQuotaAvailable = OutQueue->Quota - OutQueue->QuotaUsed;
+ }
+ else
+ {
+ if (OutQueue->QueueState == WriteEntries)
+ {
+ InfoBuffer->ReadDataAvailable = OutQueue->BytesInQueue - OutQueue->ByteOffset;
+ }
+ InfoBuffer->WriteQuotaAvailable = OutQueue->Quota - InQueue->QuotaUsed;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+NpQueryPipeInfo(IN PNP_FCB Fcb,
+ IN PNP_CCB Ccb,
+ IN PVOID Buffer,
+ IN OUT PULONG Length,
+ IN ULONG NamedPipeEnd)
+{
+ PFILE_PIPE_INFORMATION InfoBuffer = Buffer;
+
+ *Length -= sizeof(*InfoBuffer);
+
+ RtlZeroMemory(InfoBuffer, sizeof(*InfoBuffer));
+
+ InfoBuffer->ReadMode = Ccb->ReadMode[NamedPipeEnd];
+ InfoBuffer->CompletionMode = Ccb->CompletionMode[NamedPipeEnd];
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+NpCommonQueryInformation(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION IoStack;
+ NODE_TYPE_CODE NodeTypeCode;
+ ULONG NamedPipeEnd;
+ PNP_FCB Fcb;
+ PNP_CCB Ccb;
+ FILE_INFORMATION_CLASS InfoClass;
+ ULONG Length;
+ PVOID Buffer;
+ PFILE_ALL_INFORMATION AllInfo;
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ IoStack = IoGetCurrentIrpStackLocation(Irp);
+ NodeTypeCode = NpDecodeFileObject(IoStack->FileObject,
+ (PVOID*)&Fcb,
+ &Ccb,
+ &NamedPipeEnd);
+ if (!NodeTypeCode) return STATUS_PIPE_DISCONNECTED;
+
+ Buffer = Irp->AssociatedIrp.SystemBuffer;
+ Length = IoStack->Parameters.QueryFile.Length;
+ InfoClass = IoStack->Parameters.QueryFile.FileInformationClass;
+
+ if (NodeTypeCode != NPFS_NTC_CCB)
+ {
+ if (NodeTypeCode != NPFS_NTC_ROOT_DCB || InfoClass != FileNameInformation)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+ }
+
+ switch (InfoClass)
+ {
+ case FileNameInformation:
+ Status = NpQueryNameInfo(Ccb, Buffer, &Length);
+ break;
+
+ case FilePositionInformation:
+ Status = NpQueryPositionInfo(Ccb, Buffer, &Length, NamedPipeEnd);
+ break;
+
+ case FilePipeInformation:
+ Status = NpQueryPipeInfo(Fcb, Ccb, Buffer, &Length, NamedPipeEnd);
+ break;
+
+ case FilePipeLocalInformation:
+ Status = NpQueryPipeLocalInfo(Fcb, Ccb, Buffer, &Length, NamedPipeEnd);
+ break;
+
+ case FileBasicInformation:
+ Status = NpQueryBasicInfo(Ccb, Buffer, &Length);
+ break;
+
+ case FileStandardInformation:
+ Status = NpQueryStandardInfo(Ccb, Buffer, &Length, NamedPipeEnd);
+ break;
+
+ case FileInternalInformation:
+ Status = NpQueryInternalInfo(Ccb, Buffer, &Length);
+ break;
+
+ case FileAllInformation:
+
+ Length -= 12;
+ AllInfo = (PFILE_ALL_INFORMATION)Buffer;
+ NpQueryBasicInfo(Ccb, &AllInfo->BasicInformation, &Length);
+ NpQueryStandardInfo(Ccb, &AllInfo->StandardInformation, &Length, NamedPipeEnd);
+ NpQueryInternalInfo(Ccb, &AllInfo->InternalInformation, &Length);
+ NpQueryEaInfo(Ccb, &AllInfo->EaInformation, &Length);
+ NpQueryPositionInfo(Ccb, &AllInfo->PositionInformation, &Length, NamedPipeEnd);
+ Status = NpQueryNameInfo(Ccb, &AllInfo->NameInformation, &Length);
+ Length += 96;
+ break;
+
+ case FileEaInformation:
+ Status = NpQueryEaInfo(Ccb, Buffer, &Length);
+ break;
+
+ default:
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ Irp->IoStatus.Information = IoStack->Parameters.Read.Length - Length;
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+NpFsdQueryInformation(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ FsRtlEnterFileSystem();
+ NpAcquireSharedVcb();
+
+ Status = NpCommonQueryInformation(DeviceObject, Irp);
+
+ NpReleaseVcb();
+ FsRtlExitFileSystem();
+
+ if (Status != STATUS_PENDING)
+ {
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NAMED_PIPE_INCREMENT);
+ }
+
+ return Status;
+}
+
+/* EOF */