mirror of
https://github.com/reactos/reactos.git
synced 2024-11-11 01:04:11 +00:00
c424146e2c
svn path=/branches/cmake-bringup/; revision=48236
295 lines
8 KiB
C
295 lines
8 KiB
C
/*
|
|
* PROJECT: ReactOS FAT file system driver
|
|
* LICENSE: GNU GPLv3 as published by the Free Software Foundation
|
|
* FILE: drivers/filesystems/fastfat/finfo.c
|
|
* PURPOSE: File Information support routines
|
|
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#define NDEBUG
|
|
#include "fastfat.h"
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
VOID
|
|
NTAPI
|
|
FatiQueryBasicInformation(IN PFAT_IRP_CONTEXT IrpContext,
|
|
IN PFCB Fcb,
|
|
IN PFILE_OBJECT FileObject,
|
|
IN OUT PFILE_BASIC_INFORMATION Buffer,
|
|
IN OUT PLONG Length)
|
|
{
|
|
/* Zero the buffer */
|
|
RtlZeroMemory(Buffer, sizeof(FILE_BASIC_INFORMATION));
|
|
|
|
/* Deduct the written length */
|
|
*Length -= sizeof(FILE_BASIC_INFORMATION);
|
|
|
|
/* Check if it's a dir or a file */
|
|
if (FatNodeType(Fcb) == FAT_NTC_FCB)
|
|
{
|
|
// FIXME: Read dirent and get times from there
|
|
Buffer->LastAccessTime.QuadPart = 0;
|
|
Buffer->CreationTime.QuadPart = 0;
|
|
Buffer->LastWriteTime.QuadPart = 0;
|
|
}
|
|
else
|
|
{
|
|
// FIXME: May not be really correct
|
|
Buffer->FileAttributes = 0;
|
|
DPRINT1("Basic info of a directory '%wZ' is requested!\n", &Fcb->FullFileName);
|
|
}
|
|
|
|
|
|
/* If attribute is 0, set normal */
|
|
if (Buffer->FileAttributes == 0)
|
|
Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
FatiQueryStandardInformation(IN PFAT_IRP_CONTEXT IrpContext,
|
|
IN PFCB Fcb,
|
|
IN PFILE_OBJECT FileObject,
|
|
IN OUT PFILE_STANDARD_INFORMATION Buffer,
|
|
IN OUT PLONG Length)
|
|
{
|
|
/* Zero the buffer */
|
|
RtlZeroMemory(Buffer, sizeof(FILE_STANDARD_INFORMATION));
|
|
|
|
/* Deduct the written length */
|
|
*Length -= sizeof(FILE_STANDARD_INFORMATION);
|
|
|
|
Buffer->NumberOfLinks = 1;
|
|
Buffer->DeletePending = FALSE; // FIXME
|
|
|
|
/* Check if it's a dir or a file */
|
|
if (FatNodeType(Fcb) == FAT_NTC_FCB)
|
|
{
|
|
Buffer->Directory = FALSE;
|
|
|
|
Buffer->EndOfFile.LowPart = Fcb->FatHandle->Filesize;
|
|
Buffer->AllocationSize = Buffer->EndOfFile;
|
|
DPRINT("Filesize %d, chain length %d\n", Fcb->FatHandle->Filesize, Fcb->FatHandle->iChainLength);
|
|
}
|
|
else
|
|
{
|
|
Buffer->Directory = TRUE;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
FatiQueryInternalInformation(IN PFAT_IRP_CONTEXT IrpContext,
|
|
IN PFCB Fcb,
|
|
IN PFILE_OBJECT FileObject,
|
|
IN OUT PFILE_INTERNAL_INFORMATION Buffer,
|
|
IN OUT PLONG Length)
|
|
{
|
|
UNIMPLEMENTED;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
FatiQueryNameInformation(IN PFAT_IRP_CONTEXT IrpContext,
|
|
IN PFCB Fcb,
|
|
IN PFILE_OBJECT FileObject,
|
|
IN OUT PFILE_NAME_INFORMATION Buffer,
|
|
IN OUT PLONG Length)
|
|
{
|
|
ULONG ByteSize;
|
|
ULONG Trim = 0;
|
|
BOOLEAN Overflow = FALSE;
|
|
|
|
/* Deduct the minimum written length */
|
|
*Length -= FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]);
|
|
|
|
/* Build full name if needed */
|
|
if (!Fcb->FullFileName.Buffer)
|
|
{
|
|
FatSetFullFileNameInFcb(IrpContext, Fcb);
|
|
}
|
|
|
|
DPRINT("FullFileName %wZ\n", &Fcb->FullFileName);
|
|
|
|
if (*Length < Fcb->FullFileName.Length - Trim)
|
|
{
|
|
/* Buffer can't fit all data */
|
|
ByteSize = *Length;
|
|
Overflow = TRUE;
|
|
}
|
|
else
|
|
{
|
|
/* Deduct the amount of bytes we are going to write */
|
|
ByteSize = Fcb->FullFileName.Length - Trim;
|
|
*Length -= ByteSize;
|
|
}
|
|
|
|
/* Copy the name */
|
|
RtlCopyMemory(Buffer->FileName,
|
|
Fcb->FullFileName.Buffer,
|
|
ByteSize);
|
|
|
|
/* Set the length */
|
|
Buffer->FileNameLength = Fcb->FullFileName.Length - Trim;
|
|
|
|
/* Is this a shortname query? */
|
|
if (Trim)
|
|
{
|
|
/* Yes, not supported atm */
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
/* Indicate overflow by passing -1 as the length */
|
|
if (Overflow) *Length = -1;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
FatiQueryInformation(IN PFAT_IRP_CONTEXT IrpContext,
|
|
IN PIRP Irp)
|
|
{
|
|
PFILE_OBJECT FileObject;
|
|
PIO_STACK_LOCATION IrpSp;
|
|
FILE_INFORMATION_CLASS InfoClass;
|
|
TYPE_OF_OPEN FileType;
|
|
PVCB Vcb;
|
|
PFCB Fcb;
|
|
PCCB Ccb;
|
|
LONG Length;
|
|
PVOID Buffer;
|
|
BOOLEAN VcbLocked = FALSE, FcbLocked = FALSE;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
/* Get IRP stack location */
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
/* Get the file object */
|
|
FileObject = IrpSp->FileObject;
|
|
|
|
/* Copy variables to something with shorter names */
|
|
InfoClass = IrpSp->Parameters.QueryFile.FileInformationClass;
|
|
Length = IrpSp->Parameters.QueryFile.Length;
|
|
Buffer = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
DPRINT("FatiQueryInformation\n", 0);
|
|
DPRINT("\tIrp = %08lx\n", Irp);
|
|
DPRINT("\tLength = %08lx\n", Length);
|
|
DPRINT("\tFileInformationClass = %08lx\n", InfoClass);
|
|
DPRINT("\tBuffer = %08lx\n", Buffer);
|
|
|
|
FileType = FatDecodeFileObject(FileObject, &Vcb, &Fcb, &Ccb);
|
|
|
|
DPRINT("Vcb %p, Fcb %p, Ccb %p, open type %d\n", Vcb, Fcb, Ccb, FileType);
|
|
|
|
/* Acquire VCB lock */
|
|
if (InfoClass == FileNameInformation ||
|
|
InfoClass == FileAllInformation)
|
|
{
|
|
if (!FatAcquireExclusiveVcb(IrpContext, Vcb))
|
|
{
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
/* Remember we locked the VCB */
|
|
VcbLocked = TRUE;
|
|
}
|
|
|
|
/* Acquire FCB lock */
|
|
// FIXME: If not paging file
|
|
if (!FatAcquireSharedFcb(IrpContext, Fcb))
|
|
{
|
|
ASSERT(FALSE);
|
|
}
|
|
FcbLocked = TRUE;
|
|
|
|
switch (InfoClass)
|
|
{
|
|
case FileBasicInformation:
|
|
FatiQueryBasicInformation(IrpContext, Fcb, FileObject, Buffer, &Length);
|
|
break;
|
|
case FileStandardInformation:
|
|
FatiQueryStandardInformation(IrpContext, Fcb, FileObject, Buffer, &Length);
|
|
break;
|
|
case FileInternalInformation:
|
|
FatiQueryInternalInformation(IrpContext, Fcb, FileObject, Buffer, &Length);
|
|
break;
|
|
case FileNameInformation:
|
|
FatiQueryNameInformation(IrpContext, Fcb, FileObject, Buffer, &Length);
|
|
break;
|
|
default:
|
|
DPRINT1("Unimplemented information class %d requested\n", InfoClass);
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* Check for buffer overflow */
|
|
if (Length < 0)
|
|
{
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
Length = 0;
|
|
}
|
|
|
|
/* Set IoStatus.Information to amount of filled bytes */
|
|
Irp->IoStatus.Information = IrpSp->Parameters.QueryFile.Length - Length;
|
|
|
|
/* Release FCB locks */
|
|
if (FcbLocked) FatReleaseFcb(IrpContext, Fcb);
|
|
if (VcbLocked) FatReleaseVcb(IrpContext, Vcb);
|
|
|
|
/* Complete request and return status */
|
|
FatCompleteRequest(IrpContext, Irp, Status);
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
FatQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
{
|
|
NTSTATUS Status;
|
|
BOOLEAN TopLevel, CanWait;
|
|
PFAT_IRP_CONTEXT IrpContext;
|
|
|
|
CanWait = TRUE;
|
|
TopLevel = FALSE;
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
/* Get CanWait flag */
|
|
if (IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL)
|
|
CanWait = IoIsOperationSynchronous(Irp);
|
|
|
|
/* Enter FsRtl critical region */
|
|
FsRtlEnterFileSystem();
|
|
|
|
/* Set Top Level IRP if not set */
|
|
if (IoGetTopLevelIrp() == NULL)
|
|
{
|
|
IoSetTopLevelIrp(Irp);
|
|
TopLevel = TRUE;
|
|
}
|
|
|
|
/* Build an irp context */
|
|
IrpContext = FatBuildIrpContext(Irp, CanWait);
|
|
|
|
/* Perform the actual read */
|
|
Status = FatiQueryInformation(IrpContext, Irp);
|
|
|
|
/* Restore top level Irp */
|
|
if (TopLevel) IoSetTopLevelIrp(NULL);
|
|
|
|
/* Leave FsRtl critical region */
|
|
FsRtlExitFileSystem();
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
FatSetInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
{
|
|
DPRINT1("FatSetInformation()\n");
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
/* EOF */
|