Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / drivers / filesystems / npfs / fileinfo.c
diff --git a/drivers/filesystems/npfs/fileinfo.c b/drivers/filesystems/npfs/fileinfo.c
new file mode 100644 (file)
index 0000000..dd87ac7
--- /dev/null
@@ -0,0 +1,485 @@
+/*
+ * 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 */