/* * 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 */