reactos/drivers/filesystems/npfs/fileinfo.c
2020-06-24 09:04:05 +02:00

485 lines
13 KiB
C

/*
* 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 -= sizeof(FILE_ACCESS_INFORMATION) + sizeof(FILE_MODE_INFORMATION) + sizeof(FILE_ALIGNMENT_INFORMATION);
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);
break;
case FileEaInformation:
Status = NpQueryEaInfo(Ccb, Buffer, &Length);
break;
default:
Status = STATUS_INVALID_PARAMETER;
break;
}
Irp->IoStatus.Information = IoStack->Parameters.QueryFile.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 */